@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/common.js CHANGED
@@ -8,6 +8,7 @@ const os = require("os");
8
8
  const { exec } = require("child_process");
9
9
  const baEnum = require("./resources/node-bacstack-ts/dist/index.js").enum;
10
10
  const fs = require("fs");
11
+ const { BitArray } = require("./resources/bitArray.js");
11
12
 
12
13
  const logger = createLogger({
13
14
  format: format.combine(
@@ -92,7 +93,8 @@ class BacnetClientConfig {
92
93
  manual_instance_range_end,
93
94
  device_read_schedule,
94
95
  retries,
95
- cacheFileEnabled
96
+ cacheFileEnabled,
97
+ sanitise_device_schedule
96
98
  ) {
97
99
  this.apduTimeout = apduTimeout;
98
100
  this.localIpAdrress = localIpAdrress;
@@ -109,6 +111,7 @@ class BacnetClientConfig {
109
111
  this.device_read_schedule = device_read_schedule;
110
112
  this.retries = retries;
111
113
  this.cacheFileEnabled = cacheFileEnabled;
114
+ this.sanitise_device_schedule = sanitise_device_schedule;
112
115
  }
113
116
  }
114
117
 
@@ -179,7 +182,7 @@ const getIpAddress = function () {
179
182
  }
180
183
  }
181
184
 
182
- if (os.version().includes("Ubuntu")) {
185
+ if (os.version().includes("Ubuntu") || os.version().includes("SMP")) {
183
186
  let allInterfaceName = "All interfaces";
184
187
  if (!results[allInterfaceName]) {
185
188
  results[allInterfaceName] = [];
@@ -222,25 +225,17 @@ const doNodeRedRestart = function () {
222
225
  // STORE CONFIG FUNCTION ==========================================================
223
226
  //
224
227
  // ================================================================================
225
- function Store_Config(data) {
228
+ async function Store_Config(data) {
226
229
  try {
227
- fs.access("edge-bacnet-datastore.cfg", fs.constants.W_OK, async function(err) {
228
- if(err){
229
- console.log("Store_Config writeAccess error found: ", err);
230
- } else {
231
- await fs.writeFile("edge-bacnet-datastore.cfg", data, {encoding: "utf8", flag: "w"}, (err) => {
232
- if (err) {
233
- console.log("Store_Config writeFile error: ", err);
234
- }
235
- });
230
+ await fs.writeFile("edge-bacnet-datastore.cfg", data, { encoding: "utf8", flag: "w" }, (err) => {
231
+ if (err) {
232
+ console.log("Store_Config writeFile error: ", err);
236
233
  }
237
234
  });
238
- } catch(e){
235
+ } catch (e) {
239
236
  //do nothing
240
237
  }
241
- };
242
-
243
-
238
+ }
244
239
 
245
240
  // READ CONFIG SYNC FUNCTION ======================================================
246
241
  //
@@ -248,15 +243,13 @@ function Store_Config(data) {
248
243
  function Read_Config_Sync() {
249
244
  var data = "{}";
250
245
  try {
251
- data = fs.readFileSync("edge-bacnet-datastore.cfg", { encoding: 'utf8', flag: 'r' });
252
- }
253
- catch (err) {
254
- console.log("Read_Config_Sync error:", err);
255
- data = '{}';
246
+ data = fs.readFileSync("edge-bacnet-datastore.cfg", { encoding: "utf8", flag: "r" });
247
+ } catch (err) {
248
+ data = "{}";
256
249
  Store_Config(data);
257
250
  }
258
251
  return data;
259
- };
252
+ }
260
253
 
261
254
  // STORE CONFIG FUNCTION - BACNET SERVER ==========================================
262
255
  //
@@ -268,7 +261,7 @@ async function Store_Config_Server(data) {
268
261
  //console.log("Store_Config_Server writeFile error: ", err);
269
262
  }
270
263
  });
271
- } catch (err) {}
264
+ } catch (err) { }
272
265
  }
273
266
 
274
267
  // READ CONFIG SYNC FUNCTION - BACNET SERVER ======================================
@@ -279,16 +272,34 @@ function Read_Config_Sync_Server() {
279
272
  try {
280
273
  data = fs.readFileSync("edge-bacnet-server-datastore.cfg", { encoding: "utf8", flag: "r" });
281
274
  } catch (err) {
282
- //console.log("Read_Config_Sync_Server error:", err);
283
- if (err.errno == -4058) console.log("Edge-BACnet Server: No save file found, creating new file");
284
- data = "{}";
285
- Store_Config_Server(data);
275
+ if (err.errno == -4058) {
276
+ data = "{}";
277
+ Store_Config_Server(data);
278
+ }
286
279
  }
287
280
  return data;
288
281
  }
289
282
 
290
283
  function isNumber(value) {
291
- return value != null && typeof value === 'number' && !isNaN(value);
284
+ return value != null && typeof value === "number" && !isNaN(value);
285
+ }
286
+
287
+ function decodeBitArray(size, bits) {
288
+ let array = [];
289
+ for (let i = 0; i < bits.length; i++) {
290
+ let bit = bits[i];
291
+ let bitString = bit.toString(2);
292
+ if (bitString.length < size) {
293
+ const remainingLength = size - bitString.length;
294
+ const backFillString = "0".repeat(remainingLength);
295
+ array.push(backFillString + bitString);
296
+ } else if (bitString.length == size) {
297
+ array.push(bitString);
298
+ }
299
+ if (i == bits.length - 1) {
300
+ return array;
301
+ }
302
+ };
292
303
  }
293
304
 
294
305
  module.exports = {
@@ -306,4 +317,5 @@ module.exports = {
306
317
  Store_Config_Server,
307
318
  Read_Config_Sync_Server,
308
319
  isNumber,
320
+ decodeBitArray,
309
321
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitpoolos/edge-bacnet",
3
- "version": "1.2.7",
3
+ "version": "1.3.0",
4
4
  "description": "A bacnet gateway for node-red",
5
5
  "dependencies": {
6
6
  "@plus4nodered/ts-node-bacnet": "^1.0.0-beta.2",
@@ -0,0 +1,167 @@
1
+ /* BitArray DataType */
2
+
3
+ // Constructor
4
+ function BitArray(size, bits) {
5
+ // Private field - array for our bits
6
+ this.m_bits = new Array();
7
+
8
+ //.ctor - initialize as a copy of an array of true/false or from a numeric value
9
+ if (bits && bits.length) {
10
+ for (var i = 0; i < bits.length; i++)
11
+ this.m_bits.push(bits[i] ? BitArray._ON : BitArray._OFF);
12
+ } else if (!isNaN(bits)) {
13
+ this.m_bits = BitArray.shred(bits).m_bits;
14
+ }
15
+ if (size && this.m_bits.length != size) {
16
+ if (this.m_bits.length < size) {
17
+ for (var i = this.m_bits.length; i < size; i++) {
18
+ this.m_bits.push(BitArray._OFF);
19
+ }
20
+ } else {
21
+ for (var i = size; i > this.m_bits.length; i--) {
22
+ this.m_bits.pop();
23
+ }
24
+ }
25
+ }
26
+ }
27
+
28
+ /* BitArray PUBLIC INSTANCE METHODS */
29
+
30
+ // read-only property - number of bits
31
+ BitArray.prototype.getLength = function () { return this.m_bits.length; };
32
+
33
+ // accessor - get bit at index
34
+ BitArray.prototype.getAt = function (index) {
35
+ if (index < this.m_bits.length) {
36
+ return this.m_bits[index];
37
+ }
38
+ return null;
39
+ };
40
+ // accessor - set bit at index
41
+ BitArray.prototype.setAt = function (index, value) {
42
+ if (index < this.m_bits.length) {
43
+ this.m_bits[index] = value ? BitArray._ON : BitArray._OFF;
44
+ }
45
+ };
46
+
47
+ // resize the bit array (append new false/0 indexes)
48
+ BitArray.prototype.resize = function (newSize) {
49
+ var tmp = new Array();
50
+ for (var i = 0; i < newSize; i++) {
51
+ if (i < this.m_bits.length) {
52
+ tmp.push(this.m_bits[i]);
53
+ } else {
54
+ tmp.push(BitArray._OFF);
55
+ }
56
+ }
57
+ this.m_bits = tmp;
58
+ };
59
+
60
+ // Get the complimentary bit array (i.e., 01 compliments 10)
61
+ BitArray.prototype.getCompliment = function () {
62
+ var result = new BitArray(this.m_bits.length);
63
+ for (var i = 0; i < this.m_bits.length; i++) {
64
+ result.setAt(i, this.m_bits[i] ? BitArray._OFF : BitArray._ON);
65
+ }
66
+ return result;
67
+ };
68
+
69
+ // Get the string representation ("101010")
70
+ BitArray.prototype.toString = function () {
71
+ var s = new String();
72
+ for (var i = 0; i < this.m_bits.length; i++) {
73
+ s = s.concat(this.m_bits[i] === BitArray._ON ? "1" : "0");
74
+ }
75
+ return s;
76
+ };
77
+
78
+ // Get the numeric value
79
+ BitArray.prototype.toNumber = function () {
80
+ var pow = 0;
81
+ var n = 0;
82
+ for (var i = this.m_bits.length - 1; i >= 0; i--) {
83
+ if (this.m_bits[i] === BitArray._ON) {
84
+ n += Math.pow(2, pow);
85
+ }
86
+ pow++;
87
+ }
88
+ return n;
89
+ };
90
+
91
+ /* STATIC METHODS */
92
+
93
+ // Get the union of two bit arrays
94
+ BitArray.getUnion = function (bitArray1, bitArray2) {
95
+ var len = BitArray._getLen(bitArray1, bitArray2, true);
96
+ var result = new BitArray(len);
97
+ for (var i = 0; i < len; i++) {
98
+ result.setAt(i, BitArray._union(bitArray1.getAt(i), bitArray2.getAt(i)));
99
+ }
100
+ return result;
101
+ };
102
+
103
+ // Get the intersection of two bit arrays
104
+ BitArray.getIntersection = function (bitArray1, bitArray2) {
105
+ var len = BitArray._getLen(bitArray1, bitArray2, true);
106
+ var result = new BitArray(len);
107
+ for (var i = 0; i < len; i++) {
108
+ result.setAt(i, BitArray._intersect(bitArray1.getAt(i), bitArray2.getAt(i)));
109
+ }
110
+ return result;
111
+ };
112
+
113
+ // Get the difference between to bit arrays
114
+ BitArray.getDifference = function (bitArray1, bitArray2) {
115
+ var len = BitArray._getLen(bitArray1, bitArray2, true);
116
+ var result = new BitArray(len);
117
+ for (var i = 0; i < len; i++) {
118
+ result.setAt(i, BitArray._difference(bitArray1.getAt(i), bitArray2.getAt(i)));
119
+ }
120
+ return result;
121
+ };
122
+
123
+ // Convert a number into a bit array
124
+ BitArray.shred = function (number) {
125
+ var bits = new Array();
126
+ var q = number;
127
+ do {
128
+ bits.push(q % 2);
129
+ q = Math.floor(q / 2);
130
+ } while (q > 0);
131
+ return new BitArray(bits.length, bits.reverse());
132
+ };
133
+
134
+ /* BitArray PRIVATE STATIC CONSTANTS */
135
+ BitArray._ON = 1;
136
+ BitArray._OFF = 0;
137
+
138
+ /* BitArray PRIVATE STATIC METHODS */
139
+
140
+ // Calculate the intersection of two bits
141
+ BitArray._intersect = function (bit1, bit2) {
142
+ return bit1 === BitArray._ON && bit2 === BitArray._ON ? BitArray._ON : BitArray._OFF;
143
+ };
144
+
145
+ // Calculate the union of two bits
146
+ BitArray._union = function (bit1, bit2) {
147
+ return bit1 === BitArray._ON || bit2 === BitArray._ON ? BitArray._ON : BitArray._OFF;
148
+ };
149
+
150
+ // Calculate the difference of two bits
151
+ BitArray._difference = function (bit1, bit2) {
152
+ return bit1 === BitArray._ON && bit2 !== BitArray._ON ? BitArray._ON : BitArray._OFF;
153
+ };
154
+
155
+ // Get the longest or shortest (smallest) length of the two bit arrays
156
+ BitArray._getLen = function (bitArray1, bitArray2, smallest) {
157
+ var l1 = bitArray1.getLength();
158
+ var l2 = bitArray2.getLength();
159
+
160
+ return l1 > l2 ? smallest ? l2 : l1 : smallest ? l2 : l1;
161
+ };
162
+
163
+ module.exports = {
164
+ BitArray,
165
+ }
166
+
167
+ /* END BitArray DataType */
@@ -671,11 +671,15 @@ const bacappDecodeApplicationData = (buffer, offset, maxOffset, objectType, prop
671
671
  const result = bacappDecodeData(buffer, offset + len, maxOffset, tag.tagNumber, tag.value);
672
672
  if (!result)
673
673
  return;
674
- const resObj = {
674
+ let resObj = {
675
675
  len: len + result.len,
676
676
  type: result.type,
677
677
  value: result.value
678
678
  };
679
+ if (result.originalBitString) {
680
+ //protocols supported addition
681
+ resObj.originalBitString = result.originalBitString;
682
+ }
679
683
  // HACK: Drop string specific handling ASAP
680
684
  if (result.encoding !== undefined)
681
685
  resObj.encoding = result.encoding;
@@ -796,9 +800,9 @@ const decodeReadAccessResult = (buffer, offset, apduLen) => {
796
800
  return;
797
801
  len++;
798
802
  newEntry.value = [{
799
- type: baEnum.ApplicationTags.ERROR,
800
- value: err
801
- }];
803
+ type: baEnum.ApplicationTags.ERROR,
804
+ value: err
805
+ }];
802
806
  }
803
807
  values.push(newEntry);
804
808
  }
@@ -876,11 +880,13 @@ const bitstringSetBitsUsed = (bitString, bytesUsed, unusedBits) => {
876
880
  const decodeBitstring = (buffer, offset, lenValue) => {
877
881
  let len = 0;
878
882
  const bitString = { value: [], bitsUsed: 0 };
883
+ const originalBitString = { value: [] };
879
884
  if (lenValue > 0) {
880
885
  const bytesUsed = lenValue - 1;
881
886
  if (bytesUsed <= baEnum.ASN1_MAX_BITSTRING_BYTES) {
882
887
  len = 1;
883
888
  for (let i = 0; i < bytesUsed; i++) {
889
+ originalBitString.value.push(buffer[offset + len]);
884
890
  bitString.value.push(byteReverseBits(buffer[offset + len++]));
885
891
  }
886
892
  const unusedBits = buffer[offset] & 0x07;
@@ -889,7 +895,8 @@ const decodeBitstring = (buffer, offset, lenValue) => {
889
895
  }
890
896
  return {
891
897
  len: len,
892
- value: bitString
898
+ value: bitString,
899
+ originalBitString: originalBitString
893
900
  };
894
901
  };
895
902
  exports.decodeBitstring = decodeBitstring;
@@ -1033,6 +1040,10 @@ const bacappDecodeData = (buffer, offset, maxLength, tagDataType, lenValueType)
1033
1040
  result = (0, exports.decodeBitstring)(buffer, offset, lenValueType);
1034
1041
  value.len += result.len;
1035
1042
  value.value = result.value;
1043
+ if (result.originalBitString) {
1044
+ //protocols supported addition
1045
+ value.originalBitString = result.originalBitString;
1046
+ }
1036
1047
  break;
1037
1048
  case baEnum.ApplicationTags.ENUMERATED:
1038
1049
  result = (0, exports.decodeEnumerated)(buffer, offset, lenValueType);
@@ -95,7 +95,7 @@ class Client extends events_1.EventEmitter {
95
95
  if (!result)
96
96
  return debug('Couldn`t decode Error');
97
97
  this._invokeCallback(invokeId, new Error('BacnetError - Class:' + result.class + ' - Code:' + result.code));
98
- } catch(e){
98
+ } catch (e) {
99
99
  }
100
100
  }
101
101
  _processAbort(invokeId, reason) {
@@ -619,14 +619,14 @@ class Client extends events_1.EventEmitter {
619
619
  baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
620
620
  this.sendBvlc(address, buffer);
621
621
  this._addCallback(settings.invokeId, (err, data) => {
622
- try{
622
+ try {
623
623
  if (err)
624
624
  return next(err);
625
625
  const result = baServices.readProperty.decodeAcknowledge(data.buffer, data.offset, data.length);
626
626
  if (!result)
627
627
  return next(new Error('INVALID_DECODING'));
628
628
  next(null, result);
629
- } catch(e){
629
+ } catch (e) {
630
630
  return next(e);
631
631
  }
632
632
  });
@@ -716,7 +716,6 @@ class Client extends events_1.EventEmitter {
716
716
  baServices.readPropertyMultiple.encode(buffer, propertiesArray);
717
717
  baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
718
718
  this.sendBvlc(address, buffer);
719
- //this.sendBvlc(address, buffer);
720
719
  this._addCallback(settings.invokeId, (err, data) => {
721
720
  try {
722
721
  if (err)
@@ -725,7 +724,7 @@ class Client extends events_1.EventEmitter {
725
724
  if (!result)
726
725
  return next(new Error('INVALID_DECODING'));
727
726
  next(null, result);
728
- } catch(e){
727
+ } catch (e) {
729
728
  return next(e);
730
729
  }
731
730
  });
@@ -1369,7 +1368,7 @@ class Client extends events_1.EventEmitter {
1369
1368
  baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1370
1369
  baApdu.encodeComplexAck(buffer, baEnum.PduTypes.COMPLEX_ACK, baEnum.ConfirmedServiceChoice.READ_PROPERTY, invokeId);
1371
1370
  baServices.readProperty.encodeAcknowledge(buffer, objectId, property.id, property.index, value);
1372
- //baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
1371
+ baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
1373
1372
  this.sendBvlc(receiver, buffer);
1374
1373
  }
1375
1374
  readPropertyMultipleResponse(receiver, invokeId, values) {