@bitpoolos/edge-bacnet 1.4.2 → 1.4.4
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/CHANGELOG.md +38 -0
- package/bacnet_client.js +60 -10
- package/bacnet_gateway.js +149 -227
- package/bacnet_read.html +27 -2
- package/bacnet_read.js +71 -54
- package/bacnet_server.js +77 -106
- package/bitpool_inject.html +23 -0
- package/bitpool_inject.js +5 -0
- package/package.json +1 -1
- package/resources/style.css +12 -1
- package/treeBuilder.js +0 -1
package/bacnet_read.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
module.exports = function (RED) {
|
|
8
|
-
const http = require("http");
|
|
9
8
|
const { ReadCommandConfig } = require('./common');
|
|
10
9
|
const baEnum = require('./resources/node-bacstack-ts/dist/index.js').enum;
|
|
11
10
|
|
|
@@ -26,7 +25,7 @@ module.exports = function (RED) {
|
|
|
26
25
|
this.object_property_simpleWithStatus = config.object_property_simpleWithStatus;
|
|
27
26
|
this.object_property_fullObject = config.object_property_fullObject;
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
this.useDeviceName = config.useDeviceName;
|
|
30
29
|
|
|
31
30
|
this.object_props = getObjectProps(this);
|
|
32
31
|
|
|
@@ -54,64 +53,82 @@ module.exports = function (RED) {
|
|
|
54
53
|
};
|
|
55
54
|
|
|
56
55
|
node.on('input', function (msg) {
|
|
57
|
-
node.status({ fill: "blue", shape: "dot", text: "Reading values" });
|
|
58
|
-
|
|
59
|
-
let object_property_simplePayload = false;
|
|
60
|
-
let object_property_simpleWithStatus = false;
|
|
61
|
-
let object_property_fullObject = false;
|
|
62
|
-
|
|
63
|
-
let jsonType = false;
|
|
64
|
-
let mqttType = false;
|
|
65
|
-
let pointJsonType = false;
|
|
66
|
-
|
|
67
|
-
if (msg.simplePayload) {
|
|
68
|
-
object_property_simplePayload = msg.simplePayload;
|
|
69
|
-
} else if (msg.simpleWithStatus) {
|
|
70
|
-
object_property_simpleWithStatus = msg.simpleWithStatus;
|
|
71
|
-
} else if (msg.fullObject) {
|
|
72
|
-
object_property_fullObject = msg.fullObject;
|
|
73
|
-
} else {
|
|
74
|
-
object_property_simplePayload = node.object_property_simplePayload;
|
|
75
|
-
object_property_simpleWithStatus = node.object_property_simpleWithStatus;
|
|
76
|
-
object_property_fullObject = node.object_property_fullObject;
|
|
77
|
-
}
|
|
78
56
|
|
|
79
|
-
if (msg.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
pointJsonType = msg.pointJson;
|
|
57
|
+
if (msg.applyDisplayNames) {
|
|
58
|
+
|
|
59
|
+
msg.pointsToRead = node.pointsToRead;
|
|
60
|
+
node.send(msg);
|
|
61
|
+
|
|
85
62
|
} else {
|
|
86
|
-
jsonType = node.json;
|
|
87
|
-
mqttType = node.mqtt;
|
|
88
|
-
pointJsonType = node.pointJson
|
|
89
|
-
}
|
|
90
63
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
64
|
+
node.status({ fill: "blue", shape: "dot", text: "Reading values" });
|
|
65
|
+
|
|
66
|
+
let object_property_simplePayload = false;
|
|
67
|
+
let object_property_simpleWithStatus = false;
|
|
68
|
+
let object_property_fullObject = false;
|
|
69
|
+
|
|
70
|
+
let jsonType = false;
|
|
71
|
+
let mqttType = false;
|
|
72
|
+
let pointJsonType = false;
|
|
73
|
+
let useDeviceName = false;
|
|
74
|
+
|
|
75
|
+
if (msg.simplePayload) {
|
|
76
|
+
object_property_simplePayload = msg.simplePayload;
|
|
77
|
+
} else if (msg.simpleWithStatus) {
|
|
78
|
+
object_property_simpleWithStatus = msg.simpleWithStatus;
|
|
79
|
+
} else if (msg.fullObject) {
|
|
80
|
+
object_property_fullObject = msg.fullObject;
|
|
81
|
+
} else {
|
|
82
|
+
object_property_simplePayload = node.object_property_simplePayload;
|
|
83
|
+
object_property_simpleWithStatus = node.object_property_simpleWithStatus;
|
|
84
|
+
object_property_fullObject = node.object_property_fullObject;
|
|
107
85
|
}
|
|
108
|
-
};
|
|
109
86
|
|
|
110
|
-
|
|
87
|
+
if (msg.json) {
|
|
88
|
+
jsonType = msg.json;
|
|
89
|
+
} else if (msg.mqtt) {
|
|
90
|
+
mqttType = msg.mqtt;
|
|
91
|
+
} else if (msg.pointJson) {
|
|
92
|
+
pointJsonType = msg.pointJson;
|
|
93
|
+
} else {
|
|
94
|
+
jsonType = node.json;
|
|
95
|
+
mqttType = node.mqtt;
|
|
96
|
+
pointJsonType = node.pointJson
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (msg.useDeviceName) {
|
|
100
|
+
useDeviceName = msg.useDeviceName;
|
|
101
|
+
} else {
|
|
102
|
+
useDeviceName = node.useDeviceName;
|
|
103
|
+
}
|
|
111
104
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
let readConfig = new ReadCommandConfig(node.pointsToRead, node.object_props, node.roundDecimal);
|
|
106
|
+
|
|
107
|
+
let output = {
|
|
108
|
+
type: "Read",
|
|
109
|
+
id: node.id,
|
|
110
|
+
readNodeName: node.nodeName,
|
|
111
|
+
options: readConfig,
|
|
112
|
+
objectPropertyType: {
|
|
113
|
+
simplePayload: object_property_simplePayload,
|
|
114
|
+
simpleWithStatus: object_property_simpleWithStatus,
|
|
115
|
+
fullObject: object_property_fullObject
|
|
116
|
+
},
|
|
117
|
+
outputType: {
|
|
118
|
+
json: jsonType,
|
|
119
|
+
mqtt: mqttType,
|
|
120
|
+
pointJson: pointJsonType,
|
|
121
|
+
useDeviceName: useDeviceName
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
node.send(output);
|
|
126
|
+
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
node.status({});
|
|
129
|
+
}, 3000);
|
|
130
|
+
|
|
131
|
+
}
|
|
115
132
|
|
|
116
133
|
});
|
|
117
134
|
|
package/bacnet_server.js
CHANGED
|
@@ -6,12 +6,12 @@ const { EventEmitter } = require("events");
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Class representing a BACnet Server.
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* This class initializes a BACnet server with specified client, device ID, and Node-Red version.
|
|
11
11
|
* It provides methods to set device name, add objects, retrieve objects, clear server points, clear server point, and get server points.
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* Simulates a BACnet IP device on a regular IP network
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
* @constructor
|
|
16
16
|
* @param {Object} client - The BACnet client object.
|
|
17
17
|
* @param {number} deviceId - The ID of the device.
|
|
@@ -248,7 +248,7 @@ class BacnetServer extends EventEmitter {
|
|
|
248
248
|
|
|
249
249
|
/**
|
|
250
250
|
* Set the name of the device.
|
|
251
|
-
*
|
|
251
|
+
*
|
|
252
252
|
* @param {string} nodeName - The new name for the device.
|
|
253
253
|
*/
|
|
254
254
|
setDeviceName(nodeName) {
|
|
@@ -259,116 +259,85 @@ class BacnetServer extends EventEmitter {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
/**
|
|
262
|
-
* Adds a new object to the BacnetServer's object store based on the provided name and
|
|
263
|
-
*
|
|
262
|
+
* Adds a new object to the BacnetServer's object store based on the provided name and payload.
|
|
263
|
+
*
|
|
264
264
|
* @param {string} name - The name of the object to be added.
|
|
265
|
-
* @param {number|boolean|string}
|
|
265
|
+
* @param {number|boolean|string|object} payload - The payload of the object to be added.
|
|
266
266
|
* @returns {void}
|
|
267
267
|
*/
|
|
268
|
-
addObject(name,
|
|
268
|
+
addObject(name, payload) {
|
|
269
269
|
let that = this;
|
|
270
|
-
let objectType = that.getBacnetObjectType(value);
|
|
270
|
+
let objectType = that.getBacnetObjectType(payload.value ?? payload);
|
|
271
271
|
if (name && objectType) {
|
|
272
272
|
let instanceNumber;
|
|
273
273
|
if (name.includes('|')) {
|
|
274
274
|
// split name, assign last part to instanceNumber and the rest to name
|
|
275
275
|
let nameParts = name.split('|');
|
|
276
|
-
instanceNumber = nameParts
|
|
277
|
-
nameParts.pop();
|
|
276
|
+
instanceNumber = nameParts.pop();
|
|
278
277
|
name = nameParts.join('|');
|
|
279
278
|
}
|
|
280
|
-
let formattedName = name.replaceAll('.', '_');
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: 0, type: 8 }],
|
|
293
|
-
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: 0, type: 9 }],
|
|
294
|
-
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: 0, type: 9 }],
|
|
295
|
-
[baEnum.PropertyIdentifier.UNITS]: [{ value: 95, type: 9 }],
|
|
296
|
-
[baEnum.PropertyIdentifier.PRIORITY_ARRAY]: [{ value: 0, type: 9 }],
|
|
297
|
-
[baEnum.PropertyIdentifier.MAX_PRES_VALUE]: [{ value: value, type: 4 }],
|
|
298
|
-
[baEnum.PropertyIdentifier.MIN_PRES_VALUE]: [{ value: value, type: 4 }],
|
|
299
|
-
[baEnum.PropertyIdentifier.RESOLUTION]: [{ value: 0, type: 4 }],
|
|
300
|
-
[baEnum.PropertyIdentifier.PROPERTY_LIST]:
|
|
301
|
-
[
|
|
302
|
-
{ value: baEnum.PropertyIdentifier.OBJECT_NAME, type: 9 },
|
|
303
|
-
{ value: baEnum.PropertyIdentifier.OBJECT_TYPE, type: 9 },
|
|
304
|
-
{ value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
305
|
-
{ value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
306
|
-
{ value: baEnum.PropertyIdentifier.PRESENT_VALUE, type: 9 },
|
|
307
|
-
{ value: baEnum.PropertyIdentifier.STATUS_FLAGS, type: 9 },
|
|
308
|
-
{ value: baEnum.PropertyIdentifier.EVENT_STATE, type: 9 },
|
|
309
|
-
{ value: baEnum.PropertyIdentifier.OUT_OF_SERVICE, type: 9 },
|
|
310
|
-
{ value: baEnum.PropertyIdentifier.UNITS, type: 9 },
|
|
311
|
-
{ value: baEnum.PropertyIdentifier.PRIORITY_ARRAY, type: 9 },
|
|
312
|
-
{ value: baEnum.PropertyIdentifier.MAX_PRES_VALUE, type: 9 },
|
|
313
|
-
{ value: baEnum.PropertyIdentifier.MIN_PRES_VALUE, type: 9 },
|
|
314
|
-
{ value: baEnum.PropertyIdentifier.RESOLUTION, type: 9 },
|
|
315
|
-
],
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
that.objectList.push({ value: { type: baEnum.ObjectType.ANALOG_VALUE, instance: objectId }, type: 12 })
|
|
319
|
-
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
320
|
-
} else if (foundIndex !== -1) {
|
|
321
|
-
let foundObject = that.objectStore[baEnum.ObjectType.ANALOG_VALUE][foundIndex];
|
|
322
|
-
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = value;
|
|
323
|
-
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
324
|
-
}
|
|
325
|
-
} else if (objectType == "boolean") {
|
|
326
|
-
let foundIndex = that.objectStore[baEnum.ObjectType.BINARY_VALUE].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
327
|
-
if (foundIndex == -1) {
|
|
328
|
-
let objectId = that.getObjectIdentifier(baEnum.ObjectType.BINARY_VALUE);
|
|
329
|
-
that.objectStore[baEnum.ObjectType.BINARY_VALUE].push({
|
|
330
|
-
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{ value: formattedName, type: 7 }],
|
|
331
|
-
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{ value: baEnum.ObjectType.BINARY_VALUE, type: 9 }],
|
|
332
|
-
[baEnum.PropertyIdentifier.DESCRIPTION]: [{ value: '', type: 7 }],
|
|
333
|
-
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{ value: { type: baEnum.ObjectType.BINARY_VALUE, instance: objectId }, type: 12 }],
|
|
334
|
-
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{ value: value, type: 1 }],
|
|
335
|
-
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: 0, type: 8 }],
|
|
336
|
-
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: 0, type: 9 }],
|
|
337
|
-
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: 0, type: 9 }],
|
|
338
|
-
[baEnum.PropertyIdentifier.ACTIVE_TEXT]: [{ value: 'ACTIVE', type: 7 }],
|
|
339
|
-
[baEnum.PropertyIdentifier.INACTIVE_TEXT]: [{ value: 'INACTIVE', type: 7 }],
|
|
340
|
-
});
|
|
279
|
+
let formattedName = name.replaceAll('.', '_').replaceAll('/', '_');
|
|
280
|
+
|
|
281
|
+
const getCommonProperties = (type, valueType) => ({
|
|
282
|
+
[baEnum.PropertyIdentifier.OBJECT_NAME]: [{ value: formattedName, type: 7 }],
|
|
283
|
+
[baEnum.PropertyIdentifier.OBJECT_TYPE]: [{ value: type, type: 9 }],
|
|
284
|
+
[baEnum.PropertyIdentifier.DESCRIPTION]: [{ value: payload.description ?? '', type: 7 }],
|
|
285
|
+
[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER]: [{ value: { type: type, instance: that.getObjectIdentifier(type, instanceNumber) }, type: 12 }],
|
|
286
|
+
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{ value: payload.value ?? payload, type: valueType }],
|
|
287
|
+
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: payload.statusFlags ?? 0, type: 8 }],
|
|
288
|
+
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: payload.eventState ?? 0, type: 9 }],
|
|
289
|
+
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: payload.outOfService ?? 0, type: 9 }],
|
|
290
|
+
});
|
|
341
291
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
} else if (foundIndex !== -1) {
|
|
345
|
-
let foundObject = that.objectStore[baEnum.ObjectType.BINARY_VALUE][foundIndex];
|
|
346
|
-
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = value;
|
|
347
|
-
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
348
|
-
}
|
|
349
|
-
} else if (objectType == "string") {
|
|
350
|
-
let foundIndex = that.objectStore[baEnum.ObjectType.CHARACTERSTRING_VALUE].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
292
|
+
const addObjectToStore = (type, valueType, extraProperties = {}) => {
|
|
293
|
+
let foundIndex = that.objectStore[type].findIndex(ele => ele[baEnum.PropertyIdentifier.OBJECT_NAME][0].value == formattedName);
|
|
351
294
|
if (foundIndex == -1) {
|
|
352
|
-
let
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
[baEnum.PropertyIdentifier.PRESENT_VALUE]: [{ value: value, type: 7 }],
|
|
359
|
-
[baEnum.PropertyIdentifier.STATUS_FLAGS]: [{ value: 0, type: 8 }],
|
|
360
|
-
[baEnum.PropertyIdentifier.EVENT_STATE]: [{ value: 0, type: 9 }],
|
|
361
|
-
[baEnum.PropertyIdentifier.OUT_OF_SERVICE]: [{ value: 0, type: 9 }],
|
|
362
|
-
[baEnum.PropertyIdentifier.UNITS]: [{ value: 95, type: 9 }]
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
that.objectList.push({ value: { type: baEnum.ObjectType.CHARACTERSTRING_VALUE, instance: objectId }, type: 12 })
|
|
295
|
+
let newObject = {
|
|
296
|
+
...getCommonProperties(type, valueType),
|
|
297
|
+
...extraProperties
|
|
298
|
+
};
|
|
299
|
+
that.objectStore[type].push(newObject);
|
|
300
|
+
that.objectList.push({ value: { type: type, instance: newObject[baEnum.PropertyIdentifier.OBJECT_IDENTIFIER][0].value.instance }, type: 12 });
|
|
366
301
|
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
367
|
-
} else
|
|
368
|
-
let foundObject = that.objectStore[
|
|
369
|
-
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = value;
|
|
302
|
+
} else {
|
|
303
|
+
let foundObject = that.objectStore[type][foundIndex];
|
|
304
|
+
foundObject[baEnum.PropertyIdentifier.PRESENT_VALUE][0].value = payload.value ?? payload;
|
|
370
305
|
that.objectStore[baEnum.ObjectType.DEVICE][baEnum.PropertyIdentifier.OBJECT_LIST] = that.objectList;
|
|
371
306
|
}
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
if (objectType === "number") {
|
|
310
|
+
addObjectToStore(baEnum.ObjectType.ANALOG_VALUE, 4, {
|
|
311
|
+
[baEnum.PropertyIdentifier.UNITS]: [{ value: payload.units ?? 95, type: 9 }],
|
|
312
|
+
[baEnum.PropertyIdentifier.MAX_PRES_VALUE]: [{ value: payload.value ?? payload, type: 4 }],
|
|
313
|
+
[baEnum.PropertyIdentifier.MIN_PRES_VALUE]: [{ value: payload.value ?? payload, type: 4 }],
|
|
314
|
+
[baEnum.PropertyIdentifier.RESOLUTION]: [{ value: payload.resolution ?? 0, type: 4 }],
|
|
315
|
+
[baEnum.PropertyIdentifier.PRIORITY_ARRAY]: [{ value: payload.priorityArray ?? 0, type: 9 }],
|
|
316
|
+
[baEnum.PropertyIdentifier.PROPERTY_LIST]: [
|
|
317
|
+
{ value: baEnum.PropertyIdentifier.OBJECT_NAME, type: 9 },
|
|
318
|
+
{ value: baEnum.PropertyIdentifier.OBJECT_TYPE, type: 9 },
|
|
319
|
+
{ value: baEnum.PropertyIdentifier.DESCRIPTION, type: 9 },
|
|
320
|
+
{ value: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER, type: 9 },
|
|
321
|
+
{ value: baEnum.PropertyIdentifier.PRESENT_VALUE, type: 9 },
|
|
322
|
+
{ value: baEnum.PropertyIdentifier.STATUS_FLAGS, type: 9 },
|
|
323
|
+
{ value: baEnum.PropertyIdentifier.EVENT_STATE, type: 9 },
|
|
324
|
+
{ value: baEnum.PropertyIdentifier.OUT_OF_SERVICE, type: 9 },
|
|
325
|
+
{ value: baEnum.PropertyIdentifier.UNITS, type: 9 },
|
|
326
|
+
{ value: baEnum.PropertyIdentifier.PRIORITY_ARRAY, type: 9 },
|
|
327
|
+
{ value: baEnum.PropertyIdentifier.MAX_PRES_VALUE, type: 9 },
|
|
328
|
+
{ value: baEnum.PropertyIdentifier.MIN_PRES_VALUE, type: 9 },
|
|
329
|
+
{ value: baEnum.PropertyIdentifier.RESOLUTION, type: 9 },
|
|
330
|
+
]
|
|
331
|
+
});
|
|
332
|
+
} else if (objectType === "boolean") {
|
|
333
|
+
addObjectToStore(baEnum.ObjectType.BINARY_VALUE, 1, {
|
|
334
|
+
[baEnum.PropertyIdentifier.ACTIVE_TEXT]: [{ value: 'ACTIVE', type: 7 }],
|
|
335
|
+
[baEnum.PropertyIdentifier.INACTIVE_TEXT]: [{ value: 'INACTIVE', type: 7 }]
|
|
336
|
+
});
|
|
337
|
+
} else if (objectType === "string") {
|
|
338
|
+
addObjectToStore(baEnum.ObjectType.CHARACTERSTRING_VALUE, 7, {
|
|
339
|
+
[baEnum.PropertyIdentifier.UNITS]: [{ value: payload.units ?? 95, type: 9 }]
|
|
340
|
+
});
|
|
372
341
|
}
|
|
373
342
|
}
|
|
374
343
|
Store_Config_Server(JSON.stringify({ objectList: that.objectList, objectStore: that.objectStore }));
|
|
@@ -376,7 +345,7 @@ class BacnetServer extends EventEmitter {
|
|
|
376
345
|
|
|
377
346
|
/**
|
|
378
347
|
* Retrieves a specific property of an object based on the object ID, property ID, and instance number.
|
|
379
|
-
*
|
|
348
|
+
*
|
|
380
349
|
* @param {number} objectId - The ID of the object type.
|
|
381
350
|
* @param {number} propId - The ID of the property to retrieve.
|
|
382
351
|
* @param {number} instance - The instance number of the object.
|
|
@@ -405,7 +374,7 @@ class BacnetServer extends EventEmitter {
|
|
|
405
374
|
|
|
406
375
|
/**
|
|
407
376
|
* Retrieves a specific property of an object based on the object ID, property ID, and instance number and modify his value.
|
|
408
|
-
*
|
|
377
|
+
*
|
|
409
378
|
* @param {number} objectId - The ID of the object type.
|
|
410
379
|
* @param {number} propId - The ID of the property to retrieve.
|
|
411
380
|
* @param {number} instance - The instance number of the object.
|
|
@@ -436,7 +405,7 @@ class BacnetServer extends EventEmitter {
|
|
|
436
405
|
|
|
437
406
|
/**
|
|
438
407
|
* Retrieves the properties of a specific object instance from the objectStore based on the provided parameters.
|
|
439
|
-
*
|
|
408
|
+
*
|
|
440
409
|
* @param {number} objectId - The type of the object to retrieve.
|
|
441
410
|
* @param {number} propId - The property identifier to retrieve.
|
|
442
411
|
* @param {number} instance - The instance number of the object to retrieve.
|
|
@@ -534,7 +503,7 @@ class BacnetServer extends EventEmitter {
|
|
|
534
503
|
|
|
535
504
|
/**
|
|
536
505
|
* Removes a server point from the objectStore and objectList based on the provided JSON data.
|
|
537
|
-
*
|
|
506
|
+
*
|
|
538
507
|
* @param {Object} json - The JSON data containing information about the server point to be removed.
|
|
539
508
|
* @param {string} json.body.type - The type of the server point ('SV' for CharacterString, 'BV' for BinaryValue, default is AnalogValue).
|
|
540
509
|
* @param {number} json.body.instance - The instance number of the server point to be removed.
|
|
@@ -597,7 +566,7 @@ class BacnetServer extends EventEmitter {
|
|
|
597
566
|
* - name: The name of the object.
|
|
598
567
|
* - type: The type of the object (AV for Analog Value, SV for Character String Value, BV for Binary Value).
|
|
599
568
|
* - instance: The instance number of the object.
|
|
600
|
-
*
|
|
569
|
+
*
|
|
601
570
|
* @returns {Promise<Array>} A promise that resolves with an array of points sorted by instance number.
|
|
602
571
|
* @throws {Error} If an error occurs during the retrieval process.
|
|
603
572
|
*/
|
|
@@ -688,7 +657,7 @@ class BacnetServer extends EventEmitter {
|
|
|
688
657
|
|
|
689
658
|
/**
|
|
690
659
|
* Determines the BACnet object type based on the provided value.
|
|
691
|
-
*
|
|
660
|
+
*
|
|
692
661
|
* @param {any} value - The value to determine the BACnet object type for.
|
|
693
662
|
* @returns {string|null} The BACnet object type as a string ('string', 'number', 'boolean') or null if the type is not recognized.
|
|
694
663
|
*/
|
|
@@ -702,6 +671,8 @@ class BacnetServer extends EventEmitter {
|
|
|
702
671
|
return "number"
|
|
703
672
|
case "boolean":
|
|
704
673
|
return "boolean"
|
|
674
|
+
case "object":
|
|
675
|
+
return "object"
|
|
705
676
|
default:
|
|
706
677
|
return null
|
|
707
678
|
}
|
|
@@ -709,7 +680,7 @@ class BacnetServer extends EventEmitter {
|
|
|
709
680
|
|
|
710
681
|
/**
|
|
711
682
|
* Returns the object identifier for the given type and instance number.
|
|
712
|
-
*
|
|
683
|
+
*
|
|
713
684
|
* @param {string} type - The type of the object.
|
|
714
685
|
* @param {number} instanceNumber - The instance number of the object.
|
|
715
686
|
* @returns {number} The object identifier.
|
|
@@ -728,4 +699,4 @@ class BacnetServer extends EventEmitter {
|
|
|
728
699
|
}
|
|
729
700
|
}
|
|
730
701
|
|
|
731
|
-
module.exports = { BacnetServer };
|
|
702
|
+
module.exports = { BacnetServer };
|
package/bitpool_inject.html
CHANGED
|
@@ -142,6 +142,26 @@
|
|
|
142
142
|
</div>
|
|
143
143
|
</div>
|
|
144
144
|
|
|
145
|
+
|
|
146
|
+
<div class="injectHeading" style="margin-top: 20px;">
|
|
147
|
+
<a>Topic Properties</a>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<div class="objectPropertiesLabel" style="margin-top: 20px;">
|
|
151
|
+
<label
|
|
152
|
+
for="node-input-useDeviceName"
|
|
153
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
154
|
+
class="objectPropertiesLabel">
|
|
155
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.useDeviceName"></span>
|
|
156
|
+
<input
|
|
157
|
+
style="margin-left: 5px;"
|
|
158
|
+
class=" objectProp"
|
|
159
|
+
type="checkbox"
|
|
160
|
+
id="node-input-useDeviceName" />
|
|
161
|
+
<a style="white-space: nowrap; padding-left: 20px;">Use device name in topic</a>
|
|
162
|
+
</label>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
145
165
|
<div class="injectHeading" style="margin-top: 20px;">
|
|
146
166
|
<a>Msg Properties</a>
|
|
147
167
|
</div>
|
|
@@ -476,6 +496,7 @@
|
|
|
476
496
|
object_property_simplePayload: { value: false },
|
|
477
497
|
object_property_simpleWithStatus: { value: false },
|
|
478
498
|
object_property_fullObject: { value: true },
|
|
499
|
+
useDeviceName: { value: true },
|
|
479
500
|
},
|
|
480
501
|
icon: "bitpool.svg",
|
|
481
502
|
inputs: 0,
|
|
@@ -779,6 +800,8 @@
|
|
|
779
800
|
document.getElementById("node-input-object_property_fullObject").checked = node.object_property_fullObject;
|
|
780
801
|
document.getElementById("node-input-object_property_fullObject").onclick = handlePayloadCheckboxClick;
|
|
781
802
|
|
|
803
|
+
document.getElementById("node-input-useDeviceName").checked = node.useDeviceName;
|
|
804
|
+
|
|
782
805
|
|
|
783
806
|
document.getElementById("node-input-doDiscover").onclick = handleCheckboxClick;
|
|
784
807
|
document.getElementById("node-input-doPoll").onclick = handleCheckboxClick;
|
package/bitpool_inject.js
CHANGED
|
@@ -60,6 +60,9 @@ module.exports = function (RED) {
|
|
|
60
60
|
this.object_property_simplePayload = n.object_property_simplePayload;
|
|
61
61
|
this.object_property_simpleWithStatus = n.object_property_simpleWithStatus;
|
|
62
62
|
this.object_property_fullObject = n.object_property_fullObject;
|
|
63
|
+
|
|
64
|
+
this.useDeviceName = n.useDeviceName;
|
|
65
|
+
|
|
63
66
|
this.json = n.json;
|
|
64
67
|
this.mqtt = n.mqtt;
|
|
65
68
|
this.pointJson = n.pointJson;
|
|
@@ -121,6 +124,8 @@ module.exports = function (RED) {
|
|
|
121
124
|
msg.mqtt = node.mqtt;
|
|
122
125
|
msg.pointJson = node.pointJson;
|
|
123
126
|
|
|
127
|
+
msg.useDeviceName = node.useDeviceName;
|
|
128
|
+
|
|
124
129
|
|
|
125
130
|
var errors = [];
|
|
126
131
|
var props = this.props;
|
package/package.json
CHANGED
package/resources/style.css
CHANGED
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
/* Read node styles */
|
|
17
17
|
|
|
18
|
+
.refreshReadListButton {
|
|
19
|
+
border: none;
|
|
20
|
+
border-radius: 40px;
|
|
21
|
+
height: 35px;
|
|
22
|
+
width: 35px;
|
|
23
|
+
& i {
|
|
24
|
+
color: #6c757d !important;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
18
28
|
.p-treenode-label {
|
|
19
29
|
color: black;
|
|
20
30
|
width: 100%;
|
|
@@ -150,6 +160,8 @@
|
|
|
150
160
|
float: right;
|
|
151
161
|
display: flex;
|
|
152
162
|
align-items: center;
|
|
163
|
+
padding: 5px;
|
|
164
|
+
font-weight: bold;
|
|
153
165
|
}
|
|
154
166
|
.removeAllDevicesButton:hover {
|
|
155
167
|
background-color: #d5d5d5;
|
|
@@ -247,7 +259,6 @@
|
|
|
247
259
|
z-index: 10;
|
|
248
260
|
}
|
|
249
261
|
|
|
250
|
-
|
|
251
262
|
.context-menu {
|
|
252
263
|
--mouse-x: 0;
|
|
253
264
|
--mouse-y: 0;
|
package/treeBuilder.js
CHANGED
|
@@ -63,7 +63,6 @@ class treeBuilder {
|
|
|
63
63
|
// Check if the device object exists and the device name is valid
|
|
64
64
|
if (deviceObject) {
|
|
65
65
|
await this.processDevicePoints(device, deviceObject, deviceName, ipAddress, deviceId, index);
|
|
66
|
-
|
|
67
66
|
} else {
|
|
68
67
|
//console.log("Unable to find device object");
|
|
69
68
|
}
|