@robdobsn/raftjs 1.8.5 → 1.10.7
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 +1000 -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 +248 -0
- package/dist/react-native/RaftConnector.js +658 -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 +61 -0
- package/dist/react-native/RaftDeviceManager.js +665 -0
- package/dist/react-native/RaftDeviceManager.js.map +1 -0
- package/dist/react-native/RaftDeviceMgrIF.d.ts +15 -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 +37 -0
- package/dist/react-native/RaftDeviceStates.js +60 -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/RaftStreamHandler.d.ts +38 -0
- package/dist/react-native/RaftStreamHandler.js +258 -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 +136 -0
- package/dist/react-native/RaftSystemUtils.js +412 -0
- package/dist/react-native/RaftSystemUtils.js.map +1 -0
- package/dist/react-native/RaftTypes.d.ts +195 -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 +26 -0
- package/dist/react-native/main.js +51 -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 +662 -80
- 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 +2 -0
- package/dist/web/RaftConnector.js +38 -15
- 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 +19 -1
- package/dist/web/RaftDeviceManager.js +89 -3
- package/dist/web/RaftDeviceManager.js.map +1 -1
- package/dist/web/RaftDeviceStates.d.ts +1 -1
- package/dist/web/RaftDeviceStates.js +2 -2
- package/dist/web/RaftDeviceStates.js.map +1 -1
- package/dist/web/RaftMsgHandler.js.map +1 -1
- package/dist/web/RaftStreamHandler.js +2 -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/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 +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 +171 -0
- package/examples/dashboard/src/DevicesPanel.tsx +58 -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 +174 -0
- package/examples/dashboard/src/StatusPanel.tsx +71 -0
- package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +162 -0
- package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +91 -0
- package/examples/dashboard/src/SystemTypeGeneric/StateInfoGeneric.ts +30 -0
- package/examples/dashboard/src/SystemTypeGeneric/SystemTypeGeneric.ts +91 -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 +97 -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 +408 -0
- package/examples/dashboard/tsconfig.json +18 -0
- package/jest.config.js +11 -0
- package/package.json +4 -7
- 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 +1176 -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 +785 -0
- package/src/RaftCustomAttrHandler.ts +117 -0
- package/src/RaftDeviceInfo.ts +125 -0
- package/src/RaftDeviceManager.ts +844 -0
- package/src/RaftDeviceMgrIF.ts +33 -0
- package/src/RaftDeviceMsg.ts +20 -0
- package/src/RaftDeviceStates.ts +92 -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/RaftStreamHandler.ts +329 -0
- package/src/RaftStruct.ts +282 -0
- package/src/RaftSysTypeManager.ts +87 -0
- package/src/RaftSystemType.ts +34 -0
- package/src/RaftSystemUtils.ts +489 -0
- package/src/RaftTypes.ts +279 -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 +39 -0
- package/testdata/TestDeviceTypeRecs.json +492 -0
- package/tsconfig.json +30 -0
- package/tsconfig.react-native.json +29 -0
|
@@ -31,6 +31,29 @@ class RaftChannelSimulated {
|
|
|
31
31
|
this._requestedFileBlockSize = 500;
|
|
32
32
|
// Simulated device type information - this is a copy of part of DeviceTypeInfo in RaftCore
|
|
33
33
|
this._deviceTypeInfo = {
|
|
34
|
+
"AMG8833": {
|
|
35
|
+
"name": "AMG8833",
|
|
36
|
+
"desc": "Thermal Camera",
|
|
37
|
+
"manu": "Panasonic",
|
|
38
|
+
"type": "AMG8833",
|
|
39
|
+
"clas": ["TCAM"],
|
|
40
|
+
"resp": {
|
|
41
|
+
"b": 128,
|
|
42
|
+
"a": [
|
|
43
|
+
{
|
|
44
|
+
"n": "temp",
|
|
45
|
+
"t": "<h[64]",
|
|
46
|
+
"resolution": "8x8",
|
|
47
|
+
"u": "°C",
|
|
48
|
+
"r": [-55, 125],
|
|
49
|
+
"s": -4,
|
|
50
|
+
"d": 64,
|
|
51
|
+
"f": ".2f",
|
|
52
|
+
"o": "float"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
34
57
|
"LSM6DS": {
|
|
35
58
|
"name": "LSM6DS",
|
|
36
59
|
"desc": "6-Axis IMU",
|
|
@@ -96,6 +119,264 @@ class RaftChannelSimulated {
|
|
|
96
119
|
}
|
|
97
120
|
]
|
|
98
121
|
}
|
|
122
|
+
},
|
|
123
|
+
"LTR-329": {
|
|
124
|
+
"name": "LTR-329",
|
|
125
|
+
"desc": "Visible light and IR Sensor",
|
|
126
|
+
"manu": "Lite On",
|
|
127
|
+
"type": "LTR-329",
|
|
128
|
+
"clas": ["LGHT"],
|
|
129
|
+
"resp": {
|
|
130
|
+
"b": 4,
|
|
131
|
+
"a": [
|
|
132
|
+
{
|
|
133
|
+
"n": "ir",
|
|
134
|
+
"t": "<h",
|
|
135
|
+
"u": "lux",
|
|
136
|
+
"r": [0, 64000],
|
|
137
|
+
"f": "d",
|
|
138
|
+
"o": "uint16"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"n": "visible",
|
|
142
|
+
"t": "<h",
|
|
143
|
+
"u": "lux",
|
|
144
|
+
"r": [0, 64000],
|
|
145
|
+
"f": "d",
|
|
146
|
+
"o": "uint16"
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"c": {
|
|
150
|
+
"n": "ltr329_light_calc",
|
|
151
|
+
"c": "int combined = buf[0] + (((uint16_t)buf[1])<<8); out.ir = buf[2] + (((uint16_t)buf[3])<<8); out.visible = combined - out.ir;",
|
|
152
|
+
"j": "let combined = buf[0] + (buf[1] << 8); let ir = buf[2] + (buf[3] << 8); attrValues['ir'].push(ir); attrValues['visible'].push(Math.max(0, combined - ir));"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"LTR-390": {
|
|
157
|
+
"name": "LTR-390",
|
|
158
|
+
"desc": "UV and Visible light sensor",
|
|
159
|
+
"manu": "Lite On",
|
|
160
|
+
"type": "LTR-390",
|
|
161
|
+
"clas": ["LGHT"],
|
|
162
|
+
"resp": {
|
|
163
|
+
"b": 5,
|
|
164
|
+
"a": [
|
|
165
|
+
{
|
|
166
|
+
"n": "ambient",
|
|
167
|
+
"t": "<H",
|
|
168
|
+
"u": "lux",
|
|
169
|
+
"r": [0, 64000],
|
|
170
|
+
"d": 1.25,
|
|
171
|
+
"f": ".2f",
|
|
172
|
+
"o": "float"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"n": "UVI",
|
|
176
|
+
"at": 3,
|
|
177
|
+
"t": "<H",
|
|
178
|
+
"u": "index",
|
|
179
|
+
"r": [0, 64000],
|
|
180
|
+
"d": 24,
|
|
181
|
+
"f": ".3f",
|
|
182
|
+
"o": "float"
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
"actions": []
|
|
187
|
+
},
|
|
188
|
+
"VL53L4CD": {
|
|
189
|
+
"name": "VL53L4CD",
|
|
190
|
+
"desc": "ToF distance sensor with range 0-1.3m",
|
|
191
|
+
"manu": "ST",
|
|
192
|
+
"type": "VL53L4CD",
|
|
193
|
+
"clas": ["DIST"],
|
|
194
|
+
"resp": {
|
|
195
|
+
"b": 3,
|
|
196
|
+
"a": [
|
|
197
|
+
{
|
|
198
|
+
"n": "valid",
|
|
199
|
+
"t": "B",
|
|
200
|
+
"u": "",
|
|
201
|
+
"r": [0, 1],
|
|
202
|
+
"m": "0x04",
|
|
203
|
+
"x": "0x04",
|
|
204
|
+
"s": 2,
|
|
205
|
+
"f": "b",
|
|
206
|
+
"o": "bool",
|
|
207
|
+
"vs": false
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"n": "dist",
|
|
211
|
+
"t": ">H",
|
|
212
|
+
"u": "mm",
|
|
213
|
+
"r": [0, 65535],
|
|
214
|
+
"f": "3d",
|
|
215
|
+
"o": "uint16",
|
|
216
|
+
"vft": "valid"
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"us": 100000
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"RoboticalServo": {
|
|
223
|
+
"name": "Robotical Servo",
|
|
224
|
+
"desc": "Servo",
|
|
225
|
+
"manu": "Robotical",
|
|
226
|
+
"type": "RoboticalServo",
|
|
227
|
+
"clas": ["SRVO"],
|
|
228
|
+
"resp": {
|
|
229
|
+
"b": 6,
|
|
230
|
+
"a": [
|
|
231
|
+
{
|
|
232
|
+
"n": "angle",
|
|
233
|
+
"t": ">h",
|
|
234
|
+
"r": [-180.0, 180.0],
|
|
235
|
+
"f": ".1f",
|
|
236
|
+
"d": 10,
|
|
237
|
+
"o": "int16",
|
|
238
|
+
"u": "degrees"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"n": "current",
|
|
242
|
+
"t": "b",
|
|
243
|
+
"r": [-128, 127],
|
|
244
|
+
"f": "d",
|
|
245
|
+
"o": "int8"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"n": "state",
|
|
249
|
+
"t": "B",
|
|
250
|
+
"r": [0, 255],
|
|
251
|
+
"f": "02x",
|
|
252
|
+
"o": "uint8"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"n": "velocity",
|
|
256
|
+
"t": ">h",
|
|
257
|
+
"r": [-32768, 32767],
|
|
258
|
+
"f": "d",
|
|
259
|
+
"o": "int16"
|
|
260
|
+
}
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"actions": [
|
|
264
|
+
{
|
|
265
|
+
"n": "angle",
|
|
266
|
+
"t": ">h",
|
|
267
|
+
"w": "0001",
|
|
268
|
+
"wz": "0064",
|
|
269
|
+
"f": ".1f",
|
|
270
|
+
"mul": 10,
|
|
271
|
+
"sub": 0,
|
|
272
|
+
"r": [-180.0, 180.0],
|
|
273
|
+
"d": 0
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"n": "enable",
|
|
277
|
+
"t": "B",
|
|
278
|
+
"w": "20",
|
|
279
|
+
"f": "b",
|
|
280
|
+
"r": [0, 1],
|
|
281
|
+
"d": 1
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
"RoboticalDCMotor": {
|
|
286
|
+
"name": "Robotical DC Motor",
|
|
287
|
+
"desc": "DCmotor",
|
|
288
|
+
"manu": "Robotical",
|
|
289
|
+
"type": "RoboticalDCMotor",
|
|
290
|
+
"clas": ["MOTR"],
|
|
291
|
+
"resp": {
|
|
292
|
+
"b": 4,
|
|
293
|
+
"a": [
|
|
294
|
+
{
|
|
295
|
+
"n": "angle",
|
|
296
|
+
"t": ">h",
|
|
297
|
+
"r": [-180.0, 180.0],
|
|
298
|
+
"f": ".1f",
|
|
299
|
+
"d": 10,
|
|
300
|
+
"o": "int16",
|
|
301
|
+
"u": "degrees"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"n": "current",
|
|
305
|
+
"t": "b",
|
|
306
|
+
"r": [-128, 127],
|
|
307
|
+
"f": "d",
|
|
308
|
+
"o": "int8"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"n": "state",
|
|
312
|
+
"t": "B",
|
|
313
|
+
"r": [0, 255],
|
|
314
|
+
"f": "02x",
|
|
315
|
+
"o": "uint8"
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
"actions": [
|
|
320
|
+
{
|
|
321
|
+
"n": "power",
|
|
322
|
+
"t": ">h",
|
|
323
|
+
"w": "0001",
|
|
324
|
+
"wz": "0064",
|
|
325
|
+
"f": ".1f",
|
|
326
|
+
"mul": 10,
|
|
327
|
+
"sub": 0,
|
|
328
|
+
"r": [-180.0, 180.0],
|
|
329
|
+
"d": 0
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"n": "enable",
|
|
333
|
+
"t": "B",
|
|
334
|
+
"w": "20",
|
|
335
|
+
"f": "b",
|
|
336
|
+
"r": [0, 1],
|
|
337
|
+
"d": 1
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
"RoboticalLEDRing": {
|
|
342
|
+
"name": "Robotical LED Ring",
|
|
343
|
+
"desc": "12 RGB LED Ring",
|
|
344
|
+
"manu": "Robotical",
|
|
345
|
+
"type": "RoboticalLEDRing",
|
|
346
|
+
"clas": ["LED"],
|
|
347
|
+
"resp": {
|
|
348
|
+
"b": 1,
|
|
349
|
+
"a": [
|
|
350
|
+
{
|
|
351
|
+
"n": "status",
|
|
352
|
+
"t": "B",
|
|
353
|
+
"r": [0, 255],
|
|
354
|
+
"f": "02x",
|
|
355
|
+
"o": "uint8"
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
},
|
|
359
|
+
"actions": [
|
|
360
|
+
{
|
|
361
|
+
"n": "pixels",
|
|
362
|
+
"t": "BBBB",
|
|
363
|
+
"w": "04",
|
|
364
|
+
"f": "LEDPIX",
|
|
365
|
+
"NX": 3,
|
|
366
|
+
"NY": 1,
|
|
367
|
+
"concat": false,
|
|
368
|
+
"r": [0, 255]
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"n": "brightness",
|
|
372
|
+
"t": "B",
|
|
373
|
+
"w": "FF01",
|
|
374
|
+
"wz": "&p100",
|
|
375
|
+
"f": "b",
|
|
376
|
+
"r": [0, 255],
|
|
377
|
+
"d": 100
|
|
378
|
+
}
|
|
379
|
+
]
|
|
99
380
|
}
|
|
100
381
|
};
|
|
101
382
|
}
|
|
@@ -139,7 +420,7 @@ class RaftChannelSimulated {
|
|
|
139
420
|
}
|
|
140
421
|
}
|
|
141
422
|
catch (e) {
|
|
142
|
-
RaftLog_1.default.warn(`RaftChannelSimulated.connect - error parsing locator ${locator}`);
|
|
423
|
+
RaftLog_1.default.warn(`RaftChannelSimulated.connect - error parsing locator ${locator}, ${e}`);
|
|
143
424
|
return false;
|
|
144
425
|
}
|
|
145
426
|
}
|
|
@@ -303,88 +584,38 @@ class RaftChannelSimulated {
|
|
|
303
584
|
// Add 16 bit big endian deviceTimeMs mod 65536 to the buffer
|
|
304
585
|
dataView.setUint16(bytePos, deviceTimeMs % 65536, false);
|
|
305
586
|
bytePos += 2;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
// Amplitude of the sine wave (0 to 1)
|
|
315
|
-
const amplitude = 0.8;
|
|
316
|
-
// Iterate through attributes and set values
|
|
317
|
-
for (let i = 0; i < numAttributes; i++) {
|
|
318
|
-
const attr = attributes[i];
|
|
319
|
-
// Calculate phase offset for this attribute
|
|
320
|
-
const phaseOffset = (2 * Math.PI * i) / numAttributes;
|
|
321
|
-
// Generate sine wave value
|
|
587
|
+
const handledByCustomGenerator = this._fillCustomRawData(deviceTypeInfo, dataView, bytePos, dataBlockSizeBytes, deviceIntervalMs, deviceTimeMs);
|
|
588
|
+
if (!handledByCustomGenerator) {
|
|
589
|
+
const numAttributes = attributes.length;
|
|
590
|
+
const numSamplesPerCycle = 10;
|
|
591
|
+
const frequencyHz = (deviceIntervalMs > 0)
|
|
592
|
+
? (1000 / deviceIntervalMs) / numSamplesPerCycle
|
|
593
|
+
: 0.1;
|
|
322
594
|
const timeRadians = deviceTimeMs * frequencyHz * (2 * Math.PI) / 1000;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
// Write the value to the buffer based on its type
|
|
344
|
-
if (attr.t === "b") {
|
|
345
|
-
dataView.setUint8(bytePos, Math.round(rawValue));
|
|
346
|
-
bytePos += 1;
|
|
347
|
-
}
|
|
348
|
-
else if (attr.t === "B") {
|
|
349
|
-
dataView.setUint8(bytePos, Math.round(rawValue));
|
|
350
|
-
bytePos += 1;
|
|
351
|
-
}
|
|
352
|
-
else if (attr.t === "c") {
|
|
353
|
-
dataView.setInt8(bytePos, Math.round(rawValue));
|
|
354
|
-
bytePos += 1;
|
|
355
|
-
}
|
|
356
|
-
else if (attr.t === "C") {
|
|
357
|
-
dataView.setUint8(bytePos, Math.round(rawValue));
|
|
358
|
-
bytePos += 1;
|
|
359
|
-
}
|
|
360
|
-
else if (attr.t === "<h") {
|
|
361
|
-
dataView.setInt16(bytePos, Math.round(rawValue), true); // Little endian
|
|
362
|
-
bytePos += 2;
|
|
363
|
-
}
|
|
364
|
-
else if (attr.t === ">h") {
|
|
365
|
-
dataView.setInt16(bytePos, Math.round(rawValue), false); // Big endian
|
|
366
|
-
bytePos += 2;
|
|
367
|
-
}
|
|
368
|
-
else if (attr.t === "<H") {
|
|
369
|
-
dataView.setUint16(bytePos, Math.round(rawValue), true); // Little endian
|
|
370
|
-
bytePos += 2;
|
|
371
|
-
}
|
|
372
|
-
else if (attr.t === ">H") {
|
|
373
|
-
dataView.setUint16(bytePos, Math.round(rawValue), false); // Big endian
|
|
374
|
-
bytePos += 2;
|
|
375
|
-
}
|
|
376
|
-
else if (attr.t === "f" || attr.t === "<f") {
|
|
377
|
-
dataView.setFloat32(bytePos, rawValue, true); // Little endian
|
|
378
|
-
bytePos += 4;
|
|
379
|
-
}
|
|
380
|
-
else if (attr.t === ">f") {
|
|
381
|
-
dataView.setFloat32(bytePos, rawValue, false); // Big endian
|
|
382
|
-
bytePos += 4;
|
|
383
|
-
}
|
|
384
|
-
else {
|
|
385
|
-
RaftLog_1.default.warn(`RaftChannelSimulated._createSimulatedDeviceInfoMsg - unsupported attribute type ${attr.t}`);
|
|
595
|
+
// Iterate through attributes and fill the payload
|
|
596
|
+
for (let attrIdx = 0; attrIdx < numAttributes; attrIdx++) {
|
|
597
|
+
const attr = attributes[attrIdx];
|
|
598
|
+
const { typeCode, repeatCount, littleEndian } = this._parseAttrType(attr.t);
|
|
599
|
+
const scaledValues = this._generateAttributeScaledValues(attr, attrIdx, repeatCount, numAttributes, timeRadians, deviceTimeMs);
|
|
600
|
+
if (scaledValues.length !== repeatCount) {
|
|
601
|
+
RaftLog_1.default.warn(`RaftChannelSimulated._createSimulatedDeviceInfoMsg - value count mismatch for ${attr.n}`);
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
for (let elemIdx = 0; elemIdx < repeatCount; elemIdx++) {
|
|
605
|
+
const scaledValue = scaledValues[elemIdx];
|
|
606
|
+
const rawValue = this._prepareRawValue(attr, typeCode, scaledValue);
|
|
607
|
+
const nextBytePos = this._writeRawValueToBuffer(dataView, bytePos, typeCode, littleEndian, rawValue);
|
|
608
|
+
if (nextBytePos < 0) {
|
|
609
|
+
RaftLog_1.default.warn(`RaftChannelSimulated._createSimulatedDeviceInfoMsg - buffer overflow writing ${attr.n}`);
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
bytePos = nextBytePos;
|
|
613
|
+
}
|
|
386
614
|
}
|
|
387
615
|
}
|
|
616
|
+
else {
|
|
617
|
+
bytePos += dataBlockSizeBytes;
|
|
618
|
+
}
|
|
388
619
|
// Convert the buffer to a byte array
|
|
389
620
|
const dataBytes = new Uint8Array(dataBuffer);
|
|
390
621
|
// Create the JSON message structure
|
|
@@ -407,6 +638,357 @@ class RaftChannelSimulated {
|
|
|
407
638
|
msgPrefixBytes.set(encodedMsg, 2);
|
|
408
639
|
return msgPrefixBytes;
|
|
409
640
|
}
|
|
641
|
+
_parseAttrType(attrType) {
|
|
642
|
+
const repeatMatch = attrType.match(/\[(\d+)\]\s*$/);
|
|
643
|
+
const repeatCount = repeatMatch ? parseInt(repeatMatch[1], 10) : 1;
|
|
644
|
+
const coreType = repeatMatch ? attrType.slice(0, repeatMatch.index) : attrType;
|
|
645
|
+
let littleEndian = false;
|
|
646
|
+
let typeCode = coreType.trim();
|
|
647
|
+
if (typeCode.startsWith("<")) {
|
|
648
|
+
littleEndian = true;
|
|
649
|
+
typeCode = typeCode.slice(1);
|
|
650
|
+
}
|
|
651
|
+
else if (typeCode.startsWith(">")) {
|
|
652
|
+
littleEndian = false;
|
|
653
|
+
typeCode = typeCode.slice(1);
|
|
654
|
+
}
|
|
655
|
+
else if (typeCode === "f") {
|
|
656
|
+
// Match previous behaviour - plain "f" treated as little endian floats
|
|
657
|
+
littleEndian = true;
|
|
658
|
+
}
|
|
659
|
+
return { typeCode, repeatCount, littleEndian };
|
|
660
|
+
}
|
|
661
|
+
_generateAttributeScaledValues(attr, attrIdx, repeatCount, numAttributes, timeRadians, deviceTimeMs) {
|
|
662
|
+
const amplitude = 0.8;
|
|
663
|
+
if (repeatCount > 1) {
|
|
664
|
+
const useThermalGrid = (attr && typeof attr.resolution === "string") || repeatCount >= 16;
|
|
665
|
+
if (useThermalGrid) {
|
|
666
|
+
return this._generateThermalGridValues(attr, repeatCount, timeRadians, deviceTimeMs);
|
|
667
|
+
}
|
|
668
|
+
const values = [];
|
|
669
|
+
for (let elemIdx = 0; elemIdx < repeatCount; elemIdx++) {
|
|
670
|
+
const phaseOffset = (2 * Math.PI * (attrIdx + elemIdx / repeatCount)) / Math.max(1, numAttributes);
|
|
671
|
+
const sinValue = Math.sin(timeRadians + phaseOffset);
|
|
672
|
+
if (Array.isArray(attr.r) && attr.r.length >= 2) {
|
|
673
|
+
const minValue = attr.r[0];
|
|
674
|
+
const maxValue = attr.r[1];
|
|
675
|
+
const midPoint = (maxValue + minValue) / 2;
|
|
676
|
+
const range = (maxValue - minValue) / 2;
|
|
677
|
+
const value = midPoint + sinValue * range * amplitude;
|
|
678
|
+
values.push(Math.min(maxValue, Math.max(minValue, value)));
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
values.push(sinValue * 1000 * amplitude);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
return values;
|
|
685
|
+
}
|
|
686
|
+
const phaseOffset = numAttributes > 0 ? (2 * Math.PI * attrIdx) / numAttributes : 0;
|
|
687
|
+
const sinValue = Math.sin(timeRadians + phaseOffset);
|
|
688
|
+
if (Array.isArray(attr.r) && attr.r.length >= 2) {
|
|
689
|
+
const minValue = attr.r[0];
|
|
690
|
+
const maxValue = attr.r[1];
|
|
691
|
+
const midPoint = (maxValue + minValue) / 2;
|
|
692
|
+
const range = (maxValue - minValue) / 2;
|
|
693
|
+
const value = midPoint + sinValue * range * amplitude;
|
|
694
|
+
return [Math.min(maxValue, Math.max(minValue, value))];
|
|
695
|
+
}
|
|
696
|
+
return [sinValue * 1000 * amplitude];
|
|
697
|
+
}
|
|
698
|
+
_generateThermalGridValues(attr, repeatCount, timeRadians, deviceTimeMs) {
|
|
699
|
+
const { rows, cols } = this._getGridDimensions(attr, repeatCount);
|
|
700
|
+
const values = [];
|
|
701
|
+
const ambientBase = 24 + 2 * Math.sin(deviceTimeMs / 7000);
|
|
702
|
+
const hotspotPhase = deviceTimeMs / 3200;
|
|
703
|
+
const hotspotRow = (Math.sin(hotspotPhase) + 1) * (rows - 1) / 2;
|
|
704
|
+
const hotspotCol = (Math.cos(hotspotPhase) + 1) * (cols - 1) / 2;
|
|
705
|
+
const hotspotAmplitude = 6;
|
|
706
|
+
const sigma = Math.max(rows, cols) / 3 || 1;
|
|
707
|
+
for (let idx = 0; idx < repeatCount; idx++) {
|
|
708
|
+
const row = Math.floor(idx / cols);
|
|
709
|
+
const col = idx % cols;
|
|
710
|
+
const dist = Math.hypot(row - hotspotRow, col - hotspotCol);
|
|
711
|
+
const hotspot = hotspotAmplitude * Math.exp(-(dist * dist) / (2 * sigma * sigma));
|
|
712
|
+
const gentleWave = 0.5 * Math.sin(timeRadians + row * 0.35 + col * 0.25);
|
|
713
|
+
let value = ambientBase + hotspot + gentleWave;
|
|
714
|
+
if (Array.isArray(attr.r) && attr.r.length >= 2) {
|
|
715
|
+
value = Math.min(attr.r[1], Math.max(attr.r[0], value));
|
|
716
|
+
}
|
|
717
|
+
values.push(value);
|
|
718
|
+
}
|
|
719
|
+
return values;
|
|
720
|
+
}
|
|
721
|
+
_fillCustomRawData(deviceTypeInfo, dataView, bytePos, dataBlockSizeBytes, deviceIntervalMs, deviceTimeMs) {
|
|
722
|
+
var _a, _b, _c, _d, _e, _f;
|
|
723
|
+
switch (deviceTypeInfo.type) {
|
|
724
|
+
case "LTR-329": {
|
|
725
|
+
if (dataBlockSizeBytes < 4) {
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
const frequencyHz = (deviceIntervalMs > 0)
|
|
729
|
+
? (1000 / deviceIntervalMs) / 10
|
|
730
|
+
: 0.1;
|
|
731
|
+
const timeRadians = deviceTimeMs * frequencyHz * (2 * Math.PI) / 1000;
|
|
732
|
+
const range = (_d = (_c = (_b = (_a = deviceTypeInfo.resp) === null || _a === void 0 ? void 0 : _a.a) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.r) !== null && _d !== void 0 ? _d : [0, 64000];
|
|
733
|
+
const minLux = (_e = range[0]) !== null && _e !== void 0 ? _e : 0;
|
|
734
|
+
const maxLux = (_f = range[1]) !== null && _f !== void 0 ? _f : 64000;
|
|
735
|
+
const baseLux = (maxLux + minLux) / 4;
|
|
736
|
+
const amplitudeLux = (maxLux - minLux) / 6;
|
|
737
|
+
let combined = Math.round(baseLux + amplitudeLux * Math.sin(timeRadians));
|
|
738
|
+
combined = Math.max(minLux, Math.min(maxLux, combined));
|
|
739
|
+
const irBase = combined * 0.35;
|
|
740
|
+
const irVariance = (combined * 0.15) * Math.sin(timeRadians + Math.PI / 4);
|
|
741
|
+
let ir = Math.round(irBase + irVariance);
|
|
742
|
+
ir = Math.max(minLux, Math.min(combined, ir));
|
|
743
|
+
dataView.setUint16(bytePos, combined, true);
|
|
744
|
+
dataView.setUint16(bytePos + 2, ir, true);
|
|
745
|
+
return true;
|
|
746
|
+
}
|
|
747
|
+
case "LTR-390": {
|
|
748
|
+
if (dataBlockSizeBytes < 5) {
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
const numerator = (deviceIntervalMs > 0) ? (1000 / deviceIntervalMs) : 0;
|
|
752
|
+
const timeRadians = deviceTimeMs * numerator * (2 * Math.PI) / 1000 / 10;
|
|
753
|
+
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
754
|
+
const ambientLux = clamp(8000 + 4500 * Math.sin(timeRadians), 0, 64000);
|
|
755
|
+
const ambientRaw = clamp(Math.round(ambientLux * 1.25), 0, 0xFFFFF);
|
|
756
|
+
dataView.setUint8(bytePos, ambientRaw & 0xFF);
|
|
757
|
+
dataView.setUint8(bytePos + 1, (ambientRaw >> 8) & 0xFF);
|
|
758
|
+
dataView.setUint8(bytePos + 2, (ambientRaw >> 16) & 0x0F);
|
|
759
|
+
const uviIndex = clamp(3.5 + 1.8 * Math.sin(timeRadians + Math.PI / 3), 0, 12);
|
|
760
|
+
const uviRaw = clamp(Math.round(uviIndex * 24), 0, 0xFFFF);
|
|
761
|
+
dataView.setUint16(bytePos + 3, uviRaw, true);
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
764
|
+
case "VL53L4CD": {
|
|
765
|
+
if (dataBlockSizeBytes < 3) {
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
const rangeMinMm = 40;
|
|
769
|
+
const rangeMaxMm = 1300;
|
|
770
|
+
const cycleMs = 9000;
|
|
771
|
+
const timeInCycle = deviceTimeMs % cycleMs;
|
|
772
|
+
// Simulate periods where the sensor reports invalid readings (target lost)
|
|
773
|
+
const invalidReading = timeInCycle < 600 ||
|
|
774
|
+
(timeInCycle > 4200 && timeInCycle < 5100) ||
|
|
775
|
+
(timeInCycle > 7800);
|
|
776
|
+
const isValid = !invalidReading;
|
|
777
|
+
// Generate a smooth oscillating distance while valid
|
|
778
|
+
const phase = (deviceTimeMs % cycleMs) / cycleMs;
|
|
779
|
+
const smoothWave = 0.5 * (1 - Math.cos(phase * 2 * Math.PI));
|
|
780
|
+
const slowDrift = 0.05 * Math.sin(deviceTimeMs / 5000);
|
|
781
|
+
const fastRipple = 0.02 * Math.sin(deviceTimeMs / 200);
|
|
782
|
+
const normalized = Math.min(1, Math.max(0, smoothWave + slowDrift + fastRipple));
|
|
783
|
+
let distanceMm = Math.round(rangeMinMm + normalized * (rangeMaxMm - rangeMinMm));
|
|
784
|
+
// Clamp to the reported range
|
|
785
|
+
distanceMm = Math.max(rangeMinMm, Math.min(rangeMaxMm, distanceMm));
|
|
786
|
+
if (!isValid) {
|
|
787
|
+
distanceMm = 0;
|
|
788
|
+
}
|
|
789
|
+
const statusRaw = isValid ? 0x00 : 0x04;
|
|
790
|
+
dataView.setUint8(bytePos, statusRaw);
|
|
791
|
+
dataView.setUint16(bytePos + 1, distanceMm, false);
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
794
|
+
case "RoboticalLEDRing": {
|
|
795
|
+
if (dataBlockSizeBytes < 1) {
|
|
796
|
+
return false;
|
|
797
|
+
}
|
|
798
|
+
const animationPhase = (deviceTimeMs % 6000) / 6000;
|
|
799
|
+
const patternIndex = Math.floor(animationPhase * 6) % 6;
|
|
800
|
+
const brightness = Math.round((Math.sin(deviceTimeMs / 600) + 1) * 127.5);
|
|
801
|
+
const isAnimating = Math.sin(deviceTimeMs / 1500) > 0;
|
|
802
|
+
const status = ((patternIndex & 0x07) << 4) | Math.min(0x0F, brightness >> 4) | (isAnimating ? 0x80 : 0x00);
|
|
803
|
+
dataView.setUint8(bytePos, status & 0xFF);
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
case "RoboticalDCMotor": {
|
|
807
|
+
if (dataBlockSizeBytes < 4) {
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
811
|
+
const cycleMs = 3200;
|
|
812
|
+
const cycleIndex = Math.floor(deviceTimeMs / cycleMs);
|
|
813
|
+
const direction = (cycleIndex % 2 === 0) ? 1 : -1;
|
|
814
|
+
const progress = (deviceTimeMs % cycleMs) / cycleMs;
|
|
815
|
+
const baseAngle = (progress * 360) - 180;
|
|
816
|
+
const angleDegrees = direction > 0 ? baseAngle : -baseAngle;
|
|
817
|
+
const angleRaw = clamp(Math.round(angleDegrees * 10), -1800, 1800);
|
|
818
|
+
const ripple = 6 * Math.sin((deviceTimeMs % cycleMs) / 180);
|
|
819
|
+
const loadComponent = Math.abs(baseAngle) * 0.12;
|
|
820
|
+
const currentRaw = clamp(Math.round(24 + loadComponent + ripple), -128, 127);
|
|
821
|
+
const highLoad = Math.abs(loadComponent) > 8;
|
|
822
|
+
const directionBit = direction > 0 ? 0x01 : 0x00;
|
|
823
|
+
const stateRaw = 0x02 | directionBit | (highLoad ? 0x04 : 0x00);
|
|
824
|
+
dataView.setInt16(bytePos, angleRaw, false);
|
|
825
|
+
dataView.setInt8(bytePos + 2, currentRaw);
|
|
826
|
+
dataView.setUint8(bytePos + 3, stateRaw);
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
case "RoboticalServo": {
|
|
830
|
+
if (dataBlockSizeBytes < 6) {
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
const swingAmplitudeDeg = 90;
|
|
834
|
+
const cycleMs = 4000;
|
|
835
|
+
const angularSpeedRadPerMs = (2 * Math.PI) / cycleMs;
|
|
836
|
+
const phaseRadians = (deviceTimeMs % cycleMs) * angularSpeedRadPerMs;
|
|
837
|
+
const angleDegrees = swingAmplitudeDeg * Math.sin(phaseRadians);
|
|
838
|
+
const velocityDegPerSec = swingAmplitudeDeg * angularSpeedRadPerMs * 1000 * Math.cos(phaseRadians);
|
|
839
|
+
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
840
|
+
const angleRaw = clamp(Math.round(angleDegrees * 10), -1800, 1800);
|
|
841
|
+
let velocityRaw = Math.round(velocityDegPerSec);
|
|
842
|
+
velocityRaw = clamp(velocityRaw, -32768, 32767);
|
|
843
|
+
let currentRaw = Math.round(20 + 0.08 * Math.abs(velocityDegPerSec));
|
|
844
|
+
currentRaw = clamp(currentRaw, 0, 127);
|
|
845
|
+
const isMoving = Math.abs(velocityDegPerSec) > 5;
|
|
846
|
+
const stateRaw = (0x02) | (isMoving ? 0x01 : 0);
|
|
847
|
+
dataView.setInt16(bytePos, angleRaw, false);
|
|
848
|
+
dataView.setInt8(bytePos + 2, currentRaw);
|
|
849
|
+
dataView.setUint8(bytePos + 3, stateRaw);
|
|
850
|
+
dataView.setInt16(bytePos + 4, velocityRaw, false);
|
|
851
|
+
return true;
|
|
852
|
+
}
|
|
853
|
+
default:
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
_getGridDimensions(attr, repeatCount) {
|
|
858
|
+
if (attr && typeof attr.resolution === "string") {
|
|
859
|
+
const match = attr.resolution.match(/(\d+)\s*x\s*(\d+)/i);
|
|
860
|
+
if (match) {
|
|
861
|
+
const rows = parseInt(match[1], 10);
|
|
862
|
+
const cols = parseInt(match[2], 10);
|
|
863
|
+
if (rows > 0 && cols > 0) {
|
|
864
|
+
return { rows, cols };
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
const side = Math.round(Math.sqrt(repeatCount));
|
|
869
|
+
if (side > 0 && side * side === repeatCount) {
|
|
870
|
+
return { rows: side, cols: side };
|
|
871
|
+
}
|
|
872
|
+
return { rows: repeatCount, cols: 1 };
|
|
873
|
+
}
|
|
874
|
+
_prepareRawValue(attr, typeCode, scaledValue) {
|
|
875
|
+
if (this._isFloatType(typeCode)) {
|
|
876
|
+
return scaledValue;
|
|
877
|
+
}
|
|
878
|
+
let raw = scaledValue;
|
|
879
|
+
if (attr && typeof attr.a === "number") {
|
|
880
|
+
raw -= attr.a;
|
|
881
|
+
}
|
|
882
|
+
if (attr && typeof attr.d === "number") {
|
|
883
|
+
raw *= attr.d;
|
|
884
|
+
}
|
|
885
|
+
if (attr && typeof attr.s === "number" && attr.s !== 0) {
|
|
886
|
+
const shift = attr.s;
|
|
887
|
+
const shiftFactor = Math.pow(2, Math.abs(shift));
|
|
888
|
+
if (shift > 0) {
|
|
889
|
+
raw *= shiftFactor;
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
raw /= shiftFactor;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return Math.round(raw);
|
|
896
|
+
}
|
|
897
|
+
_writeRawValueToBuffer(dataView, bytePos, typeCode, littleEndian, rawValue) {
|
|
898
|
+
const valueSize = this._byteSizeForType(typeCode);
|
|
899
|
+
if (valueSize <= 0 || bytePos + valueSize > dataView.byteLength) {
|
|
900
|
+
return -1;
|
|
901
|
+
}
|
|
902
|
+
switch (typeCode) {
|
|
903
|
+
case "b":
|
|
904
|
+
dataView.setInt8(bytePos, this._clampRawValue(rawValue, typeCode));
|
|
905
|
+
break;
|
|
906
|
+
case "c":
|
|
907
|
+
dataView.setInt8(bytePos, this._clampRawValue(rawValue, typeCode));
|
|
908
|
+
break;
|
|
909
|
+
case "B":
|
|
910
|
+
case "C":
|
|
911
|
+
dataView.setUint8(bytePos, this._clampRawValue(rawValue, typeCode));
|
|
912
|
+
break;
|
|
913
|
+
case "?":
|
|
914
|
+
dataView.setUint8(bytePos, rawValue ? 1 : 0);
|
|
915
|
+
break;
|
|
916
|
+
case "h":
|
|
917
|
+
dataView.setInt16(bytePos, this._clampRawValue(rawValue, typeCode), littleEndian);
|
|
918
|
+
break;
|
|
919
|
+
case "H":
|
|
920
|
+
dataView.setUint16(bytePos, this._clampRawValue(rawValue, typeCode), littleEndian);
|
|
921
|
+
break;
|
|
922
|
+
case "i":
|
|
923
|
+
case "l":
|
|
924
|
+
dataView.setInt32(bytePos, this._clampRawValue(rawValue, typeCode), littleEndian);
|
|
925
|
+
break;
|
|
926
|
+
case "I":
|
|
927
|
+
case "L":
|
|
928
|
+
dataView.setUint32(bytePos, this._clampRawValue(rawValue, typeCode), littleEndian);
|
|
929
|
+
break;
|
|
930
|
+
case "f":
|
|
931
|
+
dataView.setFloat32(bytePos, rawValue, littleEndian);
|
|
932
|
+
break;
|
|
933
|
+
case "d":
|
|
934
|
+
dataView.setFloat64(bytePos, rawValue, littleEndian);
|
|
935
|
+
break;
|
|
936
|
+
default:
|
|
937
|
+
RaftLog_1.default.warn(`RaftChannelSimulated._writeRawValueToBuffer - unsupported attribute type ${typeCode}`);
|
|
938
|
+
return -1;
|
|
939
|
+
}
|
|
940
|
+
return bytePos + valueSize;
|
|
941
|
+
}
|
|
942
|
+
_byteSizeForType(typeCode) {
|
|
943
|
+
switch (typeCode) {
|
|
944
|
+
case "b":
|
|
945
|
+
case "B":
|
|
946
|
+
case "c":
|
|
947
|
+
case "C":
|
|
948
|
+
case "?":
|
|
949
|
+
return 1;
|
|
950
|
+
case "h":
|
|
951
|
+
case "H":
|
|
952
|
+
return 2;
|
|
953
|
+
case "i":
|
|
954
|
+
case "I":
|
|
955
|
+
case "l":
|
|
956
|
+
case "L":
|
|
957
|
+
case "f":
|
|
958
|
+
return 4;
|
|
959
|
+
case "d":
|
|
960
|
+
return 8;
|
|
961
|
+
default:
|
|
962
|
+
return 0;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
_clampRawValue(rawValue, typeCode) {
|
|
966
|
+
const value = Math.round(rawValue);
|
|
967
|
+
switch (typeCode) {
|
|
968
|
+
case "b":
|
|
969
|
+
case "c":
|
|
970
|
+
return Math.max(-128, Math.min(127, value));
|
|
971
|
+
case "B":
|
|
972
|
+
case "C":
|
|
973
|
+
case "?":
|
|
974
|
+
return Math.max(0, Math.min(255, value));
|
|
975
|
+
case "h":
|
|
976
|
+
return Math.max(-32768, Math.min(32767, value));
|
|
977
|
+
case "H":
|
|
978
|
+
return Math.max(0, Math.min(65535, value));
|
|
979
|
+
case "i":
|
|
980
|
+
case "l":
|
|
981
|
+
return Math.max(-2147483648, Math.min(2147483647, value));
|
|
982
|
+
case "I":
|
|
983
|
+
case "L":
|
|
984
|
+
return Math.max(0, Math.min(4294967295, value));
|
|
985
|
+
default:
|
|
986
|
+
return value;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
_isFloatType(typeCode) {
|
|
990
|
+
return typeCode === "f" || typeCode === "d";
|
|
991
|
+
}
|
|
410
992
|
// Helper function to convert bytes to hex string
|
|
411
993
|
_bytesToHexStr(bytes) {
|
|
412
994
|
return Array.from(bytes)
|