@tempivo/sensor-beacon 0.3.2 → 0.3.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.
Files changed (39) hide show
  1. package/README.md +22 -11
  2. package/android/build.gradle +13 -5
  3. package/android/src/main/java/expo/modules/tempivosensorbeacon/SensorBeaconNative.java +5 -13
  4. package/android/src/main/java/expo/modules/tempivosensorbeacon/TempivoSensorBeaconModule.kt +2 -4
  5. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/PartnerBleRules.kt +17 -6
  6. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorBleRuntime.kt +50 -83
  7. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconDecoder.kt +46 -18
  8. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorBeaconScanner.kt +19 -6
  9. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorError.kt +0 -17
  10. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorProfile.kt +59 -2
  11. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorQr.kt +0 -9
  12. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorSession.kt +9 -30
  13. package/dist/index.d.ts +3 -3
  14. package/dist/index.js +3 -3
  15. package/dist/native-helpers.d.ts +0 -1
  16. package/dist/native-helpers.js +3 -18
  17. package/dist/native-module.js +0 -1
  18. package/dist/normalize.d.ts +6 -0
  19. package/dist/normalize.js +29 -0
  20. package/dist/profile.d.ts +5 -0
  21. package/dist/profile.js +47 -1
  22. package/dist/qr.d.ts +2 -6
  23. package/dist/qr.js +2 -19
  24. package/dist/session-types.d.ts +8 -3
  25. package/dist/tempivo-sensor-beacon.aar +0 -0
  26. package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/Headers/TempivoSensorBridge.h +1 -3
  27. package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/TempivoSensorBridge +0 -0
  28. package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64-simulator/TempivoSensorBridge.framework/Headers/TempivoSensorBridge.h +1 -3
  29. package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64-simulator/TempivoSensorBridge.framework/TempivoSensorBridge +0 -0
  30. package/ios/Sources/TempivoSensorBeacon/TempivoSensorBeaconDecoder.swift +12 -2
  31. package/ios/Sources/TempivoSensorBeacon/TempivoSensorBeaconScanner.swift +4 -80
  32. package/ios/Sources/TempivoSensorBeacon/TempivoSensorBeaconTypes.swift +0 -15
  33. package/ios/Sources/TempivoSensorBeacon/TempivoSensorError.swift +1 -15
  34. package/ios/Sources/TempivoSensorBeacon/TempivoSensorProfile.swift +57 -3
  35. package/ios/Sources/TempivoSensorBeacon/TempivoSensorQr.swift +0 -17
  36. package/ios/Sources/TempivoSensorBeacon/TempivoSensorSession.swift +8 -36
  37. package/ios/Sources/TempivoSensorBeacon/TempivoSensorSessionTypes.swift +10 -1
  38. package/ios/TempivoSensorBeaconModule.swift +2 -11
  39. package/package.json +6 -1
@@ -1,10 +1,6 @@
1
1
  import CoreBluetooth
2
2
  import Foundation
3
3
 
