@ovok/native 1.6.51 → 1.6.52

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 (37) hide show
  1. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-builders.js +4 -2
  2. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-builders.js.map +1 -1
  3. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js +30 -6
  4. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js.map +1 -1
  5. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-frame-parser.js +16 -27
  6. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-frame-parser.js.map +1 -1
  7. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.device.js +26 -33
  8. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.device.js.map +1 -1
  9. package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.main-services.js +1 -1
  10. package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-builders.js +3 -2
  11. package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-builders.js.map +1 -1
  12. package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js +31 -7
  13. package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js.map +1 -1
  14. package/lib/module/modules/bt-management/services/devices/bc01/bc01-frame-parser.js +16 -26
  15. package/lib/module/modules/bt-management/services/devices/bc01/bc01-frame-parser.js.map +1 -1
  16. package/lib/module/modules/bt-management/services/devices/bc01/bc01.device.js +27 -34
  17. package/lib/module/modules/bt-management/services/devices/bc01/bc01.device.js.map +1 -1
  18. package/lib/module/modules/bt-management/services/devices/bc01/bc01.main-services.js +1 -1
  19. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-command-builders.d.ts +2 -1
  20. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-command-builders.d.ts.map +1 -1
  21. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts +3 -6
  22. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts +7 -17
  24. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts.map +1 -1
  25. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts +5 -2
  26. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts.map +1 -1
  27. package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.main-services.d.ts +1 -1
  28. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-command-builders.d.ts +2 -1
  29. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-command-builders.d.ts.map +1 -1
  30. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts +3 -6
  31. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts.map +1 -1
  32. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts +7 -17
  33. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts.map +1 -1
  34. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts +5 -2
  35. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts.map +1 -1
  36. package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.main-services.d.ts +1 -1
  37. package/package.json +2 -2
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
 
3
3
  import { hexToByte } from "../../../utils/hex-to-byte.js";
4
+ import { bc401ChecksumMatches } from "./bc01-command-builders.js";
4
5
 
5
6
  /** BC401 stored-record frame is always sixteen bytes: header, timestamp, analytes, checksum. */
6
7
  const BC01_RECORD_LENGTH = 16;
7
8
 
8
- /** The two opcodes the firmware uses for a stored URS-7 record. */
9
+ /** The two opcodes the firmware uses for a stored BC401 strip record. */
9
10
  const BC01_URS_OPCODE = 0xe1;
10
11
  const BC01_PAGED_URS_OPCODE = 0xe2;
11
12
 
@@ -28,16 +29,14 @@ const MINUTE_MASK = 0x3f;
28
29
  const SECOND_MASK = 0x3f;
29
30
 
30
31
  /**
31
- * URS-7 pad names, in the exact order they occupy the packed 3-bit slots
32
- * across bytes 8..14 (see M1/a.java). The eleventh slot is a Contec-firmware
33
- * field the vendor's own catalog calls "vc" and no other name is documented.
32
+ * Pad names, in the exact order they occupy the packed 3-bit slots across
33
+ * bytes 8..14 (see PHMS M1/a.java), covering both 11- and 14-pad strips.
34
34
  */
35
- const BC01_ANALYTE_ORDER = ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc"];
35
+ const BC01_ANALYTE_ORDER = ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc", "mal", "cr", "uca"];
36
36
  /**
37
37
  * BC401's packed values are colour-chart indexes, not measurements. These
38
38
  * values mirror the tables in Contec's BC401 integration (PHMS M1/a.java):
39
39
  * the index is zero-based and `7` remains the device's unmeasured sentinel.
40
- * The pH table is the URS-7 strip scale, which includes half-point readings.
41
40
  */
