@tempivo/sensor-beacon 0.3.3 → 0.4.3
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 +4 -4
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +2 -1
- package/android/src/main/java/expo/modules/tempivosensorbeacon/SensorBeaconNative.java +1 -3
- package/android/src/main/java/expo/modules/tempivosensorbeacon/TempivoSensorBeaconModule.kt +11 -2
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorBleRuntime.kt +27 -84
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorSdkScanTelemetry.kt +138 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconDecoder.kt +53 -0
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconScanner.kt +161 -74
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorQr.kt +7 -8
- package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorSession.kt +2 -10
- package/dist/decoder.d.ts +0 -2
- package/dist/decoder.js +0 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/native-module.js +5 -1
- package/dist/qr.d.ts +3 -2
- package/dist/qr.js +8 -6
- package/dist/react-native.d.ts +24 -1
- package/dist/react-native.js +22 -1
- package/dist/session-types.d.ts +4 -2
- package/dist/tempivo-sensor-beacon.aar +0 -0
- package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/TempivoSensorBridge +0 -0
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorQr.swift +10 -7
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorSession.swift +5 -3
- package/ios/Sources/TempivoSensorBeacon/TempivoSensorSessionTypes.swift +0 -1
- package/ios/TempivoSensorBeaconModule.swift +137 -14
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ public final class TempivoSensorSession: @unchecked Sendable {
|
|
|
15
15
|
|
|
16
16
|
public init() {}
|
|
17
17
|
|
|
18
|
-
public func connect(serial: String, bluetoothMac: String, pin: String
|
|
18
|
+
public func connect(serial: String, bluetoothMac: String, pin: String) throws {
|
|
19
19
|
guard let pinInt = Int32(pin.trimmingCharacters(in: .whitespacesAndNewlines)) else {
|
|
20
20
|
throw TempivoSensorError(.invalidPin, "PIN must be numeric.")
|
|
21
21
|
}
|
|
@@ -28,7 +28,9 @@ public final class TempivoSensorSession: @unchecked Sendable {
|
|
|
28
28
|
serial: TempivoSensorQrParser.normalizeSerial(serial),
|
|
29
29
|
bluetoothMac: bluetoothMac,
|
|
30
30
|
pin: pinInt,
|
|
31
|
-
legacy:
|
|
31
|
+
legacy: false,
|
|
32
|
+
deviceId: TempivoSensorQrParser.normalizeSerial(serial),
|
|
33
|
+
encryptionKey: ""
|
|
32
34
|
)
|
|
33
35
|
)
|
|
34
36
|
try throwIfBridgeError(result)
|
|
@@ -39,7 +41,7 @@ public final class TempivoSensorSession: @unchecked Sendable {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
public func connect(qr: TempivoSensorQr) throws {
|
|
42
|
-
try connect(serial: qr.serial, bluetoothMac: qr.bluetoothMac, pin: qr.pin
|
|
44
|
+
try connect(serial: qr.serial, bluetoothMac: qr.bluetoothMac, pin: qr.pin)
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
public func disconnect() {
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import CoreBluetooth
|
|
2
2
|
import ExpoModulesCore
|
|
3
|
+
import Foundation
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
#if canImport(TempivoSensorBridge)
|
|
6
|
+
import TempivoSensorBridge
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
public class TempivoSensorBeaconModule: Module {
|
|
10
|
+
#if canImport(TempivoSensorBridge)
|
|
11
|
+
private let scanBridge = TempivoSensorBridge()
|
|
12
|
+
private var sdkScanActive = false
|
|
13
|
+
#else
|
|
5
14
|
private var scanner: TempivoSensorBeaconScanner?
|
|
15
|
+
#endif
|
|
6
16
|
private let session = TempivoSensorSession()
|
|
7
17
|
|
|
8
18
|
public func definition() -> ModuleDefinition {
|
|
@@ -10,20 +20,43 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
|
|
|
10
20
|
Events("onDeviceFound")
|
|
11
21
|
|
|
12
22
|
AsyncFunction("requestPermissions") { () -> [String: Any] in
|
|
13
|
-
|
|
23
|
+
#if canImport(TempivoSensorBridge)
|
|
24
|
+
self.scanBridge.initialize()
|
|
25
|
+
#else
|
|
26
|
+
_ = self.requireCbScanner()
|
|
27
|
+
#endif
|
|
14
28
|
return self.permissionPayload()
|
|
15
29
|
}
|
|
16
30
|
|
|
17
31
|
AsyncFunction("startScan") {
|
|
18
|
-
|
|
32
|
+
#if canImport(TempivoSensorBridge)
|
|
33
|
+
self.scanBridge.initialize()
|
|
34
|
+
self.sdkScanActive = true
|
|
35
|
+
self.scanBridge.startDeviceScan { json in
|
|
36
|
+
guard self.sdkScanActive else { return }
|
|
37
|
+
guard let payload = self.devicePayloadFromBridgeJson(json) else { return }
|
|
38
|
+
self.sendEvent("onDeviceFound", payload)
|
|
39
|
+
}
|
|
40
|
+
#else
|
|
41
|
+
self.requireCbScanner().startScanning()
|
|
42
|
+
#endif
|
|
19
43
|
}
|
|
20
44
|
|
|
21
45
|
Function("stopScan") {
|
|
46
|
+
#if canImport(TempivoSensorBridge)
|
|
47
|
+
self.sdkScanActive = false
|
|
48
|
+
self.scanBridge.stopDeviceScan()
|
|
49
|
+
#else
|
|
22
50
|
self.scanner?.stopScanning()
|
|
51
|
+
#endif
|
|
23
52
|
}
|
|
24
53
|
|
|
25
54
|
Function("isScanning") { () -> Bool in
|
|
26
|
-
|
|
55
|
+
#if canImport(TempivoSensorBridge)
|
|
56
|
+
return self.sdkScanActive
|
|
57
|
+
#else
|
|
58
|
+
return self.scanner?.scanning ?? false
|
|
59
|
+
#endif
|
|
27
60
|
}
|
|
28
61
|
|
|
29
62
|
AsyncFunction("connect") { (qrJson: String) -> [String: Any] in
|
|
@@ -82,19 +115,18 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
|
|
|
82
115
|
}
|
|
83
116
|
|
|
84
117
|
OnDestroy {
|
|
118
|
+
#if canImport(TempivoSensorBridge)
|
|
119
|
+
self.sdkScanActive = false
|
|
120
|
+
self.scanBridge.stopDeviceScan()
|
|
121
|
+
#else
|
|
85
122
|
self.scanner?.stopScanning()
|
|
123
|
+
#endif
|
|
86
124
|
self.session.disconnect()
|
|
87
125
|
}
|
|
88
126
|
}
|
|
89
127
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
didDiscover discovery: SensorBeaconDiscovery
|
|
93
|
-
) {
|
|
94
|
-
sendEvent("onDeviceFound", devicePayload(discovery))
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private func requireScanner() -> TempivoSensorBeaconScanner {
|
|
128
|
+
#if !canImport(TempivoSensorBridge)
|
|
129
|
+
private func requireCbScanner() -> TempivoSensorBeaconScanner {
|
|
98
130
|
if let scanner {
|
|
99
131
|
return scanner
|
|
100
132
|
}
|
|
@@ -103,11 +135,91 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
|
|
|
103
135
|
scanner = created
|
|
104
136
|
return created
|
|
105
137
|
}
|
|
138
|
+
#endif
|
|
139
|
+
|
|
140
|
+
#if canImport(TempivoSensorBridge)
|
|
141
|
+
private func devicePayloadFromBridgeJson(_ json: String) -> [String: Any]? {
|
|
142
|
+
guard let data = json.data(using: .utf8),
|
|
143
|
+
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
144
|
+
return nil
|
|
145
|
+
}
|
|
146
|
+
guard let deviceId = dict["deviceId"] as? String else { return nil }
|
|
147
|
+
var payload: [String: Any] = ["deviceId": deviceId]
|
|
148
|
+
if let rssi = dict["rssi"] as? Int {
|
|
149
|
+
payload["rssi"] = rssi
|
|
150
|
+
} else if let rssi = dict["rssi"] as? Double {
|
|
151
|
+
payload["rssi"] = Int(rssi)
|
|
152
|
+
}
|
|
153
|
+
if let serial = dict["serialNumber"] as? String {
|
|
154
|
+
payload["serialNumber"] = serial
|
|
155
|
+
}
|
|
156
|
+
if let mac = dict["bluetoothMacAddress"] as? String {
|
|
157
|
+
payload["bluetoothMacAddress"] = mac
|
|
158
|
+
}
|
|
159
|
+
if let summary = dict["advertisementSummary"] as? String, !summary.isEmpty {
|
|
160
|
+
payload["summary"] = summary
|
|
161
|
+
}
|
|
162
|
+
if let telem = dict["advertisementTelemetry"] as? [String: Any] {
|
|
163
|
+
payload["telemetry"] = telemetryPayloadFromBridge(telem)
|
|
164
|
+
if payload["summary"] == nil, let s = telem["summary"] as? String, !s.isEmpty {
|
|
165
|
+
payload["summary"] = s
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if payload["summary"] == nil {
|
|
169
|
+
payload["summary"] = payload["serialNumber"] as? String ?? deviceId
|
|
170
|
+
}
|
|
171
|
+
return payload
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private func telemetryPayloadFromBridge(_ telem: [String: Any]) -> [String: Any] {
|
|
175
|
+
var payload: [String: Any] = [:]
|
|
176
|
+
if let firmware = telem["firmware"] as? String { payload["firmware"] = firmware }
|
|
177
|
+
if let batteryOk = telem["batteryOk"] as? Bool { payload["batteryOk"] = batteryOk }
|
|
178
|
+
if let encryptionEnabled = telem["encryptionEnabled"] as? Bool {
|
|
179
|
+
payload["encryptionEnabled"] = encryptionEnabled
|
|
180
|
+
}
|
|
181
|
+
if let cellularStatus = telem["cellularStatus"] as? String {
|
|
182
|
+
payload["cellularStatus"] = cellularStatus
|
|
183
|
+
}
|
|
184
|
+
if let measurementCounter = telem["measurementCounter"] as? Int {
|
|
185
|
+
payload["measurementCounter"] = measurementCounter
|
|
186
|
+
} else if let measurementCounter = telem["measurementCounter"] as? Int64 {
|
|
187
|
+
payload["measurementCounter"] = Int(measurementCounter)
|
|
188
|
+
}
|
|
189
|
+
if let readingTimestampUnix = telem["readingTimestampUnix"] as? Int {
|
|
190
|
+
payload["readingTimestampUnix"] = readingTimestampUnix
|
|
191
|
+
} else if let readingTimestampUnix = telem["readingTimestampUnix"] as? Int64 {
|
|
192
|
+
payload["readingTimestampUnix"] = Int(readingTimestampUnix)
|
|
193
|
+
}
|
|
194
|
+
if let periodBase = telem["periodBaseSeconds"] as? Int,
|
|
195
|
+
let periodFactor = telem["periodFactor"] as? Int,
|
|
196
|
+
periodBase > 0 {
|
|
197
|
+
payload["measurementIntervalSeconds"] = periodBase * max(periodFactor, 1)
|
|
198
|
+
}
|
|
199
|
+
if let readings = telem["readings"] as? [[String: Any]] {
|
|
200
|
+
payload["readings"] = readings.map { row in
|
|
201
|
+
var out: [String: Any] = [:]
|
|
202
|
+
if let typeHex = row["typeHex"] as? String { out["typeHex"] = typeHex }
|
|
203
|
+
if let text = row["text"] as? String { out["text"] = text }
|
|
204
|
+
if let raw24 = row["raw24"] as? Int { out["raw24"] = raw24 }
|
|
205
|
+
return out
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
payload["readings"] = [] as [[String: Any]]
|
|
209
|
+
}
|
|
210
|
+
if let readingsCount = telem["readingsCount"] as? Int {
|
|
211
|
+
payload["readingsCount"] = readingsCount
|
|
212
|
+
}
|
|
213
|
+
if let summary = telem["summary"] as? String {
|
|
214
|
+
payload["summary"] = summary
|
|
215
|
+
}
|
|
216
|
+
return payload
|
|
217
|
+
}
|
|
218
|
+
#endif
|
|
106
219
|
|
|
107
220
|
private func permissionPayload() -> [String: Any] {
|
|
108
221
|
if #available(iOS 13.1, *) {
|
|
109
222
|
let status = CBManager.authorization
|
|
110
|
-
let granted = status == .allowedAlways
|
|
111
223
|
let statusName: String
|
|
112
224
|
switch status {
|
|
113
225
|
case .allowedAlways: statusName = "granted"
|
|
@@ -115,7 +227,7 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
|
|
|
115
227
|
default: statusName = "denied"
|
|
116
228
|
}
|
|
117
229
|
return [
|
|
118
|
-
"granted":
|
|
230
|
+
"granted": status == .allowedAlways || status == .notDetermined,
|
|
119
231
|
"status": statusName,
|
|
120
232
|
"canAskAgain": status == .notDetermined,
|
|
121
233
|
"expires": "never",
|
|
@@ -193,6 +305,17 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
|
|
|
193
305
|
}
|
|
194
306
|
}
|
|
195
307
|
|
|
308
|
+
#if !canImport(TempivoSensorBridge)
|
|
309
|
+
extension TempivoSensorBeaconModule: TempivoSensorBeaconScannerDelegate {
|
|
310
|
+
public func sensorBeaconScanner(
|
|
311
|
+
_ scanner: TempivoSensorBeaconScanner,
|
|
312
|
+
didDiscover discovery: SensorBeaconDiscovery
|
|
313
|
+
) {
|
|
314
|
+
sendEvent("onDeviceFound", devicePayload(discovery))
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
#endif
|
|
318
|
+
|
|
196
319
|
internal final class SensorBeaconException: Exception {
|
|
197
320
|
private let customCode: String
|
|
198
321
|
private let customReason: String
|
package/package.json
CHANGED