@bitpoolos/edge-bacnet 1.2.8 → 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/bacnet_write.html CHANGED
@@ -291,6 +291,171 @@
291
291
  return false;
292
292
  }
293
293
  },
294
+ calculateMstpCount(slotProps) {
295
+ let count = 0;
296
+ slotProps.node.children.forEach(function (child) {
297
+ if (child.label.includes("MSTP")) {
298
+ count += child.children.length;
299
+ }
300
+ });
301
+
302
+ return count;
303
+ },
304
+ settingDeviceName(slotProps) {
305
+ let app = this;
306
+ if (slotProps.node.settingDisplayName) {
307
+ return true;
308
+ }
309
+ return false;
310
+ },
311
+ cancelDisplayNameDialog() {
312
+ let app = this;
313
+ app.deviceDisplayNameValue = "";
314
+ app.showDeviceNameDialog = false;
315
+ },
316
+ cancelPointNameDialog() {
317
+ let app = this;
318
+ app.pointDisplayNameValue = "";
319
+ app.showPointNameDialog = false;
320
+ },
321
+ onDeviceRightClick(slotProps, event) {
322
+ let app = this;
323
+ app.rightClickedDevice = slotProps;
324
+ event.preventDefault();
325
+ menu.style.setProperty("--mouse-x", event.clientX + "px");
326
+ menu.style.setProperty("--mouse-y", event.clientY + "px");
327
+ menu.style.display = "block";
328
+ },
329
+ onPointRightClick(slotProps, event) {
330
+ let app = this;
331
+ app.rightClickedPoint = slotProps;
332
+ event.preventDefault();
333
+ pointMenu.style.setProperty("--mouse-x", event.clientX + "px");
334
+ pointMenu.style.setProperty("--mouse-y", event.clientY + "px");
335
+ pointMenu.style.display = "block";
336
+ },
337
+ handleContextMenuClick(type) {
338
+ let app = this;
339
+ switch (type) {
340
+ case "purgeDevice":
341
+ app.purgeDevice(app.rightClickedDevice);
342
+ break;
343
+ case "updatePoints":
344
+ app.updatePointsForDevice(app.rightClickedDevice);
345
+ break;
346
+ case "addAllPoints":
347
+ app.addAllClicked(app.rightClickedDevice);
348
+ break;
349
+ case "removeAllPoints":
350
+ app.removeAllClicked(app.rightClickedDevice);
351
+ break;
352
+ case "setDeviceName":
353
+ app.showDeviceNameDialog = true;
354
+ app.deviceDisplayNameValue = app.rightClickedDevice.node.label;
355
+ break;
356
+ default:
357
+ break;
358
+ }
359
+ },
360
+ handlePointContextMenuClick(type) {
361
+ let app = this;
362
+ switch (type) {
363
+ case "setPointName":
364
+ app.showPointNameDialog = true;
365
+ app.pointDisplayNameValue = app.rightClickedPoint.node.label;
366
+ break;
367
+ case "updatePoint":
368
+ app.updatePoint(app.rightClickedDevice);
369
+ break;
370
+ default:
371
+ break;
372
+ }
373
+ },
374
+ purgeDevice(slotProps) {
375
+ let app = this;
376
+ let device = app.deviceList.find((ele) => {
377
+ if (ele.address.address) {
378
+ return ele.address.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
379
+ } else {
380
+ return ele.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
381
+ }
382
+ });
383
+ if (device) {
384
+ app.nodeService.purgeDevice(device).then(function (result) { });
385
+ }
386
+ },
387
+ updatePointsForDevice(slotProps) {
388
+ let app = this;
389
+ let device = app.deviceList.find((ele) => {
390
+ if (ele.address.address) {
391
+ return ele.address.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
392
+ } else {
393
+ return ele.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
394
+ }
395
+ });
396
+ if (device) {
397
+ app.nodeService.updatePointsForDevice(device).then(function (result) { });
398
+ }
399
+ },
400
+ updatePoint(slotProps) {
401
+ let app = this;
402
+ let device = app.deviceList.find((ele) => {
403
+ if (ele.address.address) {
404
+ return ele.address.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
405
+ } else {
406
+ return ele.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
407
+ }
408
+ });
409
+ if (device) {
410
+ app.nodeService.updatePoint(device).then(function (result) { });
411
+ }
412
+ },
413
+ setDeviceName() {
414
+ let app = this;
415
+ const slotProps = app.rightClickedDevice;
416
+ const displayName = app.deviceDisplayNameValue;
417
+ let device = app.deviceList.find((ele) => {
418
+ if (ele.address.address) {
419
+ return ele.address.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
420
+ } else {
421
+ return ele.address == slotProps.node.ipAddr && ele.deviceId == slotProps.node.deviceId;
422
+ }
423
+ });
424
+
425
+ if (device) {
426
+ app.nodeService.setDeviceDisplayName(device, displayName).then(function (result) {
427
+ if (result) {
428
+ slotProps.node.label = displayName;
429
+ }
430
+ });
431
+ }
432
+
433
+ app.showDeviceNameDialog = false;
434
+ },
435
+ setPointName() {
436
+ let app = this;
437
+
438
+ const slotProps = app.rightClickedPoint;
439
+ const pointDisplayName = app.pointDisplayNameValue;
440
+ const pointName = slotProps.node.pointName;
441
+
442
+ let device = app.deviceList.find((ele) => {
443
+ return ele.deviceName == slotProps.node.parentDevice;
444
+ });
445
+
446
+ if (device) {
447
+ let deviceAddress = app.getDeviceAddress(device.address);
448
+ let deviceKey = `${deviceAddress}-${device.deviceId}`;
449
+
450
+ app.nodeService.setPointDisplayName(deviceKey, pointName, pointDisplayName).then(function (result) {
451
+ if (result) {
452
+ slotProps.node.label = pointDisplayName;
453
+ }
454
+ });
455
+ }
456
+
457
+ app.showPointNameDialog = false;
458
+ },
294
459
  },
