@bitpoolos/edge-bacnet 1.0.9 → 1.1.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/bacnet_device.js CHANGED
@@ -1,21 +1,39 @@
1
1
  class BacnetDevice {
2
- constructor(config) {
2
+ constructor(fromImport, config) {
3
3
  let that = this;
4
- if(config.header.source) {
5
- that.address = {address: config.header.sender.address, net: config.header.source.net, adr: config.header.source.adr};
6
- that.isMstp = true;
7
- } else {
8
- that.address = config.header.sender.address;
9
- that.isMstp = false;
4
+
5
+ if(fromImport == true) {
6
+ that.address = config.address;
7
+ that.isMstp = config.isMstp;
8
+ that.deviceId = config.deviceId;
9
+ that.maxApdu = config.maxApdu;
10
+ that.segmentation = config.segmentation;
11
+ that.vendorId = config.vendorId;
12
+ that.lastSeen = config.lastSeen;
13
+ that.deviceName = config.deviceName;
14
+ that.pointsList = config.pointsList;
15
+ that.pointListUpdateTs = config.pointListUpdateTs;
16
+ that.manualDiscoveryMode = config.manualDiscoveryMode;
17
+
18
+ } else if(fromImport == false) {
19
+
20
+ if(config.header.source) {
21
+ that.address = {address: config.header.sender.address, net: config.header.source.net, adr: config.header.source.adr};
22
+ that.isMstp = true;
23
+ } else {
24
+ that.address = config.header.sender.address;
25
+ that.isMstp = false;
26
+ }
27
+ that.deviceId = config.payload.deviceId;
28
+ that.maxApdu = config.payload.maxApdu;
29
+ that.segmentation = config.payload.segmentation;
30
+ that.vendorId = config.payload.vendorId;
31
+ that.lastSeen = null;
32
+ that.deviceName = null;
33
+ that.pointsList = [];
34
+ that.pointListUpdateTs = null;
35
+ that.manualDiscoveryMode = false;
10
36
  }
11
- that.deviceId = config.payload.deviceId;
12
- that.maxApdu = config.payload.maxApdu;
13
- that.segmentation = config.payload.segmentation;
14
- that.vendorId = config.payload.vendorId;
15
- that.lastSeen = null;
16
- that.deviceName = null;
17
- that.pointsList = [];
18
- that.pointListUpdateTs = null;
19
37
  }
20
38
 
21
39
  updateDeviceConfig(config) {
@@ -32,6 +50,14 @@ class BacnetDevice {
32
50
  if(Number.isInteger(config.vendorId)) this.vendorId = config.payload.vendorId;
33
51
  }
34
52
 
53
+ setManualDiscoveryMode(bool) {
54
+ this.manualDiscoveryMode = bool;
55
+ }
56
+
57
+ getManualDiscoveryMode() {
58
+ return this.manualDiscoveryMode;
59
+ }
60
+
35
61
  setPointListUpdateTS(ts) {
36
62
  this.pointListUpdateTs = ts;
37
63
  }
@@ -95,17 +95,21 @@
95
95
  maxSegments: {value: "0x50", required: true},
96
96
  broadCastAddr: {value: "255.255.255.255", required: true},
97
97
  toLogIam: {value: true},
98
- //toRestartNodeRed: {value: false},
99
98
  discover_polling_schedule: {value: ""},
100
99
  discover_polling_schedule_value: {value: "1", required: true},
101
100
  discover_polling_schedule_options: {value: "Minutes", required: true},
102
101
  device_id_range_enabled: {value: false},
103
102
  device_id_range_start: {value: 0},
104
103
  device_id_range_end: {value: 4194303},
105
- deviceId: {value: 1234, required: true},
104
+ deviceId: {value: 817001, required: true},
106
105
  manual_instance_range_enabled: {value: false},
107
106
  manual_instance_range_start: {value: 0},
108
107
  manual_instance_range_end: {value: 10000},
108
+ logErrorToConsole: {value: false},
109
+ serverEnabled: {value: false},
110
+ bacnetServerRebuildSchedule: {value: ""},
111
+ bacnetServerRebuildSchedule_value: {value: "1", required: true},
112
+ bacnetServerRebuildSchedule_options: {value: "Hours", required: true}
109
113
  },
110
114
  networkInterfaces: [],
111
115
  inputs: 1,
@@ -141,8 +145,11 @@
141
145
  label: "Discovery"
142
146
  });
143
147
 
144
-
145
-
148
+ tabs.addTab(
149
+ {
150
+ id: "read-server-tab",
151
+ label: "Server"
152
+ });
146
153
 
147
154
  if (node.networkInterfaces && node.networkInterfaces.length > 0) {
148
155
  let nicSelector = document.getElementById("node-input-local_device_address");
@@ -179,17 +186,17 @@
179
186
 
180
187
  queryAdapters();
181
188
 
182
- function setBroadCastAddress() {
183
- let nicSelector = document.getElementById("node-input-local_device_address");
184
- nicSelector.onchange = function(e) {
185
- if(typeof e.target.value == "string" && e.target.value !== ""){
186
- let broadcastAddrPrefill = e.target.value.split(".").slice(0, 3).join(".") + ".255";
187
- document.getElementById("node-input-broadCastAddr").value = broadcastAddrPrefill;
188
- }
189
- };
190
- }
189
+ // function setBroadCastAddress() {
190
+ // let nicSelector = document.getElementById("node-input-local_device_address");
191
+ // nicSelector.onchange = function(e) {
192
+ // if(typeof e.target.value == "string" && e.target.value !== ""){
193
+ // let broadcastAddrPrefill = e.target.value.split(".").slice(0, 3).join(".") + ".255";
194
+ // document.getElementById("node-input-broadCastAddr").value = broadcastAddrPrefill;
195
+ // }
196
+ // };
197
+ // }
191
198
 
192
- setBroadCastAddress();
199
+ // setBroadCastAddress();
193
200
 
194
201
  function setDeviceIdRangeState(state) {
195
202
  let deviceIdRangeStart = $("#node-input-device_id_range_start");
@@ -225,14 +232,7 @@
225
232
 
226
233
  $("#node-input-manual_instance_range_enabled").change(function(e) {
227
234
  setManualInstanceRangeState(this.checked);
228
- });
229
-
230
- // document.getElementById('restart-nr-button').onclick = function () {
231
- // this.disabled = true;
232
- // document.getElementById("node-input-toRestartNodeRed").checked = true;
233
- // }
234
-
235
- // console.log("toRestartNodeRed: ", document.getElementById("node-input-toRestartNodeRed").checked);
235
+ });
236
236
 
237
237
  },
