@bitpoolos/edge-bacnet 1.2.7 → 1.3.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.
- package/CHANGELOG.md +76 -0
- package/README.md +20 -2
- package/bacnet_client.js +1662 -1572
- package/bacnet_device.js +122 -60
- package/bacnet_gateway.html +115 -71
- package/bacnet_gateway.js +165 -48
- package/bacnet_read.html +1025 -596
- package/bacnet_read.js +68 -84
- package/bacnet_server.js +187 -186
- package/bacnet_write.html +971 -738
- package/common.js +40 -28
- package/package.json +1 -1
- package/resources/bitArray.js +167 -0
- package/resources/node-bacstack-ts/dist/lib/asn1.js +16 -5
- package/resources/node-bacstack-ts/dist/lib/client.js +5 -6
- package/resources/style.css +321 -0
- package/treeBuilder.js +533 -0
package/bacnet_gateway.js
CHANGED
|
@@ -35,6 +35,7 @@ module.exports = function (RED) {
|
|
|
35
35
|
this.bacnetServer = nodeContext.get("bacnetServer") || null;
|
|
36
36
|
this.deviceRangeRegisters = config.deviceRangeRegisters;
|
|
37
37
|
this.cacheFileEnabled = config.cacheFileEnabled;
|
|
38
|
+
this.sanitise_device_schedule = config.sanitise_device_schedule;
|
|
38
39
|
|
|
39
40
|
//client and config store
|
|
40
41
|
this.bacnetConfig = nodeContext.get("bacnetConfig");
|
|
@@ -62,7 +63,8 @@ module.exports = function (RED) {
|
|
|
62
63
|
node.manual_instance_range_end,
|
|
63
64
|
node.device_read_schedule,
|
|
64
65
|
node.retries,
|
|
65
|
-
node.cacheFileEnabled
|
|
66
|
+
node.cacheFileEnabled,
|
|
67
|
+
node.sanitise_device_schedule
|
|
66
68
|
);
|
|
67
69
|
|
|
68
70
|
nodeContext.set("bacnetConfig", node.bacnetConfig);
|
|
@@ -97,8 +99,15 @@ module.exports = function (RED) {
|
|
|
97
99
|
node.bacnetClient.removeAllListeners();
|
|
98
100
|
|
|
99
101
|
// Value response event handler for READ commands
|
|
100
|
-
node.bacnetClient.on("values", (values, outputType, objectPropertyType, readNodeName) => {
|
|
102
|
+
node.bacnetClient.on("values", (values, outputType, objectPropertyType, readNodeName, deviceIndex, devicesToRead) => {
|
|
101
103
|
if (typeof values !== "undefined" && Object.keys(values).length) {
|
|
104
|
+
let publishText = `Publishing ${readNodeName} ${deviceIndex} / ${devicesToRead} `;
|
|
105
|
+
node.status({ fill: "blue", shape: "dot", text: publishText });
|
|
106
|
+
if (deviceIndex == devicesToRead) {
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
node.status({});
|
|
109
|
+
}, 3000);
|
|
110
|
+
}
|
|
102
111
|
if (outputType.json && !outputType.mqtt) {
|
|
103
112
|
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
104
113
|
sendSimpleJson(values, readNodeName);
|
|
@@ -173,12 +182,12 @@ module.exports = function (RED) {
|
|
|
173
182
|
} else if (msg.doUpdatePriorityDevices == true && msg.priorityDevices !== null) {
|
|
174
183
|
node.bacnetClient
|
|
175
184
|
.updatePriorityQueue(msg.priorityDevices)
|
|
176
|
-
.then(function (result) {})
|
|
185
|
+
.then(function (result) { })
|
|
177
186
|
.catch(function (error) {
|
|
178
187
|
logOut("Error updating priorityQueue: ", error);
|
|
179
188
|
});
|
|
180
189
|
} else if (msg.testFunc == true) {
|
|
181
|
-
node.bacnetClient.testFunction();
|
|
190
|
+
node.bacnetClient.testFunction(msg.address, msg.type, msg.instance, msg.property);
|
|
182
191
|
}
|
|
183
192
|
});
|
|
184
193
|
|
|
@@ -191,7 +200,6 @@ module.exports = function (RED) {
|
|
|
191
200
|
if (!node.bacnetClient) {
|
|
192
201
|
logOut("Issue with the bacnetClient: ", node.bacnetClient);
|
|
193
202
|
//no bacnet client present
|
|
194
|
-
//node.status({fill:"red",shape:"dot",text:"Please define client"});
|
|
195
203
|
res.send(false);
|
|
196
204
|
} else {
|
|
197
205
|
node.bacnetClient
|
|
@@ -211,7 +219,6 @@ module.exports = function (RED) {
|
|
|
211
219
|
if (!node.bacnetClient) {
|
|
212
220
|
logOut("Issue with the bacnetClient: ", node.bacnetClient);
|
|
213
221
|
//no bacnet client present
|
|
214
|
-
//node.status({fill:"red",shape:"dot",text:"Please define client"});
|
|
215
222
|
res.send(false);
|
|
216
223
|
} else {
|
|
217
224
|
node.bacnetClient
|
|
@@ -310,30 +317,130 @@ module.exports = function (RED) {
|
|
|
310
317
|
}
|
|
311
318
|
});
|
|
312
319
|
|
|
320
|
+
//route handler for purge device
|
|
321
|
+
RED.httpAdmin.post("/bitpool-bacnet-data/purgeDevice", function (req, res) {
|
|
322
|
+
if (!node.bacnetClient) {
|
|
323
|
+
logOut("Issue with the bacnetClient while getting device list: ", node.bacnetClient);
|
|
324
|
+
res.send(false);
|
|
325
|
+
} else {
|
|
326
|
+
node.bacnetClient
|
|
327
|
+
.purgeDevice(req.body.d)
|
|
328
|
+
.then(function (result) {
|
|
329
|
+
res.send(result);
|
|
330
|
+
})
|
|
331
|
+
.catch(function (error) {
|
|
332
|
+
res.send(error);
|
|
333
|
+
logOut("Error purging device: ", error);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
//route handler for updatePointsForDevice
|
|
339
|
+
RED.httpAdmin.post("/bitpool-bacnet-data/updatePointsForDevice", function (req, res) {
|
|
340
|
+
if (!node.bacnetClient) {
|
|
341
|
+
logOut("Issue with the bacnetClient while updating device points list: ", node.bacnetClient);
|
|
342
|
+
res.send(false);
|
|
343
|
+
} else {
|
|
344
|
+
node.bacnetClient
|
|
345
|
+
.updatePointsForDevice(req.body.d)
|
|
346
|
+
.then(function (result) {
|
|
347
|
+
res.send(result);
|
|
348
|
+
})
|
|
349
|
+
.catch(function (error) {
|
|
350
|
+
res.send(error);
|
|
351
|
+
logOut("Error updating device: ", error);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
//route handler for setDeviceDisplayName
|
|
357
|
+
RED.httpAdmin.post("/bitpool-bacnet-data/setDeviceDisplayName", function (req, res) {
|
|
358
|
+
if (!node.bacnetClient) {
|
|
359
|
+
logOut("Issue with the bacnetClient while updating device points list: ", node.bacnetClient);
|
|
360
|
+
res.send(false);
|
|
361
|
+
} else {
|
|
362
|
+
node.bacnetClient
|
|
363
|
+
.setDeviceDisplayName(req.body.d, req.body.n)
|
|
364
|
+
.then(function (result) {
|
|
365
|
+
res.send(result);
|
|
366
|
+
})
|
|
367
|
+
.catch(function (error) {
|
|
368
|
+
res.send(error);
|
|
369
|
+
logOut("Error setting device display name: ", error);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
//route handler for setPointDisplayName
|
|
375
|
+
RED.httpAdmin.post("/bitpool-bacnet-data/setPointDisplayName", function (req, res) {
|
|
376
|
+
if (!node.bacnetClient) {
|
|
377
|
+
logOut("Issue with the bacnetClient while updating point name: ", node.bacnetClient);
|
|
378
|
+
res.send(false);
|
|
379
|
+
} else {
|
|
380
|
+
node.bacnetClient
|
|
381
|
+
.setPointDisplayName(req.body.k, req.body.p, req.body.n)
|
|
382
|
+
.then(function (result) {
|
|
383
|
+
res.send(result);
|
|
384
|
+
})
|
|
385
|
+
.catch(function (error) {
|
|
386
|
+
res.send(error);
|
|
387
|
+
logOut("Error setting device display name: ", error);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
//route handler for importReadList
|
|
393
|
+
RED.httpAdmin.post("/bitpool-bacnet-data/importReadList", function (req, res) {
|
|
394
|
+
if (!node.bacnetClient) {
|
|
395
|
+
logOut("Issue with the bacnetClient while updating point name: ", node.bacnetClient);
|
|
396
|
+
res.send(false);
|
|
397
|
+
} else {
|
|
398
|
+
node.bacnetClient
|
|
399
|
+
.importReadList(req.body.p)
|
|
400
|
+
.then(function (result) {
|
|
401
|
+
res.send(result);
|
|
402
|
+
})
|
|
403
|
+
.catch(function (error) {
|
|
404
|
+
res.send(error);
|
|
405
|
+
logOut("Error setting device display name: ", error);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
|
|
313
411
|
function bindEventListeners() {
|
|
314
412
|
// Value response event handler for READ commands
|
|
315
|
-
node.bacnetClient.on("values", (
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
sendSimpleJson(values, readNodeName);
|
|
413
|
+
node.bacnetClient.on("values", (values, outputType, objectPropertyType, readNodeName, deviceIndex, devicesToRead) => {
|
|
414
|
+
if (typeof values !== "undefined" && Object.keys(values).length) {
|
|
415
|
+
let publishText = `Publishing ${readNodeName} ${deviceIndex} / ${devicesToRead} `;
|
|
416
|
+
node.status({ fill: "blue", shape: "dot", text: publishText });
|
|
417
|
+
if (deviceIndex == devicesToRead) {
|
|
418
|
+
setTimeout(() => {
|
|
419
|
+
node.status({});
|
|
420
|
+
}, 3000);
|
|
324
421
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
422
|
+
if (outputType.json && !outputType.mqtt) {
|
|
423
|
+
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
424
|
+
sendSimpleJson(values, readNodeName);
|
|
425
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
426
|
+
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
427
|
+
sendJsonAsMqtt(values, readNodeName);
|
|
428
|
+
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
429
|
+
sendSimpleJson(values, readNodeName);
|
|
430
|
+
}
|
|
431
|
+
} else if (!outputType.json && outputType.mqtt) {
|
|
432
|
+
if (objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
433
|
+
sendAsMqtt(values, readNodeName);
|
|
434
|
+
sendSimpleMqtt(values, readNodeName);
|
|
435
|
+
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
436
|
+
sendAsMqtt(values, readNodeName);
|
|
437
|
+
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
438
|
+
sendSimpleMqtt(values, readNodeName);
|
|
439
|
+
}
|
|
333
440
|
}
|
|
334
441
|
}
|
|
335
442
|
});
|
|
336
|
-
|
|
443
|
+
|
|
337
444
|
// Who Is / Iam event handler
|
|
338
445
|
node.bacnetClient.on("deviceFound", (device) => {
|
|
339
446
|
if (node.toLogIam) node.warn(`BACnet device found: ${device.deviceId} - ${device.address}`);
|
|
@@ -352,6 +459,13 @@ module.exports = function (RED) {
|
|
|
352
459
|
}
|
|
353
460
|
}
|
|
354
461
|
|
|
462
|
+
function getPointName(object, pointName) {
|
|
463
|
+
if (object.displayName) {
|
|
464
|
+
return object.displayName;
|
|
465
|
+
}
|
|
466
|
+
return pointName;
|
|
467
|
+
}
|
|
468
|
+
|
|
355
469
|
sendSimpleMqtt = function (values, readNodeName) {
|
|
356
470
|
let devices = Object.keys(values);
|
|
357
471
|
devices.forEach(function (device) {
|
|
@@ -359,6 +473,7 @@ module.exports = function (RED) {
|
|
|
359
473
|
let points = values[device];
|
|
360
474
|
for (var point in points) {
|
|
361
475
|
if (points[point]) {
|
|
476
|
+
let pointName = getPointName(points[point], point);
|
|
362
477
|
let pointProps = Object.keys(points[point]);
|
|
363
478
|
pointProps.forEach(function (prop) {
|
|
364
479
|
let msg = {};
|
|
@@ -370,22 +485,22 @@ module.exports = function (RED) {
|
|
|
370
485
|
node.nodeName !== "undefined" &&
|
|
371
486
|
typeof node.nodeName == "string"
|
|
372
487
|
) {
|
|
373
|
-
if(readNodeName !== ''&&
|
|
488
|
+
if (readNodeName !== '' &&
|
|
374
489
|
readNodeName !== null &&
|
|
375
490
|
readNodeName !== undefined
|
|
376
491
|
) {
|
|
377
|
-
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${
|
|
492
|
+
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${pointName}`;
|
|
378
493
|
} else {
|
|
379
|
-
msg.topic = `${node.nodeName}/${device}/${
|
|
494
|
+
msg.topic = `${node.nodeName}/${device}/${pointName}`;
|
|
380
495
|
}
|
|
381
496
|
} else {
|
|
382
|
-
if(readNodeName !== ''&&
|
|
497
|
+
if (readNodeName !== '' &&
|
|
383
498
|
readNodeName !== null &&
|
|
384
499
|
readNodeName !== undefined
|
|
385
500
|
) {
|
|
386
|
-
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${
|
|
501
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${pointName}`;
|
|
387
502
|
} else {
|
|
388
|
-
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${
|
|
503
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${pointName}`;
|
|
389
504
|
}
|
|
390
505
|
}
|
|
391
506
|
msg.payload = points[point][prop];
|
|
@@ -406,6 +521,7 @@ module.exports = function (RED) {
|
|
|
406
521
|
let points = values[device];
|
|
407
522
|
for (var point in points) {
|
|
408
523
|
if (points[point]) {
|
|
524
|
+
let pointName = getPointName(points[point], point);
|
|
409
525
|
let pointProps = Object.keys(points[point]);
|
|
410
526
|
pointProps.forEach(function (prop) {
|
|
411
527
|
let msg = {};
|
|
@@ -417,22 +533,22 @@ module.exports = function (RED) {
|
|
|
417
533
|
node.nodeName !== "undefined" &&
|
|
418
534
|
typeof node.nodeName == "string"
|
|
419
535
|
) {
|
|
420
|
-
if(readNodeName !== ''&&
|
|
536
|
+
if (readNodeName !== '' &&
|
|
421
537
|
readNodeName !== null &&
|
|
422
538
|
readNodeName !== undefined
|
|
423
539
|
) {
|
|
424
|
-
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${
|
|
540
|
+
msg.topic = `${node.nodeName}/${readNodeName}/${device}/${pointName}/${prop}`;
|
|
425
541
|
} else {
|
|
426
|
-
msg.topic = `${node.nodeName}/${device}/${
|
|
542
|
+
msg.topic = `${node.nodeName}/${device}/${pointName}/${prop}`;
|
|
427
543
|
}
|
|
428
544
|
} else {
|
|
429
|
-
if(readNodeName !== ''&&
|
|
545
|
+
if (readNodeName !== '' &&
|
|
430
546
|
readNodeName !== null &&
|
|
431
547
|
readNodeName !== undefined
|
|
432
548
|
) {
|
|
433
|
-
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${
|
|
549
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${pointName}/${prop}`;
|
|
434
550
|
} else {
|
|
435
|
-
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${
|
|
551
|
+
msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${pointName}/${prop}`;
|
|
436
552
|
}
|
|
437
553
|
}
|
|
438
554
|
msg.payload = points[point][prop];
|
|
@@ -456,6 +572,7 @@ module.exports = function (RED) {
|
|
|
456
572
|
let points = values[device];
|
|
457
573
|
for (var point in points) {
|
|
458
574
|
if (points[point]) {
|
|
575
|
+
let pointName = getPointName(points[point], point);
|
|
459
576
|
let pointProps = Object.keys(points[point]);
|
|
460
577
|
pointProps.forEach(function (prop) {
|
|
461
578
|
if (prop == "presentValue") {
|
|
@@ -473,18 +590,18 @@ module.exports = function (RED) {
|
|
|
473
590
|
node.nodeName !== "undefined" &&
|
|
474
591
|
typeof node.nodeName == "string"
|
|
475
592
|
) {
|
|
476
|
-
if(readNodeName !== ''&&
|
|
477
|
-
|
|
478
|
-
|
|
593
|
+
if (readNodeName !== '' &&
|
|
594
|
+
readNodeName !== null &&
|
|
595
|
+
readNodeName !== undefined
|
|
479
596
|
) {
|
|
480
597
|
msgg.topic = `${node.nodeName}/${readNodeName}/${device}`;
|
|
481
598
|
} else {
|
|
482
599
|
msgg.topic = `${node.nodeName}/${device}`;
|
|
483
600
|
}
|
|
484
601
|
} else {
|
|
485
|
-
if(readNodeName !== ''&&
|
|
486
|
-
|
|
487
|
-
|
|
602
|
+
if (readNodeName !== '' &&
|
|
603
|
+
readNodeName !== null &&
|
|
604
|
+
readNodeName !== undefined
|
|
488
605
|
) {
|
|
489
606
|
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}`;
|
|
490
607
|
} else {
|
|
@@ -510,18 +627,18 @@ module.exports = function (RED) {
|
|
|
510
627
|
node.nodeName !== "undefined" &&
|
|
511
628
|
typeof node.nodeName == "string"
|
|
512
629
|
) {
|
|
513
|
-
if(readNodeName !== ''&&
|
|
514
|
-
|
|
515
|
-
|
|
630
|
+
if (readNodeName !== '' &&
|
|
631
|
+
readNodeName !== null &&
|
|
632
|
+
readNodeName !== undefined
|
|
516
633
|
) {
|
|
517
634
|
msgg.topic = `${node.nodeName}/${readNodeName}/${key}`;
|
|
518
635
|
} else {
|
|
519
636
|
msgg.topic = `${node.nodeName}/${key}`;
|
|
520
637
|
}
|
|
521
638
|
} else {
|
|
522
|
-
if(readNodeName !== ''&&
|
|
523
|
-
|
|
524
|
-
|
|
639
|
+
if (readNodeName !== '' &&
|
|
640
|
+
readNodeName !== null &&
|
|
641
|
+
readNodeName !== undefined
|
|
525
642
|
) {
|
|
526
643
|
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${key}`;
|
|
527
644
|
} else {
|