42
41
  const BC01_ANALYTE_VALUES = {
43
42
  uro: [0.2, 2, 4, 8],
@@ -46,11 +45,14 @@ const BC01_ANALYTE_VALUES = {
46
45
  ket: [0, 15, 40, 80],
47
46
  glu: [0, 50, 100, 250, 500, 1000],
48
47
  pro: [0, 15, 30, 100, 300],
49
- ph: [5, 6, 6.5, 7, 7.5, 8, 8.5],
48
+ ph: [5, 6, 7, 8, 9],
50
49
  nit: [0, 1],
51
50
  leu: [0, 15, 70, 125, 500],
52
51
  sg: [1.005, 1.01, 1.015, 1.02, 1.025, 1.03],
53
- vc: [0, 10, 25, 50, 100]
52
+ vc: [0, 10, 25, 50, 100],
53
+ mal: [1, 3, 8, 15],
54
+ cr: [10, 50, 100, 200, 300],
55
+ uca: [2, 5, 15, 50]
54
56
  };
55
57
 
56
58
  /** Where the packed analyte pairs start in a 16-byte E1/E2 frame. */
@@ -73,10 +75,8 @@ const readPad = (packed, slot) => slot === 0 ? packed & 0x07 : packed >> 3 & 0x0
73
75
  * frame is a record or a heartbeat, and a frame that fails these checks is
74
76
  * skipped rather than parsed into a plausible-looking wrong reading.
75
77
  *
76
- * The checksum byte is not verified here: the SDK's read path already ensures
77
- * frame integrity before the parser sees the bytes, and a URS-7 pad value can
78
- * only land in [0, 7] anyway — a corrupt payload would fail the pad-value
79
- * check before it made it into a measurement.
78
+ * The checksum byte is verified before any value is exposed; individual
79
+ * packed indexes could otherwise decode into plausible but incorrect results.
80
80
  */
81
81
  const parseBc01Record = frame => {
82
82
  if (frame.length < BC01_RECORD_LENGTH) {
@@ -86,6 +86,9 @@ const parseBc01Record = frame => {
86
86
  if (opcode !== BC01_URS_OPCODE && opcode !== BC01_PAGED_URS_OPCODE) {
87
87
  return undefined;
88
88
  }
89
+ if (!bc401ChecksumMatches(frame.map(hexToByte))) {
90
+ return undefined;
91
+ }
89
92
  const flags = hexToByte(frame[1] ?? "");
90
93
  const yy = hexToByte(frame[2] ?? "") + YEAR_BASE;
91
94
  const mm = hexToByte(frame[3] ?? "") & MONTH_MASK;
@@ -115,18 +118,5 @@ const parseBc01Record = frame => {
115
118
  values
116
119
  };
117
120
  };
118
-
119
- /**
120
- * True when the buffer holds a complete BC401 stored record. Used by the
121
- * driver's `validatePackage` hook so the SDK's read path only advances once
122
- * the notification carries a whole 16-byte frame.
123
- */
124
- const isBc01Record = frame => {
125
- if (frame.length < BC01_RECORD_LENGTH) {
126
- return false;
127
- }
128
- const opcode = hexToByte(frame[0] ?? "");
129
- return opcode === BC01_URS_OPCODE || opcode === BC01_PAGED_URS_OPCODE;
130
- };
131
- export { BC01_ANALYTE_ORDER, BC01_ANALYTE_VALUES, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, isBc01Record, parseBc01Record };
121
+ export { BC01_ANALYTE_ORDER, BC01_ANALYTE_VALUES, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, parseBc01Record };
132
122
  //# sourceMappingURL=bc01-frame-parser.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["hexToByte","BC01_RECORD_LENGTH","BC01_URS_OPCODE","BC01_PAGED_URS_OPCODE","BC01_LAST_OF_SET_BIT","UNMEASURED","YEAR_BASE","MONTH_MASK","DAY_MASK","HOUR_MASK","MINUTE_MASK","SECOND_MASK","BC01_ANALYTE_ORDER","BC01_ANALYTE_VALUES","uro","bld","bil","ket","glu","pro","ph","nit","leu","sg","vc","ANALYTES_START","readPad","packed","slot","parseBc01Record","frame","length","undefined","opcode","flags","yy","mm","dd","hh","mi","ss","timestamp","Date","values","forEach","analyte","position","byteIndex","Math","floor","level","value","lastOfSet","pageIndex","isBc01Record"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["hexToByte","bc401ChecksumMatches","BC01_RECORD_LENGTH","BC01_URS_OPCODE","BC01_PAGED_URS_OPCODE","BC01_LAST_OF_SET_BIT","UNMEASURED","YEAR_BASE","MONTH_MASK","DAY_MASK","HOUR_MASK","MINUTE_MASK","SECOND_MASK","BC01_ANALYTE_ORDER","BC01_ANALYTE_VALUES","uro","bld","bil","ket","glu","pro","ph","nit","leu","sg","vc","mal","cr","uca","ANALYTES_START","readPad","packed","slot","parseBc01Record","frame","length","undefined","opcode","map","flags","yy","mm","dd","hh","mi","ss","timestamp","Date","values","forEach","analyte","position","byteIndex","Math","floor","level","value","lastOfSet","pageIndex"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"mappings":";;AAEA,SAASA,SAAS,QAAQ,+BAA4B;AAEtD,SAASC,oBAAoB,QAAQ,4BAAyB;;AAE9D;AACA,MAAMC,kBAAkB,GAAG,EAAE;;AAE7B;AACA,MAAMC,eAAe,GAAG,IAAI;AAC5B,MAAMC,qBAAqB,GAAG,IAAI;;AAElC;AACA;AACA;AACA;AACA,MAAMC,oBAAoB,GAAG,IAAI;;AAEjC;AACA;AACA;AACA;AACA,MAAMC,UAAU,GAAG,CAAC;AAEpB,MAAMC,SAAS,GAAG,IAAI;AACtB,MAAMC,UAAU,GAAG,IAAI;AACvB,MAAMC,QAAQ,GAAG,IAAI;AACrB,MAAMC,SAAS,GAAG,IAAI;AACtB,MAAMC,WAAW,GAAG,IAAI;AACxB,MAAMC,WAAW,GAAG,IAAI;;AAExB;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,GAAG,CACzB,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,KAAK,CACwD;AAI/D;AACA;AACA;AACA;AACA;AACA,MAAMC,mBAA2D,GAAG;EAClEC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;EACnBC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC;EACzBC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;EACjBC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;EACpBC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC;EACjCC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC;EAC1BC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;EACnBC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACXC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC;EAC1BC,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC;EAC3CC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC;EACxBC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;EAClBC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;EAC3BC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;AACpB,CAAC;;AAED;AACA,MAAMC,cAAc,GAAG,CAAC;;AAExB;;AAmBA;AACA;AACA;AACA;AACA;AACA,MAAMC,OAAO,GAAGA,CAACC,MAAc,EAAEC,IAAW,KAC1CA,IAAI,KAAK,CAAC,GAAGD,MAAM,GAAG,IAAI,GAAIA,MAAM,IAAI,CAAC,GAAI,IAAI;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAME,eAAe,GACnBC,KAAwB,IACS;EACjC,IAAIA,KAAK,CAACC,MAAM,GAAGjC,kBAAkB,EAAE;IACrC,OAAOkC,SAAS;EAClB;EAEA,MAAMC,MAAM,GAAGrC,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;EAExC,IAAIG,MAAM,KAAKlC,eAAe,IAAIkC,MAAM,KAAKjC,qBAAqB,EAAE;IAClE,OAAOgC,SAAS;EAClB;EAEA,IAAI,CAACnC,oBAAoB,CAACiC,KAAK,CAACI,GAAG,CAACtC,SAAS,CAAC,CAAC,EAAE;IAC/C,OAAOoC,SAAS;EAClB;EAEA,MAAMG,KAAK,GAAGvC,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;EACvC,MAAMM,EAAE,GAAGxC,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG3B,SAAS;EAChD,MAAMkC,EAAE,GAAGzC,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG1B,UAAU;EACjD,MAAMkC,EAAE,GAAG1C,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAGzB,QAAQ;EAC/C,MAAMkC,EAAE,GAAG3C,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAGxB,SAAS;EAChD,MAAMkC,EAAE,GAAG5C,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAGvB,WAAW;EAClD,MAAMkC,EAAE,GAAG7C,SAAS,CAACkC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAGtB,WAAW;EAElD,MAAMkC,SAAS,GAAG,IAAIC,IAAI,CAACP,EAAE,EAAEC,EAAE,GAAG,CAAC,EAAEC,EAAE,EAAEC,EAAE,EAAEC,EAAE,EAAEC,EAAE,EAAE,CAAC,CAAC;EAEzD,MAAMG,MAAkC,GAAG,CAAC,CAAC;EAE7CnC,kBAAkB,CAACoC,OAAO,CAAC,CAACC,OAAO,EAAEC,QAAQ,KAAK;IAChD,MAAMC,SAAS,GAAGvB,cAAc,GAAGwB,IAAI,CAACC,KAAK,CAACH,QAAQ,GAAG,CAAC,CAAC;IAC3D,MAAMnB,IAAI,GAAImB,QAAQ,GAAG,CAAW;IACpC,MAAMpB,MAAM,GAAG/B,SAAS,CAACkC,KAAK,CAACkB,SAAS,CAAC,IAAI,EAAE,CAAC;IAChD,MAAMG,KAAK,GAAGzB,OAAO,CAACC,MAAM,EAAEC,IAAI,CAAC;IAEnC,IAAIuB,KAAK,KAAKjD,UAAU,EAAE;MACxB;IACF;IAEA,MAAMkD,KAAK,GAAG1C,mBAAmB,CAACoC,OAAO,CAAC,CAACK,KAAK,CAAC;IAEjD,IAAIC,KAAK,KAAKpB,SAAS,EAAE;MACvBY,MAAM,CAACE,OAAO,CAAC,GAAGM,KAAK;IACzB;EACF,CAAC,CAAC;EAEF,OAAO;IACLV,SAAS;IACTW,SAAS,EAAE,CAAClB,KAAK,GAAGlC,oBAAoB,MAAM,CAAC;IAC/CqD,SAAS,EAAEnB,KAAK,GAAG,IAAI;IACvBS;EACF,CAAC;AACH,CAAC;AAED,SACEnC,kBAAkB,EAClBC,mBAAmB,EACnBT,oBAAoB,EACpBD,qBAAqB,EACrBF,kBAAkB,EAClBC,eAAe,EAEf8B,eAAe","ignoreList":[]}
@@ -6,30 +6,9 @@ import { hexToByte } from "../../../utils/hex-to-byte.js";
6
6
  import { BTManagedDevice } from "../bt-managed-device.js";
7
7
  import { Bc01CommandSequencer } from "./bc01-command-sequencer.js";
8
8
  import { BC01_ANALYTE_ORDER, parseBc01Record } from "./bc01-frame-parser.js";
9
- import { Bc01FrameReader } from "./bc01.frame-reader.js";
9
+ import { Bc01FrameReader, bc01FrameLengths } from "./bc01.frame-reader.js";
10
10
  import { bc01MainServices } from "./bc01.main-services.js";
11
11
 
12
- /** Minimum bytes a complete frame carries, keyed by its opening opcode. */
13
- const BC01_FRAME_MIN_LENGTH = {
14
- 0xf0: 2,
15
- // ACK
16
- 0xf2: 8,
17
- // Version reply (variable — 8 is the minimum PHMS reads before answering)
18
- 0xf3: 3,
19
- // Time-sync ack
20
- 0xe0: 7,
21
- // Record-count reply
22
- 0xe1: 16,
23
- // Stored URS record
24
- 0xe2: 16,
25
- // Paginated URS record
26
- 0xe3: 3,
27
- // Finish
28
- 0xe4: 36,
29
- // Quantitative record (optional path)
30
- 0xe5: 36 // Quantitative record (optional path)
31
- };
32
-
33
12
  /**
34
13
  * Contec BC401 (BC01) urine analyzer driver.
35
14
  *
@@ -41,12 +20,15 @@ const BC01_FRAME_MIN_LENGTH = {
41
20
  * 16-byte E1/E2 frame on 0xFF02.
42
21
  */
43
22
  export class BC01Device extends BTManagedDevice {
44
- onStreamStart = () => {};
23
+ onStreamStart = () => {
24
+ this.reportedTimestamps.clear();
25
+ };
26
+ reportedTimestamps = new Set();
45
27
  mainServices = bc01MainServices;
46
28
  frameReader = new Bc01FrameReader();
47
29
 
48
30
  /**
49
- * 90 s covers the maximum firmware-side reagent-pad settle time on a URS-7
31
+ * 90 s covers the maximum firmware-side reagent-pad settle time on a
50
32
  * strip and leaves headroom for a bulk memory dump of every stored record.
51
33
  * If the device does not push a frame within that window the data processor
52
34
  * times out and the driver surfaces "device unreachable".
@@ -62,14 +44,18 @@ export class BC01Device extends BTManagedDevice {
62
44
  * set. The parent's default `pollingSequencerFor` would only re-send the
63
45
  * declared reset forever, which the firmware ignores after the first one.
64
46
  */
65
- this.createCommandSequencer = () => new Bc01CommandSequencer({
66
- write: {
67
- serviceUuid: bc01MainServices[0].uuid,
68
- characteristicUuid: bc01MainServices[0].writeUuid.uuid
69
- },
70
- onRefused: reason => this.onError?.(new Error(`BC401 handshake: ${reason}`)),
71
- clockSync: params.clockSync
72
- }, params.clockSync?.now);
47
+ this.createCommandSequencer = () => {
48
+ this.reportedTimestamps.clear();
49
+ return new Bc01CommandSequencer({
50
+ write: {
51
+ serviceUuid: bc01MainServices[0].uuid,
52
+ characteristicUuid: bc01MainServices[0].writeUuid.uuid
53
+ },
54
+ onError: reason => this.onError?.(new Error(`BC401: ${reason}`)),
55
+ clockSync: params.clockSync,
56
+ clearDeviceHistory: params.clearDeviceHistory
57
+ }, params.clockSync?.now);
58
+ };
73
59
  }
74
60
 
75
61
  /**
@@ -83,7 +69,7 @@ export class BC01Device extends BTManagedDevice {
83
69
  return false;
84
70
  }
85
71
  const opcode = hexToByte(pkg[0] ?? "");
86
- const minLength = BC01_FRAME_MIN_LENGTH[opcode];
72
+ const minLength = bc01FrameLengths[opcode.toString(16).padStart(2, "0")];
87
73
  if (minLength === undefined) {
88
74
  return false;
89
75
  }
@@ -114,7 +100,9 @@ export class BC01Device extends BTManagedDevice {
114
100
  /**
115
101
  * Nothing to do here for the BC401. Every reading arrives through the
116
102
  * dependent-result path, and the state machine sees only the `OTHER`-typed
117
- * echo we return from `handleDependentResult`.
103
+ * echo we return from `handleDependentResult`. Records are deduplicated by
104
+ * their second-resolution device timestamp for this transfer because a
105
+ * paged-group retry resends the earlier frames.
118
106
  */
119
107
  handleSuccessResult() {
120
108
  return;
@@ -135,6 +123,11 @@ export class BC01Device extends BTManagedDevice {
135
123
  this.onError?.("feedback-messages.measurement.disturb-detected-error");
136
124
  return;
137
125
  }
126
+ const timestamp = parsed.timestamp.getTime();
127
+ if (this.reportedTimestamps.has(timestamp)) {
128
+ return;
129
+ }
130
+ this.reportedTimestamps.add(timestamp);
138
131
  const reading = {
139
132
  caseType: CaseType.RESULT,
140
133
  measurementTypeKey: MeasurementTypeKey.uricAcid,
@@ -1 +1 @@
1
- {"version":3,"names":["MeasurementTypeKey","CaseType","hexToByte","BTManagedDevice","Bc01CommandSequencer","BC01_ANALYTE_ORDER","parseBc01Record","Bc01FrameReader","bc01MainServices","BC01_FRAME_MIN_LENGTH","BC01Device","onStreamStart","mainServices","frameReader","stuckDataTimeout","constructor","device","params","createCommandSequencer","write","serviceUuid","uuid","characteristicUuid","writeUuid","onRefused","reason","onError","Error","clockSync","now","validatePackage","pkg","length","opcode","minLength","undefined","handleDependentResult","data","frame","reportUrsRecord","parsingCase","caseType","OTHER","handleSuccessResult","parsed","measuredValues","reduce","acc","analyte","value","values","Object","keys","reading","RESULT","measurementTypeKey","uricAcid","urineValues","recordedAt","timestamp","onResult"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01.device.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["MeasurementTypeKey","CaseType","hexToByte","BTManagedDevice","Bc01CommandSequencer","BC01_ANALYTE_ORDER","parseBc01Record","Bc01FrameReader","bc01FrameLengths","bc01MainServices","BC01Device","onStreamStart","reportedTimestamps","clear","Set","mainServices","frameReader","stuckDataTimeout","constructor","device","params","createCommandSequencer","write","serviceUuid","uuid","characteristicUuid","writeUuid","onError","reason","Error","clockSync","clearDeviceHistory","now","validatePackage","pkg","length","opcode","minLength","toString","padStart","undefined","handleDependentResult","data","frame","reportUrsRecord","parsingCase","caseType","OTHER","handleSuccessResult","parsed","measuredValues","reduce","acc","analyte","value","values","Object","keys","timestamp","getTime","has","add","reading","RESULT","measurementTypeKey","uricAcid","urineValues","recordedAt","onResult"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01.device.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAiC,YAAY;AAGxE,SAASC,QAAQ,QAAQ,6BAA0B;AAQnD,SAASC,SAAS,QAAQ,+BAA4B;AACtD,SAASC,eAAe,QAAQ,yBAAsB;AAEtD,SAASC,oBAAoB,QAAQ,6BAA0B;AAC/D,SAASC,kBAAkB,EAAEC,eAAe,QAAQ,wBAAqB;AACzE,SAASC,eAAe,EAAEC,gBAAgB,QAAQ,wBAAqB;AACvE,SAASC,gBAAgB,QAAQ,yBAAsB;;AAEvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,SAASP,eAAe,CAAyB;EAC5DQ,aAAa,GAAeA,CAAA,KAAM;IAC1C,IAAI,CAACC,kBAAkB,CAACC,KAAK,CAAC,CAAC;EACjC,CAAC;EAEgBD,kBAAkB,GAAG,IAAIE,GAAG,CAAS,CAAC;EAE7CC,YAAY,GAAeN,gBAAgB;EAC3CO,WAAW,GAAoB,IAAIT,eAAe,CAAC,CAAC;;EAE9D;AACF;AACA;AACA;AACA;AACA;EACYU,gBAAgB,GAAG,MAAM;EAEnCC,WAAWA,CAACC,MAAc,EAAEC,MAAkD,EAAE;IAC9E,KAAK,CAACD,MAAM,EAAEC,MAAM,CAAC;;IAErB;AACJ;AACA;AACA;AACA;AACA;AACA;IACI,IAAI,CAACC,sBAAsB,GAAG,MAAwB;MACpD,IAAI,CAACT,kBAAkB,CAACC,KAAK,CAAC,CAAC;MAE/B,OAAO,IAAIT,oBAAoB,CAC7B;QACEkB,KAAK,EAAE;UACLC,WAAW,EAAEd,gBAAgB,CAAC,CAAC,CAAC,CAAEe,IAAI;UACtCC,kBAAkB,EAAEhB,gBAAgB,CAAC,CAAC,CAAC,CAAEiB,SAAS,CAAEF;QACtD,CAAC;QACDG,OAAO,EAAGC,MAAM,IAAK,IAAI,CAACD,OAAO,GAAG,IAAIE,KAAK,CAAC,UAAUD,MAAM,EAAE,CAAC,CAAC;QAClEE,SAAS,EAAEV,MAAM,CAACU,SAAS;QAC3BC,kBAAkB,EAAEX,MAAM,CAACW;MAC7B,CAAC,EACDX,MAAM,CAACU,SAAS,EAAEE,GACpB,CAAC;IACH,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;EACYC,eAAe,GAAgCC,GAAG,IAAK;IAC/D,IAAIA,GAAG,CAACC,MAAM,KAAK,CAAC,EAAE;MACpB,OAAO,KAAK;IACd;IAEA,MAAMC,MAAM,GAAGlC,SAAS,CAACgC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,MAAMG,SAAS,GAAG7B,gBAAgB,CAAC4B,MAAM,CAACE,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAExE,IAAIF,SAAS,KAAKG,SAAS,EAAE;MAC3B,OAAO,KAAK;IACd;IAEA,OAAON,GAAG,CAACC,MAAM,IAAIE,SAAS;EAChC,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACYI,qBAAqB,GAC7BC,IAEC,IAGE;IACH,IAAIA,IAAI,CAACC,KAAK,EAAE;MACd,IAAI,CAACC,eAAe,CAACF,IAAI,CAACC,KAAK,CAAC;IAClC;IAEA,OAAO;MACL,GAAGD,IAAI;MACPG,WAAW,EAAE;QAAE,GAAGH,IAAI,CAACG,WAAW;QAAEC,QAAQ,EAAE7C,QAAQ,CAAC8C;MAAM;IAC/D,CAAC;EACH,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACYC,mBAAmBA,CAAA,EAAmB;IAC9C;EACF;EAEQJ,eAAeA,CAACD,KAAwB,EAAQ;IACtD,MAAMM,MAAM,GAAG3C,eAAe,CAACqC,KAAK,CAAC;IAErC,IAAI,CAACM,MAAM,EAAE;MACX;IACF;IAEA,MAAMC,cAAc,GAAG7C,kBAAkB,CAAC8C,MAAM,CAE9C,CAACC,GAAG,EAAEC,OAAO,KAAK;MAClB,MAAMC,KAAK,GAAGL,MAAM,CAACM,MAAM,CAACF,OAAO,CAAC;MAEpC,IAAIC,KAAK,KAAKd,SAAS,EAAE;QACvBY,GAAG,CAACC,OAAO,CAAC,GAAGC,KAAK;MACtB;MAEA,OAAOF,GAAG;IACZ,CAAC,EAAE,CAAC,CAAC,CAAC;IAEN,IAAII,MAAM,CAACC,IAAI,CAACP,cAAc,CAAC,CAACf,MAAM,KAAK,CAAC,EAAE;MAC5C,IAAI,CAACR,OAAO,GAAG,sDAAsD,CAAC;MAEtE;IACF;IAEA,MAAM+B,SAAS,GAAGT,MAAM,CAACS,SAAS,CAACC,OAAO,CAAC,CAAC;IAE5C,IAAI,IAAI,CAAC/C,kBAAkB,CAACgD,GAAG,CAACF,SAAS,CAAC,EAAE;MAC1C;IACF;IAEA,IAAI,CAAC9C,kBAAkB,CAACiD,GAAG,CAACH,SAAS,CAAC;IAEtC,MAAMI,OAAO,GAAG;MACdhB,QAAQ,EAAE7C,QAAQ,CAAC8D,MAAM;MACzBC,kBAAkB,EAAEhE,kBAAkB,CAACiE,QAAQ;MAC/CC,WAAW,EAAE,EAAE;MACfC,UAAU,EAAElB,MAAM,CAACS,SAAS;MAC5B,GAAGR;IACL,CAEC;IAED,IAAI,CAACkB,QAAQ,GAAGN,OAAO,CAAC;EAC1B;AACF","ignoreList":[]}
@@ -6,7 +6,7 @@ import { CaseType } from "../../../types/case-type.js";
6
6
  * Contec BC401 (a.k.a. BC01) urine analyzer — GATT profile.
7
7
  *
8
8
  * The BC401 uses Contec's proprietary FF12 service, shared across their
9
- * consumer medical devices. Every stored URS-7 measurement is pushed as a
9
+ * consumer medical devices. Every stored urine-strip measurement is pushed as a
10
10
  * 16-byte record on 0xFF02 after the host has walked the handshake documented
11
11
  * in `bc01-command-sequencer.ts`.
12
12
  *
@@ -22,10 +22,11 @@ declare const RECORD_FLAGS_INDEX = 1;
22
22
  declare const RECORD_LAST_OF_SET_BIT = 64;
23
23
  declare const asHex: (byte: number) => string;
24
24
  declare const bc401Checksum: (bytes: readonly number[]) => number;
25
+ declare const bc401ChecksumMatches: (bytes: readonly number[]) => boolean;
25
26
  declare const buildCommand: (opcode: number, arg: number) => number[];
26
27
  declare const buildResetCommand: () => number[];
27
28
  declare const buildRequestVersionCommand: () => number[];
28
29
  declare const buildSetTimeCommand: (now: Date, timezone?: "local" | "utc") => number[];
29
30
  declare const buildDeleteCommand: () => number[];
30
- export { ACK_LAST_OF_SET, asHex, bc401Checksum, buildCommand, buildDeleteCommand, buildRequestVersionCommand, buildResetCommand, buildSetTimeCommand, FINAL_RECORD_DELAY_MS, OP_REQUEST_COUNT, OP_REQUEST_QUANTITATIVE_RECORDS, OP_REQUEST_RECORDS, RECORD_FLAGS_INDEX, RECORD_LAST_OF_SET_BIT, REQUEST_ALL, REQUEST_NEXT_RECORD_GROUP, RESET_DELAY_MS, RETRY_RECORD_GROUP, RX, };
31
+ export { ACK_LAST_OF_SET, asHex, bc401Checksum, bc401ChecksumMatches, buildCommand, buildDeleteCommand, buildRequestVersionCommand, buildResetCommand, buildSetTimeCommand, FINAL_RECORD_DELAY_MS, OP_REQUEST_COUNT, OP_REQUEST_QUANTITATIVE_RECORDS, OP_REQUEST_RECORDS, RECORD_FLAGS_INDEX, RECORD_LAST_OF_SET_BIT, REQUEST_ALL, REQUEST_NEXT_RECORD_GROUP, RESET_DELAY_MS, RETRY_RECORD_GROUP, RX, };
31
32
  //# sourceMappingURL=bc01-command-builders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bc01-command-builders.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-builders.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,gBAAgB,MAAO,CAAC;AAC9B,QAAA,MAAM,kBAAkB,MAAO,CAAC;AAChC,QAAA,MAAM,+BAA+B,MAAO,CAAC;AAE7C,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,WAAW,IAAO,CAAC;AACzB,QAAA,MAAM,yBAAyB,IAAO,CAAC;AACvC,QAAA,MAAM,kBAAkB,IAAO,CAAC;AAChC,QAAA,MAAM,qBAAqB,MAAM,CAAC;AAClC,QAAA,MAAM,cAAc,MAAM,CAAC;AAE3B,QAAA,MAAM,EAAE;;;;;;;;;;CAUE,CAAC;AAEX,QAAA,MAAM,kBAAkB,IAAI,CAAC;AAC7B,QAAA,MAAM,sBAAsB,KAAO,CAAC;AAEpC,QAAA,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MACe,CAAC;AAE9C,QAAA,MAAM,aAAa,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,MACU,CAAC;AAE7D,QAAA,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,EAIzD,CAAC;AAEF,QAAA,MAAM,iBAAiB,QAAO,MAAM,EAAsB,CAAC;AAE3D,QAAA,MAAM,0BAA0B,QAAO,MAAM,EAG5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,GACvB,KAAK,IAAI,EACT,WAAU,OAAO,GAAG,KAAe,KAClC,MAAM,EAmCR,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAO,MAAM,EAAkB,CAAC;AAExD,OAAO,EACL,eAAe,EACf,KAAK,EACL,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,WAAW,EACX,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,EAAE,GACH,CAAC"}
1
+ {"version":3,"file":"bc01-command-builders.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-builders.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,gBAAgB,MAAO,CAAC;AAC9B,QAAA,MAAM,kBAAkB,MAAO,CAAC;AAChC,QAAA,MAAM,+BAA+B,MAAO,CAAC;AAE7C,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,WAAW,IAAO,CAAC;AACzB,QAAA,MAAM,yBAAyB,IAAO,CAAC;AACvC,QAAA,MAAM,kBAAkB,IAAO,CAAC;AAChC,QAAA,MAAM,qBAAqB,MAAM,CAAC;AAClC,QAAA,MAAM,cAAc,MAAM,CAAC;AAE3B,QAAA,MAAM,EAAE;;;;;;;;;;CAUE,CAAC;AAEX,QAAA,MAAM,kBAAkB,IAAI,CAAC;AAC7B,QAAA,MAAM,sBAAsB,KAAO,CAAC;AAEpC,QAAA,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MACe,CAAC;AAE9C,QAAA,MAAM,aAAa,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,MACU,CAAC;AAE7D,QAAA,MAAM,oBAAoB,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,OAEM,CAAC;AAEhE,QAAA,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,EAIzD,CAAC;AAEF,QAAA,MAAM,iBAAiB,QAAO,MAAM,EAAsB,CAAC;AAE3D,QAAA,MAAM,0BAA0B,QAAO,MAAM,EAG5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,GACvB,KAAK,IAAI,EACT,WAAU,OAAO,GAAG,KAAe,KAClC,MAAM,EAmCR,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAO,MAAM,EAAkB,CAAC;AAExD,OAAO,EACL,eAAe,EACf,KAAK,EACL,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,WAAW,EACX,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,EAAE,GACH,CAAC"}
@@ -4,13 +4,9 @@ import { DeviceCommand } from "../../../types/device-command";
4
4
  interface Bc01SequencerParams {
5
5
  /** The write channel every command goes out on. FF01 for a real BC401. */
6
6
  write: Omit<DeviceCommand, "frame">;
7
- /**
8
- * Called with why the exchange stopped. Optional; a refusal here does not
9
- * end the connection because the device continues to accept fresh commands
10
- * even after a bad handshake step. The parent driver decides what to do.
11
- */
12
- onRefused?: (reason: string) => void;
7
+ onError?: (reason: string) => void;
13
8
  clockSync?: ClockSyncOptions;
9
+ clearDeviceHistory?: boolean;
14
10
  }
15
11
  /**
16
12
  * Walks the BC401 through its post-reset handshake and pulls every stored
@@ -35,6 +31,7 @@ export declare class Bc01CommandSequencer implements CommandSequencer {
35
31
  private standardPage;
36
32
  /** Five quantitative pages per request group; 5 means a new group. */
37
33
  private quantitativePage;
34
+ private sawQuantitativeRecord;
38
35
  /** Injectable for tests; production reads `Date.now()`. */
39
36
  private readonly clock;
40
37
  constructor(params: Bc01SequencerParams, clock?: () => Date);
@@ -1 +1 @@
1
- {"version":3,"file":"bc01-command-sequencer.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAyB9D,UAAU,mBAAmB;IAE3B,0EAA0E;IAC1E,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEpC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AAEH,qBAAa,oBAAqB,YAAW,gBAAgB;IAazD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAZzB,OAAO,CAAC,MAAM,CAAS;IAEvB,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAAM;IAE1B,sEAAsE;IACtE,OAAO,CAAC,gBAAgB,CAAK;IAE7B,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAGhB,MAAM,EAAE,mBAAmB,EAC5C,KAAK,CAAC,EAAE,MAAM,IAAI;IAKb,eAAe,QAAO,SAAS,aAAa,EAAE,CAEnD;IAEK,WAAW,GAChB,OAAO,SAAS,MAAM,EAAE,KACvB,SAAS,aAAa,EAAE,GAAG,SAAS,CAiDrC;IAEF,OAAO,CAAC,kBAAkB,CA8CxB;IAEF,OAAO,CAAC,wBAAwB,CAiD9B;IAEF,OAAO,CAAC,mBAAmB,CAOzB;IAEF,OAAO,CAAC,UAAU,CAOf;CACJ;AAGD,eAAO,MAAM,6BAA6B;;;;;;CAMzC,CAAC"}
1
+ {"version":3,"file":"bc01-command-sequencer.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AA0B9D,UAAU,mBAAmB;IAE3B,0EAA0E;IAC1E,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AAEH,qBAAa,oBAAqB,YAAW,gBAAgB;IAezD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdzB,OAAO,CAAC,MAAM,CAAS;IAEvB,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAAM;IAE1B,sEAAsE;IACtE,OAAO,CAAC,gBAAgB,CAAK;IAE7B,OAAO,CAAC,qBAAqB,CAAS;IAEtC,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAGhB,MAAM,EAAE,mBAAmB,EAC5C,KAAK,CAAC,EAAE,MAAM,IAAI;IAKb,eAAe,QAAO,SAAS,aAAa,EAAE,CAEnD;IAEK,WAAW,GAChB,OAAO,SAAS,MAAM,EAAE,KACvB,SAAS,aAAa,EAAE,GAAG,SAAS,CA+FrC;IAEF,OAAO,CAAC,kBAAkB,CA8CxB;IAEF,OAAO,CAAC,wBAAwB,CAmD9B;IAEF,OAAO,CAAC,mBAAmB,CASzB;IAEF,OAAO,CAAC,UAAU,CAOf;CACJ;AAGD,eAAO,MAAM,6BAA6B;;;;;;CAMzC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /** BC401 stored-record frame is always sixteen bytes: header, timestamp, analytes, checksum. */
2
2
  declare const BC01_RECORD_LENGTH = 16;
3
- /** The two opcodes the firmware uses for a stored URS-7 record. */
3
+ /** The two opcodes the firmware uses for a stored BC401 strip record. */
4
4
  declare const BC01_URS_OPCODE = 225;
5
5
  declare const BC01_PAGED_URS_OPCODE = 226;
6
6
  /**
@@ -9,17 +9,15 @@ declare const BC01_PAGED_URS_OPCODE = 226;
9
9
  */
10
10
  declare const BC01_LAST_OF_SET_BIT = 64;
11
11
  /**
12
- * URS-7 pad names, in the exact order they occupy the packed 3-bit slots
13
- * across bytes 8..14 (see M1/a.java). The eleventh slot is a Contec-firmware
14
- * field the vendor's own catalog calls "vc" and no other name is documented.
12
+ * Pad names, in the exact order they occupy the packed 3-bit slots across
13
+ * bytes 8..14 (see PHMS M1/a.java), covering both 11- and 14-pad strips.
15
14
  */
16
- declare const BC01_ANALYTE_ORDER: readonly ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc"];
15
+ declare const BC01_ANALYTE_ORDER: readonly ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc", "mal", "cr", "uca"];
17
16
  type Bc01Analyte = (typeof BC01_ANALYTE_ORDER)[number];
18
17
  /**
19
18
  * BC401's packed values are colour-chart indexes, not measurements. These
20
19
  * values mirror the tables in Contec's BC401 integration (PHMS M1/a.java):
21
20
  * the index is zero-based and `7` remains the device's unmeasured sentinel.
22
- * The pH table is the URS-7 strip scale, which includes half-point readings.
23
21
  */
24
22
  declare const BC01_ANALYTE_VALUES: Record<Bc01Analyte, readonly number[]>;
25
23
  /** The result of decoding one 16-byte record. `lastOfSet` is what the sequencer keys on. */
@@ -44,17 +42,9 @@ interface Bc01ParsedRecord {
44
42
  * frame is a record or a heartbeat, and a frame that fails these checks is
45
43
  * skipped rather than parsed into a plausible-looking wrong reading.
46
44
  *
47
- * The checksum byte is not verified here: the SDK's read path already ensures
48
- * frame integrity before the parser sees the bytes, and a URS-7 pad value can
49
- * only land in [0, 7] anyway — a corrupt payload would fail the pad-value
50
- * check before it made it into a measurement.
45
+ * The checksum byte is verified before any value is exposed; individual
46
+ * packed indexes could otherwise decode into plausible but incorrect results.
51
47
  */
52
48
  declare const parseBc01Record: (frame: readonly string[]) => Bc01ParsedRecord | undefined;
53
- /**
54
- * True when the buffer holds a complete BC401 stored record. Used by the
55
- * driver's `validatePackage` hook so the SDK's read path only advances once
56
- * the notification carries a whole 16-byte frame.
57
- */
58
- declare const isBc01Record: (frame: readonly string[]) => boolean;
59
- export { BC01_ANALYTE_ORDER, BC01_ANALYTE_VALUES, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, Bc01ParsedRecord, isBc01Record, parseBc01Record, };
49
+ export { BC01_ANALYTE_ORDER, BC01_ANALYTE_VALUES, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, Bc01ParsedRecord, parseBc01Record, };
60
50
  //# sourceMappingURL=bc01-frame-parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bc01-frame-parser.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"names":[],"mappings":"AAIA,gGAAgG;AAChG,QAAA,MAAM,kBAAkB,KAAK,CAAC;AAE9B,mEAAmE;AACnE,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,qBAAqB,MAAO,CAAC;AAEnC;;;GAGG;AACH,QAAA,MAAM,oBAAoB,KAAO,CAAC;AAelC;;;;GAIG;AACH,QAAA,MAAM,kBAAkB,qFAYuC,CAAC;AAEhE,KAAK,WAAW,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAY/D,CAAC;AAKF,4FAA4F;AAC5F,UAAU,gBAAgB;IAExB,yFAAyF;IACzF,SAAS,EAAE,IAAI,CAAC;IAEhB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;IAEnB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACtE;AAUD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,eAAe,GACnB,OAAO,SAAS,MAAM,EAAE,KACvB,gBAAgB,GAAG,SA8CrB,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,YAAY,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,OAQhD,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,GAChB,CAAC"}
1
+ {"version":3,"file":"bc01-frame-parser.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"names":[],"mappings":"AAMA,gGAAgG;AAChG,QAAA,MAAM,kBAAkB,KAAK,CAAC;AAE9B,yEAAyE;AACzE,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,qBAAqB,MAAO,CAAC;AAEnC;;;GAGG;AACH,QAAA,MAAM,oBAAoB,KAAO,CAAC;AAelC;;;GAGG;AACH,QAAA,MAAM,kBAAkB,yGAeuC,CAAC;AAEhE,KAAK,WAAW,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAe/D,CAAC;AAKF,4FAA4F;AAC5F,UAAU,gBAAgB;IAExB,yFAAyF;IACzF,SAAS,EAAE,IAAI,CAAC;IAEhB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;IAEnB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACtE;AAUD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,eAAe,GACnB,OAAO,SAAS,MAAM,EAAE,KACvB,gBAAgB,GAAG,SAkDrB,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,CAAC"}
@@ -18,10 +18,11 @@ import { Bc01FrameReader } from "./bc01.frame-reader";
18
18
  */
19
19
  export declare class BC01Device extends BTManagedDevice<IntegratedDevices.BC01> {
20
20
  protected onStreamStart: () => void;
21
+ private readonly reportedTimestamps;
21
22
  protected mainServices: IService[];
22
23
  protected frameReader: Bc01FrameReader;
23
24
  /**
24
- * 90 s covers the maximum firmware-side reagent-pad settle time on a URS-7
25
+ * 90 s covers the maximum firmware-side reagent-pad settle time on a
25
26
  * strip and leaves headroom for a bulk memory dump of every stored record.
26
27
  * If the device does not push a frame within that window the data processor
27
28
  * times out and the driver surfaces "device unreachable".
@@ -47,7 +48,9 @@ export declare class BC01Device extends BTManagedDevice<IntegratedDevices.BC01>
47
48
  /**
48
49
  * Nothing to do here for the BC401. Every reading arrives through the
49
50
  * dependent-result path, and the state machine sees only the `OTHER`-typed
50
- * echo we return from `handleDependentResult`.
51
+ * echo we return from `handleDependentResult`. Records are deduplicated by
52
+ * their second-resolution device timestamp for this transfer because a
53
+ * paged-group retry resends the earlier frames.
51
54
  */
52
55
  protected handleSuccessResult(): void | boolean;
53
56
  private reportUrsRecord;
@@ -1 +1 @@
1
- {"version":3,"file":"bc01.device.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01.device.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAgBtD;;;;;;;;;GASG;AACH,qBAAa,UAAW,SAAQ,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrE,SAAS,CAAC,aAAa,EAAE,MAAM,IAAI,CAAY;IAE/C,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAoB;IACtD,SAAS,CAAC,WAAW,EAAE,eAAe,CAAyB;IAE/D;;;;;OAKG;IACH,SAAS,CAAC,gBAAgB,SAAU;gBAExB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,IAAI,CAAC;IAyB9E;;;;;OAKG;IACH,SAAS,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAanD;IAEF;;;;;;;OAOG;IACH,SAAS,CAAC,qBAAqB,GAC7B,MAAM,4BAA4B,CAChC,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,KACA,4BAA4B,CAC7B,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,CASC;IAEF;;;;OAIG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI,GAAG,OAAO;IAI/C,OAAO,CAAC,eAAe;CAqCxB"}
1
+ {"version":3,"file":"bc01.device.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01.device.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAoB,MAAM,qBAAqB,CAAC;AAGxE;;;;;;;;;GASG;AACH,qBAAa,UAAW,SAAQ,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrE,SAAS,CAAC,aAAa,EAAE,MAAM,IAAI,CAEjC;IAEF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IAExD,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAoB;IACtD,SAAS,CAAC,WAAW,EAAE,eAAe,CAAyB;IAE/D;;;;;OAKG;IACH,SAAS,CAAC,gBAAgB,SAAU;gBAExB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,IAAI,CAAC;IA4B9E;;;;;OAKG;IACH,SAAS,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAanD;IAEF;;;;;;;OAOG;IACH,SAAS,CAAC,qBAAqB,GAC7B,MAAM,4BAA4B,CAChC,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,KACA,4BAA4B,CAC7B,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,CASC;IAEF;;;;;;OAMG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI,GAAG,OAAO;IAI/C,OAAO,CAAC,eAAe;CA6CxB"}
@@ -3,7 +3,7 @@ import { IService } from "../../../types/service.type";
3
3
  * Contec BC401 (a.k.a. BC01) urine analyzer — GATT profile.
4
4
  *
5
5
  * The BC401 uses Contec's proprietary FF12 service, shared across their
6
- * consumer medical devices. Every stored URS-7 measurement is pushed as a
6
+ * consumer medical devices. Every stored urine-strip measurement is pushed as a
7
7
  * 16-byte record on 0xFF02 after the host has walked the handshake documented
8
8
  * in `bc01-command-sequencer.ts`.
9
9
  *
@@ -22,10 +22,11 @@ declare const RECORD_FLAGS_INDEX = 1;
22
22
  declare const RECORD_LAST_OF_SET_BIT = 64;
23
23
  declare const asHex: (byte: number) => string;
24
24
  declare const bc401Checksum: (bytes: readonly number[]) => number;
25
+ declare const bc401ChecksumMatches: (bytes: readonly number[]) => boolean;
25
26
  declare const buildCommand: (opcode: number, arg: number) => number[];
26
27
  declare const buildResetCommand: () => number[];
27
28
  declare const buildRequestVersionCommand: () => number[];
28
29
  declare const buildSetTimeCommand: (now: Date, timezone?: "local" | "utc") => number[];
29
30
  declare const buildDeleteCommand: () => number[];
30
- export { ACK_LAST_OF_SET, asHex, bc401Checksum, buildCommand, buildDeleteCommand, buildRequestVersionCommand, buildResetCommand, buildSetTimeCommand, FINAL_RECORD_DELAY_MS, OP_REQUEST_COUNT, OP_REQUEST_QUANTITATIVE_RECORDS, OP_REQUEST_RECORDS, RECORD_FLAGS_INDEX, RECORD_LAST_OF_SET_BIT, REQUEST_ALL, REQUEST_NEXT_RECORD_GROUP, RESET_DELAY_MS, RETRY_RECORD_GROUP, RX, };
31
+ export { ACK_LAST_OF_SET, asHex, bc401Checksum, bc401ChecksumMatches, buildCommand, buildDeleteCommand, buildRequestVersionCommand, buildResetCommand, buildSetTimeCommand, FINAL_RECORD_DELAY_MS, OP_REQUEST_COUNT, OP_REQUEST_QUANTITATIVE_RECORDS, OP_REQUEST_RECORDS, RECORD_FLAGS_INDEX, RECORD_LAST_OF_SET_BIT, REQUEST_ALL, REQUEST_NEXT_RECORD_GROUP, RESET_DELAY_MS, RETRY_RECORD_GROUP, RX, };
31
32
  //# sourceMappingURL=bc01-command-builders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bc01-command-builders.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-builders.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,gBAAgB,MAAO,CAAC;AAC9B,QAAA,MAAM,kBAAkB,MAAO,CAAC;AAChC,QAAA,MAAM,+BAA+B,MAAO,CAAC;AAE7C,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,WAAW,IAAO,CAAC;AACzB,QAAA,MAAM,yBAAyB,IAAO,CAAC;AACvC,QAAA,MAAM,kBAAkB,IAAO,CAAC;AAChC,QAAA,MAAM,qBAAqB,MAAM,CAAC;AAClC,QAAA,MAAM,cAAc,MAAM,CAAC;AAE3B,QAAA,MAAM,EAAE;;;;;;;;;;CAUE,CAAC;AAEX,QAAA,MAAM,kBAAkB,IAAI,CAAC;AAC7B,QAAA,MAAM,sBAAsB,KAAO,CAAC;AAEpC,QAAA,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MACe,CAAC;AAE9C,QAAA,MAAM,aAAa,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,MACU,CAAC;AAE7D,QAAA,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,EAIzD,CAAC;AAEF,QAAA,MAAM,iBAAiB,QAAO,MAAM,EAAsB,CAAC;AAE3D,QAAA,MAAM,0BAA0B,QAAO,MAAM,EAG5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,GACvB,KAAK,IAAI,EACT,WAAU,OAAO,GAAG,KAAe,KAClC,MAAM,EAmCR,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAO,MAAM,EAAkB,CAAC;AAExD,OAAO,EACL,eAAe,EACf,KAAK,EACL,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,WAAW,EACX,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,EAAE,GACH,CAAC"}
1
+ {"version":3,"file":"bc01-command-builders.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-builders.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,gBAAgB,MAAO,CAAC;AAC9B,QAAA,MAAM,kBAAkB,MAAO,CAAC;AAChC,QAAA,MAAM,+BAA+B,MAAO,CAAC;AAE7C,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,WAAW,IAAO,CAAC;AACzB,QAAA,MAAM,yBAAyB,IAAO,CAAC;AACvC,QAAA,MAAM,kBAAkB,IAAO,CAAC;AAChC,QAAA,MAAM,qBAAqB,MAAM,CAAC;AAClC,QAAA,MAAM,cAAc,MAAM,CAAC;AAE3B,QAAA,MAAM,EAAE;;;;;;;;;;CAUE,CAAC;AAEX,QAAA,MAAM,kBAAkB,IAAI,CAAC;AAC7B,QAAA,MAAM,sBAAsB,KAAO,CAAC;AAEpC,QAAA,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MACe,CAAC;AAE9C,QAAA,MAAM,aAAa,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,MACU,CAAC;AAE7D,QAAA,MAAM,oBAAoB,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,OAEM,CAAC;AAEhE,QAAA,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,EAIzD,CAAC;AAEF,QAAA,MAAM,iBAAiB,QAAO,MAAM,EAAsB,CAAC;AAE3D,QAAA,MAAM,0BAA0B,QAAO,MAAM,EAG5C,CAAC;AAEF,QAAA,MAAM,mBAAmB,GACvB,KAAK,IAAI,EACT,WAAU,OAAO,GAAG,KAAe,KAClC,MAAM,EAmCR,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAO,MAAM,EAAkB,CAAC;AAExD,OAAO,EACL,eAAe,EACf,KAAK,EACL,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,WAAW,EACX,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,EAAE,GACH,CAAC"}
@@ -4,13 +4,9 @@ import { DeviceCommand } from "../../../types/device-command";
4
4
  interface Bc01SequencerParams {
5
5
  /** The write channel every command goes out on. FF01 for a real BC401. */
6
6
  write: Omit<DeviceCommand, "frame">;
7
- /**
8
- * Called with why the exchange stopped. Optional; a refusal here does not
9
- * end the connection because the device continues to accept fresh commands
10
- * even after a bad handshake step. The parent driver decides what to do.
11
- */
12
- onRefused?: (reason: string) => void;
7
+ onError?: (reason: string) => void;
13
8
  clockSync?: ClockSyncOptions;
9
+ clearDeviceHistory?: boolean;
14
10
  }
15
11
  /**
16
12
  * Walks the BC401 through its post-reset handshake and pulls every stored
@@ -35,6 +31,7 @@ export declare class Bc01CommandSequencer implements CommandSequencer {
35
31
  private standardPage;
36
32
  /** Five quantitative pages per request group; 5 means a new group. */
37
33
  private quantitativePage;
34
+ private sawQuantitativeRecord;
38
35
  /** Injectable for tests; production reads `Date.now()`. */
39
36
  private readonly clock;
40
37
  constructor(params: Bc01SequencerParams, clock?: () => Date);
@@ -1 +1 @@
1
- {"version":3,"file":"bc01-command-sequencer.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAyB9D,UAAU,mBAAmB;IAE3B,0EAA0E;IAC1E,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEpC;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AAEH,qBAAa,oBAAqB,YAAW,gBAAgB;IAazD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAZzB,OAAO,CAAC,MAAM,CAAS;IAEvB,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAAM;IAE1B,sEAAsE;IACtE,OAAO,CAAC,gBAAgB,CAAK;IAE7B,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAGhB,MAAM,EAAE,mBAAmB,EAC5C,KAAK,CAAC,EAAE,MAAM,IAAI;IAKb,eAAe,QAAO,SAAS,aAAa,EAAE,CAEnD;IAEK,WAAW,GAChB,OAAO,SAAS,MAAM,EAAE,KACvB,SAAS,aAAa,EAAE,GAAG,SAAS,CAiDrC;IAEF,OAAO,CAAC,kBAAkB,CA8CxB;IAEF,OAAO,CAAC,wBAAwB,CAiD9B;IAEF,OAAO,CAAC,mBAAmB,CAOzB;IAEF,OAAO,CAAC,UAAU,CAOf;CACJ;AAGD,eAAO,MAAM,6BAA6B;;;;;;CAMzC,CAAC"}
1
+ {"version":3,"file":"bc01-command-sequencer.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AA0B9D,UAAU,mBAAmB;IAE3B,0EAA0E;IAC1E,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AAEH,qBAAa,oBAAqB,YAAW,gBAAgB;IAezD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdzB,OAAO,CAAC,MAAM,CAAS;IAEvB,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAAM;IAE1B,sEAAsE;IACtE,OAAO,CAAC,gBAAgB,CAAK;IAE7B,OAAO,CAAC,qBAAqB,CAAS;IAEtC,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAGhB,MAAM,EAAE,mBAAmB,EAC5C,KAAK,CAAC,EAAE,MAAM,IAAI;IAKb,eAAe,QAAO,SAAS,aAAa,EAAE,CAEnD;IAEK,WAAW,GAChB,OAAO,SAAS,MAAM,EAAE,KACvB,SAAS,aAAa,EAAE,GAAG,SAAS,CA+FrC;IAEF,OAAO,CAAC,kBAAkB,CA8CxB;IAEF,OAAO,CAAC,wBAAwB,CAmD9B;IAEF,OAAO,CAAC,mBAAmB,CASzB;IAEF,OAAO,CAAC,UAAU,CAOf;CACJ;AAGD,eAAO,MAAM,6BAA6B;;;;;;CAMzC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /** BC401 stored-record frame is always sixteen bytes: header, timestamp, analytes, checksum. */
2
2
  declare const BC01_RECORD_LENGTH = 16;
3
- /** The two opcodes the firmware uses for a stored URS-7 record. */
3
+ /** The two opcodes the firmware uses for a stored BC401 strip record. */
4
4
  declare const BC01_URS_OPCODE = 225;
5
5
  declare const BC01_PAGED_URS_OPCODE = 226;
6
6
  /**
@@ -9,17 +9,15 @@ declare const BC01_PAGED_URS_OPCODE = 226;
9
9
  */
10
10
  declare const BC01_LAST_OF_SET_BIT = 64;
11
11
  /**
12
- * URS-7 pad names, in the exact order they occupy the packed 3-bit slots
13
- * across bytes 8..14 (see M1/a.java). The eleventh slot is a Contec-firmware
14
- * field the vendor's own catalog calls "vc" and no other name is documented.
12
+ * Pad names, in the exact order they occupy the packed 3-bit slots across
13
+ * bytes 8..14 (see PHMS M1/a.java), covering both 11- and 14-pad strips.
15
14
  */
16
- declare const BC01_ANALYTE_ORDER: readonly ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc"];
15
+ declare const BC01_ANALYTE_ORDER: readonly ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc", "mal", "cr", "uca"];
17
16
  type Bc01Analyte = (typeof BC01_ANALYTE_ORDER)[number];
18
17
  /**
19
18
  * BC401's packed values are colour-chart indexes, not measurements. These
20
19
  * values mirror the tables in Contec's BC401 integration (PHMS M1/a.java):
21
20
  * the index is zero-based and `7` remains the device's unmeasured sentinel.
22
- * The pH table is the URS-7 strip scale, which includes half-point readings.
23
21
  */
24
22
  declare const BC01_ANALYTE_VALUES: Record<Bc01Analyte, readonly number[]>;
25
23
  /** The result of decoding one 16-byte record. `lastOfSet` is what the sequencer keys on. */
@@ -44,17 +42,9 @@ interface Bc01ParsedRecord {
44
42
  * frame is a record or a heartbeat, and a frame that fails these checks is
45
43
  * skipped rather than parsed into a plausible-looking wrong reading.
46
44
  *
47
- * The checksum byte is not verified here: the SDK's read path already ensures
48
- * frame integrity before the parser sees the bytes, and a URS-7 pad value can
49
- * only land in [0, 7] anyway — a corrupt payload would fail the pad-value
50
- * check before it made it into a measurement.
45
+ * The checksum byte is verified before any value is exposed; individual
46
+ * packed indexes could otherwise decode into plausible but incorrect results.
51
47
  */
52
48
  declare const parseBc01Record: (frame: readonly string[]) => Bc01ParsedRecord | undefined;
53
- /**
54
- * True when the buffer holds a complete BC401 stored record. Used by the
55
- * driver's `validatePackage` hook so the SDK's read path only advances once
56
- * the notification carries a whole 16-byte frame.
57
- */
58
- declare const isBc01Record: (frame: readonly string[]) => boolean;
59
- export { BC01_ANALYTE_ORDER, BC01_ANALYTE_VALUES, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, Bc01ParsedRecord, isBc01Record, parseBc01Record, };
49
+ export { BC01_ANALYTE_ORDER, BC01_ANALYTE_VALUES, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, Bc01ParsedRecord, parseBc01Record, };
60
50
  //# sourceMappingURL=bc01-frame-parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bc01-frame-parser.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"names":[],"mappings":"AAIA,gGAAgG;AAChG,QAAA,MAAM,kBAAkB,KAAK,CAAC;AAE9B,mEAAmE;AACnE,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,qBAAqB,MAAO,CAAC;AAEnC;;;GAGG;AACH,QAAA,MAAM,oBAAoB,KAAO,CAAC;AAelC;;;;GAIG;AACH,QAAA,MAAM,kBAAkB,qFAYuC,CAAC;AAEhE,KAAK,WAAW,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAY/D,CAAC;AAKF,4FAA4F;AAC5F,UAAU,gBAAgB;IAExB,yFAAyF;IACzF,SAAS,EAAE,IAAI,CAAC;IAEhB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;IAEnB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACtE;AAUD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,eAAe,GACnB,OAAO,SAAS,MAAM,EAAE,KACvB,gBAAgB,GAAG,SA8CrB,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,YAAY,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,OAQhD,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,GAChB,CAAC"}
1
+ {"version":3,"file":"bc01-frame-parser.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"names":[],"mappings":"AAMA,gGAAgG;AAChG,QAAA,MAAM,kBAAkB,KAAK,CAAC;AAE9B,yEAAyE;AACzE,QAAA,MAAM,eAAe,MAAO,CAAC;AAC7B,QAAA,MAAM,qBAAqB,MAAO,CAAC;AAEnC;;;GAGG;AACH,QAAA,MAAM,oBAAoB,KAAO,CAAC;AAelC;;;GAGG;AACH,QAAA,MAAM,kBAAkB,yGAeuC,CAAC;AAEhE,KAAK,WAAW,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAe/D,CAAC;AAKF,4FAA4F;AAC5F,UAAU,gBAAgB;IAExB,yFAAyF;IACzF,SAAS,EAAE,IAAI,CAAC;IAEhB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;IAEnB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACtE;AAUD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,eAAe,GACnB,OAAO,SAAS,MAAM,EAAE,KACvB,gBAAgB,GAAG,SAkDrB,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,CAAC"}
@@ -18,10 +18,11 @@ import { Bc01FrameReader } from "./bc01.frame-reader";
18
18
  */
19
19
  export declare class BC01Device extends BTManagedDevice<IntegratedDevices.BC01> {
20
20
  protected onStreamStart: () => void;
21
+ private readonly reportedTimestamps;
21
22
  protected mainServices: IService[];
22
23
  protected frameReader: Bc01FrameReader;
23
24
  /**
24
- * 90 s covers the maximum firmware-side reagent-pad settle time on a URS-7
25
+ * 90 s covers the maximum firmware-side reagent-pad settle time on a
25
26
  * strip and leaves headroom for a bulk memory dump of every stored record.
26
27
  * If the device does not push a frame within that window the data processor
27
28
  * times out and the driver surfaces "device unreachable".
@@ -47,7 +48,9 @@ export declare class BC01Device extends BTManagedDevice<IntegratedDevices.BC01>
47
48
  /**
48
49
  * Nothing to do here for the BC401. Every reading arrives through the
49
50
  * dependent-result path, and the state machine sees only the `OTHER`-typed
50
- * echo we return from `handleDependentResult`.
51
+ * echo we return from `handleDependentResult`. Records are deduplicated by
52
+ * their second-resolution device timestamp for this transfer because a
53
+ * paged-group retry resends the earlier frames.
51
54
  */
52
55
  protected handleSuccessResult(): void | boolean;
53
56
  private reportUrsRecord;
@@ -1 +1 @@
1
- {"version":3,"file":"bc01.device.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01.device.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAgBtD;;;;;;;;;GASG;AACH,qBAAa,UAAW,SAAQ,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrE,SAAS,CAAC,aAAa,EAAE,MAAM,IAAI,CAAY;IAE/C,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAoB;IACtD,SAAS,CAAC,WAAW,EAAE,eAAe,CAAyB;IAE/D;;;;;OAKG;IACH,SAAS,CAAC,gBAAgB,SAAU;gBAExB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,IAAI,CAAC;IAyB9E;;;;;OAKG;IACH,SAAS,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAanD;IAEF;;;;;;;OAOG;IACH,SAAS,CAAC,qBAAqB,GAC7B,MAAM,4BAA4B,CAChC,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,KACA,4BAA4B,CAC7B,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,CASC;IAEF;;;;OAIG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI,GAAG,OAAO;IAI/C,OAAO,CAAC,eAAe;CAqCxB"}
1
+ {"version":3,"file":"bc01.device.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01.device.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAoB,MAAM,qBAAqB,CAAC;AAGxE;;;;;;;;;GASG;AACH,qBAAa,UAAW,SAAQ,eAAe,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrE,SAAS,CAAC,aAAa,EAAE,MAAM,IAAI,CAEjC;IAEF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IAExD,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAoB;IACtD,SAAS,CAAC,WAAW,EAAE,eAAe,CAAyB;IAE/D;;;;;OAKG;IACH,SAAS,CAAC,gBAAgB,SAAU;gBAExB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,IAAI,CAAC;IA4B9E;;;;;OAKG;IACH,SAAS,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAanD;IAEF;;;;;;;OAOG;IACH,SAAS,CAAC,qBAAqB,GAC7B,MAAM,4BAA4B,CAChC,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,KACA,4BAA4B,CAC7B,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CACpD,CASC;IAEF;;;;;;OAMG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI,GAAG,OAAO;IAI/C,OAAO,CAAC,eAAe;CA6CxB"}
@@ -3,7 +3,7 @@ import { IService } from "../../../types/service.type";
3
3
  * Contec BC401 (a.k.a. BC01) urine analyzer — GATT profile.
4
4
  *
5
5
  * The BC401 uses Contec's proprietary FF12 service, shared across their
6
- * consumer medical devices. Every stored URS-7 measurement is pushed as a
6
+ * consumer medical devices. Every stored urine-strip measurement is pushed as a
7
7
  * 16-byte record on 0xFF02 after the host has walked the handshake documented
8
8
  * in `bc01-command-sequencer.ts`.
9
9
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ovok/native",
3
- "version": "1.6.51",
3
+ "version": "1.6.52",
4
4
  "description": "React native component sdk for OVOK",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",
@@ -88,7 +88,7 @@
88
88
  "@medplum/react-hooks": "3.2.23",
89
89
  "@opentelemetry/api": "^1.9.1",
90
90
  "@opentelemetry/api-logs": "^0.222.0",
91
- "@ovok/core": "^0.4.9",
91
+ "@ovok/core": "^0.4.10",
92
92
  "@react-native-community/datetimepicker": "^9.1.0",
93
93
  "@react-native-community/netinfo": "^12.0.1",
94
94
  "@react-native-google-signin/google-signin": "^16.1.2",