238
238
  oneditsave: function (test) {
@@ -242,6 +242,11 @@
242
242
  document.getElementById("node-input-discover_polling_schedule_value").value,
243
243
  document.getElementById("node-input-discover_polling_schedule_options").value
244
244
  );
245
+
246
+ document.getElementById("node-input-bacnetServerRebuildSchedule").value = getTimePeriodInSeconds(
247
+ document.getElementById("node-input-bacnetServerRebuildSchedule_value").value,
248
+ document.getElementById("node-input-bacnetServerRebuildSchedule_options").value
249
+ );
245
250
  }
246
251
  });
247
252
 
@@ -295,6 +300,10 @@
295
300
  margin-left: 50px;
296
301
  }
297
302
 
303
+ .red-ui-editor label {
304
+ font-size: 12px;
305
+ }
306
+
298
307
  </style>
299
308
 
300
309
  <div class='form-row node-input-read-tabs-row'>
@@ -330,7 +339,7 @@
330
339
 
331
340
  <div class="form-row">
332
341
  <label for="node-input-deviceId"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.deviceId"></span> Device ID </label>
333
- <input type="text" id="node-input-deviceId" placeholder="1234">
342
+ <input type="text" id="node-input-deviceId" placeholder="817001">
334
343
  </div>
335
344
 
336
345
  <div class="form-row deviceIdRange">
@@ -338,7 +347,6 @@
338
347
  <input type="checkbox" id="node-input-device_id_range_enabled" style="width: auto;"/>
339
348
  <a style="padding-left: 60px;">Start: </a><input type="number" id="node-input-device_id_range_start" style="width: 125px;" min="0" max="4194303"/>
340
349
  <a style="padding-left: 35px;">End: </a><input type="number" id="node-input-device_id_range_end" style="width: 125px;" min="1" max="4194303"/>
341
-
342
350
  </div>
343
351
  </div>
344
352
 
@@ -376,7 +384,7 @@
376
384
  </div>
377
385
 
378
386
  <div class="form-row" style="align-items: center; display: flex;">
