@tempivo/sensor-beacon 0.4.3 → 1.1.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/CHANGELOG.md +38 -0
- package/README.md +156 -6
- package/android/src/main/java/expo/modules/tempivosensorbeacon/SensorBeaconNative.java +17 -2
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/BleConnectCredentials.kt +25 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SdkMeasurementFormat.kt +111 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorBleRuntime.kt +21 -12
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorBleVendor.kt +28 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorModelHint.kt +20 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorSdkScanTelemetry.kt +5 -31
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconDecoder.kt +1 -1
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconScanner.kt +5 -6
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconTypes.kt +2 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorQr.kt +20 -1
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorSession.kt +19 -7
- package/dist/connect-helpers.d.ts +52 -0
- package/dist/connect-helpers.js +153 -0
- package/dist/decoder.d.ts +1 -0
- package/dist/decoder.js +7 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +4 -2
- package/dist/model.d.ts +5 -0
- package/dist/model.js +25 -0
- package/dist/native-helpers.js +5 -2
- package/dist/native-module.js +2 -2
- package/dist/native-types.d.ts +2 -0
- package/dist/profile.d.ts +8 -1
- package/dist/profile.js +42 -19
- package/dist/react-native.d.ts +5 -1
- package/dist/react-native.js +3 -1
- package/dist/session-types.d.ts +2 -1
- package/dist/tempivo-sensor-beacon.aar +0 -0
- package/ios/Frameworks/TempivoSensorBridge.xcframework/Info.plist +4 -4
- package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/Headers/TempivoSensorBridge.h +28 -1
- package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/TempivoSensorBridge +0 -0
- package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64-simulator/TempivoSensorBridge.framework/Headers/TempivoSensorBridge.h +28 -1
- package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64-simulator/TempivoSensorBridge.framework/TempivoSensorBridge +0 -0
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorBeaconDecoder.swift +8 -1
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorBeaconScanner.swift +10 -1
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorModelHint.swift +29 -0
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorProfile.swift +37 -13
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorQr.swift +38 -1
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorSession.swift +24 -12
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorSessionTypes.swift +1 -3
- package/ios/TempivoSensorBeaconModule.swift +83 -16
- package/package.json +4 -3
|
@@ -9,7 +9,9 @@ import TempivoSensorBridge
|
|
|
9
9
|
public class TempivoSensorBeaconModule: Module {
|
|
10
10
|
#if canImport(TempivoSensorBridge)
|
|
11
11
|
private let scanBridge = TempivoSensorBridge()
|
|
12
|
-
private var
|
|
12
|
+
private var sdkScanHandler: SensorSdkScanHandler?
|
|
13
|
+
fileprivate var sdkScanActive = false
|
|
14
|
+
private var lastSeenBySerial: [String: (deviceId: String, mac: String)] = [:]
|
|
13
15
|
#else
|
|
14
16
|
private var scanner: TempivoSensorBeaconScanner?
|
|
15
17
|
#endif
|
|
@@ -32,11 +34,11 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
32
34
|
#if canImport(TempivoSensorBridge)
|
|
33
35
|
self.scanBridge.initialize()
|
|
34
36
|
self.sdkScanActive = true
|
|
35
|
-
self.
|
|
36
|
-
|
|
37
|
-
guard let payload = self.devicePayloadFromBridgeJson(json) else { return }
|
|
38
|
-
self.sendEvent("onDeviceFound", payload)
|
|
37
|
+
if self.sdkScanHandler == nil {
|
|
38
|
+
self.sdkScanHandler = SensorSdkScanHandler(module: self)
|
|
39
39
|
}
|
|
40
|
+
self.scanBridge.setDeviceScanHandler(handler: self.sdkScanHandler)
|
|
41
|
+
self.scanBridge.startDeviceScan()
|
|
40
42
|
#else
|
|
41
43
|
self.requireCbScanner().startScanning()
|
|
42
44
|
#endif
|
|
@@ -46,6 +48,7 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
46
48
|
#if canImport(TempivoSensorBridge)
|
|
47
49
|
self.sdkScanActive = false
|
|
48
50
|
self.scanBridge.stopDeviceScan()
|
|
51
|
+
self.scanBridge.setDeviceScanHandler(handler: nil)
|
|
49
52
|
#else
|
|
50
53
|
self.scanner?.stopScanning()
|
|
51
54
|
#endif
|
|
@@ -61,8 +64,18 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
61
64
|
|
|
62
65
|
AsyncFunction("connect") { (qrJson: String) -> [String: Any] in
|
|
63
66
|
do {
|
|
67
|
+
#if canImport(TempivoSensorBridge)
|
|
68
|
+
self.pauseSdkScanForGatt()
|
|
69
|
+
#else
|
|
70
|
+
self.scanner?.stopScanning()
|
|
71
|
+
#endif
|
|
64
72
|
let qr = try TempivoSensorQrParser.parse(qrJson)
|
|
65
|
-
|
|
73
|
+
let resolved = self.resolveConnectTarget(qr: qr)
|
|
74
|
+
try self.session.connect(
|
|
75
|
+
qr: qr,
|
|
76
|
+
deviceId: resolved.deviceId,
|
|
77
|
+
bluetoothMac: resolved.bluetoothMac
|
|
78
|
+
)
|
|
66
79
|
return self.qrPayload(qr)
|
|
67
80
|
} catch {
|
|
68
81
|
throw self.mapError(error)
|
|
@@ -92,7 +105,7 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
92
105
|
AsyncFunction("triggerTransmission") { () -> [String: Any] in
|
|
93
106
|
do {
|
|
94
107
|
let result = try self.session.triggerTransmission()
|
|
95
|
-
return ["ok": result.ok
|
|
108
|
+
return ["ok": result.ok]
|
|
96
109
|
} catch {
|
|
97
110
|
throw self.mapError(error)
|
|
98
111
|
}
|
|
@@ -101,14 +114,10 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
101
114
|
AsyncFunction("getCalibration") { () -> [String: Any] in
|
|
102
115
|
do {
|
|
103
116
|
let cal = try self.session.getCalibration()
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if let ts = cal.laboratoryCalibrationTimestamp {
|
|
109
|
-
payload["laboratoryCalibrationTimestamp"] = Int(ts)
|
|
110
|
-
}
|
|
111
|
-
return payload
|
|
117
|
+
return [
|
|
118
|
+
"laboratoryCalibrationDate": cal.laboratoryCalibrationDate as Any,
|
|
119
|
+
"laboratoryCalibrationTimestamp": cal.laboratoryCalibrationTimestamp.map { Int($0) } as Any,
|
|
120
|
+
]
|
|
112
121
|
} catch {
|
|
113
122
|
throw self.mapError(error)
|
|
114
123
|
}
|
|
@@ -118,6 +127,7 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
118
127
|
#if canImport(TempivoSensorBridge)
|
|
119
128
|
self.sdkScanActive = false
|
|
120
129
|
self.scanBridge.stopDeviceScan()
|
|
130
|
+
self.scanBridge.setDeviceScanHandler(handler: nil)
|
|
121
131
|
#else
|
|
122
132
|
self.scanner?.stopScanning()
|
|
123
133
|
#endif
|
|
@@ -138,7 +148,36 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
138
148
|
#endif
|
|
139
149
|
|
|
140
150
|
#if canImport(TempivoSensorBridge)
|
|
141
|
-
|
|
151
|
+
fileprivate func rememberSeenDevice(_ payload: [String: Any]) {
|
|
152
|
+
guard let deviceId = payload["deviceId"] as? String,
|
|
153
|
+
let mac = payload["bluetoothMacAddress"] as? String else { return }
|
|
154
|
+
let serial = (payload["serialNumber"] as? String)?
|
|
155
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
156
|
+
.uppercased()
|
|
157
|
+
if let serial, !serial.isEmpty {
|
|
158
|
+
lastSeenBySerial[serial] = (deviceId, mac)
|
|
159
|
+
}
|
|
160
|
+
let macKey = mac.replacingOccurrences(of: ":", with: "").uppercased()
|
|
161
|
+
if macKey.count == 12 {
|
|
162
|
+
lastSeenBySerial[macKey] = (deviceId, mac)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
fileprivate func pauseSdkScanForGatt() {
|
|
167
|
+
sdkScanActive = false
|
|
168
|
+
scanBridge.stopDeviceScan()
|
|
169
|
+
scanBridge.setDeviceScanHandler(handler: nil)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private func resolveConnectTarget(qr: TempivoSensorQr) -> (deviceId: String, bluetoothMac: String) {
|
|
173
|
+
let serialKey = TempivoSensorQrParser.normalizeSerial(qr.serial)
|
|
174
|
+
let seen = lastSeenBySerial[serialKey] ?? lastSeenBySerial[String(serialKey.suffix(12))]
|
|
175
|
+
let deviceId = qr.deviceId ?? seen?.deviceId ?? serialKey
|
|
176
|
+
let mac = seen?.mac ?? qr.bluetoothMac
|
|
177
|
+
return (deviceId, mac)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
fileprivate func devicePayloadFromBridgeJson(_ json: String) -> [String: Any]? {
|
|
142
181
|
guard let data = json.data(using: .utf8),
|
|
143
182
|
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
144
183
|
return nil
|
|
@@ -156,6 +195,14 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
156
195
|
if let mac = dict["bluetoothMacAddress"] as? String {
|
|
157
196
|
payload["bluetoothMacAddress"] = mac
|
|
158
197
|
}
|
|
198
|
+
if let model = dict["model"] as? String, !model.isEmpty {
|
|
199
|
+
payload["model"] = model
|
|
200
|
+
} else if let telem = dict["advertisementTelemetry"] as? [String: Any],
|
|
201
|
+
let firmware = telem["firmware"] as? String {
|
|
202
|
+
payload["model"] = TempivoSensorModelHint.fromFirmware(firmware)
|
|
203
|
+
} else {
|
|
204
|
+
payload["model"] = TempivoSensorModelHint.defaultModel
|
|
205
|
+
}
|
|
159
206
|
if let summary = dict["advertisementSummary"] as? String, !summary.isEmpty {
|
|
160
207
|
payload["summary"] = summary
|
|
161
208
|
}
|
|
@@ -168,6 +215,7 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
168
215
|
if payload["summary"] == nil {
|
|
169
216
|
payload["summary"] = payload["serialNumber"] as? String ?? deviceId
|
|
170
217
|
}
|
|
218
|
+
rememberSeenDevice(payload)
|
|
171
219
|
return payload
|
|
172
220
|
}
|
|
173
221
|
|
|
@@ -268,6 +316,9 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
268
316
|
if let reading = discovery.reading {
|
|
269
317
|
payload["summary"] = reading.summary
|
|
270
318
|
payload["telemetry"] = telemetryPayload(reading)
|
|
319
|
+
payload["model"] = TempivoSensorModelHint.fromFirmware(reading.firmware)
|
|
320
|
+
} else {
|
|
321
|
+
payload["model"] = TempivoSensorModelHint.defaultModel
|
|
271
322
|
}
|
|
272
323
|
return payload
|
|
273
324
|
}
|
|
@@ -305,6 +356,22 @@ public class TempivoSensorBeaconModule: Module {
|
|
|
305
356
|
}
|
|
306
357
|
}
|
|
307
358
|
|
|
359
|
+
#if canImport(TempivoSensorBridge)
|
|
360
|
+
private final class SensorSdkScanHandler: SensorDeviceScanHandler {
|
|
361
|
+
private weak var module: TempivoSensorBeaconModule?
|
|
362
|
+
|
|
363
|
+
init(module: TempivoSensorBeaconModule) {
|
|
364
|
+
self.module = module
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
override func onDevice(deviceJson: String) {
|
|
368
|
+
guard let module, module.sdkScanActive else { return }
|
|
369
|
+
guard let payload = module.devicePayloadFromBridgeJson(deviceJson) else { return }
|
|
370
|
+
module.sendEvent("onDeviceFound", payload)
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
#endif
|
|
374
|
+
|
|
308
375
|
#if !canImport(TempivoSensorBridge)
|
|
309
376
|
extension TempivoSensorBeaconModule: TempivoSensorBeaconScannerDelegate {
|
|
310
377
|
public func sensorBeaconScanner(
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tempivo/sensor-beacon",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Tempivo sensor BLE SDK for Expo, React Native, Android, iOS
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Tempivo sensor BLE SDK. Native scan and GATT for Expo, React Native, Android, and iOS. Node helpers decode advertisements and parse QR or config (no radio).",
|
|
5
5
|
"homepage": "https://app.tempivo.com/integrations",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"expo-module.config.json",
|
|
41
41
|
"ios",
|
|
42
42
|
"LICENSE",
|
|
43
|
-
"README.md"
|
|
43
|
+
"README.md",
|
|
44
|
+
"CHANGELOG.md"
|
|
44
45
|
],
|
|
45
46
|
"publishConfig": {
|
|
46
47
|
"access": "public"
|