@tempivo/sensor-beacon 1.1.7 → 1.1.8

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/CHANGELOG.md +17 -0
  2. package/README.md +22 -4
  3. package/android/src/main/java/expo/modules/tempivosensorbeacon/SensorBeaconNative.java +19 -0
  4. package/android/src/main/java/expo/modules/tempivosensorbeacon/TempivoSensorBeaconModule.kt +16 -0
  5. package/android-aar/library/build.gradle +1 -0
  6. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/SensorBleRuntime.kt +73 -4
  7. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorCalibration.kt +4 -8
  8. package/android-aar/library/src/main/java/com/tempivo/sensor/beacon/TempivoSensorSession.kt +19 -0
  9. package/dist/calibration.d.ts +8 -0
  10. package/dist/calibration.js +49 -14
  11. package/dist/cellular-network-status.d.ts +69 -0
  12. package/dist/cellular-network-status.js +292 -0
  13. package/dist/channel-capability.d.ts +43 -0
  14. package/dist/channel-capability.js +108 -0
  15. package/dist/config-errors.d.ts +31 -0
  16. package/dist/config-errors.js +244 -0
  17. package/dist/index.d.ts +14 -2
  18. package/dist/index.js +8 -2
  19. package/dist/native-bridge.d.ts +12 -0
  20. package/dist/native-bridge.js +18 -0
  21. package/dist/native-module.d.ts +19 -0
  22. package/dist/native-module.js +117 -2
  23. package/dist/plmn-by-country.d.ts +14 -0
  24. package/dist/plmn-by-country.js +35 -0
  25. package/dist/plmn-labels.d.ts +14 -0
  26. package/dist/plmn-labels.js +37 -0
  27. package/dist/production-defaults.js +63 -9
  28. package/dist/proto/partner-to-proto.d.ts +0 -4
  29. package/dist/proto/partner-to-proto.js +12 -0
  30. package/dist/react-native.d.ts +23 -2
  31. package/dist/react-native.js +20 -2
  32. package/dist/session-types.d.ts +2 -0
  33. package/dist/tempivo-sensor-beacon.aar +0 -0
  34. package/ios/Frameworks/TempivoSensorBridge.xcframework/Info.plist +4 -4
  35. package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/TempivoSensorBridge +2 -2
  36. package/ios/Sources/TempivoSensorBeacon/TempivoSensorCalibration.swift +13 -10
  37. package/ios/Sources/TempivoSensorBeacon/TempivoSensorSessionTypes.swift +4 -1
  38. package/ios/TempivoSensorBeaconModule.swift +2 -0
  39. package/package.json +1 -1
@@ -48,11 +48,22 @@ function isBlankOrNa(value) {
48
48
  if (typeof value !== 'string')
49
49
  return false;
50
50
  const s = value.trim();
51
- return s === '' || s.toUpperCase() === 'N/A' || /^0+$/.test(s) || isDelOnly(s);
51
+ if (s === '' || s.toUpperCase() === 'N/A' || isDelOnly(s))
52
+ return true;
53
+ // All-zero cloud token: bare digits or UUID form 00000000-0000-0000-0000-000000000000
54
+ const compact = s.replace(/-/g, '');
55
+ return /^0+$/.test(compact);
52
56
  }
53
57
  function isDelOnly(value) {
54
58
  return value.length > 0 && [...value].every((ch) => ch === DEL);
55
59
  }