379
- <label for="node-input-discover_polling_schedule_value"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.bacnet_polling_schedule"></span>Global Discover Frequency</label>
387
+ <label for="node-input-discover_polling_schedule_value"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.bacnet_polling_schedule"></span>Discover Frequency</label>
380
388
  <p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
381
389
  <input type="text" id="node-input-discover_polling_schedule" style="display: none;">
382
390
  <input type="text" id="node-input-discover_polling_schedule_value" placeholder="5" style="width: 70px; margin-right: 5px;">
@@ -388,12 +396,12 @@
388
396
  </select>
389
397
  </div>
390
398
 
391
- <!-- <div class="form-row deviceIdRange">
392
- <label for="node-input-device_id_range"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.device_id_range"></span> Manual Point Discovery Instance Range </label>
399
+ <div class="form-row deviceIdRange">
400
+ <label for="node-input-device_id_range"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.device_id_range"></span>Point Discovery Range </label>
393
401
  <input type="checkbox" id="node-input-manual_instance_range_enabled" style="width: auto;"/>
394
402
  <a style="padding-left: 60px;">Start: </a><input type="number" id="node-input-manual_instance_range_start" style="width: 125px;" min="0" max="100000"/>
395
403
  <a style="padding-left: 35px;">End: </a><input type="number" id="node-input-manual_instance_range_end" style="width: 125px;" min="1" max="100000"/>
396
- </div> -->
404
+ </div>
397
405
 
398
406
  <div class="form-row">
399
407
  <label for="node-input-toLog">
@@ -401,35 +409,73 @@
401
409
  </label>
402
410
  <input type="checkbox" id="node-input-toLogIam" style="width: auto;"/>
403
411
  </div>
404
- </div>
405
-
406
-
407
412
 
408
-
413
+ <div class="form-row">
414
+ <label for="node-input-logErrorToConsole">
415
+ Log BACnet errors to console:
416
+ </label>
417
+ <input type="checkbox" id="node-input-logErrorToConsole" style="width: auto;"/>
418
+ </div>
419
+
420
+ </div>
421
+ <div id='read-server-tab' style='display:none'>
422
+ <div class="form-row">
423
+ <label for="node-input-serverEnabled">
424
+ Enabled:
425
+ </label>
426
+ <input type="checkbox" id="node-input-serverEnabled" style="width: auto;"/>
427
+ </div>
409
428
 
410
- <!-- <div class="form-row">
411
- <label for="node-input-toRestartNodeRed">
412
- Restart Node-Red:
413
- </label>
414
- <button id="restart-nr-button">Restart Node-Red</button>
415
- <input type="checkbox" id="node-input-toRestartNodeRed" style="display: none;"/>
416
- </div> -->
429
+ <div class="form-row" style="align-items: center; display: flex;">
430
+ <label for="node-input-bacnetServerRebuildSchedule_value"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.bacnetServerRebuildSchedule"></span>Clear Server Points:</label>
431
+ <p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
432
+ <input type="text" id="node-input-bacnetServerRebuildSchedule" style="display: none;">
433
+ <input type="text" id="node-input-bacnetServerRebuildSchedule_value" placeholder="5" style="width: 70px; margin-right: 5px;">
434
+ <select name="timePeriod" id="node-input-bacnetServerRebuildSchedule_options" style="width: 120px; margin-right: 5px;">
435
+ <option value="Seconds">Seconds</option>
436
+ <option value="Minutes">Minutes</option>
437
+ <option value="Hours">Hours</option>
438
+ <option value="Days">Days</option>
439
+ </select>
440
+ </div>
441
+ </div>
417
442
 
418
443
  </script>
419
444
  <script type="text/html" data-help-name="Bacnet-Gateway">
420
445
  <p> This node is the brain of the Bitpool BACnet node collection. It acts are the gateway for all BACnet communications and functionality for the collection. </p>
421
446
 
422
- <h3><strong>Properties</strong></h3>
423
- <ol class="node-ports">
447
+ <h3><strong>Gateway Tab</strong></h3>
448
+ <ul class="node-ports">
424
449
  <li>Network Interface - the desired interface for the bacstack client to bind to. This interface must not have any other BACnet clients bound to it.</li>
425
450
  <li>Broadcast Address - the desired subnet for global msgs to be broadcast and recieved on. This should be as strict as possible. Use 255.255.255.255 if unsure.</li>
426
451
  <li>Local Device Port - the port to be used for BACnet comms. Default is 47808</li>
