@robdobsn/raftjs 1.8.5 → 1.11.5
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/.editorconfig +14 -0
- package/.gitattributes +11 -0
- package/.nvmrc +1 -0
- package/TODO.md +1 -0
- package/dist/react-native/RaftAttributeHandler.d.ts +14 -0
- package/dist/react-native/RaftAttributeHandler.js +375 -0
- package/dist/react-native/RaftAttributeHandler.js.map +1 -0
- package/dist/react-native/RaftChannel.d.ts +20 -0
- package/dist/react-native/RaftChannel.js +12 -0
- package/dist/react-native/RaftChannel.js.map +1 -0
- package/dist/react-native/RaftChannelBLE.native.d.ts +95 -0
- package/dist/react-native/RaftChannelBLE.native.js +483 -0
- package/dist/react-native/RaftChannelBLE.native.js.map +1 -0
- package/dist/react-native/RaftChannelBLE.web.d.ts +40 -0
- package/dist/react-native/RaftChannelBLE.web.js +302 -0
- package/dist/react-native/RaftChannelBLE.web.js.map +1 -0
- package/dist/react-native/RaftChannelBLEFactory.d.ts +10 -0
- package/dist/react-native/RaftChannelBLEFactory.js +17 -0
- package/dist/react-native/RaftChannelBLEFactory.js.map +1 -0
- package/dist/react-native/RaftChannelBLEScanner.native.d.ts +18 -0
- package/dist/react-native/RaftChannelBLEScanner.native.js +138 -0
- package/dist/react-native/RaftChannelBLEScanner.native.js.map +1 -0
- package/dist/react-native/RaftChannelSimulated.d.ts +42 -0
- package/dist/react-native/RaftChannelSimulated.js +1001 -0
- package/dist/react-native/RaftChannelSimulated.js.map +1 -0
- package/dist/react-native/RaftChannelWebSerial.d.ts +39 -0
- package/dist/react-native/RaftChannelWebSerial.js +329 -0
- package/dist/react-native/RaftChannelWebSerial.js.map +1 -0
- package/dist/react-native/RaftChannelWebSocket.d.ts +30 -0
- package/dist/react-native/RaftChannelWebSocket.js +222 -0
- package/dist/react-native/RaftChannelWebSocket.js.map +1 -0
- package/dist/react-native/RaftCommsStats.d.ts +39 -0
- package/dist/react-native/RaftCommsStats.js +128 -0
- package/dist/react-native/RaftCommsStats.js.map +1 -0
- package/dist/react-native/RaftConnEvents.d.ts +39 -0
- package/dist/react-native/RaftConnEvents.js +54 -0
- package/dist/react-native/RaftConnEvents.js.map +1 -0
- package/dist/react-native/RaftConnector.d.ts +257 -0
- package/dist/react-native/RaftConnector.js +671 -0
- package/dist/react-native/RaftConnector.js.map +1 -0
- package/dist/react-native/RaftCustomAttrHandler.d.ts +6 -0
- package/dist/react-native/RaftCustomAttrHandler.js +93 -0
- package/dist/react-native/RaftCustomAttrHandler.js.map +1 -0
- package/dist/react-native/RaftDeviceInfo.d.ts +71 -0
- package/dist/react-native/RaftDeviceInfo.js +50 -0
- package/dist/react-native/RaftDeviceInfo.js.map +1 -0
- package/dist/react-native/RaftDeviceManager.d.ts +73 -0
- package/dist/react-native/RaftDeviceManager.js +812 -0
- package/dist/react-native/RaftDeviceManager.js.map +1 -0
- package/dist/react-native/RaftDeviceMgrIF.d.ts +19 -0
- package/dist/react-native/RaftDeviceMgrIF.js +11 -0
- package/dist/react-native/RaftDeviceMgrIF.js.map +1 -0
- package/dist/react-native/RaftDeviceMsg.d.ts +9 -0
- package/dist/react-native/RaftDeviceMsg.js +11 -0
- package/dist/react-native/RaftDeviceMsg.js.map +1 -0
- package/dist/react-native/RaftDeviceStates.d.ts +55 -0
- package/dist/react-native/RaftDeviceStates.js +81 -0
- package/dist/react-native/RaftDeviceStates.js.map +1 -0
- package/dist/react-native/RaftFileHandler.d.ts +52 -0
- package/dist/react-native/RaftFileHandler.js +502 -0
- package/dist/react-native/RaftFileHandler.js.map +1 -0
- package/dist/react-native/RaftLog.d.ts +22 -0
- package/dist/react-native/RaftLog.js +63 -0
- package/dist/react-native/RaftLog.js.map +1 -0
- package/dist/react-native/RaftMiniHDLC.d.ts +18 -0
- package/dist/react-native/RaftMiniHDLC.js +383 -0
- package/dist/react-native/RaftMiniHDLC.js.map +1 -0
- package/dist/react-native/RaftMsgHandler.d.ts +62 -0
- package/dist/react-native/RaftMsgHandler.js +511 -0
- package/dist/react-native/RaftMsgHandler.js.map +1 -0
- package/dist/react-native/RaftMsgTrackInfo.d.ts +17 -0
- package/dist/react-native/RaftMsgTrackInfo.js +42 -0
- package/dist/react-native/RaftMsgTrackInfo.js.map +1 -0
- package/dist/react-native/RaftProtocolDefs.d.ts +30 -0
- package/dist/react-native/RaftProtocolDefs.js +48 -0
- package/dist/react-native/RaftProtocolDefs.js.map +1 -0
- package/dist/react-native/RaftPublish.d.ts +2 -0
- package/dist/react-native/RaftPublish.js +81 -0
- package/dist/react-native/RaftPublish.js.map +1 -0
- package/dist/react-native/RaftStreamHandler.d.ts +49 -0
- package/dist/react-native/RaftStreamHandler.js +324 -0
- package/dist/react-native/RaftStreamHandler.js.map +1 -0
- package/dist/react-native/RaftStruct.d.ts +3 -0
- package/dist/react-native/RaftStruct.js +258 -0
- package/dist/react-native/RaftStruct.js.map +1 -0
- package/dist/react-native/RaftSysTypeManager.d.ts +16 -0
- package/dist/react-native/RaftSysTypeManager.js +78 -0
- package/dist/react-native/RaftSysTypeManager.js.map +1 -0
- package/dist/react-native/RaftSystemType.d.ts +30 -0
- package/dist/react-native/RaftSystemType.js +3 -0
- package/dist/react-native/RaftSystemType.js.map +1 -0
- package/dist/react-native/RaftSystemUtils.d.ts +152 -0
- package/dist/react-native/RaftSystemUtils.js +463 -0
- package/dist/react-native/RaftSystemUtils.js.map +1 -0
- package/dist/react-native/RaftTypes.d.ts +216 -0
- package/dist/react-native/RaftTypes.js +153 -0
- package/dist/react-native/RaftTypes.js.map +1 -0
- package/dist/react-native/RaftUpdateEvents.d.ts +33 -0
- package/dist/react-native/RaftUpdateEvents.js +46 -0
- package/dist/react-native/RaftUpdateEvents.js.map +1 -0
- package/dist/react-native/RaftUpdateManager.d.ts +61 -0
- package/dist/react-native/RaftUpdateManager.js +621 -0
- package/dist/react-native/RaftUpdateManager.js.map +1 -0
- package/dist/react-native/RaftUtils.d.ts +128 -0
- package/dist/react-native/RaftUtils.js +487 -0
- package/dist/react-native/RaftUtils.js.map +1 -0
- package/dist/react-native/RaftWifiTypes.d.ts +23 -0
- package/dist/react-native/RaftWifiTypes.js +43 -0
- package/dist/react-native/RaftWifiTypes.js.map +1 -0
- package/dist/react-native/main.d.ts +27 -0
- package/dist/react-native/main.js +52 -0
- package/dist/react-native/main.js.map +1 -0
- package/dist/web/RaftAttributeHandler.js +1 -1
- package/dist/web/RaftAttributeHandler.js.map +1 -1
- package/dist/web/RaftChannelBLE.web.js +8 -6
- package/dist/web/RaftChannelBLE.web.js.map +1 -1
- package/dist/web/RaftChannelSimulated.d.ts +10 -0
- package/dist/web/RaftChannelSimulated.js +665 -82
- package/dist/web/RaftChannelSimulated.js.map +1 -1
- package/dist/web/RaftChannelWebSerial.js +2 -2
- package/dist/web/RaftChannelWebSerial.js.map +1 -1
- package/dist/web/RaftChannelWebSocket.js +16 -1
- package/dist/web/RaftChannelWebSocket.js.map +1 -1
- package/dist/web/RaftConnector.d.ts +12 -1
- package/dist/web/RaftConnector.js +45 -9
- package/dist/web/RaftConnector.js.map +1 -1
- package/dist/web/RaftCustomAttrHandler.d.ts +2 -0
- package/dist/web/RaftCustomAttrHandler.js +54 -26
- package/dist/web/RaftCustomAttrHandler.js.map +1 -1
- package/dist/web/RaftDeviceInfo.d.ts +3 -1
- package/dist/web/RaftDeviceInfo.js +17 -3
- package/dist/web/RaftDeviceInfo.js.map +1 -1
- package/dist/web/RaftDeviceManager.d.ts +32 -2
- package/dist/web/RaftDeviceManager.js +307 -74
- package/dist/web/RaftDeviceManager.js.map +1 -1
- package/dist/web/RaftDeviceMgrIF.d.ts +5 -1
- package/dist/web/RaftDeviceStates.d.ts +20 -2
- package/dist/web/RaftDeviceStates.js +25 -4
- package/dist/web/RaftDeviceStates.js.map +1 -1
- package/dist/web/RaftMsgHandler.js.map +1 -1
- package/dist/web/RaftPublish.d.ts +2 -0
- package/dist/web/RaftPublish.js +81 -0
- package/dist/web/RaftPublish.js.map +1 -0
- package/dist/web/RaftStreamHandler.d.ts +11 -0
- package/dist/web/RaftStreamHandler.js +68 -1
- package/dist/web/RaftStreamHandler.js.map +1 -1
- package/dist/web/RaftStruct.js +197 -147
- package/dist/web/RaftStruct.js.map +1 -1
- package/dist/web/RaftSystemUtils.d.ts +17 -1
- package/dist/web/RaftSystemUtils.js +51 -0
- package/dist/web/RaftSystemUtils.js.map +1 -1
- package/dist/web/RaftTypes.d.ts +21 -0
- package/dist/web/RaftTypes.js.map +1 -1
- package/dist/web/RaftUpdateManager.js +1 -1
- package/dist/web/RaftUpdateManager.js.map +1 -1
- package/dist/web/RaftUtils.d.ts +2 -0
- package/dist/web/RaftUtils.js +20 -0
- package/dist/web/RaftUtils.js.map +1 -1
- package/dist/web/main.d.ts +2 -0
- package/dist/web/main.js +1 -0
- package/dist/web/main.js.map +1 -1
- package/eslint.config.mjs +33 -0
- package/examples/dashboard/package.json +36 -0
- package/examples/dashboard/src/CommandPanel.tsx +147 -0
- package/examples/dashboard/src/ConnManager.ts +166 -0
- package/examples/dashboard/src/DeviceActionsForm.tsx +133 -0
- package/examples/dashboard/src/DeviceAttrsForm.tsx +49 -0
- package/examples/dashboard/src/DeviceLineChart.tsx +163 -0
- package/examples/dashboard/src/DevicePanel.tsx +247 -0
- package/examples/dashboard/src/DeviceStatsPanel.tsx +65 -0
- package/examples/dashboard/src/DevicesPanel.tsx +69 -0
- package/examples/dashboard/src/DispLedGrid.tsx +110 -0
- package/examples/dashboard/src/DispOneLed.tsx +20 -0
- package/examples/dashboard/src/LatencyTest.ts +130 -0
- package/examples/dashboard/src/LatencyTestPanel.tsx +92 -0
- package/examples/dashboard/src/Main.tsx +234 -0
- package/examples/dashboard/src/SettingsManager.ts +67 -0
- package/examples/dashboard/src/SettingsScreen.tsx +179 -0
- package/examples/dashboard/src/StatusPanel.tsx +71 -0
- package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +170 -0
- package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +125 -0
- package/examples/dashboard/src/SystemTypeGeneric/StateInfoGeneric.ts +38 -0
- package/examples/dashboard/src/SystemTypeGeneric/SystemTypeGeneric.ts +125 -0
- package/examples/dashboard/src/SystemTypeMarty/RICAddOn.ts +70 -0
- package/examples/dashboard/src/SystemTypeMarty/RICAddOnBase.ts +33 -0
- package/examples/dashboard/src/SystemTypeMarty/RICAddOnManager.ts +342 -0
- package/examples/dashboard/src/SystemTypeMarty/RICCommsStats.ts +170 -0
- package/examples/dashboard/src/SystemTypeMarty/RICHWElem.ts +123 -0
- package/examples/dashboard/src/SystemTypeMarty/RICLEDPatternChecker.ts +207 -0
- package/examples/dashboard/src/SystemTypeMarty/RICROSSerial.ts +464 -0
- package/examples/dashboard/src/SystemTypeMarty/RICServoFaultDetector.ts +146 -0
- package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +105 -0
- package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +371 -0
- package/examples/dashboard/src/SystemTypeMarty/RICTypes.ts +20 -0
- package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +119 -0
- package/examples/dashboard/src/index.html +15 -0
- package/examples/dashboard/src/index.tsx +13 -0
- package/examples/dashboard/src/styles.css +570 -0
- package/examples/dashboard/tsconfig.json +18 -0
- package/jest.config.js +11 -0
- package/package.json +49 -52
- package/src/RaftAttributeHandler.ts +450 -0
- package/src/RaftChannel.ts +32 -0
- package/src/RaftChannelBLE.native.ts +617 -0
- package/src/RaftChannelBLE.web.ts +374 -0
- package/src/RaftChannelBLEFactory.ts +13 -0
- package/src/RaftChannelBLEScanner.native.ts +184 -0
- package/src/RaftChannelSimulated.ts +1177 -0
- package/src/RaftChannelWebSerial.ts +420 -0
- package/src/RaftChannelWebSocket.ts +272 -0
- package/src/RaftCommsStats.ts +142 -0
- package/src/RaftConnEvents.ts +58 -0
- package/src/RaftConnector.ts +806 -0
- package/src/RaftCustomAttrHandler.ts +117 -0
- package/src/RaftDeviceInfo.ts +125 -0
- package/src/RaftDeviceManager.ts +1014 -0
- package/src/RaftDeviceMgrIF.ts +37 -0
- package/src/RaftDeviceMsg.ts +20 -0
- package/src/RaftDeviceStates.ts +122 -0
- package/src/RaftFileHandler.ts +668 -0
- package/src/RaftLog.ts +70 -0
- package/src/RaftMiniHDLC.ts +396 -0
- package/src/RaftMsgHandler.ts +812 -0
- package/src/RaftMsgTrackInfo.ts +51 -0
- package/src/RaftProtocolDefs.ts +46 -0
- package/src/RaftPublish.ts +92 -0
- package/src/RaftStreamHandler.ts +412 -0
- package/src/RaftStruct.ts +282 -0
- package/src/RaftSysTypeManager.ts +87 -0
- package/src/RaftSystemType.ts +34 -0
- package/src/RaftSystemUtils.ts +548 -0
- package/src/RaftTypes.ts +306 -0
- package/src/RaftUpdateEvents.ts +48 -0
- package/src/RaftUpdateManager.ts +781 -0
- package/src/RaftUtils.ts +514 -0
- package/src/RaftWifiTypes.ts +36 -0
- package/src/main.ts +40 -0
- package/testdata/TestDeviceTypeRecs.json +492 -0
- package/tsconfig.json +30 -0
- package/tsconfig.react-native.json +29 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// RaftStruct
|
|
4
|
+
// Part of RaftJS
|
|
5
|
+
//
|
|
6
|
+
// Rob Dobson 2024
|
|
7
|
+
// (C) 2024 All rights reserved
|
|
8
|
+
//
|
|
9
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
10
|
+
|
|
11
|
+
type FormatInstruction =
|
|
12
|
+
| { kind: "endian"; littleEndian: boolean }
|
|
13
|
+
| { kind: "spec"; code: string; repeat: number };
|
|
14
|
+
|
|
15
|
+
function parseFormatInstructions(format: string): FormatInstruction[] {
|
|
16
|
+
const instructions: FormatInstruction[] = [];
|
|
17
|
+
let idx = 0;
|
|
18
|
+
|
|
19
|
+
while (idx < format.length) {
|
|
20
|
+
|
|
21
|
+
const char = format[idx];
|
|
22
|
+
|
|
23
|
+
// Endianness specifiers
|
|
24
|
+
if (char === "<" || char === ">") {
|
|
25
|
+
instructions.push({ kind: "endian", littleEndian: char === "<" });
|
|
26
|
+
idx++;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Ignore whitespace
|
|
31
|
+
if (/\s/.test(char)) {
|
|
32
|
+
idx++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Attribute code
|
|
37
|
+
const code = char;
|
|
38
|
+
idx++;
|
|
39
|
+
|
|
40
|
+
// Check for repeat count using [N] syntax
|
|
41
|
+
let repeat = 1;
|
|
42
|
+
if (idx < format.length && format[idx] === "[") {
|
|
43
|
+
const endIdx = format.indexOf("]", idx + 1);
|
|
44
|
+
if (endIdx === -1) {
|
|
45
|
+
throw new Error(`Invalid format string: missing closing ] in "${format}"`);
|
|
46
|
+
}
|
|
47
|
+
const repeatStr = format.slice(idx + 1, endIdx);
|
|
48
|
+
repeat = parseInt(repeatStr, 10);
|
|
49
|
+
if (!Number.isFinite(repeat) || repeat <= 0) {
|
|
50
|
+
throw new Error(`Invalid repeat count "${repeatStr}" in format string "${format}"`);
|
|
51
|
+
}
|
|
52
|
+
idx = endIdx + 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
instructions.push({ kind: "spec", code, repeat });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return instructions;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function structUnpack(format: string, data: Uint8Array): number[] {
|
|
62
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
63
|
+
const results: number[] = [];
|
|
64
|
+
let offset = 0;
|
|
65
|
+
let littleEndian = false;
|
|
66
|
+
|
|
67
|
+
const instructions = parseFormatInstructions(format);
|
|
68
|
+
|
|
69
|
+
for (const instruction of instructions) {
|
|
70
|
+
if (instruction.kind === "endian") {
|
|
71
|
+
littleEndian = instruction.littleEndian;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { code, repeat } = instruction;
|
|
76
|
+
|
|
77
|
+
for (let count = 0; count < repeat; count++) {
|
|
78
|
+
switch (code) {
|
|
79
|
+
case "x": // Padding byte
|
|
80
|
+
offset += 1;
|
|
81
|
+
break;
|
|
82
|
+
case "c": // Char
|
|
83
|
+
case "B": // Unsigned 8-bit integer
|
|
84
|
+
case "?": // Boolean (stored as uint8)
|
|
85
|
+
results.push(view.getUint8(offset));
|
|
86
|
+
offset += 1;
|
|
87
|
+
break;
|
|
88
|
+
case "b": // Signed 8-bit integer
|
|
89
|
+
results.push(view.getInt8(offset));
|
|
90
|
+
offset += 1;
|
|
91
|
+
break;
|
|
92
|
+
case "h": // Signed 16-bit integer
|
|
93
|
+
results.push(view.getInt16(offset, littleEndian));
|
|
94
|
+
offset += 2;
|
|
95
|
+
break;
|
|
96
|
+
case "H": // Unsigned 16-bit integer
|
|
97
|
+
results.push(view.getUint16(offset, littleEndian));
|
|
98
|
+
offset += 2;
|
|
99
|
+
break;
|
|
100
|
+
case "i": // Signed 32-bit integer
|
|
101
|
+
case "l": // Signed 32-bit integer
|
|
102
|
+
results.push(view.getInt32(offset, littleEndian));
|
|
103
|
+
offset += 4;
|
|
104
|
+
break;
|
|
105
|
+
case "I": // Unsigned 32-bit integer
|
|
106
|
+
case "L": // Unsigned 32-bit integer
|
|
107
|
+
results.push(view.getUint32(offset, littleEndian));
|
|
108
|
+
offset += 4;
|
|
109
|
+
break;
|
|
110
|
+
// case "q": // Signed 64-bit integer
|
|
111
|
+
// results.push(Number(view.getBigInt64(offset, littleEndian)));
|
|
112
|
+
// offset += 8;
|
|
113
|
+
// break;
|
|
114
|
+
// case "Q": // Unsigned 64-bit integer
|
|
115
|
+
// results.push(Number(view.getBigUint64(offset, littleEndian)));
|
|
116
|
+
// offset += 8;
|
|
117
|
+
// break;
|
|
118
|
+
case "f": // 32-bit float
|
|
119
|
+
results.push(view.getFloat32(offset, littleEndian));
|
|
120
|
+
offset += 4;
|
|
121
|
+
break;
|
|
122
|
+
case "d": // 64-bit float
|
|
123
|
+
results.push(view.getFloat64(offset, littleEndian));
|
|
124
|
+
offset += 8;
|
|
125
|
+
break;
|
|
126
|
+
default:
|
|
127
|
+
throw new Error(`Unknown format character: ${code}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return results;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function structSizeOf(format: string): number {
|
|
136
|
+
let size = 0;
|
|
137
|
+
const instructions = parseFormatInstructions(format);
|
|
138
|
+
|
|
139
|
+
for (const instruction of instructions) {
|
|
140
|
+
if (instruction.kind === "endian") {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const { code, repeat } = instruction;
|
|
145
|
+
let unitSize: number;
|
|
146
|
+
|
|
147
|
+
switch (code) {
|
|
148
|
+
case "x": // Padding byte
|
|
149
|
+
case "c": // Char
|
|
150
|
+
case "b": // Signed 8-bit integer
|
|
151
|
+
case "B": // Unsigned 8-bit integer
|
|
152
|
+
case "?": // Boolean (uint8)
|
|
153
|
+
unitSize = 1;
|
|
154
|
+
break;
|
|
155
|
+
case "h": // Signed 16-bit integer
|
|
156
|
+
case "H": // Unsigned 16-bit integer
|
|
157
|
+
unitSize = 2;
|
|
158
|
+
break;
|
|
159
|
+
case "i": // Signed 32-bit integer
|
|
160
|
+
case "I": // Unsigned 32-bit integer
|
|
161
|
+
case "l": // Signed 32-bit integer
|
|
162
|
+
case "L": // Unsigned 32-bit integer
|
|
163
|
+
unitSize = 4;
|
|
164
|
+
break;
|
|
165
|
+
// case "q": // Signed 64-bit integer
|
|
166
|
+
// case "Q": // Unsigned 64-bit integer
|
|
167
|
+
// unitSize = 8;
|
|
168
|
+
// break;
|
|
169
|
+
case "f": // 32-bit float
|
|
170
|
+
unitSize = 4;
|
|
171
|
+
break;
|
|
172
|
+
case "d": // 64-bit float
|
|
173
|
+
unitSize = 8;
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
throw new Error(`Unknown format character: ${code}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
size += unitSize * repeat;
|
|
180
|
+
}
|
|
181
|
+
return size;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function structPack(format: string, values: number[]): Uint8Array {
|
|
185
|
+
const size = structSizeOf(format);
|
|
186
|
+
const buffer = new ArrayBuffer(size);
|
|
187
|
+
const view = new DataView(buffer);
|
|
188
|
+
let offset = 0;
|
|
189
|
+
let littleEndian = false;
|
|
190
|
+
|
|
191
|
+
const instructions = parseFormatInstructions(format);
|
|
192
|
+
let valueIdx = 0;
|
|
193
|
+
|
|
194
|
+
for (const instruction of instructions) {
|
|
195
|
+
if (instruction.kind === "endian") {
|
|
196
|
+
littleEndian = instruction.littleEndian;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const { code, repeat } = instruction;
|
|
201
|
+
|
|
202
|
+
for (let count = 0; count < repeat; count++) {
|
|
203
|
+
switch (code) {
|
|
204
|
+
case "x": // Padding byte
|
|
205
|
+
offset += 1;
|
|
206
|
+
break;
|
|
207
|
+
case "c": // Char
|
|
208
|
+
case "b": // Signed 8-bit integer
|
|
209
|
+
if (valueIdx >= values.length) {
|
|
210
|
+
throw new Error("Insufficient values provided for structPack");
|
|
211
|
+
}
|
|
212
|
+
view.setInt8(offset, values[valueIdx++]);
|
|
213
|
+
offset += 1;
|
|
214
|
+
break;
|
|
215
|
+
case "B": // Unsigned 8-bit integer
|
|
216
|
+
case "?": // Boolean (uint8)
|
|
217
|
+
if (valueIdx >= values.length) {
|
|
218
|
+
throw new Error("Insufficient values provided for structPack");
|
|
219
|
+
}
|
|
220
|
+
view.setUint8(offset, values[valueIdx++]);
|
|
221
|
+
offset += 1;
|
|
222
|
+
break;
|
|
223
|
+
case "h": // Signed 16-bit integer
|
|
224
|
+
if (valueIdx >= values.length) {
|
|
225
|
+
throw new Error("Insufficient values provided for structPack");
|
|
226
|
+
}
|
|
227
|
+
view.setInt16(offset, values[valueIdx++], littleEndian);
|
|
228
|
+
offset += 2;
|
|
229
|
+
break;
|
|
230
|
+
case "H": // Unsigned 16-bit integer
|
|
231
|
+
if (valueIdx >= values.length) {
|
|
232
|
+
throw new Error("Insufficient values provided for structPack");
|
|
233
|
+
}
|
|
234
|
+
view.setUint16(offset, values[valueIdx++], littleEndian);
|
|
235
|
+
offset += 2;
|
|
236
|
+
break;
|
|
237
|
+
case "i": // Signed 32-bit integer
|
|
238
|
+
case "l": // Signed 32-bit integer
|
|
239
|
+
if (valueIdx >= values.length) {
|
|
240
|
+
throw new Error("Insufficient values provided for structPack");
|
|
241
|
+
}
|
|
242
|
+
view.setInt32(offset, values[valueIdx++], littleEndian);
|
|
243
|
+
offset += 4;
|
|
244
|
+
break;
|
|
245
|
+
case "I": // Unsigned 32-bit integer
|
|
246
|
+
case "L": // Unsigned 32-bit integer
|
|
247
|
+
if (valueIdx >= values.length) {
|
|
248
|
+
throw new Error("Insufficient values provided for structPack");
|
|
249
|
+
}
|
|
250
|
+
view.setUint32(offset, values[valueIdx++], littleEndian);
|
|
251
|
+
offset += 4;
|
|
252
|
+
break;
|
|
253
|
+
// case "q": // Signed 64-bit integer
|
|
254
|
+
// view.setBigInt64(offset, BigInt(values[valueIdx++]), littleEndian);
|
|
255
|
+
// offset += 8;
|
|
256
|
+
// break;
|
|
257
|
+
// case "Q": // Unsigned 64-bit integer
|
|
258
|
+
// view.setBigUint64(offset, BigInt(values[valueIdx++]), littleEndian);
|
|
259
|
+
// offset += 8;
|
|
260
|
+
// break;
|
|
261
|
+
case "f": // 32-bit float
|
|
262
|
+
if (valueIdx >= values.length) {
|
|
263
|
+
throw new Error("Insufficient values provided for structPack");
|
|
264
|
+
}
|
|
265
|
+
view.setFloat32(offset, values[valueIdx++], littleEndian);
|
|
266
|
+
offset += 4;
|
|
267
|
+
break;
|
|
268
|
+
case "d": // 64-bit float
|
|
269
|
+
if (valueIdx >= values.length) {
|
|
270
|
+
throw new Error("Insufficient values provided for structPack");
|
|
271
|
+
}
|
|
272
|
+
view.setFloat64(offset, values[valueIdx++], littleEndian);
|
|
273
|
+
offset += 8;
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
throw new Error(`Unknown format character: ${code}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return new Uint8Array(buffer);
|
|
282
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { RaftSystemType } from "./RaftSystemType";
|
|
2
|
+
|
|
3
|
+
type RaftSystemTypeCreator = () => RaftSystemType;
|
|
4
|
+
|
|
5
|
+
export default class RaftSysTypeManager {
|
|
6
|
+
// Singleton instance
|
|
7
|
+
private static _instance: RaftSysTypeManager;
|
|
8
|
+
|
|
9
|
+
// System type map
|
|
10
|
+
private _sysTypes: Map<string, RaftSystemTypeCreator> = new Map();
|
|
11
|
+
private _defaultSysTypeFactory: RaftSystemTypeCreator | null = null;
|
|
12
|
+
|
|
13
|
+
// Get instance (Singleton)
|
|
14
|
+
public static getInstance(): RaftSysTypeManager {
|
|
15
|
+
if (!RaftSysTypeManager._instance) {
|
|
16
|
+
RaftSysTypeManager._instance = new RaftSysTypeManager();
|
|
17
|
+
}
|
|
18
|
+
return RaftSysTypeManager._instance;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Add a system type by name with its factory
|
|
22
|
+
public addSystemType(sysType: string, factory: RaftSystemTypeCreator): void {
|
|
23
|
+
if (this._sysTypes.has(sysType)) {
|
|
24
|
+
throw new Error(`System type '${sysType}' is already registered.`);
|
|
25
|
+
}
|
|
26
|
+
this._sysTypes.set(sysType, factory);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Set the default system type factory
|
|
30
|
+
public addDefaultSystemType(factory: RaftSystemTypeCreator): void {
|
|
31
|
+
this._defaultSysTypeFactory = factory;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Create a system type by name
|
|
35
|
+
public createSystemType(sysType: string): RaftSystemType | null {
|
|
36
|
+
const factory = this._sysTypes.get(sysType);
|
|
37
|
+
if (!factory) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return factory();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Create the default system type
|
|
44
|
+
public createDefaultSystemType(): RaftSystemType | null {
|
|
45
|
+
if (!this._defaultSysTypeFactory) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return this._defaultSysTypeFactory();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Get a list of all unique BLE service UUIDs
|
|
52
|
+
getAllServiceUUIDs(): string[] {
|
|
53
|
+
const serviceUUIDs = new Set<string>();
|
|
54
|
+
this._sysTypes.forEach((factory) => {
|
|
55
|
+
const sysType = factory();
|
|
56
|
+
if (!sysType.BLEServiceUUIDs) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
sysType.BLEServiceUUIDs.forEach((uuid) => serviceUUIDs.add(uuid));
|
|
60
|
+
});
|
|
61
|
+
return Array.from(serviceUUIDs);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Get a list of all device name prefixes to filter on
|
|
65
|
+
getAllNamePrefixes(): string[] {
|
|
66
|
+
const deviceNames = new Set<string>();
|
|
67
|
+
this._sysTypes.forEach((factory) => {
|
|
68
|
+
const sysType = factory();
|
|
69
|
+
if (!sysType.BLEDeviceNames) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
sysType.BLEDeviceNames.forEach((name) => deviceNames.add(name));
|
|
73
|
+
});
|
|
74
|
+
return Array.from(deviceNames);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Find the system type for a given BLE device name prefix
|
|
78
|
+
getSystemTypeByBLENamePrefix(name: string): RaftSystemType | null {
|
|
79
|
+
for (const factory of this._sysTypes.values()) {
|
|
80
|
+
const sysType = factory();
|
|
81
|
+
if (sysType.BLEDeviceNames && sysType.BLEDeviceNames.some((prefix) => name.startsWith(prefix))) {
|
|
82
|
+
return sysType;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import RaftDeviceMgrIF from "./RaftDeviceMgrIF";
|
|
2
|
+
import RaftSystemUtils from "./RaftSystemUtils";
|
|
3
|
+
import { RaftEventFn } from "./RaftTypes";
|
|
4
|
+
|
|
5
|
+
export type RaftSubscribeForUpdatesCBType = (systemUtils: RaftSystemUtils, enable: boolean) => Promise<void>;
|
|
6
|
+
export type RaftStateIsInvalidCBType = () => void;
|
|
7
|
+
export type RaftRxOtherMsgType = (payload: Uint8Array, _frameTimeMs: number) => void;
|
|
8
|
+
|
|
9
|
+
export interface ConnectorOptions {
|
|
10
|
+
wsSuffix?: string;
|
|
11
|
+
connTimeoutMs?: number;
|
|
12
|
+
bleConnItvlMs?: number;
|
|
13
|
+
bleUuid?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface RaftSystemType {
|
|
17
|
+
nameForDialogs: string;
|
|
18
|
+
defaultWiFiHostname?: string;
|
|
19
|
+
BLEServiceUUIDs?: string[];
|
|
20
|
+
BLECmdUUID?: string;
|
|
21
|
+
BLERespUUID?: string;
|
|
22
|
+
BLEDeviceNames?: string[];
|
|
23
|
+
firmwareDestName?: string;
|
|
24
|
+
normalFileDestName?: string;
|
|
25
|
+
connectorOptions: ConnectorOptions;
|
|
26
|
+
setup: (systemUtils: RaftSystemUtils, onEvent: RaftEventFn | null) => void;
|
|
27
|
+
subscribeForUpdates: RaftSubscribeForUpdatesCBType | null;
|
|
28
|
+
stateIsInvalid: RaftStateIsInvalidCBType | null;
|
|
29
|
+
rxOtherMsgType: RaftRxOtherMsgType | null;
|
|
30
|
+
deviceMgrIF?: RaftDeviceMgrIF;
|
|
31
|
+
nonRaftTypeCode?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type RaftGetSystemTypeCBType = (systemUtils: RaftSystemUtils) => Promise<RaftSystemType | null>;
|