@robotical/raftjs 1.3.3 → 1.4.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 (128) hide show
  1. package/dist/react-native/RaftAttributeHandler.d.ts +1 -1
  2. package/dist/react-native/RaftAttributeHandler.js +18 -10
  3. package/dist/react-native/RaftAttributeHandler.js.map +1 -1
  4. package/dist/react-native/RaftChannelBLE.native.d.ts +11 -11
  5. package/dist/react-native/RaftChannelBLE.native.js +61 -41
  6. package/dist/react-native/RaftChannelBLE.native.js.map +1 -1
  7. package/dist/react-native/RaftChannelBLE.web.d.ts +3 -4
  8. package/dist/react-native/RaftChannelBLE.web.js +7 -8
  9. package/dist/react-native/RaftChannelBLE.web.js.map +1 -1
  10. package/dist/react-native/RaftChannelBLEScanner.native.d.ts +6 -6
  11. package/dist/react-native/RaftChannelBLEScanner.native.js +38 -46
  12. package/dist/react-native/RaftChannelBLEScanner.native.js.map +1 -1
  13. package/dist/react-native/RaftConnector.d.ts +3 -3
  14. package/dist/react-native/RaftConnector.js +4 -4
  15. package/dist/react-native/RaftConnector.js.map +1 -1
  16. package/dist/react-native/RaftCustomAttrHandler.d.ts +1 -1
  17. package/dist/react-native/RaftCustomAttrHandler.js +4 -4
  18. package/dist/react-native/RaftCustomAttrHandler.js.map +1 -1
  19. package/dist/react-native/RaftDeviceInfo.d.ts +3 -0
  20. package/dist/react-native/RaftDeviceManager.d.ts +16 -11
  21. package/dist/react-native/RaftDeviceManager.js +196 -50
  22. package/dist/react-native/RaftDeviceManager.js.map +1 -1
  23. package/dist/react-native/RaftDeviceMgrIF.d.ts +9 -6
  24. package/dist/react-native/RaftDeviceStates.d.ts +5 -1
  25. package/dist/react-native/RaftDeviceStates.js +3 -3
  26. package/dist/react-native/RaftDeviceStates.js.map +1 -1
  27. package/dist/react-native/RaftMsgHandler.d.ts +1 -1
  28. package/dist/react-native/RaftMsgHandler.js +1 -2
  29. package/dist/react-native/RaftMsgHandler.js.map +1 -1
  30. package/dist/react-native/RaftStruct.d.ts +3 -0
  31. package/dist/react-native/RaftStruct.js +208 -0
  32. package/dist/react-native/RaftStruct.js.map +1 -0
  33. package/dist/react-native/RaftSysTypeManager.d.ts +14 -0
  34. package/dist/react-native/RaftSysTypeManager.js +53 -0
  35. package/dist/react-native/RaftSysTypeManager.js.map +1 -0
  36. package/dist/react-native/RaftSystemType.d.ts +3 -0
  37. package/dist/react-native/RaftTypes.d.ts +14 -15
  38. package/dist/react-native/RaftTypes.js +13 -50
  39. package/dist/react-native/RaftTypes.js.map +1 -1
  40. package/dist/react-native/RaftUpdateManager.js +6 -3
  41. package/dist/react-native/RaftUpdateManager.js.map +1 -1
  42. package/dist/react-native/RaftUtils.d.ts +1 -0
  43. package/dist/react-native/RaftUtils.js +17 -4
  44. package/dist/react-native/RaftUtils.js.map +1 -1
  45. package/dist/react-native/main.d.ts +2 -1
  46. package/dist/react-native/main.js +4 -4
  47. package/dist/react-native/main.js.map +1 -1
  48. package/dist/web/RaftAttributeHandler.d.ts +1 -1
  49. package/dist/web/RaftAttributeHandler.js +18 -10
  50. package/dist/web/RaftAttributeHandler.js.map +1 -1
  51. package/dist/web/RaftChannelBLE.web.d.ts +3 -4
  52. package/dist/web/RaftChannelBLE.web.js +7 -8
  53. package/dist/web/RaftChannelBLE.web.js.map +1 -1
  54. package/dist/web/RaftConnector.d.ts +3 -3
  55. package/dist/web/RaftConnector.js +4 -4
  56. package/dist/web/RaftConnector.js.map +1 -1
  57. package/dist/web/RaftCustomAttrHandler.d.ts +1 -1
  58. package/dist/web/RaftCustomAttrHandler.js +4 -4
  59. package/dist/web/RaftCustomAttrHandler.js.map +1 -1
  60. package/dist/web/RaftDeviceInfo.d.ts +3 -0
  61. package/dist/web/RaftDeviceManager.d.ts +16 -11
  62. package/dist/web/RaftDeviceManager.js +196 -50
  63. package/dist/web/RaftDeviceManager.js.map +1 -1
  64. package/dist/web/RaftDeviceMgrIF.d.ts +9 -6
  65. package/dist/web/RaftDeviceStates.d.ts +5 -1
  66. package/dist/web/RaftDeviceStates.js +3 -3
  67. package/dist/web/RaftDeviceStates.js.map +1 -1
  68. package/dist/web/RaftMsgHandler.d.ts +1 -1
  69. package/dist/web/RaftMsgHandler.js +1 -2
  70. package/dist/web/RaftMsgHandler.js.map +1 -1
  71. package/dist/web/RaftStruct.d.ts +3 -0
  72. package/dist/web/RaftStruct.js +208 -0
  73. package/dist/web/RaftStruct.js.map +1 -0
  74. package/dist/web/RaftSysTypeManager.d.ts +14 -0
  75. package/dist/web/RaftSysTypeManager.js +53 -0
  76. package/dist/web/RaftSysTypeManager.js.map +1 -0
  77. package/dist/web/RaftSystemType.d.ts +3 -0
  78. package/dist/web/RaftTypes.d.ts +14 -15
  79. package/dist/web/RaftTypes.js +13 -50
  80. package/dist/web/RaftTypes.js.map +1 -1
  81. package/dist/web/RaftUpdateManager.js +6 -3
  82. package/dist/web/RaftUpdateManager.js.map +1 -1
  83. package/dist/web/RaftUtils.d.ts +1 -0
  84. package/dist/web/RaftUtils.js +17 -4
  85. package/dist/web/RaftUtils.js.map +1 -1
  86. package/dist/web/main.d.ts +2 -1
  87. package/dist/web/main.js +4 -4
  88. package/dist/web/main.js.map +1 -1
  89. package/examples/dashboard/package.json +8 -15
  90. package/examples/dashboard/src/ConnManager.ts +18 -14
  91. package/examples/dashboard/src/DeviceActionsForm.tsx +49 -49
  92. package/examples/dashboard/src/DeviceLineChart.tsx +44 -20
  93. package/examples/dashboard/src/DevicePanel.tsx +33 -2
  94. package/examples/dashboard/src/DevicesPanel.tsx +5 -4
  95. package/examples/dashboard/src/LatencyTest.ts +130 -0
  96. package/examples/dashboard/src/LatencyTestPanel.tsx +92 -0
  97. package/examples/dashboard/src/Main.tsx +191 -73
  98. package/examples/dashboard/src/SettingsManager.ts +67 -0
  99. package/examples/dashboard/src/SettingsScreen.tsx +174 -0
  100. package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +14 -8
  101. package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +12 -5
  102. package/examples/dashboard/src/SystemTypeGeneric/StateInfoGeneric.ts +30 -0
  103. package/examples/dashboard/src/SystemTypeGeneric/SystemTypeGeneric.ts +91 -0
  104. package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +23 -4
  105. package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +1 -1
  106. package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +5 -2
  107. package/examples/dashboard/src/index.html +2 -2
  108. package/examples/dashboard/src/index.tsx +0 -2
  109. package/examples/dashboard/src/styles.css +14 -0
  110. package/package.json +6 -14
  111. package/src/RaftAttributeHandler.ts +23 -14
  112. package/src/RaftChannelBLE.native.ts +77 -53
  113. package/src/RaftChannelBLE.web.ts +8 -8
  114. package/src/RaftChannelBLEScanner.native.ts +38 -44
  115. package/src/RaftConnector.ts +5 -5
  116. package/src/RaftCustomAttrHandler.ts +5 -5
  117. package/src/RaftDeviceInfo.ts +3 -0
  118. package/src/RaftDeviceManager.ts +236 -65
  119. package/src/RaftDeviceMgrIF.ts +11 -6
  120. package/src/RaftDeviceStates.ts +7 -3
  121. package/src/RaftMsgHandler.ts +1 -2
  122. package/src/RaftStruct.ts +209 -0
  123. package/src/RaftSysTypeManager.ts +60 -0
  124. package/src/RaftSystemType.ts +3 -0
  125. package/src/RaftTypes.ts +30 -33
  126. package/src/RaftUpdateManager.ts +6 -3
  127. package/src/RaftUtils.ts +14 -4
  128. package/src/main.ts +2 -2