452
+
453
+ </ul>
454
+
455
+ <h3><strong>Discovery Tab</strong></h3>
456
+ <ul class="node-ports">
427
457
  <li>APDU Timeout - BACnet msg timeout option</li>
428
458
  <li>Max APDU Size - BACnet max apdu size</li>
429
459
  <li>Max Segments - BACnet max segments</li>
430
460
  <li>Global Discover Frequency - the frequency at which the gateway issues global WhoIs BACnet commands. This should be limited to the least amount possible, as over-loading a network can be a serious issue with BACnet commmunications.</li>
461
+ <li>Manual Point Discovery Instance Range - if a BACnet device doesnt have a Object list (BACnet objectType:propertyId - 8:76), the this bacnet client will enter into manual discovery mode, where it iterates through types and instnace ranges. This range can be used to limit this manual scanning </li>
431
462
  <li>Log Device Found - toggles logging of found devices to the node-red debug tab.</li>
432
- </ol>
463
+ <li>Log BACnet Errors to Console - toggles logging of BACnet related errors to the node-red console</li>
464
+ </ul>
465
+
466
+ <h3><strong>Server Tab</strong></h3>
467
+ <p>This section provides the ability to simulate a BACnet device and BACnet points using node-red. </p>
468
+ <p>Injecting a msg.topic and msg.payload into the gateway node will create a virtual point that can be discovered by other devices via BACnet/IP</p>
469
+ <p>This node only supports 2 BACnet object types, Analog Value - to show numeric data, and a Character String - to show string data.</p>
470
+ <ul class="node-ports">
471
+ <li>Enabled - toggles whether or not the local BACnet server is started or not. </li>
472
+ <li>Clear Server Points - a schedule for the locally generated BACnet points to get cleared from the node object store</li>
473
+ </ul>
474
+
475
+ <h3><strong>Examples</strong></h3>
476
+ <p>For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu on top right -> Import -> Examples -> @bitpoolos/edge-bacnet</p>
477
+ <p>To find screen shot examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
478
+
433
479
 
434
480
  <h3>Resources:</h3>
435
481
  <h4><strong>Online Docs:</strong></h4>
