kard-network-ble-mesh 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -0
- package/android/build.gradle +94 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +18 -0
- package/android/src/main/AndroidManifestNew.xml +17 -0
- package/android/src/main/java/com/blemesh/BleMeshModule.kt +1143 -0
- package/android/src/main/java/com/blemesh/BleMeshPackage.kt +16 -0
- package/ios/BleMesh.m +45 -0
- package/ios/BleMesh.swift +1075 -0
- package/kard-network-ble-mesh.podspec +27 -0
- package/lib/commonjs/index.js +241 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/index.js +236 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/index.d.ts +103 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/package.json +90 -0
- package/src/index.ts +334 -0
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# kard-network-ble-mesh
|
|
2
|
+
|
|
3
|
+
A React Native library for BLE (Bluetooth Low Energy) mesh networking. Build decentralized, peer-to-peer messaging apps that work without internet connectivity.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Cross-platform**: Works on both iOS and Android
|
|
8
|
+
- **Mesh networking**: Messages automatically relay through peers
|
|
9
|
+
- **End-to-end encryption**: Noise protocol for secure private messages
|
|
10
|
+
- **Seamless permissions**: Handles permission requests automatically
|
|
11
|
+
- **Message deduplication**: Built-in deduplication prevents duplicate messages
|
|
12
|
+
- **Peer discovery**: Automatic discovery of nearby devices
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install kard-network-ble-mesh
|
|
18
|
+
# or
|
|
19
|
+
yarn add kard-network-ble-mesh
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### iOS
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd ios && pod install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Add the following to your `Info.plist`:
|
|
29
|
+
|
|
30
|
+
```xml
|
|
31
|
+
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
32
|
+
<string>This app uses Bluetooth to communicate with nearby devices</string>
|
|
33
|
+
<key>NSBluetoothPeripheralUsageDescription</key>
|
|
34
|
+
<string>This app uses Bluetooth to communicate with nearby devices</string>
|
|
35
|
+
<key>UIBackgroundModes</key>
|
|
36
|
+
<array>
|
|
37
|
+
<string>bluetooth-central</string>
|
|
38
|
+
<string>bluetooth-peripheral</string>
|
|
39
|
+
</array>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Android
|
|
43
|
+
|
|
44
|
+
Add the following permissions to your `AndroidManifest.xml` (they are already included in the library manifest):
|
|
45
|
+
|
|
46
|
+
```xml
|
|
47
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
48
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
49
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
50
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
51
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
52
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
53
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { BleMesh } from 'kard-network-ble-mesh';
|
|
60
|
+
|
|
61
|
+
// Start the mesh service (automatically requests permissions)
|
|
62
|
+
await BleMesh.start({ nickname: 'Alice' });
|
|
63
|
+
|
|
64
|
+
// Listen for events
|
|
65
|
+
BleMesh.onPeerListUpdated(({ peers }) => {
|
|
66
|
+
console.log('Connected peers:', peers);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
BleMesh.onMessageReceived(({ message }) => {
|
|
70
|
+
console.log('Received message:', message);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Send a public broadcast message
|
|
74
|
+
await BleMesh.sendMessage('Hello everyone!');
|
|
75
|
+
|
|
76
|
+
// Send a private encrypted message
|
|
77
|
+
await BleMesh.sendPrivateMessage('Secret message', recipientPeerId);
|
|
78
|
+
|
|
79
|
+
// Get current peers
|
|
80
|
+
const peers = await BleMesh.getPeers();
|
|
81
|
+
|
|
82
|
+
// Stop the service
|
|
83
|
+
await BleMesh.stop();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## API Reference
|
|
87
|
+
|
|
88
|
+
### BleMesh
|
|
89
|
+
|
|
90
|
+
The main singleton instance for interacting with the BLE mesh.
|
|
91
|
+
|
|
92
|
+
#### Methods
|
|
93
|
+
|
|
94
|
+
##### `start(config?: MeshServiceConfig): Promise<void>`
|
|
95
|
+
|
|
96
|
+
Starts the mesh service. Automatically requests required permissions.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
interface MeshServiceConfig {
|
|
100
|
+
nickname?: string; // Default: 'anon'
|
|
101
|
+
autoRequestPermissions?: boolean; // Default: true
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
##### `stop(): Promise<void>`
|
|
106
|
+
|
|
107
|
+
Stops the mesh service and disconnects from all peers.
|
|
108
|
+
|
|
109
|
+
##### `setNickname(nickname: string): Promise<void>`
|
|
110
|
+
|
|
111
|
+
Updates your nickname and broadcasts the change to peers.
|
|
112
|
+
|
|
113
|
+
##### `getMyPeerId(): Promise<string>`
|
|
114
|
+
|
|
115
|
+
Returns your unique peer ID (derived from your public key fingerprint).
|
|
116
|
+
|
|
117
|
+
##### `getMyNickname(): Promise<string>`
|
|
118
|
+
|
|
119
|
+
Returns your current nickname.
|
|
120
|
+
|
|
121
|
+
##### `getPeers(): Promise<Peer[]>`
|
|
122
|
+
|
|
123
|
+
Returns an array of all discovered peers.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
interface Peer {
|
|
127
|
+
peerId: string;
|
|
128
|
+
nickname: string;
|
|
129
|
+
isConnected: boolean;
|
|
130
|
+
rssi?: number;
|
|
131
|
+
lastSeen: number;
|
|
132
|
+
isVerified: boolean;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
##### `sendMessage(content: string, channel?: string): Promise<string>`
|
|
137
|
+
|
|
138
|
+
Sends a public broadcast message. Returns the message ID.
|
|
139
|
+
|
|
140
|
+
##### `sendPrivateMessage(content: string, recipientPeerId: string): Promise<string>`
|
|
141
|
+
|
|
142
|
+
Sends an encrypted private message to a specific peer. Returns the message ID.
|
|
143
|
+
|
|
144
|
+
##### `sendReadReceipt(messageId: string, recipientPeerId: string): Promise<void>`
|
|
145
|
+
|
|
146
|
+
Sends a read receipt for a received message.
|
|
147
|
+
|
|
148
|
+
##### `hasEncryptedSession(peerId: string): Promise<boolean>`
|
|
149
|
+
|
|
150
|
+
Checks if an encrypted session exists with the specified peer.
|
|
151
|
+
|
|
152
|
+
##### `initiateHandshake(peerId: string): Promise<void>`
|
|
153
|
+
|
|
154
|
+
Initiates a Noise handshake with a peer for encrypted communication.
|
|
155
|
+
|
|
156
|
+
##### `getIdentityFingerprint(): Promise<string>`
|
|
157
|
+
|
|
158
|
+
Returns your identity fingerprint for verification.
|
|
159
|
+
|
|
160
|
+
##### `getPeerFingerprint(peerId: string): Promise<string | null>`
|
|
161
|
+
|
|
162
|
+
Returns a peer's identity fingerprint for verification.
|
|
163
|
+
|
|
164
|
+
##### `broadcastAnnounce(): Promise<void>`
|
|
165
|
+
|
|
166
|
+
Forces a broadcast announce to refresh your presence on the mesh.
|
|
167
|
+
|
|
168
|
+
#### Events
|
|
169
|
+
|
|
170
|
+
##### `onPeerListUpdated(callback): () => void`
|
|
171
|
+
|
|
172
|
+
Called when the peer list changes.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
BleMesh.onPeerListUpdated(({ peers }) => {
|
|
176
|
+
console.log('Peers updated:', peers);
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
##### `onMessageReceived(callback): () => void`
|
|
181
|
+
|
|
182
|
+
Called when a message is received.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
BleMesh.onMessageReceived(({ message }) => {
|
|
186
|
+
console.log('Message from', message.senderNickname, ':', message.content);
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
##### `onConnectionStateChanged(callback): () => void`
|
|
191
|
+
|
|
192
|
+
Called when the connection state changes.
|
|
193
|
+
|
|
194
|
+
##### `onReadReceipt(callback): () => void`
|
|
195
|
+
|
|
196
|
+
Called when a read receipt is received.
|
|
197
|
+
|
|
198
|
+
##### `onDeliveryAck(callback): () => void`
|
|
199
|
+
|
|
200
|
+
Called when a delivery acknowledgment is received.
|
|
201
|
+
|
|
202
|
+
##### `onError(callback): () => void`
|
|
203
|
+
|
|
204
|
+
Called when an error occurs.
|
|
205
|
+
|
|
206
|
+
## Protocol Compatibility
|
|
207
|
+
|
|
208
|
+
This library uses the same binary protocol as:
|
|
209
|
+
- [bitchat (iOS)](https://github.com/permissionlesstech/bitchat)
|
|
210
|
+
- [bitchat-android](https://github.com/permissionlesstech/bitchat-android)
|
|
211
|
+
|
|
212
|
+
Messages can be exchanged between all three platforms.
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.1.0"
|
|
9
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def isNewArchitectureEnabled() {
|
|
14
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
apply plugin: "com.android.library"
|
|
18
|
+
apply plugin: "kotlin-android"
|
|
19
|
+
|
|
20
|
+
def getExtOrDefault(name) {
|
|
21
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["BleMesh_" + name]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def getExtOrIntegerDefault(name) {
|
|
25
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["BleMesh_" + name]).toInteger()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def supportsNamespace() {
|
|
29
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
30
|
+
def major = parsed[0].toInteger()
|
|
31
|
+
def minor = parsed[1].toInteger()
|
|
32
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
android {
|
|
36
|
+
if (supportsNamespace()) {
|
|
37
|
+
namespace "com.blemesh"
|
|
38
|
+
|
|
39
|
+
sourceSets {
|
|
40
|
+
main {
|
|
41
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
47
|
+
|
|
48
|
+
defaultConfig {
|
|
49
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
50
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
51
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
buildFeatures {
|
|
55
|
+
buildConfig true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
buildTypes {
|
|
59
|
+
release {
|
|
60
|
+
minifyEnabled false
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
lintOptions {
|
|
65
|
+
disable "GradleCompatible"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
compileOptions {
|
|
69
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
70
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
kotlinOptions {
|
|
74
|
+
jvmTarget = "1.8"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
sourceSets {
|
|
78
|
+
main {
|
|
79
|
+
java.srcDirs = ['src/main/java']
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
repositories {
|
|
85
|
+
mavenCentral()
|
|
86
|
+
google()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
dependencies {
|
|
90
|
+
implementation "com.facebook.react:react-android"
|
|
91
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
|
|
92
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
|
|
93
|
+
implementation "androidx.core:core-ktx:1.12.0"
|
|
94
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
package="com.blemesh">
|
|
3
|
+
|
|
4
|
+
<!-- BLE Permissions -->
|
|
5
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
6
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
7
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
8
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
9
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
10
|
+
|
|
11
|
+
<!-- Location Permissions (required for BLE scanning) -->
|
|
12
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
13
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
14
|
+
|
|
15
|
+
<!-- Declare BLE feature -->
|
|
16
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
17
|
+
|
|
18
|
+
</manifest>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
|
|
3
|
+
<!-- BLE Permissions -->
|
|
4
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
5
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
6
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
7
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
8
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
9
|
+
|
|
10
|
+
<!-- Location Permissions (required for BLE scanning) -->
|
|
11
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
12
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
13
|
+
|
|
14
|
+
<!-- Declare BLE feature -->
|
|
15
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
16
|
+
|
|
17
|
+
</manifest>
|