@iotize/device-com-ble.cordova 3.5.2 → 3.6.2-alpha.2
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 +174 -174
- package/bundles/iotize-device-com-ble.cordova.umd.js +19 -0
- package/bundles/iotize-device-com-ble.cordova.umd.js.map +1 -1
- package/bundles/iotize-device-com-ble.cordova.umd.min.js +1 -1
- package/bundles/iotize-device-com-ble.cordova.umd.min.js.map +1 -1
- package/esm2015/iotize-device-com-ble.cordova.ngsummary.json +1 -1
- package/esm2015/lib/ble-com-protocol.js.map +1 -1
- package/esm2015/lib/cordova-ble-error.js.map +1 -1
- package/esm2015/lib/cordova-interface.js.map +1 -1
- package/esm2015/lib/cordova-service-adapter.js.map +1 -1
- package/esm2015/lib/definitions.js.map +1 -1
- package/esm2015/lib/iotize-ble-cordova-plugin.js.map +1 -1
- package/esm2015/lib/logger.js.map +1 -1
- package/esm2015/lib/scanner.js.map +1 -1
- package/esm2015/lib/utility.js +18 -0
- package/esm2015/lib/utility.js.map +1 -1
- package/esm2015/lib/utility.metadata.json +1 -1
- package/esm2015/lib/utility.ngsummary.json +1 -1
- package/esm2015/public_api.js +1 -1
- package/esm2015/public_api.js.map +1 -1
- package/esm2015/public_api.metadata.json +1 -1
- package/esm2015/public_api.ngsummary.json +1 -1
- package/fesm2015/iotize-device-com-ble.cordova.js +19 -1
- package/fesm2015/iotize-device-com-ble.cordova.js.map +1 -1
- package/iotize-device-com-ble.cordova.metadata.json +1 -1
- package/lib/definitions.d.ts +5 -1
- package/lib/utility.d.ts +4 -0
- package/package.json +1 -1
- package/plugin.xml +68 -68
- package/public_api.d.ts +1 -1
- package/src/android/.gradle/4.8.1/fileHashes/fileHashes.bin +0 -0
- package/src/android/.gradle/4.8.1/fileHashes/fileHashes.lock +0 -0
- package/src/android/src/ble/BLECom.java +6 -6
- package/src/android/src/ble/BLEComError.java +11 -0
- package/src/android/src/ble/BLEProtocol.java +874 -0
- package/src/android/src/ble/BLEScanner.java +284 -0
- package/src/android/src/ble/JSONBuilder.java +12 -1
- package/src/android/src/ble/PluginResponse.java +1 -1
- package/src/android/src/ble/TapUtility.java +27 -0
- package/src/android/src/ble/characteristics/AbstractLwM2MRequestCharacteristic.java +48 -0
- package/src/android/src/ble/characteristics/CharacteristicAdapter.java +221 -0
- package/src/android/src/ble/characteristics/CharacteristicAdapterCallbacks.java +21 -0
- package/src/android/src/ble/characteristics/LwM2M20BytesRequestCharacteristicAdapter.java +161 -0
- package/src/android/src/ble/characteristics/LwM2MMTURequestCharacteristicAdapter.java +134 -0
- package/src/android/src/ble/commands/BLECommand.java +18 -0
- package/src/android/src/ble/commands/CharacteristicOperationCompletedNotifier.java +38 -0
- package/src/android/src/ble/commands/CommandCompletedNotifier.java +10 -0
- package/src/android/src/ble/commands/DescriptorOperationCompletedNotifier.java +37 -0
- package/src/android/src/ble/commands/GattOperationCompletedNotifier.java +29 -0
- package/src/ios/BLECom.swift +732 -732
- package/src/ios/BLEManager.swift +6 -6
- package/src/ios/BLETapPeripheral.swift +9 -1
- package/src/windows/iotize-ble-com.js +159 -159
- package/www/plugin.js +1 -1
- package/src/android/.gradle/6.8.2/fileHashes/fileHashes.lock +0 -0
- package/src/android/.gradle/6.8.2/gc.properties +0 -0
- package/src/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/src/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/src/android/.gradle/checksums/checksums.lock +0 -0
- package/src/android/.gradle/configuration-cache/gc.properties +0 -0
- package/src/android/.gradle/vcs-1/gc.properties +0 -0
- package/src/android/.gradle/vcsWorkingDirs/gc.properties +0 -0
- package/src/android/.idea/android.iml +0 -9
- package/src/android/.idea/gradle.xml +0 -16
- package/src/android/.idea/modules.xml +0 -8
- package/src/android/.idea/vcs.xml +0 -6
- package/src/windows/IoTizeBLE.pdb +0 -0
- package/src/windows/IoTizeBLE.pri +0 -0
- /package/src/android/.gradle/{6.8.2 → 4.8.1}/fileChanges/last-build.bin +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
package com.iotize.plugin.cordova.ble;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import static android.os.Build.VERSION_CODES.LOLLIPOP;
|
|
5
|
+
|
|
6
|
+
import android.bluetooth.BluetoothAdapter;
|
|
7
|
+
import android.bluetooth.BluetoothDevice;
|
|
8
|
+
import android.bluetooth.le.BluetoothLeScanner;
|
|
9
|
+
import android.bluetooth.le.ScanCallback;
|
|
10
|
+
import android.bluetooth.le.ScanFilter;
|
|
11
|
+
import android.bluetooth.le.ScanRecord;
|
|
12
|
+
import android.bluetooth.le.ScanResult;
|
|
13
|
+
import android.bluetooth.le.ScanSettings;
|
|
14
|
+
import android.content.Context;
|
|
15
|
+
import android.content.pm.PackageManager;
|
|
16
|
+
import android.os.Build;
|
|
17
|
+
import android.util.Log;
|
|
18
|
+
|
|
19
|
+
import androidx.annotation.NonNull;
|
|
20
|
+
import androidx.annotation.RequiresApi;
|
|
21
|
+
|
|
22
|
+
import com.iotize.android.device.api.device.scanner.IDeviceScanner;
|
|
23
|
+
import com.iotize.android.device.api.device.scanner.IOnDeviceDiscovered;
|
|
24
|
+
|
|
25
|
+
import java.util.List;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
|
31
|
+
public class BLEScanner implements IDeviceScanner<BLEScanner.BLEScanData> {
|
|
32
|
+
|
|
33
|
+
private static final String TAG = "BLEScanner";
|
|
34
|
+
|
|
35
|
+
@NonNull
|
|
36
|
+
private final BluetoothAdapter mBluetoothAdapter;
|
|
37
|
+
@NonNull
|
|
38
|
+
private final Context mContext;
|
|
39
|
+
@NonNull
|
|
40
|
+
private final List<ScanFilter> filters;
|
|
41
|
+
|
|
42
|
+
// Device scan callback.
|
|
43
|
+
protected BLE_Callback mLeScanCallback;
|
|
44
|
+
protected BLE_Callback_API21 mLeScanCallback_API21;
|
|
45
|
+
private BluetoothLeScanner mBluetoothScanner;
|
|
46
|
+
private IOnDeviceDiscovered<BLEScanData> onDeviceDiscovered;
|
|
47
|
+
private boolean mRunning;
|
|
48
|
+
|
|
49
|
+
public BLEScanner(@NonNull Context context,
|
|
50
|
+
@NonNull BluetoothAdapter bluetoothAdapter,
|
|
51
|
+
@NonNull List<ScanFilter> filters) {
|
|
52
|
+
this.mBluetoothAdapter = bluetoothAdapter;
|
|
53
|
+
if (Build.VERSION.SDK_INT < LOLLIPOP)
|
|
54
|
+
mLeScanCallback = new BLE_Callback();
|
|
55
|
+
else {
|
|
56
|
+
mLeScanCallback_API21 = new BLE_Callback_API21();
|
|
57
|
+
}
|
|
58
|
+
this.mContext = context;
|
|
59
|
+
this.filters = filters;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public void setOnDeviceDiscoveredCallback(IOnDeviceDiscovered<BLEScanData> onDeviceDiscovered) {
|
|
63
|
+
this.onDeviceDiscovered = onDeviceDiscovered;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public void start() {
|
|
67
|
+
if (mRunning) {
|
|
68
|
+
Log.w(TAG, "Scan is already running... ignoring this call");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
mRunning = true;
|
|
72
|
+
if (Build.VERSION.SDK_INT < LOLLIPOP) {
|
|
73
|
+
Log.i(TAG, "Starting Bluetooth scan...");
|
|
74
|
+
mBluetoothAdapter.startLeScan(mLeScanCallback);
|
|
75
|
+
} else {
|
|
76
|
+
Log.i(TAG, "Starting Bluetooth Low Energy scan...");
|
|
77
|
+
try {
|
|
78
|
+
ScanSettings.Builder buildSettings = new ScanSettings.Builder();
|
|
79
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
80
|
+
buildSettings.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
|
|
81
|
+
}
|
|
82
|
+
buildSettings.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
|
|
83
|
+
buildSettings.setReportDelay(0); // we want the result immediately
|
|
84
|
+
ScanSettings settings = buildSettings.build();
|
|
85
|
+
mBluetoothScanner = mBluetoothAdapter.getBluetoothLeScanner();
|
|
86
|
+
mBluetoothScanner.startScan(this.filters, settings, mLeScanCallback_API21);
|
|
87
|
+
} catch (Exception e) {
|
|
88
|
+
Log.e(TAG, "Cannot run bluetooth scan: " + e.getMessage(), e);
|
|
89
|
+
stop();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
95
|
+
public void stop() {
|
|
96
|
+
try {
|
|
97
|
+
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
|
|
98
|
+
if (mBluetoothScanner != null) {
|
|
99
|
+
mBluetoothScanner.stopScan(mLeScanCallback_API21);
|
|
100
|
+
}
|
|
101
|
+
mBluetoothAdapter.cancelDiscovery();
|
|
102
|
+
}
|
|
103
|
+
} catch (Throwable e) {
|
|
104
|
+
Log.e(TAG, "Error while stopping ble scan: " + e.getMessage(), e);
|
|
105
|
+
} finally {
|
|
106
|
+
mRunning = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected void onDeviceDiscovered(BLEScanData device) {
|
|
111
|
+
Log.v(TAG, "onDeviceDiscovered() " + device.getDevice().getName());
|
|
112
|
+
|
|
113
|
+
if (this.onDeviceDiscovered != null) {
|
|
114
|
+
this.onDeviceDiscovered.onDeviceDiscovered(device);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @return true if device has bluetooth feature
|
|
120
|
+
*/
|
|
121
|
+
public boolean isAvailable() {
|
|
122
|
+
PackageManager pm = mContext.getPackageManager();
|
|
123
|
+
return pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @return true if device bluetooth is enabled
|
|
128
|
+
*/
|
|
129
|
+
public boolean isEnabled() {
|
|
130
|
+
return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
|
135
|
+
class BLE_Callback implements BluetoothAdapter.LeScanCallback {
|
|
136
|
+
@Override
|
|
137
|
+
public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {
|
|
138
|
+
Log.v(TAG, "Scan result: " + device + " RSSI: " + rssi);
|
|
139
|
+
onDeviceDiscovered(new BluetoothDeviceAdpaterBeforeLollipop(device, rssi, scanRecord));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
//YRT170410 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
|
|
145
|
+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
146
|
+
private class BLE_Callback_API21 extends ScanCallback {
|
|
147
|
+
@Override
|
|
148
|
+
public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) {
|
|
149
|
+
super.onScanResult(callbackType, result);
|
|
150
|
+
Log.v(TAG, "Scan result: " + result);
|
|
151
|
+
//if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
|
|
152
|
+
BluetoothDevice device = result.getDevice();
|
|
153
|
+
onDeviceDiscovered(new BluetoothDeviceAdpaterFromLollipop(result));
|
|
154
|
+
//}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@Override
|
|
158
|
+
public void onScanFailed(int errorCode) {
|
|
159
|
+
Log.e(TAG, "Scan failed with error code: " + errorCode);
|
|
160
|
+
BLEScanner.this.onScanFailed(errorCode);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private void onScanFailed(int errorCode) {
|
|
165
|
+
if (this.onDeviceDiscovered != null) {
|
|
166
|
+
this.onDeviceDiscovered.onScanFailed(
|
|
167
|
+
new BleScanError(errorCode)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
public interface BLEScanData {
|
|
174
|
+
|
|
175
|
+
int getRssi();
|
|
176
|
+
|
|
177
|
+
int getTxPower();
|
|
178
|
+
|
|
179
|
+
BluetoothDevice getDevice();
|
|
180
|
+
|
|
181
|
+
byte[] getScanRecordBytes();
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
186
|
+
public class BluetoothDeviceAdpaterFromLollipop implements BLEScanner.BLEScanData {
|
|
187
|
+
private final ScanResult result;
|
|
188
|
+
|
|
189
|
+
public BluetoothDeviceAdpaterFromLollipop(ScanResult result) {
|
|
190
|
+
this.result = result;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@Override
|
|
194
|
+
public int getRssi() {
|
|
195
|
+
return this.result.getRssi();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@Override
|
|
199
|
+
public int getTxPower() {
|
|
200
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
201
|
+
return this.result.getTxPower();
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@Override
|
|
209
|
+
public BluetoothDevice getDevice() {
|
|
210
|
+
return this.result.getDevice();
|
|
211
|
+
}
|
|
212
|
+
@Override
|
|
213
|
+
public byte[] getScanRecordBytes() {
|
|
214
|
+
final ScanRecord scanRecord = this.result.getScanRecord();
|
|
215
|
+
if (scanRecord == null) {
|
|
216
|
+
return new byte[0];
|
|
217
|
+
}
|
|
218
|
+
return scanRecord.getBytes();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@Override
|
|
222
|
+
public boolean equals(Object obj) {
|
|
223
|
+
if (obj == null) {
|
|
224
|
+
return this.getDevice() == null;
|
|
225
|
+
}
|
|
226
|
+
if (!(obj instanceof BLEScanner.BLEScanData)) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
return this.result.getDevice().equals(((BLEScanner.BLEScanData) obj).getDevice());
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public class BluetoothDeviceAdpaterBeforeLollipop implements BLEScanner.BLEScanData {
|
|
234
|
+
|
|
235
|
+
private final BluetoothDevice device;
|
|
236
|
+
private final int rssi;
|
|
237
|
+
private final byte[] scanRecord;
|
|
238
|
+
|
|
239
|
+
public BluetoothDeviceAdpaterBeforeLollipop(BluetoothDevice device, int rssi, final byte[] scanRecord) {
|
|
240
|
+
this.device = device;
|
|
241
|
+
this.rssi = rssi;
|
|
242
|
+
this.scanRecord = scanRecord;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@Override
|
|
246
|
+
public int getRssi() {
|
|
247
|
+
return this.rssi;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@Override
|
|
251
|
+
public int getTxPower() {
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@Override
|
|
256
|
+
public BluetoothDevice getDevice() {
|
|
257
|
+
return this.device;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@Override
|
|
261
|
+
public byte[] getScanRecordBytes() {
|
|
262
|
+
return this.scanRecord;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@Override
|
|
266
|
+
public boolean equals(Object obj) {
|
|
267
|
+
if (obj == null) {
|
|
268
|
+
return this.getDevice() == null;
|
|
269
|
+
}
|
|
270
|
+
if (!(obj instanceof BLEScanner.BLEScanData)) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
return this.device.equals(((BLEScanner.BLEScanData) obj).getDevice());
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
class BleScanError extends Exception {
|
|
278
|
+
public BleScanError(int errorCode) {
|
|
279
|
+
super("BLE scan failed (error code: " + errorCode + ")");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
}
|
|
@@ -13,9 +13,9 @@ import android.util.Log;
|
|
|
13
13
|
|
|
14
14
|
import com.google.gson.Gson;
|
|
15
15
|
import com.google.gson.GsonBuilder;
|
|
16
|
-
import com.iotize.android.communication.protocol.ble.scanner.BLEScanner;
|
|
17
16
|
import com.iotize.plugin.cordova.ble.models.ServiceDescription;
|
|
18
17
|
|
|
18
|
+
import org.json.JSONArray;
|
|
19
19
|
import org.json.JSONException;
|
|
20
20
|
import org.json.JSONObject;
|
|
21
21
|
|
|
@@ -39,6 +39,8 @@ public class JSONBuilder {
|
|
|
39
39
|
json.put("address", bluetoothDevice.getAddress());
|
|
40
40
|
// json.put("type", bluetoothDevice.getType());
|
|
41
41
|
json.put("rssi", device.getRssi());
|
|
42
|
+
json.put("txPower", device.getTxPower());
|
|
43
|
+
json.put("scanRecord", JSONBuilder.toJSONObject(device.getScanRecordBytes()));
|
|
42
44
|
|
|
43
45
|
return json;
|
|
44
46
|
} catch (JSONException e) {
|
|
@@ -61,6 +63,15 @@ public class JSONBuilder {
|
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
static JSONArray toJSONObject(byte[] bytes) {
|
|
67
|
+
JSONArray json = new JSONArray();
|
|
68
|
+
for (byte aByte : bytes) {
|
|
69
|
+
json.put(aByte);
|
|
70
|
+
}
|
|
71
|
+
return json;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
64
75
|
public static ArrayList<ServiceDescription> toServicesDescription(List<BluetoothGattService> services) {
|
|
65
76
|
ArrayList<ServiceDescription> result = new ArrayList<>();
|
|
66
77
|
for (BluetoothGattService service : services) {
|
|
@@ -10,8 +10,8 @@ import android.bluetooth.BluetoothGatt;
|
|
|
10
10
|
import android.bluetooth.BluetoothGattCharacteristic;
|
|
11
11
|
|
|
12
12
|
import com.google.gson.JsonParser;
|
|
13
|
-
import com.iotize.android.communication.protocol.ble.characteristics.CharacteristicAdapter;
|
|
14
13
|
import com.iotize.android.core.util.Helper;
|
|
14
|
+
import com.iotize.plugin.cordova.ble.characteristics.CharacteristicAdapter;
|
|
15
15
|
|
|
16
16
|
import org.apache.cordova.CallbackContext;
|
|
17
17
|
import org.apache.cordova.PluginResult;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.iotize.plugin.cordova.ble;
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.le.ScanFilter;
|
|
4
|
+
import android.os.Build;
|
|
5
|
+
import android.os.ParcelUuid;
|
|
6
|
+
|
|
7
|
+
import com.iotize.android.communication.protocol.ble.Constants;
|
|
8
|
+
|
|
9
|
+
import java.util.ArrayList;
|
|
10
|
+
import java.util.Collections;
|
|
11
|
+
import java.util.List;
|
|
12
|
+
|
|
13
|
+
public class TapUtility {
|
|
14
|
+
|
|
15
|
+
static List<ScanFilter> createTapFilter() {
|
|
16
|
+
if (Build.VERSION.SDK_INT >= 21) {
|
|
17
|
+
List<ScanFilter> filters = new ArrayList();
|
|
18
|
+
ScanFilter.Builder buildFilterTapService = new ScanFilter.Builder();
|
|
19
|
+
buildFilterTapService.setServiceUuid(new ParcelUuid(Constants.SERVICE_SPP_OVER_LE));
|
|
20
|
+
filters.add(buildFilterTapService.build());
|
|
21
|
+
return filters;
|
|
22
|
+
} else {
|
|
23
|
+
return Collections.emptyList();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package com.iotize.plugin.cordova.ble.characteristics;
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.BluetoothGatt;
|
|
4
|
+
import android.bluetooth.BluetoothGattCharacteristic;
|
|
5
|
+
import android.os.Build;
|
|
6
|
+
|
|
7
|
+
import androidx.annotation.NonNull;
|
|
8
|
+
import androidx.annotation.Nullable;
|
|
9
|
+
import androidx.annotation.RequiresApi;
|
|
10
|
+
|
|
11
|
+
import com.iotize.android.communication.protocol.ble.exception.BLEComException;
|
|
12
|
+
import com.iotize.android.communication.protocol.ble.exception.CannotWriteCharacteristicException;
|
|
13
|
+
import com.iotize.android.communication.protocol.ble.exception.WritePacketIsTooBigException;
|
|
14
|
+
import com.iotize.plugin.cordova.ble.BLEProtocol;
|
|
15
|
+
|
|
16
|
+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
|
17
|
+
public abstract class AbstractLwM2MRequestCharacteristic extends CharacteristicAdapter implements CharacteristicAdapterCallbacks {
|
|
18
|
+
|
|
19
|
+
@Nullable
|
|
20
|
+
protected Exception initializeError;
|
|
21
|
+
protected boolean isInitialized = false;
|
|
22
|
+
|
|
23
|
+
AbstractLwM2MRequestCharacteristic(@NonNull BLEProtocol protocol, @NonNull BluetoothGattCharacteristic characteristic) {
|
|
24
|
+
super(protocol, characteristic, null);
|
|
25
|
+
this.callbacks = this;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public abstract void sendLwM2MTapRequest(@NonNull BluetoothGatt gatt, @NonNull byte[] data) throws WritePacketIsTooBigException, CannotWriteCharacteristicException;
|
|
29
|
+
|
|
30
|
+
public abstract void reset();
|
|
31
|
+
|
|
32
|
+
@Nullable
|
|
33
|
+
public abstract byte[] getTapResponse();
|
|
34
|
+
|
|
35
|
+
public abstract void initialize(@NonNull BluetoothGatt gatt, @Nullable OnCharacteristicInitialized callback);
|
|
36
|
+
|
|
37
|
+
public boolean isInitialized() throws Exception {
|
|
38
|
+
if (initializeError != null) {
|
|
39
|
+
throw initializeError;
|
|
40
|
+
}
|
|
41
|
+
return isInitialized;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public interface OnCharacteristicInitialized {
|
|
45
|
+
void onCharacteristicInitializedSuccess();
|
|
46
|
+
void onCharacteristicInitializedFail(@NonNull Exception err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
package com.iotize.plugin.cordova.ble.characteristics;
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.BluetoothGatt;
|
|
4
|
+
import android.bluetooth.BluetoothGattCharacteristic;
|
|
5
|
+
import android.bluetooth.BluetoothGattDescriptor;
|
|
6
|
+
import android.os.Build;
|
|
7
|
+
import android.util.Log;
|
|
8
|
+
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
import androidx.annotation.RequiresApi;
|
|
12
|
+
|
|
13
|
+
import com.iotize.android.communication.protocol.ble.BLECommandRunnable;
|
|
14
|
+
import com.iotize.android.communication.protocol.ble.exception.CannotSetCharacteristicNotification;
|
|
15
|
+
import com.iotize.android.communication.protocol.ble.exception.CannotWriteCharacteristicException;
|
|
16
|
+
import com.iotize.android.communication.protocol.ble.exception.CharacteristicNotificationNotSupported;
|
|
17
|
+
import com.iotize.android.communication.protocol.ble.exception.DescriptorNotAvailableException;
|
|
18
|
+
import com.iotize.android.communication.protocol.ble.exception.WritePacketIsTooBigException;
|
|
19
|
+
import com.iotize.android.core.util.Helper;
|
|
20
|
+
import com.iotize.plugin.cordova.ble.BLEProtocol;
|
|
21
|
+
import com.iotize.plugin.cordova.ble.commands.BLECommand;
|
|
22
|
+
import com.iotize.plugin.cordova.ble.commands.CharacteristicOperationCompletedNotifier;
|
|
23
|
+
import com.iotize.plugin.cordova.ble.commands.DescriptorOperationCompletedNotifier;
|
|
24
|
+
|
|
25
|
+
import java.util.UUID;
|
|
26
|
+
|
|
27
|
+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
|
28
|
+
public class CharacteristicAdapter implements CharacteristicAdapterCallbacks {
|
|
29
|
+
|
|
30
|
+
static final UUID NOTIFICATION_DESCRIPTOR_UUID =
|
|
31
|
+
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
|
|
32
|
+
|
|
33
|
+
private static final String TAG = "AbstractCharacteristicA";
|
|
34
|
+
@NonNull
|
|
35
|
+
public final BluetoothGattCharacteristic characteristic;
|
|
36
|
+
|
|
37
|
+
@NonNull
|
|
38
|
+
protected final BLEProtocol protocol;
|
|
39
|
+
|
|
40
|
+
@Nullable
|
|
41
|
+
private OnCharacteristicValueChangedCallback onCharacteristicValueChangedCallback;
|
|
42
|
+
|
|
43
|
+
@Nullable
|
|
44
|
+
protected CharacteristicAdapterCallbacks callbacks;
|
|
45
|
+
|
|
46
|
+
@Nullable
|
|
47
|
+
private OnCharacteristicOperationResult cmdCallback;
|
|
48
|
+
|
|
49
|
+
public CharacteristicAdapter(
|
|
50
|
+
@NonNull BLEProtocol protocol,
|
|
51
|
+
@NonNull BluetoothGattCharacteristic characteristic,
|
|
52
|
+
@Nullable CharacteristicAdapterCallbacks callbacks) {
|
|
53
|
+
this.protocol = protocol;
|
|
54
|
+
this.characteristic = characteristic;
|
|
55
|
+
this.callbacks = callbacks;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public void setCallbacks(CharacteristicAdapterCallbacks callbacks) {
|
|
59
|
+
this.callbacks = callbacks;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public boolean isWritable() {
|
|
63
|
+
int properties = this.characteristic.getProperties();
|
|
64
|
+
return (properties & (BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) != 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public void startNotification(BluetoothGatt gatt, OnCharacteristicOperationResult callback) {
|
|
68
|
+
this.startOrStopValueChangedSubscription(gatt, true, callback);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public void stopNotification(BluetoothGatt gatt, OnCharacteristicOperationResult callback) {
|
|
72
|
+
this.startOrStopValueChangedSubscription(gatt, false, callback);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private void startOrStopValueChangedSubscription(BluetoothGatt gatt, boolean start, OnCharacteristicOperationResult callback) {
|
|
76
|
+
queueCommand(callback, () -> {
|
|
77
|
+
if (gatt.setCharacteristicNotification(characteristic, start)) {
|
|
78
|
+
|
|
79
|
+
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(NOTIFICATION_DESCRIPTOR_UUID);
|
|
80
|
+
|
|
81
|
+
if (descriptor == null) {
|
|
82
|
+
throw new DescriptorNotAvailableException(characteristic, NOTIFICATION_DESCRIPTOR_UUID);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (start) {
|
|
86
|
+
int properties = characteristic.getProperties();
|
|
87
|
+
if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
|
|
88
|
+
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
|
|
89
|
+
} else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
|
|
90
|
+
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
|
|
91
|
+
} else {
|
|
92
|
+
throw new CharacteristicNotificationNotSupported(this.characteristic);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!gatt.writeDescriptor(descriptor)) {
|
|
99
|
+
throw new CannotSetCharacteristicNotification(this.characteristic);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
throw new CannotSetCharacteristicNotification(this.characteristic);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
void queueCommand(@Nullable OnCharacteristicOperationResult cb, @NonNull BLECommandRunnable runnable) {
|
|
108
|
+
this.protocol.queueCommand(new BLECommand(
|
|
109
|
+
runnable,
|
|
110
|
+
new CharacteristicOperationCompletedNotifier(cb, this.characteristic)
|
|
111
|
+
));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
void queueCommand(@Nullable OnDescriptorOperationResult cb, @NonNull BLECommandRunnable runnable, BluetoothGattDescriptor descriptor) {
|
|
115
|
+
this.protocol.queueCommand(new BLECommand(
|
|
116
|
+
runnable,
|
|
117
|
+
new DescriptorOperationCompletedNotifier(cb, descriptor)
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public byte[] getValue() {
|
|
123
|
+
return this.characteristic.getValue();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public void read(@Nullable OnCharacteristicOperationResult callback) {
|
|
127
|
+
queueCommand(callback, () -> {
|
|
128
|
+
this.protocol.getGatt().readCharacteristic(this.characteristic);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public void readDescriptor(@NonNull UUID descriptorUUID, @Nullable OnDescriptorOperationResult callback) {
|
|
133
|
+
BluetoothGattDescriptor descriptor = this.characteristic.getDescriptor(descriptorUUID);
|
|
134
|
+
if (descriptor == null && callback != null) {
|
|
135
|
+
callback.onError(null, new DescriptorNotAvailableException(this.characteristic, descriptorUUID));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
queueCommand(callback, () -> {
|
|
139
|
+
this.protocol.getGatt().readDescriptor(descriptor);
|
|
140
|
+
}, descriptor);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public void onValueChanged(OnCharacteristicValueChangedCallback onCharacteristicValueChangedCallback) {
|
|
144
|
+
this.onCharacteristicValueChangedCallback = onCharacteristicValueChangedCallback;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public void write(BluetoothGatt gatt, byte[] packet, int writeType, @Nullable OnCharacteristicOperationResult callback) throws CannotWriteCharacteristicException, WritePacketIsTooBigException {
|
|
148
|
+
queueCommand(callback, () -> {
|
|
149
|
+
if (packet.length > protocol.getMTU()) {
|
|
150
|
+
// throw new WritePacketIsTooBigException(packet);
|
|
151
|
+
Log.w(TAG, "current mtu is " + protocol.getMTU() + " bytes but writing " + packet.length + " bytes");
|
|
152
|
+
}
|
|
153
|
+
Log.d(TAG, "_writeData ... packet = 0x" + Helper.ByteArrayToHexString(packet) + " (size = " + packet.length + ")");
|
|
154
|
+
this.characteristic.setValue(packet);
|
|
155
|
+
this.characteristic.setWriteType(writeType);
|
|
156
|
+
boolean writeSuccess = gatt.writeCharacteristic(this.characteristic);
|
|
157
|
+
if (!writeSuccess) {
|
|
158
|
+
Log.w(TAG, "Cannot write on characteristic on first try. WRITE ENABLED: " + this.isWritable() + "/ Write type: " + this.characteristic.getWriteType());
|
|
159
|
+
throw new CannotWriteCharacteristicException(gatt, this.characteristic);
|
|
160
|
+
}
|
|
161
|
+
Log.d(TAG, "_writeData OK ! packet = 0x" + Helper.ByteArrayToHexString(packet) + " (size = " + packet.length + ")");
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@Override
|
|
166
|
+
public void onCharacteristicValueChanged(BluetoothGatt gatt) {
|
|
167
|
+
if (this.onCharacteristicValueChangedCallback != null) {
|
|
168
|
+
this.onCharacteristicValueChangedCallback.onCharacteristicValueChanged(this.characteristic.getValue());
|
|
169
|
+
}
|
|
170
|
+
if (this.callbacks != null) {
|
|
171
|
+
this.callbacks.onCharacteristicValueChanged(gatt);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@Override
|
|
176
|
+
public void onCharacteristicWrite(BluetoothGatt gatt, int status) throws WritePacketIsTooBigException, CannotWriteCharacteristicException {
|
|
177
|
+
if (this.callbacks != null) {
|
|
178
|
+
this.callbacks.onCharacteristicWrite(gatt, status);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@Override
|
|
183
|
+
public void onCharacteristicRead(BluetoothGatt gatt, int status) {
|
|
184
|
+
if (this.callbacks != null) {
|
|
185
|
+
this.callbacks.onCharacteristicRead(gatt, status);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@Override
|
|
190
|
+
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
|
191
|
+
if (descriptor.getUuid().equals(NOTIFICATION_DESCRIPTOR_UUID)) {
|
|
192
|
+
if (this.cmdCallback != null) {
|
|
193
|
+
this.cmdCallback.onResult(this.characteristic, status);
|
|
194
|
+
this.cmdCallback = null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (this.callbacks != null) {
|
|
198
|
+
this.callbacks.onDescriptorWrite(gatt, descriptor, status);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public interface OnCharacteristicOperationResult {
|
|
203
|
+
|
|
204
|
+
void onResult(@NonNull BluetoothGattCharacteristic characteristic, int statusCode);
|
|
205
|
+
|
|
206
|
+
void onError(@NonNull BluetoothGattCharacteristic characteristic, @NonNull Exception ex);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public interface OnDescriptorOperationResult {
|
|
210
|
+
|
|
211
|
+
void onResult(@NonNull BluetoothGattDescriptor descriptor, int statusCode);
|
|
212
|
+
|
|
213
|
+
void onError(@Nullable BluetoothGattDescriptor descriptor, @NonNull Exception ex);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public interface OnCharacteristicValueChangedCallback {
|
|
217
|
+
|
|
218
|
+
void onCharacteristicValueChanged(byte[] value);
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.iotize.plugin.cordova.ble.characteristics;
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.BluetoothGatt;
|
|
4
|
+
import android.bluetooth.BluetoothGattDescriptor;
|
|
5
|
+
|
|
6
|
+
import com.iotize.android.communication.protocol.ble.exception.CannotWriteCharacteristicException;
|
|
7
|
+
import com.iotize.android.communication.protocol.ble.exception.WritePacketIsTooBigException;
|
|
8
|
+
|
|
9
|
+
import java.util.UUID;
|
|
10
|
+
|
|
11
|
+
public interface CharacteristicAdapterCallbacks {
|
|
12
|
+
|
|
13
|
+
void onCharacteristicValueChanged(BluetoothGatt gatt);
|
|
14
|
+
|
|
15
|
+
void onCharacteristicWrite(BluetoothGatt gatt, int status) throws WritePacketIsTooBigException, CannotWriteCharacteristicException;
|
|
16
|
+
|
|
17
|
+
void onCharacteristicRead(BluetoothGatt gatt, int status);
|
|
18
|
+
|
|
19
|
+
void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status);
|
|
20
|
+
|
|
21
|
+
}
|