4
- #if canImport(TempivoSensorBridge)
5
- import TempivoSensorBridge
6
- #endif
7
-
8
4
  public protocol TempivoSensorBeaconScannerDelegate: AnyObject {
9
5
  func sensorBeaconScanner(_ scanner: TempivoSensorBeaconScanner, didDiscover discovery: SensorBeaconDiscovery)
10
6
  func sensorBeaconScanner(_ scanner: TempivoSensorBeaconScanner, didUpdateState state: CBManagerState)
@@ -14,21 +10,15 @@ public extension TempivoSensorBeaconScannerDelegate {
14
10
  func sensorBeaconScanner(_ scanner: TempivoSensorBeaconScanner, didUpdateState state: CBManagerState) {}
15
11
  }
16
12
 
17
- /// Active BLE scan. iPhone uses the same hardware runtime scan as Tempivo.
18
- /// Manufacturer-only CoreBluetooth misses HC7 / FW 7+ on iPhone.
13
+ /// Active BLE scan for Tempivo sensor beacons (manufacturer `0x026C`). Advertising only. No GATT or connect.
19
14
  public final class TempivoSensorBeaconScanner: NSObject {
20
15
 
21
16
  public weak var delegate: TempivoSensorBeaconScannerDelegate?
22
17
 
23
18
  private var central: CBCentralManager!
24
19
  private var frameCache = SensorBeaconFrameCache()
25
- private var lastSeen: [String: TempivoSensorSeenDevice] = [:]
26
20
  private var isScanning = false
27
21
  private var pendingStart = false
28
- #if canImport(TempivoSensorBridge)
29
- private let runtime = TempivoSensorBridge()
30
- private var useRuntimeScan: Bool { !ProcessInfo.processInfo.isiOSAppOnMac }
31
- #endif
32
22
 
33
23
  public override init() {
34
24
  super.init()
@@ -46,25 +36,10 @@ public final class TempivoSensorBeaconScanner: NSObject {
46
36
  /// Clears cached `0x03` / `0x04` frames. Does not stop an active scan.
47
37
  public func clearCache() {
48
38
  frameCache.clear()
49
- lastSeen.removeAll()
50
- }
51
-
52
- public func lookup(serial: String) -> TempivoSensorSeenDevice? {
53
- lastSeen[TempivoSensorBeaconDecoder.macKey(serial)]
54
39
  }
55
40
 
56
- /// Starts an active scan. iPhone: hardware runtime. Mac: manufacturer advertisements.
41
+ /// Starts an active scan (duplicate advertisements allowed). Requires Bluetooth powered on.
57
42
  public func startScanning() {
58
- #if canImport(TempivoSensorBridge)
59
- if useRuntimeScan {
60
- runtime.initialize()
61
- isScanning = true
62
- runtime.startDeviceScan { [weak self] json in
63
- self?.handleRuntimeScanJson(json)
64
- }
65
- return
66
- }
67
- #endif
68
43
  pendingStart = true
69
44
  if central.state == .poweredOn {
70
45
  beginScanningIfNeeded()
@@ -74,12 +49,8 @@ public final class TempivoSensorBeaconScanner: NSObject {
74
49
  /// Stops scanning and clears pending start.
75
50
  public func stopScanning() {
76
51
  pendingStart = false
77
- #if canImport(TempivoSensorBridge)
78
- runtime.stopDeviceScan()
79
- #endif
80
- if isScanning {
81
- central.stopScan()
82
- }
52
+ guard isScanning else { return }
53
+ central.stopScan()
83
54
  isScanning = false
84
55
  }
85
56
 
@@ -162,55 +133,8 @@ public final class TempivoSensorBeaconScanner: NSObject {
162
133
  bluetoothMacAddress: bluetoothMacAddress,
163
134
  reading: reading
164
135
  )
165
- if let serial = (serialNumber ?? reading?.serialNumber).map({ TempivoSensorBeaconDecoder.macKey($0) }),
166
- !serial.isEmpty {
167
- let seen = TempivoSensorSeenDevice(
168
- deviceId: deviceId,
169
- bluetoothMac: bluetoothMacAddress ?? reading?.bluetoothMacAddress,
170
- serial: serial,
171
- firmware: reading?.firmware
172
- )
173
- lastSeen[serial] = seen
174
- }
175
136
  delegate?.sensorBeaconScanner(self, didDiscover: discovery)
176
137
  }
177
-
178
- private func handleRuntimeScanJson(_ raw: String) {
179
- guard let data = raw.data(using: .utf8),
180
- let obj = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
181
- else { return }
182
- let deviceId = (obj["deviceId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
183
- let serial = (obj["serialNumber"] as? String).map { TempivoSensorBeaconDecoder.macKey($0) } ?? ""
184
- guard !deviceId.isEmpty, !serial.isEmpty else { return }
185
- let mac = obj["bluetoothMacAddress"] as? String
186
- let rssi = (obj["rssi"] as? NSNumber)?.intValue ?? (obj["rssi"] as? Int) ?? 0
187
- let firmware = obj["firmware"] as? String
188
- let reading = SensorBeaconReading(
189
- serialNumber: serial,
190
- bluetoothMacAddress: mac,
191
- firmware: firmware
192
- )
193
- rememberSeen(deviceId: deviceId, bluetoothMac: mac, serial: serial, firmware: firmware)
194
- delegate?.sensorBeaconScanner(
195
- self,
196
- didDiscover: SensorBeaconDiscovery(
197
- deviceId: deviceId,
198
- rssi: rssi,
199
- serialNumber: serial,
200
- bluetoothMacAddress: mac,
201
- reading: reading
202
- )
203
- )
204
- }
205
-
206
- private func rememberSeen(deviceId: String, bluetoothMac: String?, serial: String, firmware: String?) {
207
- lastSeen[serial] = TempivoSensorSeenDevice(
208
- deviceId: deviceId,
209
- bluetoothMac: bluetoothMac,
210
- serial: serial,
211
- firmware: firmware
212
- )
213
- }
214
138
  }
215
139
 
216
140
  extension TempivoSensorBeaconScanner: CBCentralManagerDelegate {
@@ -101,18 +101,3 @@ public struct SensorBeaconDiscovery: Sendable, Equatable {
101
101
  self.reading = reading
102
102
  }
103
103
  }
104
-
105
- /// Last advertisement used to resolve GATT connect (scan device id + firmware).
106
- public struct TempivoSensorSeenDevice: Sendable, Equatable {
107
- public let deviceId: String
108
- public let bluetoothMac: String?
109
- public let serial: String
110
- public let firmware: String?
111
-
112
- public init(deviceId: String, bluetoothMac: String?, serial: String, firmware: String?) {
113
- self.deviceId = deviceId
114
- self.bluetoothMac = bluetoothMac
115
- self.serial = serial
116
- self.firmware = firmware
117
- }
118
- }
@@ -17,21 +17,7 @@ public struct TempivoSensorError: Error, LocalizedError, Sendable {
17
17
 
18
18
  public init(_ code: TempivoSensorErrorCode, _ message: String) {
19
19
  self.code = code
20
- self.message = Self.sanitizeClientMessage(message)
21
- }
22
-
23
- public static func sanitizeClientMessage(_ raw: String) -> String {
24
- var text = raw
25
- let full = NSRange(location: 0, length: text.utf16.count)
26
- if let regex = try? NSRegularExpression(pattern: #"(?i)pl\.[A-Za-z][A-Za-z0-9_.$]*"#) {
27
- text = regex.stringByReplacingMatches(in: text, range: full, withTemplate: "")
28
- }
29
- let full2 = NSRange(location: 0, length: text.utf16.count)
30
- if let regex = try? NSRegularExpression(pattern: #"(?i)\befento[A-Za-z0-9_$]*"#) {
31
- text = regex.stringByReplacingMatches(in: text, range: full2, withTemplate: "")
32
- }
33
- text = text.replacingOccurrences(of: #"\s+"#, with: " ", options: .regularExpression)
34
- return text.trimmingCharacters(in: CharacterSet(charactersIn: " :-.\n\t/"))
20
+ self.message = message
35
21
  }
36
22
 
37
23
  public var errorDescription: String? { message }
@@ -16,7 +16,11 @@ public enum TempivoSensorProfile {
16
16
  }
17
17
  let body: [String: Any]
18
18
  if let nested = obj["profile"] as? [String: Any],
19
- nested["temperatureAlerts"] != nil || nested["schedule"] != nil || nested["slug"] != nil {
19
+ nested["temperatureAlerts"] != nil ||
20
+ nested["schedule"] != nil ||
21
+ nested["slug"] != nil ||
22
+ nested["measurementIntervalMinutes"] != nil ||
23
+ nested["transmissionIntervalSeconds"] != nil {
20
24
  body = nested
21
25
  } else {
22
26
  body = obj
@@ -26,7 +30,13 @@ public enum TempivoSensorProfile {
26
30
  }
27
31
  let rawAlerts = body["temperatureAlerts"] as? [Any] ?? []
28
32
  let alerts = try rawAlerts.enumerated().map { try parseAlert($0.element, index: $0.offset) }
29
- return TempivoSensorConfiguration(temperatureAlerts: alerts, schedule: try parseSchedule(body["schedule"] as? [String: Any]))
33
+ let intervals = try parseOptionalIntervals(body)
34
+ return TempivoSensorConfiguration(
35
+ temperatureAlerts: alerts,
36
+ schedule: try parseSchedule(body["schedule"] as? [String: Any]),
37
+ measurementIntervalMinutes: intervals.measurement,
38
+ transmissionIntervalSeconds: intervals.transmission
39
+ )
30
40
  }
31
41
 
32
42
  public static func jsonString(_ cfg: TempivoSensorConfiguration) throws -> String {
@@ -56,11 +66,55 @@ public enum TempivoSensorProfile {
56
66
  "utcOffsetMinutes": cfg.schedule.utcOffsetMinutes,
57
67
  ]
58
68
  }
59
- let root: [String: Any] = ["temperatureAlerts": alerts, "schedule": schedule]
69
+ var root: [String: Any] = ["temperatureAlerts": alerts, "schedule": schedule]
70
+ if let m = cfg.measurementIntervalMinutes { root["measurementIntervalMinutes"] = m }
71
+ if let t = cfg.transmissionIntervalSeconds { root["transmissionIntervalSeconds"] = t }
60
72
  let data = try JSONSerialization.data(withJSONObject: root, options: [])
61
73
  return String(data: data, encoding: .utf8) ?? "{}"
62
74
  }
63
75
 
76
+ private static let minMeasurementMinutes: Double = 60
77
+ private static let maxMeasurementMinutes: Double = 600
78
+ private static let minTransmissionSeconds = 3600
79
+ private static let maxTransmissionSeconds = 604_800
80
+
81
+ private static func parseOptionalIntervals(_ body: [String: Any]) throws -> (measurement: Double?, transmission: Int?) {
82
+ var measurement: Double?
83
+ var transmission: Int?
84
+ if body["measurementIntervalMinutes"] != nil {
85
+ guard let n = number(body["measurementIntervalMinutes"]), n > 0 else {
86
+ throw TempivoSensorError(.invalidConfig, "measurementIntervalMinutes must be a positive number.")
87
+ }
88
+ if n < minMeasurementMinutes {
89
+ throw TempivoSensorError(.invalidConfig, "measurementIntervalMinutes must be at least \(Int(minMeasurementMinutes)) (1 hour).")
90
+ }
91
+ if n > maxMeasurementMinutes {
92
+ throw TempivoSensorError(.invalidConfig, "measurementIntervalMinutes must be at most \(Int(maxMeasurementMinutes)).")
93
+ }
94
+ measurement = n
95
+ }
96
+ if body["transmissionIntervalSeconds"] != nil {
97
+ guard let n = number(body["transmissionIntervalSeconds"]), n > 0, n == floor(n) else {
98
+ throw TempivoSensorError(.invalidConfig, "transmissionIntervalSeconds must be a positive integer.")
99
+ }
100
+ let sec = Int(n)
101
+ if sec < minTransmissionSeconds {
102
+ throw TempivoSensorError(.invalidConfig, "transmissionIntervalSeconds must be at least \(minTransmissionSeconds) (1 hour).")
103
+ }
104
+ if sec > maxTransmissionSeconds {
105
+ throw TempivoSensorError(.invalidConfig, "transmissionIntervalSeconds must be at most \(maxTransmissionSeconds).")
106
+ }
107
+ transmission = sec
108
+ }
109
+ if let measurement, let transmission {
110
+ let maxTx = measurement * 60 * 60
111
+ if Double(transmission) > maxTx {
112
+ throw TempivoSensorError(.invalidConfig, "transmissionIntervalSeconds must be at most 60 times the measurement interval.")
113
+ }
114
+ }
115
+ return (measurement, transmission)
116
+ }
117
+
64
118
  private static func parseAlert(_ raw: Any, index: Int) throws -> TempivoTemperatureAlert {
65
119
  guard let item = raw as? [String: Any] else {
66
120
  throw TempivoSensorError(.invalidConfig, "temperatureAlerts[\(index)] must be an object.")
@@ -30,23 +30,6 @@ public enum TempivoSensorQrParser {
30
30
  public static let defaultModel = "HC7"
31
31
 
32
32
  public static func sessionType(fromModel model: String?) -> TempivoSensorSessionType {
33
- sessionType(fromModel: model, firmware: nil)
34
- }
35
-
36
- public static func sessionType(fromModel model: String?, firmware: String?) -> TempivoSensorSessionType {
37
- if let firmware {
38
- let t = firmware.trimmingCharacters(in: .whitespacesAndNewlines)
39
- if t.range(of: "^FW\\s*5", options: [.regularExpression, .caseInsensitive]) != nil {
40
- return .legacy
41
- }
42
- if let match = t.range(of: "^(\\d+)\\.\\d+", options: .regularExpression) {
43
- let majorStr = String(t[match]).split(separator: ".").first.flatMap { Int($0) }
44
- if let major = majorStr {
45
- if major >= 7 { return .modern }
46
- if major >= 1 { return .legacy }
47
- }
48
- }
49
- }
50
33
  guard let model, !model.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
51
34
  return .modern
52
35
  }
@@ -15,19 +15,10 @@ public final class TempivoSensorSession: @unchecked Sendable {
15
15
 
16
16
  public init() {}
17
17
 
18
- public func connect(
19
- serial: String,
20
- bluetoothMac: String,
21
- pin: String,
22
- sessionType: TempivoSensorSessionType = .modern,
23
- deviceId: String? = nil,
24
- firmware: String? = nil
25
- ) throws {
26
- let trimmedPin = pin.trimmingCharacters(in: .whitespacesAndNewlines)
27
- guard let pinInt = Int32(trimmedPin) else {
18
+ public func connect(serial: String, bluetoothMac: String, pin: String, sessionType: TempivoSensorSessionType = .modern) throws {
19
+ guard let pinInt = Int32(pin.trimmingCharacters(in: .whitespacesAndNewlines)) else {
28
20
  throw TempivoSensorError(.invalidPin, "PIN must be numeric.")
29
21
  }
30
- let resolved = TempivoSensorQrParser.sessionType(fromModel: sessionType == .legacy ? "HC5" : "HC7", firmware: firmware)
31
22
  #if canImport(TempivoSensorBridge)
32
23
  lock.lock()
33
24
  defer { lock.unlock() }
@@ -37,9 +28,7 @@ public final class TempivoSensorSession: @unchecked Sendable {
37
28
  serial: TempivoSensorQrParser.normalizeSerial(serial),
38
29
  bluetoothMac: bluetoothMac,
39
30
  pin: pinInt,
40
- legacy: resolved == .legacy,
41
- deviceId: deviceId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "",
42
- encryptionKey: trimmedPin
31
+ legacy: sessionType == .legacy
43
32
  )
44
33
  )
45
34
  try throwIfBridgeError(result)
@@ -49,22 +38,8 @@ public final class TempivoSensorSession: @unchecked Sendable {
49
38
  #endif
50
39
  }
51
40
 
52
- public func connect(qr: TempivoSensorQr, seen: TempivoSensorSeenDevice? = nil) throws {
53
- let deviceId = seen?.deviceId.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
54
- if deviceId.isEmpty {
55
- throw TempivoSensorError(
56
- .connectFailed,
57
- "Sensor not in last scan. Scan first, then connect."
58
- )
59
- }
60
- try connect(
61
- serial: qr.serial,
62
- bluetoothMac: seen?.bluetoothMac ?? qr.bluetoothMac,
63
- pin: qr.pin,
64
- sessionType: qr.sessionType,
65
- deviceId: deviceId,
66
- firmware: seen?.firmware
67
- )
41
+ public func connect(qr: TempivoSensorQr) throws {
42
+ try connect(serial: qr.serial, bluetoothMac: qr.bluetoothMac, pin: qr.pin, sessionType: qr.sessionType)
68
43
  }
69
44
 
70
45
  public func disconnect() {
@@ -173,17 +148,14 @@ public final class TempivoSensorSession: @unchecked Sendable {
173
148
 
174
149
  private func throwIfBridgeError(_ result: [String: Any]) throws {
175
150
  guard let code = intValue(result["errorCode"]), code != 0 else { return }
176
- let detail = TempivoSensorError.sanitizeClientMessage(
177
- (result["message"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
178
- )
179
151
  switch code {
180
152
  case 1: throw TempivoSensorError(.invalidPin, "Invalid PIN.")
181
153
  case 2: throw TempivoSensorError(.notConnected, "Not connected.")
182
154
  case 3: throw TempivoSensorError(.unsupportedCommand, "Unsupported command.")
183
155
  case 4: throw TempivoSensorError(.runtimeUnavailable, "Sensor GATT is not available on this device.")
184
- case 5: throw TempivoSensorError(.connectFailed, detail.isEmpty ? "Could not connect." : "Could not connect. \(detail)")
185
- case 6: throw TempivoSensorError(.invalidConfig, detail.isEmpty ? "Invalid configuration." : detail)
186
- default: throw TempivoSensorError(.unknown, detail.isEmpty ? "Sensor request failed." : "Sensor request failed. \(detail)")
156
+ case 5: throw TempivoSensorError(.connectFailed, "Could not connect.")
157
+ case 6: throw TempivoSensorError(.invalidConfig, (result["message"] as? String) ?? "Invalid configuration.")
158
+ default: throw TempivoSensorError(.unknown, "Sensor request failed.")
187
159
  }
188
160
  }
189
161
  }
@@ -65,10 +65,19 @@ public struct TempivoSchedule: Sendable, Equatable {
65
65
  public struct TempivoSensorConfiguration: Sendable, Equatable {
66
66
  public var temperatureAlerts: [TempivoTemperatureAlert]
67
67
  public var schedule: TempivoSchedule
68
+ public var measurementIntervalMinutes: Double?
69
+ public var transmissionIntervalSeconds: Int?
68
70
 
69
- public init(temperatureAlerts: [TempivoTemperatureAlert], schedule: TempivoSchedule) {
71
+ public init(
72
+ temperatureAlerts: [TempivoTemperatureAlert],
73
+ schedule: TempivoSchedule,
74
+ measurementIntervalMinutes: Double? = nil,
75
+ transmissionIntervalSeconds: Int? = nil
76
+ ) {
70
77
  self.temperatureAlerts = temperatureAlerts
71
78
  self.schedule = schedule
79
+ self.measurementIntervalMinutes = measurementIntervalMinutes
80
+ self.transmissionIntervalSeconds = transmissionIntervalSeconds
72
81
  }
73
82
  }
74
83
 
@@ -28,13 +28,8 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
28
28
 
29
29
  AsyncFunction("connect") { (qrJson: String) -> [String: Any] in
30
30
  do {
31
- self.scanner?.stopScanning()
32
- if !Thread.isMainThread {
33
- Thread.sleep(forTimeInterval: 0.2)
34
- }
35
31
  let qr = try TempivoSensorQrParser.parse(qrJson)
36
- let seen = self.scanner?.lookup(serial: qr.serial)
37
- try self.session.connect(qr: qr, seen: seen)
32
+ try self.session.connect(qr: qr)
38
33
  return self.qrPayload(qr)
39
34
  } catch {
40
35
  throw self.mapError(error)
@@ -194,11 +189,7 @@ public class TempivoSensorBeaconModule: Module, TempivoSensorBeaconScannerDelega
194
189
  if let sensor = error as? TempivoSensorError {
195
190
  return SensorBeaconException(code: sensor.code.rawValue, reason: sensor.message)
196
191
  }
197
- let reason = TempivoSensorError.sanitizeClientMessage(error.localizedDescription)
198
- return SensorBeaconException(
199
- code: "unknown",
200
- reason: reason.isEmpty ? "Sensor request failed." : reason
201
- )
192
+ return SensorBeaconException(code: "unknown", reason: error.localizedDescription)
202
193
  }
203
194
  }
204
195
 
package/package.json CHANGED
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "@tempivo/sensor-beacon",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Tempivo sensor BLE SDK for Expo, React Native, Android, iOS, and Node.",
5
5
  "homepage": "https://app.tempivo.com/integrations",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/tempivo/tempivo-app.git",
9
+ "directory": "packages/tempivo-sensor-beacon"
10
+ },
6
11
  "author": "Tempivo",
7
12
  "type": "module",
8
13
  "main": "dist/index.js",