@@ -11,11 +11,10 @@ import { DeviceAttributeState, DevicesState, DeviceState, getDeviceKey } from ".
11
11
  import { DeviceMsgJson } from "./RaftDeviceMsg";
12
12
  import { RaftOKFail } from './RaftTypes';
13
13
  import { DeviceTypeInfo, DeviceTypeAction, DeviceTypeInfoRecs, RaftDevTypeInfoResponse } from "./RaftDeviceInfo";
14
- import struct, { DataType } from 'python-struct';
15
14
  import AttributeHandler from "./RaftAttributeHandler";
16
15
  import RaftSystemUtils from "./RaftSystemUtils";
17
16
  import RaftDeviceMgrIF from "./RaftDeviceMgrIF";
18
- import { Buffer } from 'buffer';
17
+ import { structPack } from "./RaftStruct";
19
18
 
20
19
  export class DeviceManager implements RaftDeviceMgrIF{
21
20
 
@@ -32,7 +31,7 @@ export class DeviceManager implements RaftDeviceMgrIF{
32
31
  private _attributeHandler = new AttributeHandler();
33
32
 
34
33
  // Devices state
35
- private _devicesState = new DevicesState();
34
+ public _devicesState = new DevicesState();
36
35
 
37
36
  // Last time each device was updated - used to detect devices that are no longer present
38
37
  private _deviceLastUpdateTime: { [deviceKey: string]: number } = {};
@@ -45,9 +44,9 @@ export class DeviceManager implements RaftDeviceMgrIF{
45
44
  private _systemUtils: RaftSystemUtils | null = null;
46
45
 
47
46
  // Device callbacks
48
- private _callbackNewDevice: ((deviceKey: string, state: DeviceState) => void) | null = null;
49
- private _callbackNewDeviceAttribute: ((deviceKey: string, attrState: DeviceAttributeState) => void) | null = null;
50
- private _callbackNewAttributeData: ((deviceKey: string, attrState: DeviceAttributeState) => void) | null = null;
47
+ private _newDeviceCallbacks: Array<(deviceKey: string, state: DeviceState) => void> = [];
48
+ private _newDeviceAttributeCallbacks: Array<(deviceKey: string, attrState: DeviceAttributeState) => void> = [];
49
+ private _newAttributeDataCallbacks: Array<(deviceKey: string, attrState: DeviceAttributeState) => void> = [];
51
50
 
52
51
  public getDevicesState(): DevicesState {
53
52
  return this._devicesState;
@@ -67,6 +66,15 @@ export class DeviceManager implements RaftDeviceMgrIF{
67
66
  constructor() {
68
67
  }
69
68
 
69
+ ////////////////////////////////////////////////////////////////////////////
70
+ // Settings
71
+ ////////////////////////////////////////////////////////////////////////////
72
+
73
+ public setMaxDataPointsToStore(maxDatapointsToStore: number): void {
74
+ this._maxDatapointsToStore = maxDatapointsToStore;
75
+ // console.log(`DeviceManager setMaxDataPointsToStore ${maxDatapointsToStore}`);
76
+ }
77
+
70
78
  ////////////////////////////////////////////////////////////////////////////
71
79
  // Send REST commands
72
80
  ////////////////////////////////////////////////////////////////////////////
@@ -77,7 +85,7 @@ export class DeviceManager implements RaftDeviceMgrIF{
77
85
  const msgHandler = this._systemUtils?.getMsgHandler();
78
86
  if (msgHandler) {
79
87
  const msgRslt = await msgHandler.sendRICRESTURL<RaftOKFail>(cmd);
80
- return msgRslt.isOk();
88
+ return msgRslt.rslt === "ok";
81
89
  }
82
90
  return false;
83
91
  } catch (error) {
@@ -98,21 +106,37 @@ export class DeviceManager implements RaftDeviceMgrIF{
98
106
  }
99
107
 
100
108
  ////////////////////////////////////////////////////////////////////////////
101
- // Callbacks
109
+ // Register callbacks
102
110
  ////////////////////////////////////////////////////////////////////////////
103
111
 
104
- // Register state change callbacks
105
- public onNewDevice(callback: (deviceKey: string, state: DeviceState) => void): void {
106
- // Save the callback
107
- this._callbackNewDevice = callback;
112
+ public addNewDeviceCallback(callback: (deviceKey: string, state: DeviceState) => void): void {
113
+ if (!this._newDeviceCallbacks.includes(callback)) {
114
+ this._newDeviceCallbacks.push(callback);
115
+ }
108
116
  }
109
- public onNewDeviceAttribute(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void {
110
- // Save the callback
111
- this._callbackNewDeviceAttribute = callback;
117
+
118
+ public removeNewDeviceCallback(callback: (deviceKey: string, state: DeviceState) => void): void {
119
+ this._newDeviceCallbacks = this._newDeviceCallbacks.filter((cb) => cb !== callback);
112
120
  }
113
- public onNewAttributeData(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void {
114
- // Save the callback
115
- this._callbackNewAttributeData = callback;
121
+
122
+ public addNewAttributeCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void {
123
+ if (!this._newDeviceAttributeCallbacks.includes(callback)) {
124
+ this._newDeviceAttributeCallbacks.push(callback);
125
+ }
126
+ }
127
+
128
+ public removeNewAttributeCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void {
129
+ this._newDeviceAttributeCallbacks = this._newDeviceAttributeCallbacks.filter((cb) => cb !== callback);
130
+ }
131
+
132
+ public addAttributeDataCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void {
133
+ if (!this._newAttributeDataCallbacks.includes(callback)) {
134
+ this._newAttributeDataCallbacks.push(callback);
135
+ }
136
+ }
137
+
138
+ public removeAttributeDataCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void {
139
+ this._newAttributeDataCallbacks = this._newAttributeDataCallbacks.filter((cb) => cb !== callback);
116
140
  }
117
141
 
118
142
  ////////////////////////////////////////////////////////////////////////////
@@ -124,14 +148,145 @@ export class DeviceManager implements RaftDeviceMgrIF{
124
148
  await this._systemUtils?.setRaftName(friendlyName);
125
149
  }
126
150
 
151
+ ////////////////////////////////////////////////////////////////////////////
152
+ // Handle device message binary
153
+ ////////////////////////////////////////////////////////////////////////////
154
+
155
+ public async handleClientMsgBinary(rxMsg: Uint8Array) {
156
+ // console.log(`DeviceManager client1 msg ${RaftUtils.bufferToHex(rxMsg)}`);
157
+
158
+ // Example messages
159
+ // 0080 0015 81 0000006a 0004 53b7 feff00000100081857079314 0011 80 00000000 0011 53b2 075106e400d60054 0010 80 00000000 0012 5231 000d0000010e01
160
+ // 0080 0011 80 00000000 0011 53f1 075806e900d70052 0010 80 00000000 0012 5231 000d0000010e01
161
+
162
+ // First two bytes of each message are the message type (0080)
163
+ // There are then a series of sections each of which is the data for a device
164
+ // First two bytes of each section is the section length (big endian) not including the length bytes
165
+ // Next byte is the connection mode (0 for direct connect, 1+ for bus number) and the MSB of this byte is 1 if the device is online
166
+ // Next is the device address (4 bytes big endian)
167
+ // Next is the device type index (2 bytes big endian)
168
+ // Finally the device data which can be one or more groups of attributes defined by the schema
169
+
170
+ // Iterate through sections
171
+ let msgPos = 2;
172
+ while (msgPos < rxMsg.length) {
173
+
174
+ // Check length
175
+ if (rxMsg.length < msgPos + 11) {
176
+ console.warn(`DeviceManager handleClientMsgBinary invalid length ${rxMsg.length}`);
177
+ return;
178
+ }
179
+
180
+ // Get the length of the section
181
+ const sectionLen = (rxMsg[msgPos] << 8) + rxMsg[msgPos + 1];
182
+ if (sectionLen > rxMsg.length) {
183
+ console.warn(`DeviceManager handleClientMsgBinary invalid msgPos ${msgPos} msgLen ${sectionLen} rxMsgLen ${rxMsg.length}`);
184
+ return;
185
+ }
186
+
187
+ // Extract message elements
188
+ const busNum = rxMsg[msgPos + 2] & 0x7f;
189
+ const isOnline = (rxMsg[msgPos + 2] & 0x80) !== 0;
190
+ const devAddr = (rxMsg[msgPos + 3] << 24) + (rxMsg[msgPos + 4] << 16) + (rxMsg[msgPos + 5] << 8) + rxMsg[msgPos + 6];
191
+ const devTypeIdx = (rxMsg[msgPos + 7] << 8) + rxMsg[msgPos + 8];
192
+ let attrGroupPos = msgPos + 9;
193
+
194
+ // Debug
195
+ // console.log(`DeviceManager overallLen ${rxMsg.length} sectionPos ${msgPos} sectionLen ${sectionLen} ${RaftUtils.bufferToHex(rxMsg.slice(msgPos, msgPos + sectionLen))}`);
196
+ // console.log(`DeviceManager connMode ${busNum} isOnline ${isOnline} devAddr ${devAddr} devTypeIdx ${devTypeIdx} attrGroupDataLen ${sectionLen - 9}`);
197
+
198
+ // Device key
199
+ const deviceKey = getDeviceKey(busNum.toString(), devAddr.toString(), devTypeIdx.toString());
200
+
201
+ // Update the last update time
202
+ this._deviceLastUpdateTime[deviceKey] = Date.now();
203
+
204
+ // Check if a device state already exists
205
+ if (!(deviceKey in this._devicesState) || (this._devicesState[deviceKey].deviceTypeInfo === undefined)) {
206
+ // Get the device type info
207
+ const deviceTypeInfo = await this.getDeviceTypeInfo(busNum.toString(), devAddr.toString(), devTypeIdx.toString());
208
+ // console.log(`DeviceManager deviceTypeInfo ${JSON.stringify(deviceTypeInfo)}`);
209
+
210
+ // Check if device record exists
211
+ if (deviceKey in this._devicesState) {
212
+ if (deviceTypeInfo !== undefined) {
213
+ this._devicesState[deviceKey].deviceTypeInfo = deviceTypeInfo;
214
+ this._devicesState[deviceKey].deviceType = deviceTypeInfo.name || "";
215
+ this._devicesState[deviceKey].busName = busNum.toString();
216
+ this._devicesState[deviceKey].deviceAddress = devAddr.toString();
217
+ }
218
+ } else {
219
+ // Create device record - device type info may be undefined
220
+ this._devicesState[deviceKey] = {
221
+ deviceTypeInfo: deviceTypeInfo,
222
+ deviceTimeline: {
223
+ timestampsUs: [],
224
+ lastReportTimestampUs: 0,
225
+ reportTimestampOffsetUs: 0
226
+ },
227
+ deviceAttributes: {},
228
+ deviceIsNew: true,
229
+ stateChanged: false,
230
+ isOnline: true,
231
+ deviceAddress: devAddr.toString(),
232
+ deviceType: deviceTypeInfo?.name || "",
233
+ busName: busNum.toString()
234
+ };
235
+ }
236
+ }
237
+
238
+ // Get device state
239
+ const deviceState = this._devicesState[deviceKey];
240
+ deviceState.isOnline = isOnline;
241
+
242
+ // Check if device type info is available
243
+ if (deviceState.deviceTypeInfo && deviceState.deviceTypeInfo.resp) {
244
+
245
+ // Iterate over attributes in the group
246
+ const pollRespMetadata = deviceState.deviceTypeInfo!.resp!;
247
+
248
+ // Iterate over attribute groups
249
+ while (attrGroupPos < msgPos + sectionLen + 2) {
250
+ const curTimelineLen = deviceState.deviceTimeline.timestampsUs.length;
251
+ const newMsgBufIdx = this._attributeHandler.processMsgAttrGroup(rxMsg, attrGroupPos,
252
+ deviceState.deviceTimeline, pollRespMetadata,
253
+ deviceState.deviceAttributes,
254
+ this._maxDatapointsToStore);
255
+ if (newMsgBufIdx < 0)
256
+ break;
257
+ attrGroupPos = newMsgBufIdx;
258
+ if (deviceState.deviceTimeline.timestampsUs.length !== curTimelineLen) {
259
+ deviceState.stateChanged = true;
260
+ }
261
+ }
262
+ }
263
+
264
+ // Move to next message
265
+ msgPos += sectionLen + 2;
266
+ }
267
+
268
+ // Check for devices that have not been updated for a while
269
+ if (this._removeDevicesFlag) {
270
+ const nowTime = Date.now();
271
+ Object.entries(this._deviceLastUpdateTime).forEach(([deviceKey, lastUpdateTime]) => {
272
+ if ((nowTime - lastUpdateTime) > this._removeDevicesTimeMs) {
273
+ delete this._devicesState[deviceKey];
274
+ }
275
+ });
276
+ }
277
+
278
+ // Process the callback
279
+ this.processStateCallback();
280
+ }
281
+
127
282
  ////////////////////////////////////////////////////////////////////////////
128
283
  // Handle device message JSON
129
284
  ////////////////////////////////////////////////////////////////////////////
130
285
 
131
- public handleClientMsgJson(jsonMsg: string) {
286
+ public async handleClientMsgJson(jsonMsg: string) {
132
287
 
133
- let data = JSON.parse(jsonMsg) as DeviceMsgJson;
134
- // console.log(`DeviceManager websocket message ${JSON.stringify(data)}`);
288
+ const data = JSON.parse(jsonMsg) as DeviceMsgJson;
289
+ // console.log(`DeviceManager client msg ${JSON.stringify(data)}`);
135
290
 
136
291
  // Iterate over the buses
137
292
  Object.entries(data).forEach(([busName, devices]) => {
@@ -150,8 +305,17 @@ export class DeviceManager implements RaftDeviceMgrIF{
150
305
  return;
151
306
  }
152
307
 
308
+ // Device type name
309
+ let deviceTypeName = "";
310
+ if (attrGroups && typeof attrGroups === 'object' && "_t" in attrGroups && typeof attrGroups._t === "string") {
311
+ deviceTypeName = attrGroups._t || "";
312
+ } else {
313
+ console.warn(`DeviceManager missing device type attrGroups ${JSON.stringify(attrGroups)}`);
314
+ return;
315
+ }
316
+
153
317
  // Device key
154
- const deviceKey = getDeviceKey(busName, devAddr);
318
+ const deviceKey = getDeviceKey(busName, devAddr, deviceTypeName);
155
319
 
156
320
  // Update the last update time
157
321
  this._deviceLastUpdateTime[deviceKey] = Date.now();
@@ -159,14 +323,6 @@ export class DeviceManager implements RaftDeviceMgrIF{
159
323
  // Check if a device state already exists
160
324
  if (!(deviceKey in this._devicesState) || (this._devicesState[deviceKey].deviceTypeInfo === undefined)) {
161
325
 
162
- let deviceTypeName = "";
163
- if (attrGroups && typeof attrGroups === 'object' && "_t" in attrGroups && typeof attrGroups._t === "string") {
164
- deviceTypeName = attrGroups._t || "";
165
- } else {
166
- console.warn(`DeviceManager missing device type attrGroups ${JSON.stringify(attrGroups)}`);
167
- return;
168
- }
169
-
170
326
  // Get the device type info
171
327
  const deviceTypeInfo = await this.getDeviceTypeInfo(busName, devAddr, deviceTypeName);
172
328
 
@@ -174,6 +330,9 @@ export class DeviceManager implements RaftDeviceMgrIF{
174
330
  if (deviceKey in this._devicesState) {
175
331
  if (deviceTypeInfo !== undefined) {
176
332
  this._devicesState[deviceKey].deviceTypeInfo = deviceTypeInfo;
333
+ this._devicesState[deviceKey].deviceType = deviceTypeName;
334
+ this._devicesState[deviceKey].deviceAddress = devAddr;
335
+ this._devicesState[deviceKey].busName = busName;
177
336
  }
178
337
  } else {
179
338
  // Create device record - device type info may be undefined
@@ -187,7 +346,10 @@ export class DeviceManager implements RaftDeviceMgrIF{
187
346
  deviceAttributes: {},
188
347
  deviceIsNew: true,
189
348
  stateChanged: false,
190
- isOnline: true
349
+ isOnline: true,
350
+ deviceAddress: devAddr,
351
+ deviceType: deviceTypeName,
352
+ busName: busName
191
353
  };
192
354
  }
193
355
  }
@@ -221,9 +383,6 @@ export class DeviceManager implements RaftDeviceMgrIF{
221
383
  // Convert the hex string to an arraybuffer by converting each pair of hex chars to a byte
222
384
  const msgBytes = this.hexToBytes(msgHexStr);
223
385
 
224
- // Convert to a Buffer
225
- const msgBuffer = Buffer.from(msgBytes);
226
-
227
386
  // Work through the message which may contain multiple data instances
228
387
  let msgBufIdx = 0;
229
388
 
@@ -234,7 +393,7 @@ export class DeviceManager implements RaftDeviceMgrIF{
234
393
  while (msgBufIdx < msgBytes.length) {
235
394
 
236
395
  const curTimelineLen = deviceState.deviceTimeline.timestampsUs.length;
237
- const newMsgBufIdx = this._attributeHandler.processMsgAttrGroup(msgBuffer, msgBufIdx,
396
+ const newMsgBufIdx = this._attributeHandler.processMsgAttrGroup(msgBytes, msgBufIdx,
238
397
  deviceState.deviceTimeline, pollRespMetadata,
239
398
  deviceState.deviceAttributes,
240
399
  this._maxDatapointsToStore);
@@ -274,33 +433,18 @@ export class DeviceManager implements RaftDeviceMgrIF{
274
433
 
275
434
  // Check if device record is new
276
435
  if (deviceState.deviceIsNew) {
277
- if (this._callbackNewDevice) {
278
- this._callbackNewDevice(
279
- deviceKey,
280
- deviceState
281
- );
282
- }
436
+ this._newDeviceCallbacks.forEach((cb) => cb(deviceKey, deviceState));
283
437
  deviceState.deviceIsNew = false;
284
438
  }
285
439
 
286
440
  // Iterate over the attributes
287
- Object.entries(deviceState.deviceAttributes).forEach(([_attrKey, attrState]) => {
441
+ Object.entries(deviceState.deviceAttributes).forEach(([, attrState]): void => {
288
442
  if (attrState.newAttribute) {
289
- if (this._callbackNewDeviceAttribute) {
290
- this._callbackNewDeviceAttribute(
291
- deviceKey,
292
- attrState
293
- );
294
- }
443
+ this._newDeviceAttributeCallbacks.forEach((cb) => cb(deviceKey, attrState));
295
444
  attrState.newAttribute = false;
296
445
  }
297
446
  if (attrState.newData) {
298
- if (this._callbackNewAttributeData) {
299
- this._callbackNewAttributeData(
300
- deviceKey,
301
- attrState
302
- );
303
- }
447
+ this._newAttributeDataCallbacks.forEach((cb) => cb(deviceKey, attrState));
304
448
  attrState.newData = false;
305
449
  }
306
450
  });
@@ -352,17 +496,45 @@ export class DeviceManager implements RaftDeviceMgrIF{
352
496
  // Send action to device
353
497
  ////////////////////////////////////////////////////////////////////////////
354
498
 
355
- public async sendAction(deviceKey: string, action: DeviceTypeAction, data: DataType[]): Promise<boolean> {
499
+ private toHex(data: Uint8Array): string {
500
+ return Array.from(data)
501
+ .map(byte => byte.toString(16).padStart(2, "0"))
502
+ .join("");
503
+ }
504
+
505
+ public async sendAction(deviceKey: string, action: DeviceTypeAction, data: number[]): Promise<boolean> {
356
506
  // console.log(`DeviceManager sendAction ${deviceKey} action name ${action.n} value ${value} prefix ${action.w}`);
357
507
 
358
- // Form the write bytes
359
- let writeBytes = action.t ? struct.pack(action.t, data) : Buffer.from([]);
508
+ let writeBytes: Uint8Array;
509
+
510
+ // Check for one data item
511
+ if (data.length === 1) {
512
+
513
+ let value = data[0];
514
+
515
+ // Check for conversion
516
+ if (action.sub !== undefined) {
517
+ value = value - action.sub;
518
+ }
519
+ if (action.mul !== undefined) {
520
+ value = value * action.mul;
521
+ }
522
+
523
+ // Form the write bytes
524
+ writeBytes = action.t ? structPack(action.t, [value]) : new Uint8Array(0);
525
+
526
+ } else
527
+ {
528
+
529
+ // Form the write bytes which may have multiple data items
530
+ writeBytes = action.t ? structPack(action.t, data) : new Uint8Array(0);
531
+ }
360
532
 
361
533
  // Convert to hex string
362
- let writeHexStr = Buffer.from(writeBytes).toString('hex');
534
+ let writeHexStr = this.toHex(writeBytes);
363
535
 
364
- // Add prefix
365
- writeHexStr = action.w + writeHexStr;
536
+ // Add prefix and postfix
537
+ writeHexStr = (action.w ? action.w : "") + writeHexStr + (action.wz ? action.wz : "");
366
538
 
367
539
  // Separate the bus and address in the deviceKey (_ char)
368
540
  const devBus = deviceKey.split("_")[0]
@@ -380,7 +552,7 @@ export class DeviceManager implements RaftDeviceMgrIF{
380
552
  const msgHandler = this._systemUtils?.getMsgHandler();
381
553
  if (msgHandler) {
382
554
  const msgRslt = await msgHandler.sendRICRESTURL<RaftOKFail>(cmd);
383
- return msgRslt.isOk();
555
+ return msgRslt.rslt === "ok";
384
556
  }
385
557
  return false;
386
558
  } catch (error) {
@@ -393,13 +565,13 @@ export class DeviceManager implements RaftDeviceMgrIF{
393
565
  // Send a compound action to the device
394
566
  ////////////////////////////////////////////////////////////////////////////
395
567
 
396
- public async sendCompoundAction(deviceKey: string, action: DeviceTypeAction, data: DataType[][]): Promise<boolean> {
568
+ public async sendCompoundAction(deviceKey: string, action: DeviceTypeAction, data: number[][]): Promise<boolean> {
397
569
  // console.log(`DeviceManager sendAction ${deviceKey} action name ${action.n} value ${value} prefix ${action.w}`);
398
570
 
399
571
  // Check if all data to be sent at once
400
572
  if (action.concat) {
401
573
  // Form a single list by flattening data
402
- let dataToWrite: DataType[] = [];
574
+ let dataToWrite: number[] = [];
403
575
  for (let dataIdx = 0; dataIdx < data.length; dataIdx++) {
404
576
  dataToWrite = dataToWrite.concat(data[dataIdx]);
405
577
  }
@@ -412,7 +584,7 @@ export class DeviceManager implements RaftDeviceMgrIF{
412
584
  for (let dataIdx = 0; dataIdx < data.length; dataIdx++) {
413
585
 
414
586
  // Create the data to write by prepending the index to the data for this index
415
- let dataToWrite = [dataIdx as DataType].concat(data[dataIdx]);
587
+ const dataToWrite = [dataIdx as number].concat(data[dataIdx]);
416
588
 
417
589
  // Use sendAction to send this
418
590
  allOk = allOk && await this.sendAction(deviceKey, action, dataToWrite);
@@ -432,5 +604,4 @@ export class DeviceManager implements RaftDeviceMgrIF{
432
604
  }
433
605
  return bytes;
434
606
  }
435
-
436
607
  }
@@ -7,7 +7,6 @@
7
7
  //
8
8
  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
9
 
10
- import { DataType } from "python-struct";
11
10
  import { DeviceTypeAction } from "./RaftDeviceInfo";
12
11
  import { DeviceAttributeState, DevicesState, DeviceState } from "./RaftDeviceStates";
13
12
 
@@ -17,12 +16,18 @@ export default interface RaftDeviceMgrIF {
17
16
  getDevicesState(): DevicesState;
18
17
  getDeviceState(deviceKey: string): DeviceState;
19
18
 
19
+ // Settings
20
+ setMaxDataPointsToStore(maxDataPointsToStore: number): void;
21
+
20
22
  // Callbacks
21
- onNewDevice(callback: (deviceKey: string, state: DeviceState) => void): void;
22
- onNewDeviceAttribute(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void;
23
- onNewAttributeData(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void;
23
+ addNewDeviceCallback(callback: (deviceKey: string, state: DeviceState) => void): void;
24
+ removeNewDeviceCallback(callback: (deviceKey: string, state: DeviceState) => void): void;
25
+ addNewAttributeCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void;
26
+ removeNewAttributeCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void;
27
+ addAttributeDataCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void;
28
+ removeAttributeDataCallback(callback: (deviceKey: string, attrState: DeviceAttributeState) => void): void;
24
29
 
25
30
  // Send action to device
26
- sendAction(deviceKey: string, action: DeviceTypeAction, data: DataType[]): void;
27
- sendCompoundAction(deviceKey: string, action: DeviceTypeAction, data: DataType[][]): void;
31
+ sendAction(deviceKey: string, action: DeviceTypeAction, data: number[]): void;
32
+ sendCompoundAction(deviceKey: string, action: DeviceTypeAction, data: number[][]): void;
28
33
  }
@@ -30,7 +30,7 @@ export function deviceAttrGetLatestFormatted(attrState: DeviceAttributeState): s
30
30
  decimalPlaces = parseInt(parts[1], 10);
31
31
  }
32
32
  const formattedNumber = value.toFixed(decimalPlaces);
33
- let fieldWidth = parseInt(parts[0], 10);
33
+ const fieldWidth = parseInt(parts[0], 10);
34
34
  return fieldWidth ? formattedNumber.padStart(fieldWidth, ' ') : formattedNumber;
35
35
  } else if (format.endsWith('x')) {
36
36
  // Hexadecimal formatting
@@ -51,6 +51,7 @@ export interface DeviceAttributeState {
51
51
  name: string;
52
52
  newAttribute: boolean;
53
53
  newData: boolean;
54
+ numNewValues: number;
54
55
  values: number[];
55
56
  units: string;
56
57
  range: number[];
@@ -76,6 +77,9 @@ export interface DeviceState {
76
77
  deviceIsNew: boolean;
77
78
  stateChanged: boolean;
78
79
  isOnline: boolean;
80
+ deviceAddress: string;
81
+ deviceType: string;
82
+ busName: string;
79
83
  }
80
84
 
81
85
  export class DevicesState {
@@ -83,6 +87,6 @@ export class DevicesState {
83
87
  }
84
88
 
85
89
  // Add the getDeviceKey method to generate a composite key
86
- export function getDeviceKey(busName: string, devAddr: string): string {
87
- return `${busName}_${devAddr}`;
90
+ export function getDeviceKey(busName: string, devAddr: string, devType: string): string {
91
+ return `${busName}_${devAddr}_${devType}`;
88
92
  }
@@ -571,7 +571,6 @@ export default class RaftMsgHandler {
571
571
  // if (msgRsltCode === RaftMsgResultCode.MESSAGE_RESULT_OK) {
572
572
  const resolve = this._msgTrackInfos[msgNum].resolve;
573
573
  if (resolve) {
574
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
575
574
  RaftLog.verbose(`_msgCompleted msgNum ${msgNum} result ${msgRsltCode.toString()} ${JSON.stringify(msgRsltObj)}`);
576
575
  (resolve as ((arg: object | null) => void))(msgRsltObj);
577
576
  }
@@ -679,7 +678,7 @@ export default class RaftMsgHandler {
679
678
  // RICREST protocol
680
679
  msgBuf[msgBufPos++] = RICRESTElemCode.RICREST_ELEM_CODE_FILEBLOCK;
681
680
 
682
- // Buffer header
681
+ // Header
683
682
  msgBuf[msgBufPos++] = streamID & 0xff;
684
683
  msgBuf[msgBufPos++] = (blockStart >> 16) & 0xff;
685
684
  msgBuf[msgBufPos++] = (blockStart >> 8) & 0xff;