@ovok/native 0.4.11 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +667 -8
- package/lib/commonjs/modules/bt-management/services/bt-manager.js +13 -15
- package/lib/commonjs/modules/bt-management/services/bt-manager.js.map +1 -1
- package/lib/commonjs/modules/bt-management/services/device-creator.js +1 -7
- package/lib/commonjs/modules/bt-management/services/device-creator.js.map +1 -1
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.device.js +51 -113
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.device.js.map +1 -1
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.main-services.js +77 -41
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01.main-services.js.map +1 -1
- package/lib/commonjs/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.js +12 -24
- package/lib/commonjs/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.js.map +1 -1
- package/lib/module/modules/bt-management/services/bt-manager.js +13 -15
- package/lib/module/modules/bt-management/services/bt-manager.js.map +1 -1
- package/lib/module/modules/bt-management/services/device-creator.js +1 -7
- package/lib/module/modules/bt-management/services/device-creator.js.map +1 -1
- package/lib/module/modules/bt-management/services/devices/bc01/bc01.device.js +51 -113
- package/lib/module/modules/bt-management/services/devices/bc01/bc01.device.js.map +1 -1
- package/lib/module/modules/bt-management/services/devices/bc01/bc01.main-services.js +77 -41
- package/lib/module/modules/bt-management/services/devices/bc01/bc01.main-services.js.map +1 -1
- package/lib/module/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.js +12 -24
- package/lib/module/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.js.map +1 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/bt-manager.d.ts +1 -0
- package/lib/typescript/commonjs/src/modules/bt-management/services/bt-manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/device-creator.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts +13 -33
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.main-services.d.ts +17 -11
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01.main-services.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.d.ts +25 -0
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.d.ts.map +1 -1
- package/lib/typescript/module/src/modules/bt-management/services/bt-manager.d.ts +1 -0
- package/lib/typescript/module/src/modules/bt-management/services/bt-manager.d.ts.map +1 -1
- package/lib/typescript/module/src/modules/bt-management/services/device-creator.d.ts.map +1 -1
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts +13 -33
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.device.d.ts.map +1 -1
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.main-services.d.ts +17 -11
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01.main-services.d.ts.map +1 -1
- package/lib/typescript/module/src/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.d.ts +25 -0
- package/lib/typescript/module/src/modules/bt-management/services/devices/standard-gatt/standard-gatt.devices.d.ts.map +1 -1
- package/package.json +13 -12
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js +0 -184
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js.map +0 -1
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-frame-parser.js +0 -114
- package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-frame-parser.js.map +0 -1
- package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js +0 -180
- package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js.map +0 -1
- package/lib/module/modules/bt-management/services/devices/bc01/bc01-frame-parser.js +0 -110
- package/lib/module/modules/bt-management/services/devices/bc01/bc01-frame-parser.js.map +0 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts +0 -53
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts.map +0 -1
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts +0 -53
- package/lib/typescript/commonjs/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts.map +0 -1
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts +0 -53
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.d.ts.map +0 -1
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts +0 -53
- package/lib/typescript/module/src/modules/bt-management/services/devices/bc01/bc01-frame-parser.d.ts.map +0 -1
package/lib/commonjs/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_hexToByte","require","OP_RESET","OP_REQUEST_VERSION","OP_SET_TIME","OP_REQUEST_COUNT","OP_REQUEST_RECORDS","ACK_LAST_OF_SET","REQUEST_ALL","RX","ACK","VERSION_REPLY","TIME_SYNC_ACK","COUNT_REPLY","STORED_RECORD_URS","STORED_RECORD_PAGED","FINISH","RECORD_FLAGS_INDEX","RECORD_LAST_OF_SET_BIT","asHex","byte","toString","padStart","bc401Checksum","bytes","reduce","acc","buildCommand","opcode","arg","chk","buildResetCommand","buildRequestVersionCommand","buildSetTimeCommand","now","yy","getFullYear","mo","getMonth","dd","getDate","hh","getHours","mi","getMinutes","ss","getSeconds","ms","getMilliseconds","msLo","msHi","payload","Bc01CommandSequencer","isDone","constructor","params","clock","Date","initialCommands","commandFor","nextCommand","frame","length","undefined","hexToByte","answerStoredRecord","flags","write","map","withoutResponse","exports","bc01CommandSequencerInternals"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.parseBc01Record = exports.isBc01Record = exports.BC01_URS_OPCODE = exports.BC01_RECORD_LENGTH = exports.BC01_PAGED_URS_OPCODE = exports.BC01_LAST_OF_SET_BIT = exports.BC01_ANALYTE_ORDER = void 0;
|
|
7
|
-
var _hexToByte = require("../../../utils/hex-to-byte.js");
|
|
8
|
-
/** BC401 stored-record frame is always sixteen bytes: header, timestamp, analytes, checksum. */
|
|
9
|
-
const BC01_RECORD_LENGTH = exports.BC01_RECORD_LENGTH = 16;
|
|
10
|
-
|
|
11
|
-
/** The two opcodes the firmware uses for a stored URS-7 record. */
|
|
12
|
-
const BC01_URS_OPCODE = exports.BC01_URS_OPCODE = 0xe1;
|
|
13
|
-
const BC01_PAGED_URS_OPCODE = exports.BC01_PAGED_URS_OPCODE = 0xe2;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The bit `0x40` of the flags byte marks the last record of a paginated set.
|
|
17
|
-
* The sequencer keys off it to send the `[0x92, 0x7E, chk]` acknowledgement.
|
|
18
|
-
*/
|
|
19
|
-
const BC01_LAST_OF_SET_BIT = exports.BC01_LAST_OF_SET_BIT = 0x40;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A pad reading of `7` means the strip was not measured on that reagent.
|
|
23
|
-
* We drop those pads from the output rather than reporting them as level "7".
|
|
24
|
-
*/
|
|
25
|
-
const UNMEASURED = 7;
|
|
26
|
-
const YEAR_BASE = 2000;
|
|
27
|
-
const MONTH_MASK = 0x0f;
|
|
28
|
-
const DAY_MASK = 0x1f;
|
|
29
|
-
const HOUR_MASK = 0x1f;
|
|
30
|
-
const MINUTE_MASK = 0x3f;
|
|
31
|
-
const SECOND_MASK = 0x3f;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* URS-7 pad names, in the exact order they occupy the packed 3-bit slots
|
|
35
|
-
* across bytes 8..14 (see M1/a.java). The eleventh slot is a Contec-firmware
|
|
36
|
-
* field the vendor's own catalog calls "vc" and no other name is documented.
|
|
37
|
-
*/
|
|
38
|
-
const BC01_ANALYTE_ORDER = exports.BC01_ANALYTE_ORDER = ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc"];
|
|
39
|
-
|
|
40
|
-
/** Where the packed analyte pairs start in a 16-byte E1/E2 frame. */
|
|
41
|
-
const ANALYTES_START = 8;
|
|
42
|
-
|
|
43
|
-
/** The result of decoding one 16-byte record. `lastOfSet` is what the sequencer keys on. */
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Extracts one pad's level index from the packed byte. Two pads share a byte:
|
|
47
|
-
* the first uses the low 3 bits, the second uses bits 3..5. Bit 6 and 7 are
|
|
48
|
-
* unused reserved space per the vendor's own decoding in M1/a.java.
|
|
49
|
-
*/
|
|
50
|
-
const readPad = (packed, slot) => slot === 0 ? packed & 0x07 : packed >> 3 & 0x07;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Decodes a 16-byte E1 or E2 frame into its timestamp and analyte indices.
|
|
54
|
-
*
|
|
55
|
-
* Returns `undefined` for any frame that is not the right length or does not
|
|
56
|
-
* open with an E1/E2 opcode — the caller is not asked to guess whether a
|
|
57
|
-
* frame is a record or a heartbeat, and a frame that fails these checks is
|
|
58
|
-
* skipped rather than parsed into a plausible-looking wrong reading.
|
|
59
|
-
*
|
|
60
|
-
* The checksum byte is not verified here: the SDK's read path already ensures
|
|
61
|
-
* frame integrity before the parser sees the bytes, and a URS-7 pad value can
|
|
62
|
-
* only land in [0, 7] anyway — a corrupt payload would fail the pad-value
|
|
63
|
-
* check before it made it into a measurement.
|
|
64
|
-
*/
|
|
65
|
-
const parseBc01Record = frame => {
|
|
66
|
-
if (frame.length < BC01_RECORD_LENGTH) {
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
const opcode = (0, _hexToByte.hexToByte)(frame[0] ?? "");
|
|
70
|
-
if (opcode !== BC01_URS_OPCODE && opcode !== BC01_PAGED_URS_OPCODE) {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
const flags = (0, _hexToByte.hexToByte)(frame[1] ?? "");
|
|
74
|
-
const yy = (0, _hexToByte.hexToByte)(frame[2] ?? "") + YEAR_BASE;
|
|
75
|
-
const mm = (0, _hexToByte.hexToByte)(frame[3] ?? "") & MONTH_MASK;
|
|
76
|
-
const dd = (0, _hexToByte.hexToByte)(frame[4] ?? "") & DAY_MASK;
|
|
77
|
-
const hh = (0, _hexToByte.hexToByte)(frame[5] ?? "") & HOUR_MASK;
|
|
78
|
-
const mi = (0, _hexToByte.hexToByte)(frame[6] ?? "") & MINUTE_MASK;
|
|
79
|
-
const ss = (0, _hexToByte.hexToByte)(frame[7] ?? "") & SECOND_MASK;
|
|
80
|
-
const timestamp = new Date(yy, mm - 1, dd, hh, mi, ss, 0);
|
|
81
|
-
const values = {};
|
|
82
|
-
BC01_ANALYTE_ORDER.forEach((analyte, position) => {
|
|
83
|
-
const byteIndex = ANALYTES_START + Math.floor(position / 2);
|
|
84
|
-
const slot = position % 2;
|
|
85
|
-
const packed = (0, _hexToByte.hexToByte)(frame[byteIndex] ?? "");
|
|
86
|
-
const level = readPad(packed, slot);
|
|
87
|
-
if (level === UNMEASURED) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
values[analyte] = level;
|
|
91
|
-
});
|
|
92
|
-
return {
|
|
93
|
-
timestamp,
|
|
94
|
-
lastOfSet: (flags & BC01_LAST_OF_SET_BIT) !== 0,
|
|
95
|
-
pageIndex: flags & 0x0f,
|
|
96
|
-
values
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* True when the buffer holds a complete BC401 stored record. Used by the
|
|
102
|
-
* driver's `validatePackage` hook so the SDK's read path only advances once
|
|
103
|
-
* the notification carries a whole 16-byte frame.
|
|
104
|
-
*/
|
|
105
|
-
exports.parseBc01Record = parseBc01Record;
|
|
106
|
-
const isBc01Record = frame => {
|
|
107
|
-
if (frame.length < BC01_RECORD_LENGTH) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
const opcode = (0, _hexToByte.hexToByte)(frame[0] ?? "");
|
|
111
|
-
return opcode === BC01_URS_OPCODE || opcode === BC01_PAGED_URS_OPCODE;
|
|
112
|
-
};
|
|
113
|
-
exports.isBc01Record = isBc01Record;
|
|
114
|
-
//# sourceMappingURL=bc01-frame-parser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_hexToByte","require","BC01_RECORD_LENGTH","exports","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","ANALYTES_START","readPad","packed","slot","parseBc01Record","frame","length","undefined","opcode","hexToByte","flags","yy","mm","dd","hh","mi","ss","timestamp","Date","values","forEach","analyte","position","byteIndex","Math","floor","level","lastOfSet","pageIndex","isBc01Record"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { hexToByte } from "../../../utils/hex-to-byte.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* The FF01/FF02 opcodes the BC401 firmware speaks, as reverse-engineered from
|
|
7
|
-
* PHMS 3.0.03 (`I1/b.java` for the switch, `B3/B5.java` for the builders and
|
|
8
|
-
* checksum, `L1/f.java` for the reset write).
|
|
9
|
-
*/
|
|
10
|
-
const OP_RESET = 0x80;
|
|
11
|
-
const OP_REQUEST_VERSION = 0x82;
|
|
12
|
-
const OP_SET_TIME = 0x83;
|
|
13
|
-
const OP_REQUEST_COUNT = 0x90;
|
|
14
|
-
const OP_REQUEST_RECORDS = 0x92;
|
|
15
|
-
|
|
16
|
-
/** Payload byte for `OP_REQUEST_RECORDS` that acknowledges the last record of the set. */
|
|
17
|
-
const ACK_LAST_OF_SET = 0x7e;
|
|
18
|
-
|
|
19
|
-
/** Payload byte for `OP_REQUEST_COUNT` and the initial `OP_REQUEST_RECORDS`. */
|
|
20
|
-
const REQUEST_ALL = 0x00;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Device-to-host frame prefixes the FSM keys on. Values are decimal opcodes as
|
|
24
|
-
* they appear in the decompiled Java (`switch(bArr[0])`), rendered here as
|
|
25
|
-
* their real hex opcodes.
|
|
26
|
-
*/
|
|
27
|
-
const RX = {
|
|
28
|
-
ACK: 0xf0,
|
|
29
|
-
VERSION_REPLY: 0xf2,
|
|
30
|
-
TIME_SYNC_ACK: 0xf3,
|
|
31
|
-
COUNT_REPLY: 0xe0,
|
|
32
|
-
STORED_RECORD_URS: 0xe1,
|
|
33
|
-
STORED_RECORD_PAGED: 0xe2,
|
|
34
|
-
FINISH: 0xe3
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/** Position in a 16-byte URS record where the flags byte sits; bit 0x40 marks the last of a set. */
|
|
38
|
-
const RECORD_FLAGS_INDEX = 1;
|
|
39
|
-
const RECORD_LAST_OF_SET_BIT = 0x40;
|
|
40
|
-
/**
|
|
41
|
-
* Formats one byte as a two-digit lowercase hex string, matching the way the
|
|
42
|
-
* SDK's transport already spells raw bytes.
|
|
43
|
-
*/
|
|
44
|
-
const asHex = byte => (byte & 0xff).toString(16).padStart(2, "0");
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* BC401 checksum: sum of the low 7 bits of every byte, folded back into 7 bits.
|
|
48
|
-
* Matches `B5.a` in the decompiled Java exactly.
|
|
49
|
-
*/
|
|
50
|
-
const bc401Checksum = bytes => bytes.reduce((acc, byte) => acc + (byte & 0x7f), 0) & 0x7f;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Builds a "one payload byte plus checksum" command frame. This is the shape
|
|
54
|
-
* of every BC401 host-to-device command that carries an argument: opcode,
|
|
55
|
-
* argument, checksum-over-both.
|
|
56
|
-
*/
|
|
57
|
-
const buildCommand = (opcode, arg) => {
|
|
58
|
-
const chk = bc401Checksum([opcode, arg]);
|
|
59
|
-
return [opcode, arg, chk];
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Builds the two-byte reset frame. It is the one command that does not carry
|
|
64
|
-
* an argument or a checksum — PHMS writes it as `[0x80, 0x00]` verbatim
|
|
65
|
-
* (`L1/f.java:694`).
|
|
66
|
-
*/
|
|
67
|
-
const buildResetCommand = () => [OP_RESET, 0x00];
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Builds the request-version reply. The Java sends it as `[0x82, 0x02]` where
|
|
71
|
-
* `0x02` doubles as the checksum of `0x82` under the BC401 rule
|
|
72
|
-
* (`0x82 & 0x7f = 0x02`), so the same formula that guards every other command
|
|
73
|
-
* produces the right byte here.
|
|
74
|
-
*/
|
|
75
|
-
const buildRequestVersionCommand = () => {
|
|
76
|
-
const chk = bc401Checksum([OP_REQUEST_VERSION]);
|
|
77
|
-
return [OP_REQUEST_VERSION, chk];
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Builds the `SET_TIME` frame for the moment the sequencer receives it. The
|
|
82
|
-
* device does not run its own clock across power cycles, so timestamps on
|
|
83
|
-
* stored records only make sense once the app tells it what "now" is.
|
|
84
|
-
* Millisecond field is written little-endian, matching `I1/b.java`.
|
|
85
|
-
*/
|
|
86
|
-
const buildSetTimeCommand = now => {
|
|
87
|
-
const yy = now.getFullYear() - 2000;
|
|
88
|
-
const mo = now.getMonth() + 1;
|
|
89
|
-
const dd = now.getDate();
|
|
90
|
-
const hh = now.getHours();
|
|
91
|
-
const mi = now.getMinutes();
|
|
92
|
-
const ss = now.getSeconds();
|
|
93
|
-
const ms = now.getMilliseconds();
|
|
94
|
-
const msLo = ms & 0xff;
|
|
95
|
-
const msHi = ms >> 8 & 0xff;
|
|
96
|
-
const payload = [OP_SET_TIME, yy, mo, dd, hh, mi, ss, msLo, msHi];
|
|
97
|
-
const chk = bc401Checksum(payload);
|
|
98
|
-
return [...payload, chk];
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Walks the BC401 through its post-reset handshake and pulls every stored
|
|
103
|
-
* record.
|
|
104
|
-
*
|
|
105
|
-
* The device is self-clocking: it answers each command with a single frame,
|
|
106
|
-
* and the first byte of that frame names what it is. So the sequencer keeps
|
|
107
|
-
* no counter of its own — it looks at the reply, decides what belongs next,
|
|
108
|
-
* and returns that. A frame whose opcode is not part of the handshake is left
|
|
109
|
-
* unanswered so the driver's stuck-data watchdog surfaces the stall rather
|
|
110
|
-
* than the sequencer sending a command the device did not ask for.
|
|
111
|
-
*
|
|
112
|
-
* `initialCommands()` returns only the reset. The rest of the handshake -
|
|
113
|
-
* VERSION, SET_TIME, GET_COUNT, GET_RECORDS - is driven entirely by the
|
|
114
|
-
* device's own replies, because sending them any earlier would race the
|
|
115
|
-
* firmware boot the reset triggers.
|
|
116
|
-
*/
|
|
117
|
-
// eslint-disable-next-line import/group-exports
|
|
118
|
-
export class Bc01CommandSequencer {
|
|
119
|
-
isDone = false;
|
|
120
|
-
|
|
121
|
-
/** Injectable for tests; production reads `Date.now()`. */
|
|
122
|
-
|
|
123
|
-
constructor(params, clock = () => new Date()) {
|
|
124
|
-
this.params = params;
|
|
125
|
-
this.clock = clock;
|
|
126
|
-
}
|
|
127
|
-
initialCommands = () => [this.commandFor(buildResetCommand())];
|
|
128
|
-
nextCommand = frame => {
|
|
129
|
-
if (this.isDone || frame.length === 0) {
|
|
130
|
-
return undefined;
|
|
131
|
-
}
|
|
132
|
-
const opcode = hexToByte(frame[0] ?? "0");
|
|
133
|
-
switch (opcode) {
|
|
134
|
-
case RX.ACK:
|
|
135
|
-
return [this.commandFor(buildRequestVersionCommand())];
|
|
136
|
-
case RX.VERSION_REPLY:
|
|
137
|
-
return [this.commandFor(buildSetTimeCommand(this.clock()))];
|
|
138
|
-
case RX.TIME_SYNC_ACK:
|
|
139
|
-
return [this.commandFor(buildCommand(OP_REQUEST_COUNT, REQUEST_ALL))];
|
|
140
|
-
case RX.COUNT_REPLY:
|
|
141
|
-
return [this.commandFor(buildCommand(OP_REQUEST_RECORDS, REQUEST_ALL))];
|
|
142
|
-
case RX.STORED_RECORD_URS:
|
|
143
|
-
case RX.STORED_RECORD_PAGED:
|
|
144
|
-
return this.answerStoredRecord(frame);
|
|
145
|
-
case RX.FINISH:
|
|
146
|
-
this.isDone = true;
|
|
147
|
-
return undefined;
|
|
148
|
-
default:
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* The device pages every record it holds, one 16-byte frame at a time. Only
|
|
155
|
-
* the frame whose flags byte carries `0x40` needs an acknowledgement; every
|
|
156
|
-
* other page is a status update we let ride while the transfer continues.
|
|
157
|
-
*/
|
|
158
|
-
answerStoredRecord = frame => {
|
|
159
|
-
const flags = hexToByte(frame[RECORD_FLAGS_INDEX] ?? "0");
|
|
160
|
-
if ((flags & RECORD_LAST_OF_SET_BIT) === 0) {
|
|
161
|
-
return undefined;
|
|
162
|
-
}
|
|
163
|
-
return [this.commandFor(buildCommand(OP_REQUEST_RECORDS, ACK_LAST_OF_SET))];
|
|
164
|
-
};
|
|
165
|
-
commandFor = bytes => ({
|
|
166
|
-
...this.params.write,
|
|
167
|
-
frame: bytes.map(asHex),
|
|
168
|
-
withoutResponse: true
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// eslint-disable-next-line import/group-exports
|
|
173
|
-
export const bc01CommandSequencerInternals = {
|
|
174
|
-
bc401Checksum,
|
|
175
|
-
buildCommand,
|
|
176
|
-
buildResetCommand,
|
|
177
|
-
buildRequestVersionCommand,
|
|
178
|
-
buildSetTimeCommand
|
|
179
|
-
};
|
|
180
|
-
//# sourceMappingURL=bc01-command-sequencer.js.map
|
package/lib/module/modules/bt-management/services/devices/bc01/bc01-command-sequencer.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["hexToByte","OP_RESET","OP_REQUEST_VERSION","OP_SET_TIME","OP_REQUEST_COUNT","OP_REQUEST_RECORDS","ACK_LAST_OF_SET","REQUEST_ALL","RX","ACK","VERSION_REPLY","TIME_SYNC_ACK","COUNT_REPLY","STORED_RECORD_URS","STORED_RECORD_PAGED","FINISH","RECORD_FLAGS_INDEX","RECORD_LAST_OF_SET_BIT","asHex","byte","toString","padStart","bc401Checksum","bytes","reduce","acc","buildCommand","opcode","arg","chk","buildResetCommand","buildRequestVersionCommand","buildSetTimeCommand","now","yy","getFullYear","mo","getMonth","dd","getDate","hh","getHours","mi","getMinutes","ss","getSeconds","ms","getMilliseconds","msLo","msHi","payload","Bc01CommandSequencer","isDone","constructor","params","clock","Date","initialCommands","commandFor","nextCommand","frame","length","undefined","answerStoredRecord","flags","write","map","withoutResponse","bc01CommandSequencerInternals"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { hexToByte } from "../../../utils/hex-to-byte.js";
|
|
4
|
-
|
|
5
|
-
/** BC401 stored-record frame is always sixteen bytes: header, timestamp, analytes, checksum. */
|
|
6
|
-
const BC01_RECORD_LENGTH = 16;
|
|
7
|
-
|
|
8
|
-
/** The two opcodes the firmware uses for a stored URS-7 record. */
|
|
9
|
-
const BC01_URS_OPCODE = 0xe1;
|
|
10
|
-
const BC01_PAGED_URS_OPCODE = 0xe2;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The bit `0x40` of the flags byte marks the last record of a paginated set.
|
|
14
|
-
* The sequencer keys off it to send the `[0x92, 0x7E, chk]` acknowledgement.
|
|
15
|
-
*/
|
|
16
|
-
const BC01_LAST_OF_SET_BIT = 0x40;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* A pad reading of `7` means the strip was not measured on that reagent.
|
|
20
|
-
* We drop those pads from the output rather than reporting them as level "7".
|
|
21
|
-
*/
|
|
22
|
-
const UNMEASURED = 7;
|
|
23
|
-
const YEAR_BASE = 2000;
|
|
24
|
-
const MONTH_MASK = 0x0f;
|
|
25
|
-
const DAY_MASK = 0x1f;
|
|
26
|
-
const HOUR_MASK = 0x1f;
|
|
27
|
-
const MINUTE_MASK = 0x3f;
|
|
28
|
-
const SECOND_MASK = 0x3f;
|
|
29
|
-
|
|
30
|
-
/**
|
|
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.
|
|
34
|
-
*/
|
|
35
|
-
const BC01_ANALYTE_ORDER = ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc"];
|
|
36
|
-
|
|
37
|
-
/** Where the packed analyte pairs start in a 16-byte E1/E2 frame. */
|
|
38
|
-
const ANALYTES_START = 8;
|
|
39
|
-
|
|
40
|
-
/** The result of decoding one 16-byte record. `lastOfSet` is what the sequencer keys on. */
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Extracts one pad's level index from the packed byte. Two pads share a byte:
|
|
44
|
-
* the first uses the low 3 bits, the second uses bits 3..5. Bit 6 and 7 are
|
|
45
|
-
* unused reserved space per the vendor's own decoding in M1/a.java.
|
|
46
|
-
*/
|
|
47
|
-
const readPad = (packed, slot) => slot === 0 ? packed & 0x07 : packed >> 3 & 0x07;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Decodes a 16-byte E1 or E2 frame into its timestamp and analyte indices.
|
|
51
|
-
*
|
|
52
|
-
* Returns `undefined` for any frame that is not the right length or does not
|
|
53
|
-
* open with an E1/E2 opcode — the caller is not asked to guess whether a
|
|
54
|
-
* frame is a record or a heartbeat, and a frame that fails these checks is
|
|
55
|
-
* skipped rather than parsed into a plausible-looking wrong reading.
|
|
56
|
-
*
|
|
57
|
-
* The checksum byte is not verified here: the SDK's read path already ensures
|
|
58
|
-
* frame integrity before the parser sees the bytes, and a URS-7 pad value can
|
|
59
|
-
* only land in [0, 7] anyway — a corrupt payload would fail the pad-value
|
|
60
|
-
* check before it made it into a measurement.
|
|
61
|
-
*/
|
|
62
|
-
const parseBc01Record = frame => {
|
|
63
|
-
if (frame.length < BC01_RECORD_LENGTH) {
|
|
64
|
-
return undefined;
|
|
65
|
-
}
|
|
66
|
-
const opcode = hexToByte(frame[0] ?? "");
|
|
67
|
-
if (opcode !== BC01_URS_OPCODE && opcode !== BC01_PAGED_URS_OPCODE) {
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
70
|
-
const flags = hexToByte(frame[1] ?? "");
|
|
71
|
-
const yy = hexToByte(frame[2] ?? "") + YEAR_BASE;
|
|
72
|
-
const mm = hexToByte(frame[3] ?? "") & MONTH_MASK;
|
|
73
|
-
const dd = hexToByte(frame[4] ?? "") & DAY_MASK;
|
|
74
|
-
const hh = hexToByte(frame[5] ?? "") & HOUR_MASK;
|
|
75
|
-
const mi = hexToByte(frame[6] ?? "") & MINUTE_MASK;
|
|
76
|
-
const ss = hexToByte(frame[7] ?? "") & SECOND_MASK;
|
|
77
|
-
const timestamp = new Date(yy, mm - 1, dd, hh, mi, ss, 0);
|
|
78
|
-
const values = {};
|
|
79
|
-
BC01_ANALYTE_ORDER.forEach((analyte, position) => {
|
|
80
|
-
const byteIndex = ANALYTES_START + Math.floor(position / 2);
|
|
81
|
-
const slot = position % 2;
|
|
82
|
-
const packed = hexToByte(frame[byteIndex] ?? "");
|
|
83
|
-
const level = readPad(packed, slot);
|
|
84
|
-
if (level === UNMEASURED) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
values[analyte] = level;
|
|
88
|
-
});
|
|
89
|
-
return {
|
|
90
|
-
timestamp,
|
|
91
|
-
lastOfSet: (flags & BC01_LAST_OF_SET_BIT) !== 0,
|
|
92
|
-
pageIndex: flags & 0x0f,
|
|
93
|
-
values
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* True when the buffer holds a complete BC401 stored record. Used by the
|
|
99
|
-
* driver's `validatePackage` hook so the SDK's read path only advances once
|
|
100
|
-
* the notification carries a whole 16-byte frame.
|
|
101
|
-
*/
|
|
102
|
-
const isBc01Record = frame => {
|
|
103
|
-
if (frame.length < BC01_RECORD_LENGTH) {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
const opcode = hexToByte(frame[0] ?? "");
|
|
107
|
-
return opcode === BC01_URS_OPCODE || opcode === BC01_PAGED_URS_OPCODE;
|
|
108
|
-
};
|
|
109
|
-
export { BC01_ANALYTE_ORDER, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, isBc01Record, parseBc01Record };
|
|
110
|
-
//# sourceMappingURL=bc01-frame-parser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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","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","lastOfSet","pageIndex","isBc01Record"],"sourceRoot":"../../../../../../../src","sources":["modules/bt-management/services/devices/bc01/bc01-frame-parser.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { CommandSequencer } from "../../../types/command-sequencer";
|
|
2
|
-
import { DeviceCommand } from "../../../types/device-command";
|
|
3
|
-
interface Bc01SequencerParams {
|
|
4
|
-
/** The write channel every command goes out on. FF01 for a real BC401. */
|
|
5
|
-
write: Omit<DeviceCommand, "frame">;
|
|
6
|
-
/**
|
|
7
|
-
* Called with why the exchange stopped. Optional; a refusal here does not
|
|
8
|
-
* end the connection because the device continues to accept fresh commands
|
|
9
|
-
* even after a bad handshake step. The parent driver decides what to do.
|
|
10
|
-
*/
|
|
11
|
-
onRefused?: (reason: string) => void;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Walks the BC401 through its post-reset handshake and pulls every stored
|
|
15
|
-
* record.
|
|
16
|
-
*
|
|
17
|
-
* The device is self-clocking: it answers each command with a single frame,
|
|
18
|
-
* and the first byte of that frame names what it is. So the sequencer keeps
|
|
19
|
-
* no counter of its own — it looks at the reply, decides what belongs next,
|
|
20
|
-
* and returns that. A frame whose opcode is not part of the handshake is left
|
|
21
|
-
* unanswered so the driver's stuck-data watchdog surfaces the stall rather
|
|
22
|
-
* than the sequencer sending a command the device did not ask for.
|
|
23
|
-
*
|
|
24
|
-
* `initialCommands()` returns only the reset. The rest of the handshake -
|
|
25
|
-
* VERSION, SET_TIME, GET_COUNT, GET_RECORDS - is driven entirely by the
|
|
26
|
-
* device's own replies, because sending them any earlier would race the
|
|
27
|
-
* firmware boot the reset triggers.
|
|
28
|
-
*/
|
|
29
|
-
export declare class Bc01CommandSequencer implements CommandSequencer {
|
|
30
|
-
private readonly params;
|
|
31
|
-
private isDone;
|
|
32
|
-
/** Injectable for tests; production reads `Date.now()`. */
|
|
33
|
-
private readonly clock;
|
|
34
|
-
constructor(params: Bc01SequencerParams, clock?: () => Date);
|
|
35
|
-
initialCommands: () => readonly DeviceCommand[];
|
|
36
|
-
nextCommand: (frame: readonly string[]) => readonly DeviceCommand[] | undefined;
|
|
37
|
-
/**
|
|
38
|
-
* The device pages every record it holds, one 16-byte frame at a time. Only
|
|
39
|
-
* the frame whose flags byte carries `0x40` needs an acknowledgement; every
|
|
40
|
-
* other page is a status update we let ride while the transfer continues.
|
|
41
|
-
*/
|
|
42
|
-
private answerStoredRecord;
|
|
43
|
-
private commandFor;
|
|
44
|
-
}
|
|
45
|
-
export declare const bc01CommandSequencerInternals: {
|
|
46
|
-
bc401Checksum: (bytes: readonly number[]) => number;
|
|
47
|
-
buildCommand: (opcode: number, arg: number) => number[];
|
|
48
|
-
buildResetCommand: () => number[];
|
|
49
|
-
buildRequestVersionCommand: () => number[];
|
|
50
|
-
buildSetTimeCommand: (now: Date) => number[];
|
|
51
|
-
};
|
|
52
|
-
export {};
|
|
53
|
-
//# sourceMappingURL=bc01-command-sequencer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bc01-command-sequencer.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAuC9D,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;CACtC;AAqED;;;;;;;;;;;;;;;GAeG;AAEH,qBAAa,oBAAqB,YAAW,gBAAgB;IAOzD,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,MAAM,CAAS;IAEvB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAGhB,MAAM,EAAE,mBAAmB,EAC5C,KAAK,GAAE,MAAM,IAAuB;IAK/B,eAAe,QAAO,SAAS,aAAa,EAAE,CAEnD;IAEK,WAAW,GAChB,OAAO,SAAS,MAAM,EAAE,KACvB,SAAS,aAAa,EAAE,GAAG,SAAS,CAoCrC;IAEF;;;;OAIG;IACH,OAAO,CAAC,kBAAkB,CAUxB;IAEF,OAAO,CAAC,UAAU,CAIf;CACJ;AAGD,eAAO,MAAM,6BAA6B;2BA3JZ,SAAS,MAAM,EAAE,KAAG,MAAM;2BAQ1B,MAAM,OAAO,MAAM,KAAG,MAAM,EAAE;6BAW9B,MAAM,EAAE;sCAQC,MAAM,EAAE;+BAYb,IAAI,KAAG,MAAM,EAAE;CA0HhD,CAAC"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/** BC401 stored-record frame is always sixteen bytes: header, timestamp, analytes, checksum. */
|
|
2
|
-
declare const BC01_RECORD_LENGTH = 16;
|
|
3
|
-
/** The two opcodes the firmware uses for a stored URS-7 record. */
|
|
4
|
-
declare const BC01_URS_OPCODE = 225;
|
|
5
|
-
declare const BC01_PAGED_URS_OPCODE = 226;
|
|
6
|
-
/**
|
|
7
|
-
* The bit `0x40` of the flags byte marks the last record of a paginated set.
|
|
8
|
-
* The sequencer keys off it to send the `[0x92, 0x7E, chk]` acknowledgement.
|
|
9
|
-
*/
|
|
10
|
-
declare const BC01_LAST_OF_SET_BIT = 64;
|
|
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.
|
|
15
|
-
*/
|
|
16
|
-
declare const BC01_ANALYTE_ORDER: readonly ["uro", "bld", "bil", "ket", "glu", "pro", "ph", "nit", "leu", "sg", "vc"];
|
|
17
|
-
/** The result of decoding one 16-byte record. `lastOfSet` is what the sequencer keys on. */
|
|
18
|
-
interface Bc01ParsedRecord {
|
|
19
|
-
/** Local wall-clock time the device recorded, with millisecond precision unavailable. */
|
|
20
|
-
timestamp: Date;
|
|
21
|
-
/** True when the flags byte set bit 0x40 — this is the frame that must be acknowledged. */
|
|
22
|
-
lastOfSet: boolean;
|
|
23
|
-
/** Low nibble of the flags byte; the page counter the firmware writes. */
|
|
24
|
-
pageIndex: number;
|
|
25
|
-
/**
|
|
26
|
-
* Analyte level indices, absent for any pad the strip did not measure.
|
|
27
|
-
* A pad the strip did measure carries a value in [0, 6]; the vendor's own
|
|
28
|
-
* lookup tables translate that to a categorical result per analyte.
|
|
29
|
-
*/
|
|
30
|
-
values: Partial<Record<(typeof BC01_ANALYTE_ORDER)[number], number>>;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Decodes a 16-byte E1 or E2 frame into its timestamp and analyte indices.
|
|
34
|
-
*
|
|
35
|
-
* Returns `undefined` for any frame that is not the right length or does not
|
|
36
|
-
* open with an E1/E2 opcode — the caller is not asked to guess whether a
|
|
37
|
-
* frame is a record or a heartbeat, and a frame that fails these checks is
|
|
38
|
-
* skipped rather than parsed into a plausible-looking wrong reading.
|
|
39
|
-
*
|
|
40
|
-
* The checksum byte is not verified here: the SDK's read path already ensures
|
|
41
|
-
* frame integrity before the parser sees the bytes, and a URS-7 pad value can
|
|
42
|
-
* only land in [0, 7] anyway — a corrupt payload would fail the pad-value
|
|
43
|
-
* check before it made it into a measurement.
|
|
44
|
-
*/
|
|
45
|
-
declare const parseBc01Record: (frame: readonly string[]) => Bc01ParsedRecord | undefined;
|
|
46
|
-
/**
|
|
47
|
-
* True when the buffer holds a complete BC401 stored record. Used by the
|
|
48
|
-
* driver's `validatePackage` hook so the SDK's read path only advances once
|
|
49
|
-
* the notification carries a whole 16-byte frame.
|
|
50
|
-
*/
|
|
51
|
-
declare const isBc01Record: (frame: readonly string[]) => boolean;
|
|
52
|
-
export { BC01_ANALYTE_ORDER, BC01_LAST_OF_SET_BIT, BC01_PAGED_URS_OPCODE, BC01_RECORD_LENGTH, BC01_URS_OPCODE, Bc01ParsedRecord, isBc01Record, parseBc01Record, };
|
|
53
|
-
//# sourceMappingURL=bc01-frame-parser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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;AAKhE,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;;;;OAIG;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,SA0CrB,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,YAAY,GAAI,OAAO,SAAS,MAAM,EAAE,KAAG,OAQhD,CAAC;AAEF,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,GAChB,CAAC"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { CommandSequencer } from "../../../types/command-sequencer";
|
|
2
|
-
import { DeviceCommand } from "../../../types/device-command";
|
|
3
|
-
interface Bc01SequencerParams {
|
|
4
|
-
/** The write channel every command goes out on. FF01 for a real BC401. */
|
|
5
|
-
write: Omit<DeviceCommand, "frame">;
|
|
6
|
-
/**
|
|
7
|
-
* Called with why the exchange stopped. Optional; a refusal here does not
|
|
8
|
-
* end the connection because the device continues to accept fresh commands
|
|
9
|
-
* even after a bad handshake step. The parent driver decides what to do.
|
|
10
|
-
*/
|
|
11
|
-
onRefused?: (reason: string) => void;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Walks the BC401 through its post-reset handshake and pulls every stored
|
|
15
|
-
* record.
|
|
16
|
-
*
|
|
17
|
-
* The device is self-clocking: it answers each command with a single frame,
|
|
18
|
-
* and the first byte of that frame names what it is. So the sequencer keeps
|
|
19
|
-
* no counter of its own — it looks at the reply, decides what belongs next,
|
|
20
|
-
* and returns that. A frame whose opcode is not part of the handshake is left
|
|
21
|
-
* unanswered so the driver's stuck-data watchdog surfaces the stall rather
|
|
22
|
-
* than the sequencer sending a command the device did not ask for.
|
|
23
|
-
*
|
|
24
|
-
* `initialCommands()` returns only the reset. The rest of the handshake -
|
|
25
|
-
* VERSION, SET_TIME, GET_COUNT, GET_RECORDS - is driven entirely by the
|
|
26
|
-
* device's own replies, because sending them any earlier would race the
|
|
27
|
-
* firmware boot the reset triggers.
|
|
28
|
-
*/
|
|
29
|
-
export declare class Bc01CommandSequencer implements CommandSequencer {
|
|
30
|
-
private readonly params;
|
|
31
|
-
private isDone;
|
|
32
|
-
/** Injectable for tests; production reads `Date.now()`. */
|
|
33
|
-
private readonly clock;
|
|
34
|
-
constructor(params: Bc01SequencerParams, clock?: () => Date);
|
|
35
|
-
initialCommands: () => readonly DeviceCommand[];
|
|
36
|
-
nextCommand: (frame: readonly string[]) => readonly DeviceCommand[] | undefined;
|
|
37
|
-
/**
|
|
38
|
-
* The device pages every record it holds, one 16-byte frame at a time. Only
|
|
39
|
-
* the frame whose flags byte carries `0x40` needs an acknowledgement; every
|
|
40
|
-
* other page is a status update we let ride while the transfer continues.
|
|
41
|
-
*/
|
|
42
|
-
private answerStoredRecord;
|
|
43
|
-
private commandFor;
|
|
44
|
-
}
|
|
45
|
-
export declare const bc01CommandSequencerInternals: {
|
|
46
|
-
bc401Checksum: (bytes: readonly number[]) => number;
|
|
47
|
-
buildCommand: (opcode: number, arg: number) => number[];
|
|
48
|
-
buildResetCommand: () => number[];
|
|
49
|
-
buildRequestVersionCommand: () => number[];
|
|
50
|
-
buildSetTimeCommand: (now: Date) => number[];
|
|
51
|
-
};
|
|
52
|
-
export {};
|
|
53
|
-
//# sourceMappingURL=bc01-command-sequencer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bc01-command-sequencer.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/modules/bt-management/services/devices/bc01/bc01-command-sequencer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAuC9D,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;CACtC;AAqED;;;;;;;;;;;;;;;GAeG;AAEH,qBAAa,oBAAqB,YAAW,gBAAgB;IAOzD,OAAO,CAAC,QAAQ,CAAC,MAAM;IANzB,OAAO,CAAC,MAAM,CAAS;IAEvB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAGhB,MAAM,EAAE,mBAAmB,EAC5C,KAAK,GAAE,MAAM,IAAuB;IAK/B,eAAe,QAAO,SAAS,aAAa,EAAE,CAEnD;IAEK,WAAW,GAChB,OAAO,SAAS,MAAM,EAAE,KACvB,SAAS,aAAa,EAAE,GAAG,SAAS,CAoCrC;IAEF;;;;OAIG;IACH,OAAO,CAAC,kBAAkB,CAUxB;IAEF,OAAO,CAAC,UAAU,CAIf;CACJ;AAGD,eAAO,MAAM,6BAA6B;2BA3JZ,SAAS,MAAM,EAAE,KAAG,MAAM;2BAQ1B,MAAM,OAAO,MAAM,KAAG,MAAM,EAAE;6BAW9B,MAAM,EAAE;sCAQC,MAAM,EAAE;+BAYb,IAAI,KAAG,MAAM,EAAE;CA0HhD,CAAC"}
|