295
460
  components: {
296
461
  "p-tree": primevue.tree,
@@ -337,6 +502,16 @@
337
502
  document.getElementById("node-input-applicationTag").value = node.applicationTag;
338
503
  document.getElementById("node-input-priority").value = node.priority;
339
504
 
505
+ var menu = document.querySelector(".context-menu");
506
+ window.addEventListener("click", (event) => {
507
+ menu.style.display = "none";
508
+ });
509
+
510
+ var pointMenu = document.querySelector(".point-context-menu");
511
+ window.addEventListener("click", (event) => {
512
+ pointMenu.style.display = "none";
513
+ });
514
+
340
515
  //remove loading animation
341
516
  let loadingGif = document.getElementById("loadingGif");
342
517
  let loadingText = document.getElementById("loadingText");
@@ -431,11 +606,7 @@
431
606
  .statusOffline {
432
607
  color: red;
433
608
  }
434
- /*
435
- .deviceLabel {
436
- position: absolute;
437
- }
438
- */
609
+
439
610
  .objectPropertiesLabel {
440
611
  display: flex !important;
441
612
  flex-direction: row;
@@ -562,6 +733,65 @@
562
733
  </div>
563
734
 
564
735
  <div id="node-input-tabs-content">
736
+
737
+ <!-- Start Device Context Menu -->
738
+ <ul
739
+ class="red-ui-menu red-ui-menu-dropdown red-ui-menu-dropdown-direction-right red-ui-menu-dropdown-noicons red-ui-menu-dropdown-submenus context-menu">
740
+ <li class="context-menu-item" @click="handleContextMenuClick('purgeDevice')">
741
+ <a class="red-ui-menu-label">
742
+ <i class="pi pi-wrench context-menu-icon"></i>
743
+ <span class="context-menu-item-text">Purge Device</span>
744
+ </a>
745
+ </li>
746
+ <li class="context-menu-item" @click="handleContextMenuClick('updatePoints')">
747
+ <a class="red-ui-menu-label">
748
+ <i class="pi pi-refresh context-menu-icon"></i>
749
+ <span class="context-menu-item-text">Update Points</span>
750
+ </a>
751
+ </li>
752
+ <li class="red-ui-menu-divider"></li>
753
+ <li class="context-menu-item" @click="handleContextMenuClick('addAllPoints')">
754
+ <a class="red-ui-menu-label">
755
+ <i class="pi pi-plus-circle context-menu-icon"></i>
756
+ <span class="context-menu-item-text">Add All Points </span>
757
+ </a>
758
+ </li>
759
+ <li class="context-menu-item" @click="handleContextMenuClick('removeAllPoints')">
760
+ <a class="red-ui-menu-label">
761
+ <i class="pi pi-minus-circle context-menu-icon"></i>
762
+ <span class="context-menu-item-text">Remove All Points</span>
763
+ </a>
764
+ </li>
765
+ <li class="red-ui-menu-divider"></li>
766
+ <li class="context-menu-item" @click="handleContextMenuClick('setDeviceName')">
767
+ <a class="red-ui-menu-label">
768
+ <i class="pi pi-pencil context-menu-icon"></i>
769
+ <span class="context-menu-item-text">Set Device Name</span>
770
+ </a>
771
+ </li>
772
+ </ul>
773
+ <!-- End Device Context Menu -->
774
+
775
+ <!-- Start Point Context Menu -->
776
+ <ul
777
+ class="red-ui-menu red-ui-menu-dropdown red-ui-menu-dropdown-direction-right red-ui-menu-dropdown-noicons red-ui-menu-dropdown-submenus point-context-menu">
778
+ <li class="context-menu-item" @click="handlePointContextMenuClick('setPointName')">
779
+ <a class="red-ui-menu-label">
780
+ <i class="pi pi-pencil context-menu-icon"></i>
781
+ <span class="context-menu-item-text">Set Point Name</span>
782
+ </a>
783
+ </li>
784
+ <li class="red-ui-menu-divider"></li>
785
+ <li class="context-menu-item" @click="handlePointContextMenuClick('updatePoint')">
786
+ <a class="red-ui-menu-label">
787
+ <i class="pi pi-refresh context-menu-icon"></i>
788
+ <span class="context-menu-item-text">Update Point</span>
789
+ </a>
790
+ </li>
791
+ </ul>
792
+ <!-- End Point Context Menu -->
793
+
794
+
565
795
  <div id="read-networkTree-tab" style="display:none">
566
796
  <div id="read-networkTree-tab-content" class="networkTreeContent" style="display:none">
567
797
  <div>
@@ -574,30 +804,44 @@
574
804
  <div id="deviceListApp">
575
805
  <p-tree :value="devices" selectable="false" :filter="true" filterMode="lenient" v-if="hasData()">
576
806
  <template #device="slotProps">
577
- <div v-if="isDeviceActive(slotProps)" class="deviceLabelParent">
578
- <b class="deviceLabel">{{slotProps.node.label}} <b class="statusOnline deviceStatus">Online</b></b>
579
- </div>
580
- <div v-else>
581
- <b class="deviceLabel">{{slotProps.node.label}} <b class="statusOffline deviceStatus">Offline</b></b>
807
+ <div @contextmenu="onDeviceRightClick(slotProps, $event)" class="p-treenode-label">
808
+
809
+ <div v-if="isDeviceActive(slotProps)" class="deviceLabelParent">
810
+ <b class="deviceLabel">
811
+ <span class="statusOnline deviceStatus dotOnline dot"></span>
812
+ {{slotProps.node.label}}
813
+ </b>
814
+ </div>
815
+ <div v-else>
816
+ <b class="deviceLabel">
817
+ <span class="statusOffline deviceStatus dotOffline dot"></span>
818
+ {{slotProps.node.label}}
819
+ </b>
820
+ </div>
821
+
582
822
  </div>
583
823
  </template>
584
824
 
585
825
  <template #point="slotProps" v-model:class="pointContent">
586
- <b class="pointLabel">{{slotProps.node.label}}</b>
587
- <template v-if="isSlotAdded(slotProps)">
588
- <button class="addPointButton bacnetbutton">
589
- <i class="pi pi-check-circle " style="color: #00AEEF;"></i>
590
- </button>
591
- </template>
592
- <template v-else>
593
- <button @click="addPointClicked(slotProps, this)" class="addPointButton bacnetbutton">
594
- <i class="pi pi-plus-circle "></i>
826
+ <div @contextmenu="onDeviceRightClick(slotProps, $event)" class="p-treenode-label">
827
+
828
+ <b class="pointLabel">{{slotProps.node.label}}</b>
829
+ <template v-if="isSlotAdded(slotProps)">
830
+ <button class="addPointButton bacnetbutton">
831
+ <i class="pi pi-check-circle " style="color: #00AEEF;"></i>
832
+ </button>
833
+ </template>
834
+ <template v-else>
835
+ <button @click="addPointClicked(slotProps, this)" class="addPointButton bacnetbutton">
836
+ <i class="pi pi-plus-circle "></i>
837
+ </button>
838
+ </template>
839
+
840
+ <button @click="removePointClicked(slotProps, this)" class="minusPointButton bacnetbutton">
841
+ <i class="pi pi-minus-circle "></i>
595
842
  </button>
596
- </template>
843
+ </div>
597
844
 
598
- <button @click="removePointClicked(slotProps, this)" class="minusPointButton bacnetbutton">
599
- <i class="pi pi-minus-circle "></i>
600
- </button>
601
845
  </template>
602
846
  </p-tree>
603
847
  <div v-else style="text-align: center; padding-top: 20px;">
@@ -755,4 +999,4 @@
755
999
  <li><a href="https://wiki.bitpool.com/">wiki.bitpool.com</a> - find more documentation.</li>
756
1000
  <li><a href="https://bacnet.org/">BACnet</a> - find more about the protocol.</li>
757
1001
  </ul>
758
- </script>
1002
+ </script>
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(
@@ -181,7 +182,7 @@ const getIpAddress = function () {
181
182
  }
182
183
  }
183
184
 
184
- if (os.version().includes("Ubuntu")) {
185
+ if (os.version().includes("Ubuntu") || os.version().includes("SMP")) {
185
186
  let allInterfaceName = "All interfaces";
186
187
  if (!results[allInterfaceName]) {
187
188
  results[allInterfaceName] = [];
@@ -244,7 +245,6 @@ function Read_Config_Sync() {
244
245
  try {
245
246
  data = fs.readFileSync("edge-bacnet-datastore.cfg", { encoding: "utf8", flag: "r" });
246
247
  } catch (err) {
247
- console.log("Read_Config_Sync error:", err);
248
248
  data = "{}";
249
249
  Store_Config(data);
250
250
  }
@@ -261,7 +261,7 @@ async function Store_Config_Server(data) {
261
261
  //console.log("Store_Config_Server writeFile error: ", err);
262
262
  }
263
263
  });
264
- } catch (err) {}
264
+ } catch (err) { }
265
265
  }
266
266
 
267
267
  // READ CONFIG SYNC FUNCTION - BACNET SERVER ======================================
@@ -273,7 +273,6 @@ function Read_Config_Sync_Server() {
273
273
  data = fs.readFileSync("edge-bacnet-server-datastore.cfg", { encoding: "utf8", flag: "r" });
274
274
  } catch (err) {
275
275
  if (err.errno == -4058) {
276
- console.log("Edge-BACnet Server: No save file found, creating new file");
277
276
  data = "{}";
278
277
  Store_Config_Server(data);
279
278
  }
@@ -285,6 +284,24 @@ function isNumber(value) {
285
284
  return value != null && typeof value === "number" && !isNaN(value);
286
285
  }
287
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
+ };
303
+ }
304
+
288
305
  module.exports = {
289
306
  BacnetConfig,
290
307
  BacnetClientConfig,
@@ -300,4 +317,5 @@ module.exports = {
300
317
  Store_Config_Server,
301
318
  Read_Config_Sync_Server,
302
319
  isNumber,
320
+ decodeBitArray,
303
321
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitpoolos/edge-bacnet",
3
- "version": "1.2.8",
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",
@@ -50,4 +50,4 @@
50
50
  "type": "github",
51
51
  "url": "git+https://github.com/bitpool/edge-bacnet.git"
52
52
  }
53
- }
53
+ }
@@ -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);