@depz/sensor-sdk 0.1.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.
Files changed (130) hide show
  1. package/README.md +69 -0
  2. package/dist/dataset.d.ts +93 -0
  3. package/dist/dataset.d.ts.map +1 -0
  4. package/dist/dataset.js +253 -0
  5. package/dist/dataset.js.map +1 -0
  6. package/dist/device/device.d.ts +185 -0
  7. package/dist/device/device.d.ts.map +1 -0
  8. package/dist/device/device.js +421 -0
  9. package/dist/device/device.js.map +1 -0
  10. package/dist/device/link.d.ts +62 -0
  11. package/dist/device/link.d.ts.map +1 -0
  12. package/dist/device/link.js +130 -0
  13. package/dist/device/link.js.map +1 -0
  14. package/dist/discovery.d.ts +109 -0
  15. package/dist/discovery.d.ts.map +1 -0
  16. package/dist/discovery.js +281 -0
  17. package/dist/discovery.js.map +1 -0
  18. package/dist/errors.d.ts +39 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +69 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/index.d.ts +42 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +31 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/protocol/bno086.d.ts +36 -0
  27. package/dist/protocol/bno086.d.ts.map +1 -0
  28. package/dist/protocol/bno086.js +38 -0
  29. package/dist/protocol/bno086.js.map +1 -0
  30. package/dist/protocol/common.d.ts +103 -0
  31. package/dist/protocol/common.d.ts.map +1 -0
  32. package/dist/protocol/common.js +121 -0
  33. package/dist/protocol/common.js.map +1 -0
  34. package/dist/protocol/crc.d.ts +17 -0
  35. package/dist/protocol/crc.d.ts.map +1 -0
  36. package/dist/protocol/crc.js +55 -0
  37. package/dist/protocol/crc.js.map +1 -0
  38. package/dist/protocol/framing.d.ts +65 -0
  39. package/dist/protocol/framing.d.ts.map +1 -0
  40. package/dist/protocol/framing.js +152 -0
  41. package/dist/protocol/framing.js.map +1 -0
  42. package/dist/protocol/fwdepz.d.ts +21 -0
  43. package/dist/protocol/fwdepz.d.ts.map +1 -0
  44. package/dist/protocol/fwdepz.js +46 -0
  45. package/dist/protocol/fwdepz.js.map +1 -0
  46. package/dist/protocol/identity.d.ts +14 -0
  47. package/dist/protocol/identity.d.ts.map +1 -0
  48. package/dist/protocol/identity.js +28 -0
  49. package/dist/protocol/identity.js.map +1 -0
  50. package/dist/protocol/sr04.d.ts +38 -0
  51. package/dist/protocol/sr04.d.ts.map +1 -0
  52. package/dist/protocol/sr04.js +58 -0
  53. package/dist/protocol/sr04.js.map +1 -0
  54. package/dist/protocol/usb-ids.d.ts +60 -0
  55. package/dist/protocol/usb-ids.d.ts.map +1 -0
  56. package/dist/protocol/usb-ids.js +79 -0
  57. package/dist/protocol/usb-ids.js.map +1 -0
  58. package/dist/protocol/vl53l8.d.ts +59 -0
  59. package/dist/protocol/vl53l8.d.ts.map +1 -0
  60. package/dist/protocol/vl53l8.js +116 -0
  61. package/dist/protocol/vl53l8.js.map +1 -0
  62. package/dist/sensors/bno086/bno086.d.ts +197 -0
  63. package/dist/sensors/bno086/bno086.d.ts.map +1 -0
  64. package/dist/sensors/bno086/bno086.js +543 -0
  65. package/dist/sensors/bno086/bno086.js.map +1 -0
  66. package/dist/sensors/bno086/reports.d.ts +289 -0
  67. package/dist/sensors/bno086/reports.d.ts.map +1 -0
  68. package/dist/sensors/bno086/reports.js +397 -0
  69. package/dist/sensors/bno086/reports.js.map +1 -0
  70. package/dist/sensors/bno086/sh2.d.ts +307 -0
  71. package/dist/sensors/bno086/sh2.d.ts.map +1 -0
  72. package/dist/sensors/bno086/sh2.js +480 -0
  73. package/dist/sensors/bno086/sh2.js.map +1 -0
  74. package/dist/sensors/bno086/shtp.d.ts +98 -0
  75. package/dist/sensors/bno086/shtp.d.ts.map +1 -0
  76. package/dist/sensors/bno086/shtp.js +205 -0
  77. package/dist/sensors/bno086/shtp.js.map +1 -0
  78. package/dist/sensors/sr04.d.ts +65 -0
  79. package/dist/sensors/sr04.d.ts.map +1 -0
  80. package/dist/sensors/sr04.js +121 -0
  81. package/dist/sensors/sr04.js.map +1 -0
  82. package/dist/sensors/vl53l8/assets/ch.d.ts +16 -0
  83. package/dist/sensors/vl53l8/assets/ch.d.ts.map +1 -0
  84. package/dist/sensors/vl53l8/assets/ch.js +22 -0
  85. package/dist/sensors/vl53l8/assets/ch.js.map +1 -0
  86. package/dist/sensors/vl53l8/assets/cx.d.ts +16 -0
  87. package/dist/sensors/vl53l8/assets/cx.d.ts.map +1 -0
  88. package/dist/sensors/vl53l8/assets/cx.js +22 -0
  89. package/dist/sensors/vl53l8/assets/cx.js.map +1 -0
  90. package/dist/sensors/vl53l8/assets/decode.d.ts +7 -0
  91. package/dist/sensors/vl53l8/assets/decode.d.ts.map +1 -0
  92. package/dist/sensors/vl53l8/assets/decode.js +35 -0
  93. package/dist/sensors/vl53l8/assets/decode.js.map +1 -0
  94. package/dist/sensors/vl53l8/assets/index.d.ts +19 -0
  95. package/dist/sensors/vl53l8/assets/index.d.ts.map +1 -0
  96. package/dist/sensors/vl53l8/assets/index.js +11 -0
  97. package/dist/sensors/vl53l8/assets/index.js.map +1 -0
  98. package/dist/sensors/vl53l8/cnh.d.ts +113 -0
  99. package/dist/sensors/vl53l8/cnh.d.ts.map +1 -0
  100. package/dist/sensors/vl53l8/cnh.js +299 -0
  101. package/dist/sensors/vl53l8/cnh.js.map +1 -0
  102. package/dist/sensors/vl53l8/uld.d.ts +346 -0
  103. package/dist/sensors/vl53l8/uld.d.ts.map +1 -0
  104. package/dist/sensors/vl53l8/uld.js +1388 -0
  105. package/dist/sensors/vl53l8/uld.js.map +1 -0
  106. package/dist/sensors/vl53l8/vl53l8.d.ts +182 -0
  107. package/dist/sensors/vl53l8/vl53l8.d.ts.map +1 -0
  108. package/dist/sensors/vl53l8/vl53l8.js +411 -0
  109. package/dist/sensors/vl53l8/vl53l8.js.map +1 -0
  110. package/dist/transport/loopback.d.ts +18 -0
  111. package/dist/transport/loopback.d.ts.map +1 -0
  112. package/dist/transport/loopback.js +53 -0
  113. package/dist/transport/loopback.js.map +1 -0
  114. package/dist/transport/node.d.ts +51 -0
  115. package/dist/transport/node.d.ts.map +1 -0
  116. package/dist/transport/node.js +123 -0
  117. package/dist/transport/node.js.map +1 -0
  118. package/dist/transport/replay.d.ts +68 -0
  119. package/dist/transport/replay.d.ts.map +1 -0
  120. package/dist/transport/replay.js +196 -0
  121. package/dist/transport/replay.js.map +1 -0
  122. package/dist/transport/types.d.ts +23 -0
  123. package/dist/transport/types.d.ts.map +1 -0
  124. package/dist/transport/types.js +7 -0
  125. package/dist/transport/types.js.map +1 -0
  126. package/dist/transport/webserial.d.ts +69 -0
  127. package/dist/transport/webserial.d.ts.map +1 -0
  128. package/dist/transport/webserial.js +196 -0
  129. package/dist/transport/webserial.js.map +1 -0
  130. package/package.json +77 -0
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Node.js transport over the optional `serialport` peer dependency.
3
+ * Import via `@depz/sensor-sdk/node` only — never from the root export, so
4
+ * browser bundles stay serialport-free.
5
+ */
6
+ import { listDepzDevicesFrom, openDeviceFrom, } from "../discovery.js";
7
+ async function loadSerialport() {
8
+ try {
9
+ const mod = (await import("serialport"));
10
+ return { SerialPort: mod.SerialPort, list: () => mod.SerialPort.list() };
11
+ }
12
+ catch (err) {
13
+ throw new Error("the optional peer dependency 'serialport' is required for NodeSerialTransport " +
14
+ "(npm i serialport)", { cause: err });
15
+ }
16
+ }
17
+ /** Enumerate system serial ports (Node only). */
18
+ export async function listSerialPorts() {
19
+ const { list } = await loadSerialport();
20
+ return list();
21
+ }
22
+ export class NodeSerialTransport {
23
+ path;
24
+ info;
25
+ port = null;
26
+ queue = [];
27
+ waiter = null;
28
+ ended = false;
29
+ disconnectCbs = [];
30
+ constructor(path, serialNumber) {
31
+ this.path = path;
32
+ this.info = { path, serialNumber };
33
+ }
34
+ async open(opts) {
35
+ const { SerialPort } = await loadSerialport();
36
+ const port = new SerialPort({
37
+ path: this.path,
38
+ baudRate: opts?.baudRate ?? 115200,
39
+ autoOpen: false,
40
+ });
41
+ await new Promise((resolve, reject) => port.open((err) => (err ? reject(err) : resolve())));
42
+ port.on("data", (data) => {
43
+ this.queue.push(new Uint8Array(data));
44
+ this.waiter?.();
45
+ });
46
+ port.on("close", () => this.end());
47
+ port.on("error", () => this.end());
48
+ this.port = port;
49
+ }
50
+ end() {
51
+ if (this.ended)
52
+ return;
53
+ this.ended = true;
54
+ this.waiter?.();
55
+ const cbs = this.disconnectCbs;
56
+ this.disconnectCbs = [];
57
+ cbs.forEach((cb) => cb());
58
+ }
59
+ async write(data) {
60
+ const port = this.port;
61
+ if (!port || !port.isOpen)
62
+ throw new Error("port not open");
63
+ await new Promise((resolve, reject) => port.write(data, (err) => (err ? reject(err) : resolve())));
64
+ }
65
+ async *readable() {
66
+ for (;;) {
67
+ while (this.queue.length === 0) {
68
+ if (this.ended)
69
+ return;
70
+ await new Promise((resolve) => (this.waiter = resolve));
71
+ this.waiter = null;
72
+ }
73
+ yield this.queue.shift();
74
+ }
75
+ }
76
+ async close() {
77
+ const port = this.port;
78
+ if (port && port.isOpen) {
79
+ await new Promise((resolve) => port.close(() => resolve()));
80
+ }
81
+ this.end();
82
+ }
83
+ onDisconnect(cb) {
84
+ this.disconnectCbs.push(cb);
85
+ return () => {
86
+ this.disconnectCbs = this.disconnectCbs.filter((c) => c !== cb);
87
+ };
88
+ }
89
+ }
90
+ // ── discovery (Node / serialport — full behavior) ─────────────────────────────
91
+ function toPortInfo(p) {
92
+ return {
93
+ path: p.path,
94
+ serialNumber: p.serialNumber,
95
+ usbVid: p.vendorId !== undefined ? parseInt(p.vendorId, 16) : undefined,
96
+ usbPid: p.productId !== undefined ? parseInt(p.productId, 16) : undefined,
97
+ };
98
+ }
99
+ const nodeFactory = (port) => new NodeSerialTransport(port.path, port.serialNumber);
100
+ /**
101
+ * Enumerate DEPZ devices on the system's serial ports (Node only).
102
+ *
103
+ * With `matchUsb` (default) only ports carrying a known DEPZ (vid,pid) are
104
+ * probed — fast, and it never pokes unrelated ports. Set `matchUsb: false`
105
+ * for a legacy probe-everything scan.
106
+ */
107
+ export async function listDepzDevices(opts = {}) {
108
+ const ports = (await listSerialPorts()).map(toPortInfo);
109
+ return listDepzDevicesFrom(ports, nodeFactory, opts);
110
+ }
111
+ /**
112
+ * Open the right sensor class for `target` over `serialport` (Node only).
113
+ *
114
+ * `target` is a port path (string), a candidate index (number, sorted by USB
115
+ * iSerial), a `DeviceInfo` from `listDepzDevices()`, or omitted for the
116
+ * lowest-serial candidate. Throws `NoDepzDeviceError` when nothing matches —
117
+ * it never grabs an arbitrary system port. See {@link openDeviceFrom}.
118
+ */
119
+ export async function openDevice(target, opts = {}) {
120
+ const ports = (await listSerialPorts()).map(toPortInfo);
121
+ return openDeviceFrom(ports, nodeFactory, target, opts);
122
+ }
123
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/transport/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * `.depzrec` capture and replay transports (contracts/08_RECORDING_FORMAT.md).
3
+ * Mirrors the Python reference `depz_sensor_sdk.transport.record_replay`.
4
+ */
5
+ import type { SerialTransport, SerialTransportInfo } from "./types.js";
6
+ export declare const RECORDING_SCHEMA = "depz.rec/1";
7
+ /**
8
+ * Wraps any transport and tees both directions into `.depzrec` JSONL text.
9
+ * Get the capture with `dump()` (line 1 is the header; browser-friendly —
10
+ * no filesystem involved).
11
+ */
12
+ export declare class RecordingTransport implements SerialTransport {
13
+ private readonly inner;
14
+ private readonly lines;
15
+ private readonly t0;
16
+ constructor(inner: SerialTransport, opts?: {
17
+ headerExtra?: Record<string, unknown>;
18
+ });
19
+ get info(): SerialTransportInfo;
20
+ /** The capture so far as `.depzrec` file content. */
21
+ dump(): string;
22
+ private emit;
23
+ open(opts?: {
24
+ baudRate?: number;
25
+ }): Promise<void>;
26
+ write(data: Uint8Array): Promise<void>;
27
+ readable(): AsyncIterableIterator<Uint8Array>;
28
+ close(): Promise<void>;
29
+ onDisconnect(cb: () => void): () => void;
30
+ }
31
+ /**
32
+ * Replays the `rx` side of a `.depzrec` capture **causally**: an rx event
33
+ * is released only after the host has written at least as many tx bytes as
34
+ * preceded that event in the recording. Without this gating a replay would
35
+ * deliver responses before the SDK even sends the requests.
36
+ *
37
+ * `strictTx` additionally asserts the written bytes match the recorded tx
38
+ * stream byte-for-byte (protocol regression mode). `realtime` paces rx
39
+ * events by their recorded timestamps.
40
+ */
41
+ export declare class ReplayTransport implements SerialTransport {
42
+ readonly info: SerialTransportInfo;
43
+ /** Parsed header line (unknown fields preserved, contract 08). */
44
+ readonly header: Record<string, unknown>;
45
+ private readonly rx;
46
+ private readonly txStream;
47
+ private readonly realtime;
48
+ private readonly strictTx;
49
+ private txWritten;
50
+ private rxIdx;
51
+ private closedFlag;
52
+ private waiters;
53
+ private disconnectCbs;
54
+ constructor(content: string, opts?: {
55
+ realtime?: boolean;
56
+ strictTx?: boolean;
57
+ });
58
+ /** True once every recorded rx event has been delivered. */
59
+ get exhausted(): boolean;
60
+ open(): Promise<void>;
61
+ private notifyAll;
62
+ private waitChange;
63
+ write(data: Uint8Array): Promise<void>;
64
+ readable(): AsyncIterableIterator<Uint8Array>;
65
+ close(): Promise<void>;
66
+ onDisconnect(cb: () => void): () => void;
67
+ }
68
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/transport/replay.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEvE,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAgB7C;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAqB;gBAE5B,KAAK,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAUpF,IAAI,IAAI,IAAI,mBAAmB,CAE9B;IAED,qDAAqD;IACrD,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,IAAI;IAMZ,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrC,QAAQ,IAAI,qBAAqB,CAAC,UAAU,CAAC;IAOpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAGzC;AASD;;;;;;;;;GASG;AACH,qBAAa,eAAgB,YAAW,eAAe;IACrD,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAsB;IACxD,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,aAAa,CAAyB;gBAElC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE;IA0B9E,4DAA4D;IAC5D,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAIZ,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBrC,QAAQ,IAAI,qBAAqB,CAAC,UAAU,CAAC;IAwB9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAMzC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * `.depzrec` capture and replay transports (contracts/08_RECORDING_FORMAT.md).
3
+ * Mirrors the Python reference `depz_sensor_sdk.transport.record_replay`.
4
+ */
5
+ import { LinkClosedError } from "../errors.js";
6
+ export const RECORDING_SCHEMA = "depz.rec/1";
7
+ function bytesToHex(data) {
8
+ let s = "";
9
+ for (const b of data)
10
+ s += b.toString(16).padStart(2, "0");
11
+ return s;
12
+ }
13
+ function hexToBytes(hex) {
14
+ const out = new Uint8Array(hex.length >>> 1);
15
+ for (let i = 0; i < out.length; i++) {
16
+ out[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
17
+ }
18
+ return out;
19
+ }
20
+ /**
21
+ * Wraps any transport and tees both directions into `.depzrec` JSONL text.
22
+ * Get the capture with `dump()` (line 1 is the header; browser-friendly —
23
+ * no filesystem involved).
24
+ */
25
+ export class RecordingTransport {
26
+ inner;
27
+ lines = [];
28
+ t0 = performance.now();
29
+ constructor(inner, opts) {
30
+ this.inner = inner;
31
+ const header = {
32
+ schema: RECORDING_SCHEMA,
33
+ created_utc: new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
34
+ ...opts?.headerExtra,
35
+ };
36
+ this.lines.push(JSON.stringify(header));
37
+ }
38
+ get info() {
39
+ return this.inner.info;
40
+ }
41
+ /** The capture so far as `.depzrec` file content. */
42
+ dump() {
43
+ return this.lines.join("\n") + "\n";
44
+ }
45
+ emit(dir, data) {
46
+ if (data.length === 0)
47
+ return;
48
+ const t = Math.max(0, Math.round((performance.now() - this.t0) * 1000));
49
+ this.lines.push(JSON.stringify({ t, dir, data: bytesToHex(data) }));
50
+ }
51
+ open(opts) {
52
+ return this.inner.open(opts);
53
+ }
54
+ async write(data) {
55
+ // Record before the (async) write completes so an rx caused by this tx
56
+ // can never be captured ahead of it — replay causality depends on it.
57
+ this.emit("tx", data);
58
+ await this.inner.write(data);
59
+ }
60
+ async *readable() {
61
+ for await (const chunk of this.inner.readable()) {
62
+ this.emit("rx", chunk);
63
+ yield chunk;
64
+ }
65
+ }
66
+ close() {
67
+ return this.inner.close();
68
+ }
69
+ onDisconnect(cb) {
70
+ return this.inner.onDisconnect(cb);
71
+ }
72
+ }
73
+ /**
74
+ * Replays the `rx` side of a `.depzrec` capture **causally**: an rx event
75
+ * is released only after the host has written at least as many tx bytes as
76
+ * preceded that event in the recording. Without this gating a replay would
77
+ * deliver responses before the SDK even sends the requests.
78
+ *
79
+ * `strictTx` additionally asserts the written bytes match the recorded tx
80
+ * stream byte-for-byte (protocol regression mode). `realtime` paces rx
81
+ * events by their recorded timestamps.
82
+ */
83
+ export class ReplayTransport {
84
+ info = { path: "replay" };
85
+ /** Parsed header line (unknown fields preserved, contract 08). */
86
+ header;
87
+ rx = [];
88
+ txStream;
89
+ realtime;
90
+ strictTx;
91
+ txWritten = 0;
92
+ rxIdx = 0;
93
+ closedFlag = false;
94
+ waiters = [];
95
+ disconnectCbs = [];
96
+ constructor(content, opts) {
97
+ this.realtime = opts?.realtime ?? false;
98
+ this.strictTx = opts?.strictTx ?? false;
99
+ const lines = content.split("\n").filter((l) => l.trim().length > 0);
100
+ this.header =
101
+ lines.length > 0 ? JSON.parse(lines[0]) : {};
102
+ const txChunks = [];
103
+ let txLen = 0;
104
+ for (const line of lines.slice(1)) {
105
+ const ev = JSON.parse(line);
106
+ const data = hexToBytes(ev.data);
107
+ if (ev.dir === "rx") {
108
+ this.rx.push({ tUs: ev.t, data, txPrefix: txLen });
109
+ }
110
+ else {
111
+ txChunks.push(data);
112
+ txLen += data.length;
113
+ }
114
+ }
115
+ this.txStream = new Uint8Array(txLen);
116
+ let off = 0;
117
+ for (const chunk of txChunks) {
118
+ this.txStream.set(chunk, off);
119
+ off += chunk.length;
120
+ }
121
+ }
122
+ /** True once every recorded rx event has been delivered. */
123
+ get exhausted() {
124
+ return this.rxIdx >= this.rx.length;
125
+ }
126
+ async open() { }
127
+ notifyAll() {
128
+ const waiters = this.waiters;
129
+ this.waiters = [];
130
+ for (const w of waiters)
131
+ w();
132
+ }
133
+ waitChange() {
134
+ return new Promise((resolve) => this.waiters.push(resolve));
135
+ }
136
+ async write(data) {
137
+ if (this.closedFlag)
138
+ throw new LinkClosedError("replay transport closed");
139
+ if (this.strictTx) {
140
+ const expected = this.txStream.subarray(this.txWritten, this.txWritten + data.length);
141
+ let mismatch = expected.length !== data.length;
142
+ for (let i = 0; !mismatch && i < data.length; i++) {
143
+ if (expected[i] !== data[i])
144
+ mismatch = true;
145
+ }
146
+ if (mismatch) {
147
+ throw new Error(`replay strictTx mismatch at offset ${this.txWritten}: ` +
148
+ `expected ${bytesToHex(expected)}, got ${bytesToHex(data)}`);
149
+ }
150
+ }
151
+ this.txWritten += data.length;
152
+ this.notifyAll();
153
+ }
154
+ async *readable() {
155
+ const t0 = performance.now();
156
+ while (!this.closedFlag) {
157
+ if (this.exhausted) {
158
+ // Recording drained: behave like a silent port until close().
159
+ await this.waitChange();
160
+ continue;
161
+ }
162
+ const ev = this.rx[this.rxIdx];
163
+ if (this.txWritten < ev.txPrefix) {
164
+ await this.waitChange();
165
+ continue;
166
+ }
167
+ if (this.realtime) {
168
+ const dueMs = t0 + ev.tUs / 1000;
169
+ const waitMs = dueMs - performance.now();
170
+ if (waitMs > 0)
171
+ await new Promise((r) => setTimeout(r, waitMs));
172
+ if (this.closedFlag)
173
+ return;
174
+ }
175
+ this.rxIdx += 1;
176
+ yield ev.data;
177
+ }
178
+ }
179
+ async close() {
180
+ if (this.closedFlag)
181
+ return;
182
+ this.closedFlag = true;
183
+ this.notifyAll();
184
+ const cbs = this.disconnectCbs;
185
+ this.disconnectCbs = [];
186
+ for (const cb of cbs)
187
+ cb();
188
+ }
189
+ onDisconnect(cb) {
190
+ this.disconnectCbs.push(cb);
191
+ return () => {
192
+ this.disconnectCbs = this.disconnectCbs.filter((c) => c !== cb);
193
+ };
194
+ }
195
+ }
196
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/transport/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Byte-transport abstraction (contracts/07_SDK_FACADE.md §1 "link").
3
+ * WebSerial (browser), serialport (Node), loopback (tests) and .depzrec
4
+ * replay all implement this. The SDK core touches nothing else.
5
+ */
6
+ export interface SerialTransportInfo {
7
+ usbVendorId?: number;
8
+ usbProductId?: number;
9
+ path?: string;
10
+ serialNumber?: string;
11
+ }
12
+ export interface SerialTransport {
13
+ open(opts?: {
14
+ baudRate?: number;
15
+ }): Promise<void>;
16
+ write(data: Uint8Array): Promise<void>;
17
+ /** Raw chunks as they arrive; ends on close/disconnect. */
18
+ readable(): AsyncIterableIterator<Uint8Array>;
19
+ close(): Promise<void>;
20
+ readonly info: SerialTransportInfo;
21
+ onDisconnect(cb: () => void): () => void;
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transport/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,2DAA2D;IAC3D,QAAQ,IAAI,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC1C"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Byte-transport abstraction (contracts/07_SDK_FACADE.md §1 "link").
3
+ * WebSerial (browser), serialport (Node), loopback (tests) and .depzrec
4
+ * replay all implement this. The SDK core touches nothing else.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transport/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * WebSerial transport (Chrome/Edge, secure context). The `SerialPort` must be
3
+ * obtained by the app inside a user gesture (`navigator.serial.requestPort()`)
4
+ * and passed here — the SDK never triggers the permission picker itself.
5
+ */
6
+ import { type DeviceInfo, type ListOptions, type OpenDeviceOptions, type OpenTarget } from "../discovery.js";
7
+ import type { DepzDevice } from "../device/device.js";
8
+ import type { SerialTransport, SerialTransportInfo } from "./types.js";
9
+ export interface WebSerialPortLike {
10
+ open(options: {
11
+ baudRate: number;
12
+ }): Promise<void>;
13
+ close(): Promise<void>;
14
+ getInfo(): {
15
+ usbVendorId?: number;
16
+ usbProductId?: number;
17
+ };
18
+ readable: ReadableStream<Uint8Array> | null;
19
+ writable: WritableStream<Uint8Array> | null;
20
+ addEventListener?(type: "disconnect", cb: () => void): void;
21
+ removeEventListener?(type: "disconnect", cb: () => void): void;
22
+ }
23
+ /** Feature-detect Web Serial support in the current environment. */
24
+ export declare function isWebSerialSupported(): boolean;
25
+ /** Previously-granted ports (survive page reloads per origin+device). */
26
+ export declare function getGrantedPorts(): Promise<WebSerialPortLike[]>;
27
+ /**
28
+ * Watch physical connect events; used by the firmware-update flow to
29
+ * re-acquire a device after it reboots. Returns an unsubscribe function.
30
+ */
31
+ export declare function watchConnect(cb: (port: WebSerialPortLike) => void): () => void;
32
+ export declare class WebSerialTransport implements SerialTransport {
33
+ private port;
34
+ readonly info: SerialTransportInfo;
35
+ private reader;
36
+ private writer;
37
+ private disconnectCbs;
38
+ private disconnectHandler;
39
+ constructor(port: WebSerialPortLike);
40
+ open(opts?: {
41
+ baudRate?: number;
42
+ }): Promise<void>;
43
+ write(data: Uint8Array): Promise<void>;
44
+ readable(): AsyncIterableIterator<Uint8Array>;
45
+ close(): Promise<void>;
46
+ onDisconnect(cb: () => void): () => void;
47
+ private fireDisconnect;
48
+ }
49
+ /**
50
+ * Probe the already-granted WebSerial ports and return the DEPZ devices among
51
+ * them, ordered by DEVICE serial (GET_SERIAL) — the USB iSerial is unavailable
52
+ * in the browser, so the serial is read over the protocol. By default every
53
+ * granted port is probed (`matchUsb: false`) since a granted port is
54
+ * user-curated; pass `matchUsb: true` to probe only known-DEPZ vid/pids.
55
+ */
56
+ export declare function listDepzDevices(opts?: ListOptions): Promise<DeviceInfo[]>;
57
+ /**
58
+ * Open the right sensor class for a granted WebSerial port.
59
+ *
60
+ * `target` is a `WebSerialPortLike` (typically fresh from
61
+ * `navigator.serial.requestPort()`), a granted-port path string / `DeviceInfo`
62
+ * from `listDepzDevices()`, a candidate index (number, ordered by device
63
+ * serial), or omitted for the smallest-serial DEPZ candidate. `opts.serial`
64
+ * selects the candidate whose device serial matches exactly. Selection probes
65
+ * the granted ports; explicit targets open directly. Throws
66
+ * `NoDepzDeviceError` when nothing matches.
67
+ */
68
+ export declare function openDevice(target?: OpenTarget | WebSerialPortLike, opts?: OpenDeviceOptions): Promise<DepzDevice>;
69
+ //# sourceMappingURL=webserial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webserial.d.ts","sourceRoot":"","sources":["../../src/transport/webserial.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAML,KAAK,UAAU,EAEf,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGvE,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC5C,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC5C,gBAAgB,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC5D,mBAAmB,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAChE;AAaD,oEAAoE;AACpE,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,yEAAyE;AACzE,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAGpE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI,CAS9E;AAED,qBAAa,kBAAmB,YAAW,eAAe;IAO5C,OAAO,CAAC,IAAI;IANxB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,iBAAiB,CAA6B;gBAElC,IAAI,EAAE,iBAAiB;IAKrC,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrC,QAAQ,IAAI,qBAAqB,CAAC,UAAU,CAAC;IAmB9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB5B,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAOxC,OAAO,CAAC,cAAc;CAKvB;AAkCD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAQnF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAC9B,MAAM,CAAC,EAAE,UAAU,GAAG,iBAAiB,EACvC,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,UAAU,CAAC,CAiBrB"}