60
+ /** CoAP path compare: `/m` and `m` are the same factory endpoint. */
61
+ function eqEndpoint(actual, expected) {
62
+ if (typeof actual !== 'string')
63
+ return false;
64
+ const norm = (s) => s.trim().replace(/^\/+/, '').toLowerCase();
65
+ return norm(actual) === norm(expected);
66
+ }
56
67
  function plmnAutomatic(value) {
57
68
  const n = u32(value);
58
69
  return n === U32_MAX || n === PLMN_AUTOMATIC;
@@ -87,6 +98,36 @@ function rulesOff(rules) {
87
98
  function firmwareOk(firmware) {
88
99
  return firmware.trim().length > 0;
89
100
  }
101
+ /** Sheet default 300; Tempivo field often uses 60. Any positive period is fine. */
102
+ function measurementPeriodBaseOk(value) {
103
+ const n = u32(value);
104
+ return n != null && n > 0;
105
+ }
106
+ /**
107
+ * Sheet default DISABLE (1). Value 2 is OK when BLE stays on
108
+ * (`bleTurnoffTime` never / max).
109
+ */
110
+ function networkTroubleshootingOk(value, bleTurnoffTime) {
111
+ const n = u32(value);
112
+ if (n === 1)
113
+ return true;
114
+ if (n === 2 && eqU32(bleTurnoffTime, U32_MAX))
115
+ return true;
116
+ return false;
117
+ }
118
+ /** Sheet default 10800; Tempivo often uses 3600. Any positive interval is fine. */
119
+ function transmissionIntervalOk(value) {
120
+ const n = u32(value);
121
+ return n != null && n > 0;
122
+ }
123
+ function networkTroubleshootingLabel(value) {
124
+ const n = u32(value);
125
+ if (n === 1)
126
+ return '1 (DISABLE)';
127
+ if (n === 2)
128
+ return '2 (BLE always on)';
129
+ return show(n ?? value);
130
+ }
90
131
  export function checkProductionDefaults(proto, extra) {
91
132
  const lines = [];
92
133
  const pushNum = (name, key, expected, label = String(expected)) => {
@@ -97,10 +138,20 @@ export function checkProductionDefaults(proto, extra) {
97
138
  const actual = proto[key];
98
139
  lines.push(line(name, expected, show(actual), eqStr(actual, expected)));
99
140
  };
100
- pushNum('Measurement period base', 'measurementPeriodBase', 300);
141
+ const pushEndpoint = (name, key, expected) => {
142
+ const actual = proto[key];
143
+ lines.push(line(name, expected, show(actual), eqEndpoint(actual, expected)));
144
+ };
145
+ {
146
+ const actual = proto.measurementPeriodBase;
147
+ lines.push(line('Measurement period base', 'any > 0', show(u32(actual) ?? actual), measurementPeriodBaseOk(actual)));
148
+ }
101
149
  pushNum('Measurement period factor', 'measurementPeriodFactor', 1);
102
150
  pushNum('BLE turn off', 'bleTurnoffTime', U32_MAX, 'never');
103
- pushNum('BLE on network issues', 'networkTroubleshooting', 1, 'DISABLE');
151
+ {
152
+ const actual = proto.networkTroubleshooting;
153
+ lines.push(line('BLE on network issues', 'DISABLE or BLE always on', networkTroubleshootingLabel(actual), networkTroubleshootingOk(actual, proto.bleTurnoffTime)));
154
+ }
104
155
  pushStr('APN', 'apn', 'iot.1nce.net');
105
156
  lines.push(line('APN user', 'N/A', showCredential(proto.apnUsername), isBlankOrNa(proto.apnUsername)));
106
157
  lines.push(line('APN password', 'N/A', showCredential(proto.apnPassword), isBlankOrNa(proto.apnPassword)));
@@ -110,7 +161,10 @@ export function checkProductionDefaults(proto, extra) {
110
161
  lines.push(line('NB-IoT bands', 'regional', mask == null ? 'missing' : `0x${mask.toString(16)}`, mask != null));
111
162
  }
112
163
  pushNum('Supervision period', 'supervisionPeriod', 86400);
113
- pushNum('Transmission interval', 'transmissionInterval', 10800);
164
+ {
165
+ const actual = proto.transmissionInterval;
166
+ lines.push(line('Transmission interval', 'any > 0', show(u32(actual) ?? actual), transmissionIntervalOk(actual)));
167
+ }
114
168
  pushNum('Transfer limit', 'transferLimit', 65535, 'Disabled');
115
169
  pushNum('Transfer limit period', 'transferLimitTimer', 65535, 'Disabled');
116
170
  pushNum('ACK interval', 'ackInterval', U32_MAX, 'ALWAYS');
@@ -118,11 +172,11 @@ export function checkProductionDefaults(proto, extra) {
118
172
  lines.push(line('Cloud token value', 'zeros', show(proto.cloudToken), isBlankOrNa(proto.cloudToken)));
119
173
  pushStr('Server', 'dataServerIp', 'assets.tempivo.com');
120
174
  pushNum('Server port', 'dataServerPort', 5683);
121
- pushStr('Measurements endpoint', 'dataEndpoint', '/m');
122
- pushStr('Configuration endpoint', 'configurationEndpoint', '/c');
123
- pushStr('Device info endpoint', 'deviceInfoEndpoint', '/i');
124
- pushStr('Time endpoint', 'timeEndpoint', '/t');
125
- pushStr('Extended configuration endpoint', 'extendedConfigurationEndpoint', '/e');
175
+ pushEndpoint('Measurements endpoint', 'dataEndpoint', '/m');
176
+ pushEndpoint('Configuration endpoint', 'configurationEndpoint', '/c');
177
+ pushEndpoint('Device info endpoint', 'deviceInfoEndpoint', '/i');
178
+ pushEndpoint('Time endpoint', 'timeEndpoint', '/t');
179
+ pushEndpoint('Extended configuration endpoint', 'extendedConfigurationEndpoint', '/e');
126
180
  lines.push(line('DNS server', 'Automatic', show(proto.dnsServerIp), dnsAutomatic(proto.dnsServerIp)));
127
181
  pushNum('DNS TTL', 'dnsTtlConfig', 864002, 'refresh if communication fails');
128
182
  pushStr('Update server', 'updateServerIp', 'nbiot.efento.io');
@@ -1,7 +1,3 @@
1
- /**
2
- * Partner temperatureAlerts + schedule + intervals → ProtoConfig bytes.
3
- * Mirrors scripts/efento-local-mac/partner_rules.py (interleaved L/H/OR).
4
- */
5
1
  import type { TempivoSensorConfiguration } from '../session-types.js';
6
2
  import { type ProtoConfigObject } from './decode-proto-config.js';
7
3
  /**
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Partner temperatureAlerts + schedule + intervals → ProtoConfig bytes.
3
+ * Mirrors scripts/efento-local-mac/partner_rules.py (interleaved L/H/OR).
4
+ */
5
+ import { assertProbeAlertsAllowed, channelTypesFromProtoConfig, } from '../channel-capability.js';
1
6
  import { decodeProtoConfigBase64, decodeProtoConfigBytes, } from './decode-proto-config.js';
2
7
  import protobuf from 'protobufjs/light.js';
3
8
  import descriptor from './efento-protobuf-descriptor.js';
@@ -226,6 +231,13 @@ export function assertSafePartnerProtoWrite(cfg, options = {}) {
226
231
  }
227
232
  /** Patch partner alerts/schedule/intervals onto a baseline ProtoConfig object. */
228
233
  export function applyPartnerConfigToProtoObject(baseline, partner) {
234
+ const channelTypes = channelTypesFromProtoConfig(baseline);
235
+ if (channelTypes) {
236
+ assertProbeAlertsAllowed(partner.temperatureAlerts, {
237
+ kind: 'channelTypes',
238
+ channelTypes,
239
+ });
240
+ }
229
241
  const { rules, mask } = compileAlerts(partner.temperatureAlerts ?? []);
230
242
  const out = { rules };
231
243
  for (const field of WRITE_BASELINE_FIELDS) {
@@ -9,10 +9,31 @@ export { isMissingAdvertisementFirmware, sensorModelFromFirmware } from './model
9
9
  export type { SensorStickerModel } from './model.js';
10
10
  export { buildSensorQrConnectJson, draftSensorQrConnectJsonFromScanDevice, formatSensorReadingLine, mergeScanTargetIntoSensorQr, normalizeSensorStickerModel, parseSensorQrForConnect, pinFromSensorQrRecord, resolveSensorBleConnectCredentialsFromPin, sensorQrConnectJsonFromLoose, sensorQrSerialMatchesSelected, serialHexFromSensorQrScan, tryParseSensorQrJson, } from './connect-helpers.js';
11
11
  export type { ParsedSensorQrLoose, SensorBleConnectCredentials } from './connect-helpers.js';
12
- export { calibrationFromExtendedJson, decodeLaboratoryCalibrationTimestamp, } from './calibration.js';
12
+ export { calibrationFromExtendedJson, decodeLaboratoryCalibrationTimestamp, formatLaboratoryCalibration, normalizeLaboratoryCalibration, } from './calibration.js';
13
13
  export { BLE_MAX_MEASUREMENT_INTERVAL_MINUTES, BLE_MAX_TRANSMISSION_INTERVAL_SECONDS, BLE_MIN_MEASUREMENT_INTERVAL_MINUTES, BLE_MIN_TRANSMISSION_INTERVAL_SECONDS, DEFAULT_ALERT_HYSTERESIS_C, compileSensorProfileToBleJson, configurationFromApiProfile, parseSensorConfiguration, parseSensorConfigurationFromDevice, parseSensorConfigurationFromDeviceJson, parseSensorConfigurationJson, pickPartnerConfigurationJson, } from './profile.js';
14
14
  export type { TempivoSchedule, TempivoScheduleAlways, TempivoScheduleWeek, TempivoSensorCalibration, TempivoSensorConfiguration, TempivoSensorQr, TempivoSensorSessionType, TempivoTemperatureAlert, TempivoTemperatureChannel, TempivoTemperatureMaxAlert, TempivoTemperatureMinAlert, TempivoTemperatureRangeAlert, TempivoTriggerTransmissionResult, } from './session-types.js';
15
15
  export type { TempivoDeviceFoundSubscription, TempivoNativeCalibration, TempivoNativeMeasurement, TempivoNativePermissionResponse, TempivoNativePermissionStatus, TempivoNativeQr, TempivoNativeTelemetry, TempivoSensorBeaconDevice, } from './native-types.js';
16
- export { isNativeSensorBeaconAvailable, requestPermissions, startScan, stopScan, isScanning, addDeviceFoundListener, connect, disconnect, getConfiguration, setConfigurationJson, triggerTransmission, clearMeasurementQueue, getCalibration, getProtoConfiguration, } from './native-module.js';
16
+ import { getCellularNetworkStatusJson as getCellularNetworkStatusJsonNative, deleteMeasurements as deleteMeasurementsNative, setOperator as setOperatorNative, isNativeSensorBeaconAvailable, requestPermissions, startScan, stopScan, isScanning, addDeviceFoundListener, connect, disconnect, getConfiguration, getConfigurationErrors, setConfigurationJson, triggerTransmission, clearMeasurementQueue, getCalibration, getProtoConfiguration } from './native-module.js';
17
+ import { type TempivoCellularNetworkStatusView, type TempivoCellularStatusLocale } from './cellular-network-status.js';
18
+ export { isNativeSensorBeaconAvailable, requestPermissions, startScan, stopScan, isScanning, addDeviceFoundListener, connect, disconnect, getConfiguration, getConfigurationErrors, setConfigurationJson, triggerTransmission, clearMeasurementQueue, getCalibration, getProtoConfiguration, };
19
+ /** Raw GATT JSON (no label formatting). */
20
+ export declare const getCellularNetworkStatusJson: typeof getCellularNetworkStatusJsonNative;
21
+ export declare const deleteMeasurements: typeof deleteMeasurementsNative;
22
+ export declare const setOperator: typeof setOperatorNative;
23
+ /**
24
+ * GATT cellular status with short partner labels.
25
+ * Composed here (static imports) so Metro file: links do not dynamic-import label helpers.
26
+ */
27
+ export declare function getCellularNetworkStatus(opts?: {
28
+ locale?: TempivoCellularStatusLocale;
29
+ afterServerTrigger?: boolean;
30
+ }): Promise<TempivoCellularNetworkStatusView>;
31
+ export { PREFERRED_PLMN_BY_COUNTRY_ISO2, resolveSetOperator, } from './plmn-by-country.js';
32
+ export { cellularNetworkStatusViewFromJson, formatCellularNetworkStatusLabel, formatCellularNetworkStatusLabelWithOperator, formatCellularNetworkStatusSummary, formatCellularServerDetailLabel, isCellularConnectionFullyOk, isCellularRegistrationOk, isCellularServerCommunicationOk, isSimCardOk, isValidCellularIpAddress, normalizeCellularSignalStrengthDbm, parseCellularNetworkStatusJson, parseCellularNetworkStatusObject, resolveCellularStatusTone, } from './cellular-network-status.js';
33
+ export type { TempivoCellularNetworkStatus, TempivoCellularNetworkStatusView, TempivoCellularStatusLocale, TempivoCellularStatusTone, } from './cellular-network-status.js';
34
+ export { getOperatorNameFromPlmn, PLMN_OPERATOR_LABELS } from './plmn-labels.js';
35
+ export type { TempivoPlmnOperatorOption } from './plmn-labels.js';
36
+ export { configurationErrorsFromProtoConfig, decodeConfigurationError, decodeConfigurationErrorCodes, formatConfigurationErrorTimestamp, } from './config-errors.js';
37
+ export type { TempivoConfigErrorParameter, TempivoConfigErrorSide, TempivoConfigErrorValue, TempivoConfigurationError, TempivoConfigurationErrors, } from './config-errors.js';
17
38
  export { checkProductionDefaults } from './production-defaults.js';
18
39
  export type { ProductionCheckLine, ProductionCheckResult } from './production-defaults.js';
@@ -7,7 +7,25 @@ export { TempivoSensorError } from './errors.js';
7
7
  export { DEFAULT_SENSOR_MODEL, bluetoothMacFromSerial, normalizeSensorSerial, encodeSensorPinPayload, parseSensorQrJson, sessionTypeFromModel, } from './qr.js';
8
8
  export { isMissingAdvertisementFirmware, sensorModelFromFirmware } from './model.js';
9
9
  export { buildSensorQrConnectJson, draftSensorQrConnectJsonFromScanDevice, formatSensorReadingLine, mergeScanTargetIntoSensorQr, normalizeSensorStickerModel, parseSensorQrForConnect, pinFromSensorQrRecord, resolveSensorBleConnectCredentialsFromPin, sensorQrConnectJsonFromLoose, sensorQrSerialMatchesSelected, serialHexFromSensorQrScan, tryParseSensorQrJson, } from './connect-helpers.js';
10
- export { calibrationFromExtendedJson, decodeLaboratoryCalibrationTimestamp, } from './calibration.js';
10
+ export { calibrationFromExtendedJson, decodeLaboratoryCalibrationTimestamp, formatLaboratoryCalibration, normalizeLaboratoryCalibration, } from './calibration.js';
11
11
  export { BLE_MAX_MEASUREMENT_INTERVAL_MINUTES, BLE_MAX_TRANSMISSION_INTERVAL_SECONDS, BLE_MIN_MEASUREMENT_INTERVAL_MINUTES, BLE_MIN_TRANSMISSION_INTERVAL_SECONDS, DEFAULT_ALERT_HYSTERESIS_C, compileSensorProfileToBleJson, configurationFromApiProfile, parseSensorConfiguration, parseSensorConfigurationFromDevice, parseSensorConfigurationFromDeviceJson, parseSensorConfigurationJson, pickPartnerConfigurationJson, } from './profile.js';
12
- export { isNativeSensorBeaconAvailable, requestPermissions, startScan, stopScan, isScanning, addDeviceFoundListener, connect, disconnect, getConfiguration, setConfigurationJson, triggerTransmission, clearMeasurementQueue, getCalibration, getProtoConfiguration, } from './native-module.js';
12
+ import { getCellularNetworkStatusJson as getCellularNetworkStatusJsonNative, deleteMeasurements as deleteMeasurementsNative, setOperator as setOperatorNative, isNativeSensorBeaconAvailable, requestPermissions, startScan, stopScan, isScanning, addDeviceFoundListener, connect, disconnect, getConfiguration, getConfigurationErrors, setConfigurationJson, triggerTransmission, clearMeasurementQueue, getCalibration, getProtoConfiguration, } from './native-module.js';
13
+ import { cellularNetworkStatusViewFromJson, } from './cellular-network-status.js';
14
+ export { isNativeSensorBeaconAvailable, requestPermissions, startScan, stopScan, isScanning, addDeviceFoundListener, connect, disconnect, getConfiguration, getConfigurationErrors, setConfigurationJson, triggerTransmission, clearMeasurementQueue, getCalibration, getProtoConfiguration, };
15
+ /** Raw GATT JSON (no label formatting). */
16
+ export const getCellularNetworkStatusJson = getCellularNetworkStatusJsonNative;
17
+ export const deleteMeasurements = deleteMeasurementsNative;
18
+ export const setOperator = setOperatorNative;
19
+ /**
20
+ * GATT cellular status with short partner labels.
21
+ * Composed here (static imports) so Metro file: links do not dynamic-import label helpers.
22
+ */
23
+ export async function getCellularNetworkStatus(opts) {
24
+ const json = await getCellularNetworkStatusJsonNative();
25
+ return cellularNetworkStatusViewFromJson(json, opts);
26
+ }
27
+ export { PREFERRED_PLMN_BY_COUNTRY_ISO2, resolveSetOperator, } from './plmn-by-country.js';
28
+ export { cellularNetworkStatusViewFromJson, formatCellularNetworkStatusLabel, formatCellularNetworkStatusLabelWithOperator, formatCellularNetworkStatusSummary, formatCellularServerDetailLabel, isCellularConnectionFullyOk, isCellularRegistrationOk, isCellularServerCommunicationOk, isSimCardOk, isValidCellularIpAddress, normalizeCellularSignalStrengthDbm, parseCellularNetworkStatusJson, parseCellularNetworkStatusObject, resolveCellularStatusTone, } from './cellular-network-status.js';
29
+ export { getOperatorNameFromPlmn, PLMN_OPERATOR_LABELS } from './plmn-labels.js';
30
+ export { configurationErrorsFromProtoConfig, decodeConfigurationError, decodeConfigurationErrorCodes, formatConfigurationErrorTimestamp, } from './config-errors.js';
13
31
  export { checkProductionDefaults } from './production-defaults.js';
@@ -64,7 +64,9 @@ export type TempivoSensorQr = {
64
64
  deviceId?: string;
65
65
  };
66
66
  export type TempivoSensorCalibration = {
67
+ /** Calendar date UTC (`YYYY-MM-DD`). Device stores date only, no wall-clock time. */
67
68
  laboratoryCalibrationDate: string | null;
69
+ /** Unix seconds UTC at start of that day (days-since-epoch from device are converted). */
68
70
  laboratoryCalibrationTimestamp: number | null;
69
71
  };
70
72
  export type TempivoTriggerTransmissionResult = {
Binary file
@@ -8,7 +8,7 @@
8
8
  <key>BinaryPath</key>
9
9
  <string>TempivoSensorBridge.framework/TempivoSensorBridge</string>
10
10
  <key>LibraryIdentifier</key>
11
- <string>ios-arm64-simulator</string>
11
+ <string>ios-arm64</string>
12
12
  <key>LibraryPath</key>
13
13
  <string>TempivoSensorBridge.framework</string>
14
14
  <key>SupportedArchitectures</key>
@@ -17,14 +17,12 @@
17
17
  </array>
18
18
  <key>SupportedPlatform</key>
19
19
  <string>ios</string>
20
- <key>SupportedPlatformVariant</key>
21
- <string>simulator</string>
22
20
  </dict>
23
21
  <dict>
24
22
  <key>BinaryPath</key>
25
23
  <string>TempivoSensorBridge.framework/TempivoSensorBridge</string>
26
24
  <key>LibraryIdentifier</key>
27
- <string>ios-arm64</string>
25
+ <string>ios-arm64-simulator</string>
28
26
  <key>LibraryPath</key>
29
27
  <string>TempivoSensorBridge.framework</string>
30
28
  <key>SupportedArchitectures</key>
@@ -33,6 +31,8 @@
33
31
  </array>
34
32
  <key>SupportedPlatform</key>
35
33
  <string>ios</string>
34
+ <key>SupportedPlatformVariant</key>
35
+ <string>simulator</string>
36
36
  </dict>
37
37
  </array>
38
38
  <key>CFBundlePackageType</key>
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/ios/Frameworks/TempivoSensorBridge.xcframework/ios-arm64/TempivoSensorBridge.framework/TempivoSensorBridge
3
- size: 78427712 bytes
4
- sha256: 3d8331bcccc757e88f3cc11ebd41a81837c0712942178f3bfdd869094b90cd45
3
+ size: 78429152 bytes
4
+ sha256: 7b5b15b4fd17ad5cfbafa8852fd8e7401870a8e0208eb89c00af07b08de0710c
@@ -5,18 +5,21 @@ public enum TempivoSensorCalibrationDecoder {
5
5
 
6
6
  public static func decode(_ raw: Int64?) -> TempivoSensorCalibration {
7
7
  guard let raw, raw > 0 else {
8
- return TempivoSensorCalibration(laboratoryCalibrationDate: nil, laboratoryCalibrationTimestamp: nil)
8
+ return TempivoSensorCalibration(
9
+ laboratoryCalibrationDate: nil,
10
+ laboratoryCalibrationTimestamp: nil
11
+ )
9
12
  }
10
- let seconds = raw < 100_000 ? raw * secondsPerDay : raw
11
- let date = Date(timeIntervalSince1970: TimeInterval(seconds))
12
- let fmt = DateFormatter()
13
- fmt.calendar = Calendar(identifier: .gregorian)
14
- fmt.timeZone = TimeZone(secondsFromGMT: 0)
15
- fmt.locale = Locale(identifier: "en_US_POSIX")
16
- fmt.dateFormat = "yyyy-MM-dd"
13
+ let unixSeconds = raw < 100_000 ? raw * secondsPerDay : raw
14
+ let date = Date(timeIntervalSince1970: TimeInterval(unixSeconds))
15
+ let dateFmt = DateFormatter()
16
+ dateFmt.calendar = Calendar(identifier: .gregorian)
17
+ dateFmt.timeZone = TimeZone(secondsFromGMT: 0)
18
+ dateFmt.locale = Locale(identifier: "en_US_POSIX")
19
+ dateFmt.dateFormat = "yyyy-MM-dd"
17
20
  return TempivoSensorCalibration(
18
- laboratoryCalibrationDate: fmt.string(from: date),
19
- laboratoryCalibrationTimestamp: raw
21
+ laboratoryCalibrationDate: dateFmt.string(from: date),
22
+ laboratoryCalibrationTimestamp: unixSeconds
20
23
  )
21
24
  }
22
25
  }
@@ -84,7 +84,10 @@ public struct TempivoSensorCalibration: Sendable, Equatable {
84
84
  public var laboratoryCalibrationDate: String?
85
85
  public var laboratoryCalibrationTimestamp: Int64?
86
86
 
87
- public init(laboratoryCalibrationDate: String?, laboratoryCalibrationTimestamp: Int64?) {
87
+ public init(
88
+ laboratoryCalibrationDate: String?,
89
+ laboratoryCalibrationTimestamp: Int64?
90
+ ) {
88
91
  self.laboratoryCalibrationDate = laboratoryCalibrationDate
89
92
  self.laboratoryCalibrationTimestamp = laboratoryCalibrationTimestamp
90
93
  }
@@ -31,6 +31,8 @@ public class TempivoSensorBeaconModule: Module {
31
31
  }
32
32
 
33
33
  AsyncFunction("startScan") {
34
+ // Own GATT stops advertising; release before scan (JS reload may leave a live session).
35
+ self.session.disconnect()
34
36
  #if canImport(TempivoSensorBridge)
35
37
  self.scanBridge.initialize()
36
38
  self.sdkScanActive = true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tempivo/sensor-beacon",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
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": {