@robotical/raftjs 1.3.5 → 1.4.1
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/dist/react-native/RaftAttributeHandler.d.ts +1 -1
- package/dist/react-native/RaftAttributeHandler.js +18 -10
- package/dist/react-native/RaftAttributeHandler.js.map +1 -1
- package/dist/react-native/RaftChannelBLE.native.d.ts +11 -11
- package/dist/react-native/RaftChannelBLE.native.js +61 -41
- package/dist/react-native/RaftChannelBLE.native.js.map +1 -1
- package/dist/react-native/RaftChannelBLE.web.d.ts +3 -4
- package/dist/react-native/RaftChannelBLE.web.js +7 -8
- package/dist/react-native/RaftChannelBLE.web.js.map +1 -1
- package/dist/react-native/RaftChannelBLEScanner.native.d.ts +6 -6
- package/dist/react-native/RaftChannelBLEScanner.native.js +38 -46
- package/dist/react-native/RaftChannelBLEScanner.native.js.map +1 -1
- package/dist/react-native/RaftConnector.d.ts +3 -3
- package/dist/react-native/RaftConnector.js +4 -4
- package/dist/react-native/RaftConnector.js.map +1 -1
- package/dist/react-native/RaftCustomAttrHandler.d.ts +1 -1
- package/dist/react-native/RaftCustomAttrHandler.js +4 -4
- package/dist/react-native/RaftCustomAttrHandler.js.map +1 -1
- package/dist/react-native/RaftDeviceInfo.d.ts +3 -0
- package/dist/react-native/RaftDeviceManager.d.ts +16 -11
- package/dist/react-native/RaftDeviceManager.js +196 -50
- package/dist/react-native/RaftDeviceManager.js.map +1 -1
- package/dist/react-native/RaftDeviceMgrIF.d.ts +9 -6
- package/dist/react-native/RaftDeviceStates.d.ts +5 -1
- package/dist/react-native/RaftDeviceStates.js +3 -3
- package/dist/react-native/RaftDeviceStates.js.map +1 -1
- package/dist/react-native/RaftMsgHandler.d.ts +1 -1
- package/dist/react-native/RaftMsgHandler.js +1 -2
- package/dist/react-native/RaftMsgHandler.js.map +1 -1
- package/dist/react-native/RaftStruct.d.ts +3 -0
- package/dist/react-native/RaftStruct.js +208 -0
- package/dist/react-native/RaftStruct.js.map +1 -0
- package/dist/react-native/RaftSysTypeManager.d.ts +14 -0
- package/dist/react-native/RaftSysTypeManager.js +53 -0
- package/dist/react-native/RaftSysTypeManager.js.map +1 -0
- package/dist/react-native/RaftSystemType.d.ts +3 -0
- package/dist/react-native/RaftTypes.d.ts +14 -15
- package/dist/react-native/RaftTypes.js +13 -50
- package/dist/react-native/RaftTypes.js.map +1 -1
- package/dist/react-native/RaftUpdateManager.js +6 -3
- package/dist/react-native/RaftUpdateManager.js.map +1 -1
- package/dist/react-native/RaftUtils.d.ts +1 -0
- package/dist/react-native/RaftUtils.js +17 -4
- package/dist/react-native/RaftUtils.js.map +1 -1
- package/dist/react-native/main.d.ts +2 -1
- package/dist/react-native/main.js +4 -4
- package/dist/react-native/main.js.map +1 -1
- package/dist/web/RaftAttributeHandler.d.ts +1 -1
- package/dist/web/RaftAttributeHandler.js +18 -10
- package/dist/web/RaftAttributeHandler.js.map +1 -1
- package/dist/web/RaftChannelBLE.web.d.ts +3 -4
- package/dist/web/RaftChannelBLE.web.js +7 -8
- package/dist/web/RaftChannelBLE.web.js.map +1 -1
- package/dist/web/RaftConnector.d.ts +3 -3
- package/dist/web/RaftConnector.js +4 -4
- package/dist/web/RaftConnector.js.map +1 -1
- package/dist/web/RaftCustomAttrHandler.d.ts +1 -1
- package/dist/web/RaftCustomAttrHandler.js +4 -4
- package/dist/web/RaftCustomAttrHandler.js.map +1 -1
- package/dist/web/RaftDeviceInfo.d.ts +3 -0
- package/dist/web/RaftDeviceManager.d.ts +16 -11
- package/dist/web/RaftDeviceManager.js +196 -50
- package/dist/web/RaftDeviceManager.js.map +1 -1
- package/dist/web/RaftDeviceMgrIF.d.ts +9 -6
- package/dist/web/RaftDeviceStates.d.ts +5 -1
- package/dist/web/RaftDeviceStates.js +3 -3
- package/dist/web/RaftDeviceStates.js.map +1 -1
- package/dist/web/RaftMsgHandler.d.ts +1 -1
- package/dist/web/RaftMsgHandler.js +1 -2
- package/dist/web/RaftMsgHandler.js.map +1 -1
- package/dist/web/RaftStruct.d.ts +3 -0
- package/dist/web/RaftStruct.js +208 -0
- package/dist/web/RaftStruct.js.map +1 -0
- package/dist/web/RaftSysTypeManager.d.ts +14 -0
- package/dist/web/RaftSysTypeManager.js +53 -0
- package/dist/web/RaftSysTypeManager.js.map +1 -0
- package/dist/web/RaftSystemType.d.ts +3 -0
- package/dist/web/RaftTypes.d.ts +14 -15
- package/dist/web/RaftTypes.js +13 -50
- package/dist/web/RaftTypes.js.map +1 -1
- package/dist/web/RaftUpdateManager.js +6 -3
- package/dist/web/RaftUpdateManager.js.map +1 -1
- package/dist/web/RaftUtils.d.ts +1 -0
- package/dist/web/RaftUtils.js +17 -4
- package/dist/web/RaftUtils.js.map +1 -1
- package/dist/web/main.d.ts +2 -1
- package/dist/web/main.js +4 -4
- package/dist/web/main.js.map +1 -1
- package/examples/dashboard/package.json +8 -15
- package/examples/dashboard/src/ConnManager.ts +18 -14
- package/examples/dashboard/src/DeviceActionsForm.tsx +49 -49
- package/examples/dashboard/src/DeviceLineChart.tsx +44 -20
- package/examples/dashboard/src/DevicePanel.tsx +33 -2
- package/examples/dashboard/src/DevicesPanel.tsx +5 -4
- package/examples/dashboard/src/LatencyTest.ts +130 -0
- package/examples/dashboard/src/LatencyTestPanel.tsx +92 -0
- package/examples/dashboard/src/Main.tsx +191 -73
- package/examples/dashboard/src/SettingsManager.ts +67 -0
- package/examples/dashboard/src/SettingsScreen.tsx +174 -0
- package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +14 -8
- package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +12 -5
- package/examples/dashboard/src/SystemTypeGeneric/StateInfoGeneric.ts +30 -0
- package/examples/dashboard/src/SystemTypeGeneric/SystemTypeGeneric.ts +91 -0
- package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +23 -4
- package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +1 -1
- package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +5 -2
- package/examples/dashboard/src/index.html +2 -2
- package/examples/dashboard/src/index.tsx +0 -2
- package/examples/dashboard/src/styles.css +14 -0
- package/package.json +7 -15
- package/src/RaftAttributeHandler.ts +23 -14
- package/src/RaftChannelBLE.native.ts +77 -53
- package/src/RaftChannelBLE.web.ts +8 -8
- package/src/RaftChannelBLEScanner.native.ts +38 -44
- package/src/RaftConnector.ts +5 -5
- package/src/RaftCustomAttrHandler.ts +5 -5
- package/src/RaftDeviceInfo.ts +3 -0
- package/src/RaftDeviceManager.ts +236 -65
- package/src/RaftDeviceMgrIF.ts +11 -6
- package/src/RaftDeviceStates.ts +7 -3
- package/src/RaftMsgHandler.ts +1 -2
- package/src/RaftStruct.ts +209 -0
- package/src/RaftSysTypeManager.ts +60 -0
- package/src/RaftSystemType.ts +3 -0
- package/src/RaftTypes.ts +30 -33
- package/src/RaftUpdateManager.ts +6 -3
- package/src/RaftUtils.ts +14 -4
- package/src/main.ts +2 -2
package/src/RaftDeviceManager.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
|
49
|
-
private
|
|
50
|
-
private
|
|
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.
|
|
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
|
-
//
|
|
109
|
+
// Register callbacks
|
|
102
110
|
////////////////////////////////////////////////////////////////////////////
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
this.
|
|
117
|
+
|
|
118
|
+
public removeNewDeviceCallback(callback: (deviceKey: string, state: DeviceState) => void): void {
|
|
119
|
+
this._newDeviceCallbacks = this._newDeviceCallbacks.filter((cb) => cb !== callback);
|
|
112
120
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.
|
|
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
|
-
|
|
134
|
-
// console.log(`DeviceManager
|
|
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(
|
|
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
|
-
|
|
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(([
|
|
441
|
+
Object.entries(deviceState.deviceAttributes).forEach(([, attrState]): void => {
|
|
288
442
|
if (attrState.newAttribute) {
|
|
289
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
359
|
-
|
|
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 =
|
|
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.
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
}
|
package/src/RaftDeviceMgrIF.ts
CHANGED
|
@@ -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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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:
|
|
27
|
-
sendCompoundAction(deviceKey: string, action: DeviceTypeAction, data:
|
|
31
|
+
sendAction(deviceKey: string, action: DeviceTypeAction, data: number[]): void;
|
|
32
|
+
sendCompoundAction(deviceKey: string, action: DeviceTypeAction, data: number[][]): void;
|
|
28
33
|
}
|
package/src/RaftDeviceStates.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
}
|
package/src/RaftMsgHandler.ts
CHANGED
|
@@ -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
|
-
//
|
|
681
|
+
// Header
|
|
683
682
|
msgBuf[msgBufPos++] = streamID & 0xff;
|
|
684
683
|
msgBuf[msgBufPos++] = (blockStart >> 16) & 0xff;
|
|
685
684
|
msgBuf[msgBufPos++] = (blockStart >> 8) & 0xff;
|