package/bacnet_gateway.js CHANGED
@@ -6,6 +6,7 @@ module.exports = function (RED) {
6
6
  const { BacnetClient } = require('./bacnet_client');
7
7
  const { BacnetClientConfig, getIpAddress, doNodeRedRestart } = require('./common');
8
8
  const { exec } = require("child_process");
9
+ const { BacnetServer } = require("./bacnet_server.js");
9
10
 
10
11
  function BitpoolBacnetGatewayDevice (config) {
11
12
  RED.nodes.createNode(this, config);
@@ -30,6 +31,10 @@ module.exports = function (RED) {
30
31
  this.nodeName = config.name;
31
32
  this.toRestartNodeRed = config.toRestartNodeRed;
32
33
  this.deviceId = config.deviceId;
34
+ this.logErrorToConsole = config.logErrorToConsole;
35
+ this.bacnetServerEnabled = config.serverEnabled;
36
+ this.bacnetServerRebuildSchedule = config.bacnetServerRebuildSchedule;
37
+ this.bacnetServer = nodeContext.get("bacnetServer") || null;
33
38
 
34
39
  //client and config store
35
40
  this.bacnetConfig = nodeContext.get("bacnetConfig");
@@ -68,22 +73,11 @@ module.exports = function (RED) {
68
73
  node.deviceId,
69
74
  node.manual_instance_range_enabled,
70
75
  node.manual_instance_range_start,
71
- node.manual_instance_range_end
76
+ node.manual_instance_range_end,
77
+ node.bacnetServerEnabled
72
78
  );
73
- nodeContext.set("bacnetConfig", node.bacnetConfig);
74
-
75
- //console.log("toRestartNodeRed: ", node.toRestartNodeRed);
76
-
77
- // if(node.toRestartNodeRed == true) {
78
-
79
- // doNodeRedRestart().then(function(result) {
80
- // console.log("restart result: ", result);
81
- // }).catch(function(error) {
82
- // console.log("restart error: ", error);
83
- // });
84
79
 
85
- // node.toRestartNodeRed = false;
86
- // }
80
+ nodeContext.set("bacnetConfig", node.bacnetConfig);
87
81
 
88
82
  if(typeof node.bacnetClient !== 'undefined') {
89
83
  node.bacnetClient.removeAllListeners();
@@ -94,6 +88,20 @@ module.exports = function (RED) {
94
88
  nodeContext.set("bacnetClient", node.bacnetClient);
95
89
  }
96
90
 
91
+ if(node.bacnetServerEnabled == true && node.bacnetClient && node.bacnetServer) {
92
+ node.bacnetServer.deviceId = node.deviceId;
93
+ }
94
+ }
95
+
96
+ node.bacnetClient.bacnetServerEnabled = node.bacnetServerEnabled;
97
+
98
+ if(node.bacnetServerEnabled == true && node.bacnetClient) {
99
+ if(node.bacnetServer == null) {
100
+ node.bacnetServer = new BacnetServer(node.bacnetClient, node.deviceId, node.bacnetServerRebuildSchedule, RED.version());
101
+ nodeContext.set("bacnetServer", node.bacnetServer);
102
+ }
103
+ } else if(node.bacnetServerEnabled == false) {
104
+ node.bacnetServer = null;
97
105
  }
98
106
 
99
107
  // Clears event handlers of all listeners, avoiding memory leak
@@ -105,9 +113,9 @@ module.exports = function (RED) {
105
113
  if (outputType.json && !outputType.mqtt) {
106
114
  if(objectPropertyType.fullObject && objectPropertyType.simplePayload) {
107
115
  sendSimpleJson(values);
108
- node.send(values);
116
+ sendJsonAsMqtt(values);
109
117
  } else if(objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
110
- node.send(values);
118
+ sendJsonAsMqtt(values);
111
119
  } else if(!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
112
120
  sendSimpleJson(values);
113
121
  }
@@ -135,15 +143,25 @@ module.exports = function (RED) {
135
143
  }
136
144
  });
137
145
 
146
+ node.bacnetClient.on('bacnetErrorLog', (param1, param2) => {
147
+ logOut(param1, param2);
148
+ });
149
+
138
150
  node.status({});
139
151
 
140
152
  } else {
141
- console.log("Issue with client info: ", node);
142
153
  // No client information found
143
154
  node.status({fill:"red",shape:"dot",text:"Please define client"})
144
155
  }
145
156
 
146
157
  node.on('input', function(msg) {
158
+
159
+ if(msg.topic && msg.payload) {
160
+ if(node.bacnetServer) {
161
+ node.bacnetServer.addObject(msg.topic, msg.payload);
162
+ }
163
+ }
164
+
147
165
  if(msg.type == "Read") {
148
166
 
149
167
  node.bacnetClient.doRead(msg.options, msg.outputType, msg.objectPropertyType, msg._msgid);
@@ -155,7 +173,7 @@ module.exports = function (RED) {
155
173
 
156
174
  } else if(msg.doDiscover == true) {
157
175
 
158
- node.status({fill:"blue",shape:"dot",text:"Forcing a global Who is"})
176
+ node.status({fill:"blue",shape:"dot",text:"Sending global Who is"})
159
177
 
160
178
  node.bacnetClient.globalWhoIs();
161
179
 
@@ -171,7 +189,7 @@ module.exports = function (RED) {
171
189
  //route handler for network data
172
190
  RED.httpAdmin.get('/bitpool-bacnet-data/getNetworkTree', function(req, res) {
173
191
  if(!node.bacnetClient) {
174
- console.log("Issue with the bacnetClient: ", node.bacnetClient);
192
+ logOut("Issue with the bacnetClient: ", node.bacnetClient);
175
193
  //no bacnet client present
176
194
  node.status({fill:"red",shape:"dot",text:"Please define client"});
177
195
  res.send(false);
@@ -180,7 +198,7 @@ module.exports = function (RED) {
180
198
  res.send(result);
181
199
  }).catch(function(error) {
182
200
  res.send(error);
183
- console.log("Error getting network data: ", error);
201
+ logOut("Error getting network data: ", error);
184
202
  });
185
203
  }
186
204
  });
@@ -188,7 +206,7 @@ module.exports = function (RED) {
188
206
  //route handler for rebuild data model command
189
207
  RED.httpAdmin.get('/bitpool-bacnet-data/rebuildDataModel', function(req, res) {
190
208
  if(!node.bacnetClient) {
191
- console.log("Issue with the bacnetClient: ", node.bacnetClient);
209
+ logOut("Issue with the bacnetClient: ", node.bacnetClient);
192
210
  //no bacnet client present
193
211
  node.status({fill:"red",shape:"dot",text:"Please define client"});
194
212
  res.send(false);
@@ -197,7 +215,7 @@ module.exports = function (RED) {
197
215
  res.send(result);
198
216
  }).catch(function(error) {
199
217
  res.send(error);
200
- console.log("Error getting network data: ", error);
218
+ logOut("Error getting network data: ", error);
201
219
  });
202
220
  }
203
221
  });
@@ -207,7 +225,7 @@ module.exports = function (RED) {
207
225
  getIpAddress().then(function(result) {
208
226
  res.send(result);
209
227
  }).catch(function(error) {
210
- console.log("Error getting network interfaces for client: ", error);
228
+ logOut("Error getting network interfaces for client: ", error);
211
229
  });
212
230
  });
213
231
 
@@ -221,9 +239,9 @@ module.exports = function (RED) {
221
239
  if (outputType.json && !outputType.mqtt) {
222
240
  if(objectPropertyType.fullObject && objectPropertyType.simplePayload) {
223
241
  sendSimpleJson(values);
224
- node.send(values);
242
+ sendJsonAsMqtt(values);
225
243
  } else if(objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
226
- node.send(values);
244
+ sendJsonAsMqtt(values);
227
245
  } else if(!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
228
246
  sendSimpleJson(values);
229
247
  }
@@ -245,6 +263,18 @@ module.exports = function (RED) {
245
263
  });
246
264
  }
247
265
 
266
+ function logOut(param1, param2) {
267
+ if(node.logErrorToConsole == true) {
268
+ if(arguments.length == 1) {
269
+ console.log("BACnet Error: ");
270
+ console.log(param1);
271
+ } else if(arguments.length == 2) {
272
+ console.log("BACnet Error: ");
273
+ console.log(param1, param2);
274
+ }
275
+ }
276
+ }
277
+
248
278
  // Returns true if any config values have changed
249
279
  function configHasChanged() {
250
280
  if(node.bacnetConfig == null){ return true;}
@@ -262,11 +292,13 @@ module.exports = function (RED) {
262
292
  if(node.manual_instance_range_enabled !== node.bacnetConfig.manual_instance_range_enabled){ return true;}
263
293
  if(node.manual_instance_range_start !== node.bacnetConfig.manual_instance_range_start){ return true;}
264
294
  if(node.manual_instance_range_end !== node.bacnetConfig.manual_instance_range_end){ return true;}
295
+ if(node.bacnetServerEnabled !== node.bacnetConfig.bacnetServerEnabled){ return true;}
296
+ if(node.deviceId !== node.bacnetConfig.deviceId){ return true;}
265
297
 
266
298
  return false;
267
299
  };
268
300
 
269
- sendSimpleMqtt = function(values){
301
+ sendSimpleMqtt = function(values) {
270
302
  let devices = Object.keys(values);
271
303
  devices.forEach(function(device) {
272
304
  if(device !== "_msgid") {
@@ -294,7 +326,6 @@ module.exports = function (RED) {
294
326
  });
295
327
  };
296
328
 
297
-
298
329
  // Breaks down response JSON object into mqtt topic / payload
299
330
  sendAsMqtt = function(values) {
300
331
  let devices = Object.keys(values);
@@ -347,6 +378,28 @@ module.exports = function (RED) {
347
378
  });
348
379
  };
349
380
 
381
+ sendJsonAsMqtt = function(values) {
382
+ if(typeof values == "object") {
383
+ let keys = Object.keys(values);
384
+ keys.forEach(function(key) {
385
+ let points = values[key];
386
+ let msgg = {};
387
+
388
+ if(node.nodeName !== "gateway" &&
389
+ node.nodeName !== "" &&
390
+ node.nodeName !== "null" &&
391
+ node.nodeName !== "undefined" &&
392
+ typeof node.nodeName == "string") {
393
+ msgg.topic = `${node.nodeName}/${key}`;
394
+ } else {
395
+ msgg.topic = `BITPOOL_BACNET_GATEWAY/${key}`;
396
+ }
397
+ msgg.payload = points;
398
+ node.send(msgg);
399
+ });
400
+ }
401
+ };
402
+
350
403
  };
351
404
 
352
405
  RED.nodes.registerType('Bacnet-Gateway', BitpoolBacnetGatewayDevice);