@bitpoolos/edge-bacnet 1.0.6 → 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_client.js +650 -233
- package/bacnet_device.js +65 -16
- package/bacnet_gateway.html +242 -99
- package/bacnet_gateway.js +211 -27
- package/bacnet_object.js +1 -1
- package/bacnet_read.html +211 -133
- package/bacnet_read.js +24 -24
- package/bacnet_server.js +321 -0
- package/bacnet_write.html +24 -15
- package/bacnet_write.js +0 -2
- package/common.js +95 -9
- package/edge-bacnet-datastore.cfg +0 -0
- package/package.json +6 -4
- package/resources/confirmationservice.min.js +1 -0
- package/resources/confirmdialog.min.js +1 -0
- package/resources/fonts/primeicons.woff2 +0 -0
- package/resources/node-bacnet/CHANGELOG.md +481 -0
- package/resources/{bacstack → node-bacnet}/LICENSE.md +3 -1
- package/resources/node-bacnet/README.md +91 -0
- package/resources/node-bacnet/docs/Client.html +4422 -0
- package/resources/node-bacnet/docs/bacnet-icon-quad.png +0 -0
- package/resources/node-bacnet/docs/bacnet-icon-quad128.png +0 -0
- package/resources/node-bacnet/docs/bacnet-icon-quad64.png +0 -0
- package/resources/node-bacnet/docs/bacnet-icon-small.xcf +0 -0
- package/resources/node-bacnet/docs/bacnet-icon.xcf +0 -0
- package/resources/node-bacnet/docs/bacnet.html +7032 -0
- package/resources/node-bacnet/docs/client.js.html +1759 -0
- package/resources/node-bacnet/docs/enum.js.html +2530 -0
- package/resources/node-bacnet/docs/global.html +2068 -0
- package/resources/node-bacnet/docs/images/mocha-logo.svg +65 -0
- package/resources/node-bacnet/docs/index.html +283 -0
- package/resources/node-bacnet/docs/scripts/collapse.js +11 -0
- package/resources/node-bacnet/docs/scripts/jquery-3.1.1.min.js +4 -0
- package/resources/node-bacnet/docs/scripts/linenumber.js +26 -0
- package/resources/node-bacnet/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/resources/node-bacnet/docs/scripts/prettify/lang-css.js +2 -0
- package/resources/node-bacnet/docs/scripts/prettify/prettify.js +28 -0
- package/resources/node-bacnet/docs/scripts/search.js +47 -0
- package/resources/node-bacnet/docs/services_i-am.js.html +157 -0
- package/resources/node-bacnet/docs/services_time-sync.js.html +118 -0
- package/resources/node-bacnet/docs/services_who-is.js.html +138 -0
- package/resources/node-bacnet/docs/styles/jsdoc.css +683 -0
- package/resources/node-bacnet/docs/styles/prettify.css +82 -0
- package/resources/node-bacnet/examples/discover-devices.js +66 -0
- package/resources/node-bacnet/examples/read-device.js +510 -0
- package/resources/node-bacnet/examples/subscribe-cov.js +75 -0
- package/resources/{bacstack → node-bacnet}/index.js +3 -0
- package/resources/{bacstack → node-bacnet}/lib/apdu.js +56 -39
- package/resources/{bacstack → node-bacnet}/lib/asn1.js +550 -532
- package/resources/node-bacnet/lib/bvlc.js +90 -0
- package/resources/node-bacnet/lib/client.js +1695 -0
- package/resources/node-bacnet/lib/enum.js +2463 -0
- package/resources/node-bacnet/lib/npdu.js +123 -0
- package/resources/{bacstack → node-bacnet}/lib/services/add-list-element.js +12 -6
- package/resources/{bacstack → node-bacnet}/lib/services/alarm-acknowledge.js +3 -3
- package/resources/{bacstack → node-bacnet}/lib/services/alarm-summary.js +5 -4
- package/resources/{bacstack → node-bacnet}/lib/services/atomic-read-file.js +49 -26
- package/resources/{bacstack → node-bacnet}/lib/services/atomic-write-file.js +40 -23
- package/resources/{bacstack → node-bacnet}/lib/services/cov-notify.js +33 -17
- package/resources/{bacstack → node-bacnet}/lib/services/create-object.js +23 -13
- package/resources/{bacstack → node-bacnet}/lib/services/delete-object.js +7 -2
- package/resources/{bacstack → node-bacnet}/lib/services/device-communication-control.js +8 -3
- package/resources/{bacstack → node-bacnet}/lib/services/error.js +7 -0
- package/resources/{bacstack → node-bacnet}/lib/services/event-information.js +10 -9
- package/resources/{bacstack → node-bacnet}/lib/services/event-notify-data.js +38 -16
- package/resources/{bacstack → node-bacnet}/lib/services/get-enrollment-summary.js +24 -11
- package/resources/{bacstack → node-bacnet}/lib/services/get-event-information.js +28 -13
- package/resources/node-bacnet/lib/services/i-am.js +90 -0
- package/resources/{bacstack/lib/services/i-have-broadcast.js → node-bacnet/lib/services/i-have.js} +3 -2
- package/resources/{bacstack → node-bacnet}/lib/services/index.js +7 -4
- package/resources/{bacstack → node-bacnet}/lib/services/life-safety-operation.js +3 -2
- package/resources/{bacstack → node-bacnet}/lib/services/private-transfer.js +3 -2
- package/resources/{bacstack → node-bacnet}/lib/services/read-property-multiple.js +11 -6
- package/resources/{bacstack → node-bacnet}/lib/services/read-property.js +42 -24
- package/resources/{bacstack → node-bacnet}/lib/services/read-range.js +37 -27
- package/resources/node-bacnet/lib/services/register-foreign-device.js +18 -0
- package/resources/{bacstack → node-bacnet}/lib/services/reinitialize-device.js +9 -4
- package/resources/{bacstack → node-bacnet}/lib/services/subscribe-cov.js +9 -4
- package/resources/{bacstack → node-bacnet}/lib/services/subscribe-property.js +18 -8
- package/resources/{bacstack → node-bacnet}/lib/services/time-sync.js +28 -5
- package/resources/{bacstack → node-bacnet}/lib/services/who-has.js +3 -3
- package/resources/{bacstack → node-bacnet}/lib/services/who-is.js +42 -9
- package/resources/{bacstack → node-bacnet}/lib/services/write-property-multiple.js +33 -16
- package/resources/{bacstack → node-bacnet}/lib/services/write-property.js +23 -13
- package/resources/node-bacnet/lib/transport.js +82 -0
- package/resources/node-bacnet/package.json +92 -0
- package/resources/primeicons.css +90 -2
- package/resources/bacstack/.codeclimate.yml +0 -15
- package/resources/bacstack/.dockerignore +0 -5
- package/resources/bacstack/.editorconfig +0 -13
- package/resources/bacstack/.eslintrc.yml +0 -13
- package/resources/bacstack/.github/ISSUE_TEMPLATE.md +0 -26
- package/resources/bacstack/.github/PULL_REQUEST_TEMPLATE.md +0 -14
- package/resources/bacstack/.github/workflows/ci.yml +0 -39
- package/resources/bacstack/.jscsrc +0 -8
- package/resources/bacstack/.jshintrc +0 -50
- package/resources/bacstack/.travis.yml +0 -27
- package/resources/bacstack/CHANGELOG.md +0 -232
- package/resources/bacstack/CODE_OF_CONDUCT.md +0 -74
- package/resources/bacstack/CONTRIBUTING.md +0 -77
- package/resources/bacstack/Dockerfile +0 -15
- package/resources/bacstack/FAQ.md +0 -64
- package/resources/bacstack/README.md +0 -157
- package/resources/bacstack/docker-compose.yml +0 -9
- package/resources/bacstack/lib/adpu.js +0 -190
- package/resources/bacstack/lib/bvlc.js +0 -43
- package/resources/bacstack/lib/client.js +0 -1028
- package/resources/bacstack/lib/enum.js +0 -1314
- package/resources/bacstack/lib/npdu.js +0 -119
- package/resources/bacstack/lib/services/i-am-broadcast.js +0 -51
- package/resources/bacstack/lib/services.js +0 -1963
- package/resources/bacstack/lib/transport.js +0 -52
- package/resources/bacstack/package-lock.json +0 -7974
- package/resources/bacstack/package.json +0 -84
- package/resources/bacstack/test/compliance/who-is.spec.js +0 -37
- package/resources/bacstack/test/integration/acknowledge-alarm.spec.js +0 -14
- package/resources/bacstack/test/integration/add-list-element.spec.js +0 -16
- package/resources/bacstack/test/integration/confirmed-event-notification.spec.js +0 -30
- package/resources/bacstack/test/integration/confirmed-private-transfer.spec.js +0 -15
- package/resources/bacstack/test/integration/create-object.spec.js +0 -16
- package/resources/bacstack/test/integration/delete-object.spec.js +0 -14
- package/resources/bacstack/test/integration/device-communication-control.spec.js +0 -14
- package/resources/bacstack/test/integration/get-alarm-summary.spec.js +0 -14
- package/resources/bacstack/test/integration/get-enrollment-summary.spec.js +0 -15
- package/resources/bacstack/test/integration/get-event-information.spec.js +0 -14
- package/resources/bacstack/test/integration/read-file.spec.js +0 -14
- package/resources/bacstack/test/integration/read-property-multiple.spec.js +0 -110
- package/resources/bacstack/test/integration/read-property.spec.js +0 -14
- package/resources/bacstack/test/integration/read-range.spec.js +0 -14
- package/resources/bacstack/test/integration/reinitialize-sevice.spec.js +0 -14
- package/resources/bacstack/test/integration/remove-list-element.spec.js +0 -16
- package/resources/bacstack/test/integration/subscribe-cov.spec.js +0 -14
- package/resources/bacstack/test/integration/subscribe-property.spec.js +0 -14
- package/resources/bacstack/test/integration/time-sync-utc.spec.js +0 -10
- package/resources/bacstack/test/integration/time-sync.spec.js +0 -10
- package/resources/bacstack/test/integration/unconfirmed-event-notification.spec.js +0 -28
- package/resources/bacstack/test/integration/unconfirmed-private-transfer.spec.js +0 -11
- package/resources/bacstack/test/integration/utils.js +0 -30
- package/resources/bacstack/test/integration/who-is.spec.js +0 -17
- package/resources/bacstack/test/integration/write-file.spec.js +0 -14
- package/resources/bacstack/test/integration/write-property-multiple.spec.js +0 -19
- package/resources/bacstack/test/integration/write-property.spec.js +0 -14
- package/resources/bacstack/test/unit/apdu.spec.js +0 -162
- package/resources/bacstack/test/unit/asn1.spec.js +0 -39
- package/resources/bacstack/test/unit/bacnet-apdu.spec.js +0 -161
- package/resources/bacstack/test/unit/bacnet-asn1.spec.js +0 -32
- package/resources/bacstack/test/unit/bacnet-bvlc.spec.js +0 -57
- package/resources/bacstack/test/unit/bacnet-npdu.spec.js +0 -118
- package/resources/bacstack/test/unit/bacnet-services.spec.js +0 -2052
- package/resources/bacstack/test/unit/bvlc.spec.js +0 -58
- package/resources/bacstack/test/unit/npdu.spec.js +0 -119
- package/resources/bacstack/test/unit/service-add-list-element.spec.js +0 -24
- package/resources/bacstack/test/unit/service-alarm-acknowledge.spec.js +0 -71
- package/resources/bacstack/test/unit/service-alarm-summary.spec.js +0 -22
- package/resources/bacstack/test/unit/service-atomic-read-file.spec.js +0 -54
- package/resources/bacstack/test/unit/service-atomic-write-file.spec.js +0 -56
- package/resources/bacstack/test/unit/service-cov-notify.spec.js +0 -98
- package/resources/bacstack/test/unit/service-create-object.spec.js +0 -90
- package/resources/bacstack/test/unit/service-delete-object.spec.js +0 -17
- package/resources/bacstack/test/unit/service-device-communication-control.spec.js +0 -29
- package/resources/bacstack/test/unit/service-error.spec.js +0 -17
- package/resources/bacstack/test/unit/service-event-information.spec.js +0 -48
- package/resources/bacstack/test/unit/service-event-notify-data.spec.js +0 -310
- package/resources/bacstack/test/unit/service-get-enrollment-summary.spec.js +0 -45
- package/resources/bacstack/test/unit/service-get-event-information.spec.js +0 -62
- package/resources/bacstack/test/unit/service-i-am.spec.js +0 -19
- package/resources/bacstack/test/unit/service-i-have-broadcast.spec.js +0 -18
- package/resources/bacstack/test/unit/service-life-safety-operation.spec.js +0 -19
- package/resources/bacstack/test/unit/service-private-transfer.spec.js +0 -18
- package/resources/bacstack/test/unit/service-read-property-multiple.spec.js +0 -131
- package/resources/bacstack/test/unit/service-read-property.spec.js +0 -541
- package/resources/bacstack/test/unit/service-read-range.spec.js +0 -97
- package/resources/bacstack/test/unit/service-reinitialize-device.spec.js +0 -27
- package/resources/bacstack/test/unit/service-subscribe-cov.spec.js +0 -32
- package/resources/bacstack/test/unit/service-subscribe-property.spec.js +0 -50
- package/resources/bacstack/test/unit/service-time-sync.spec.js +0 -18
- package/resources/bacstack/test/unit/service-who-has.spec.js +0 -33
- package/resources/bacstack/test/unit/service-who-is.spec.js +0 -17
- package/resources/bacstack/test/unit/service-write-property-multiple.spec.js +0 -143
- package/resources/bacstack/test/unit/service-write-property.spec.js +0 -198
- package/resources/bacstack/test/unit/utils.js +0 -6
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var getBuffer = function() {
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const iconv = require('iconv-lite');
|
|
4
|
+
const baEnum = require('./enum');
|
|
5
|
+
const debug = require('debug')('bacnet:asn1:debug');
|
|
6
|
+
const trace = require('debug')('bacnet:asn1:trace');
|
|
7
|
+
|
|
8
|
+
const START_YEAR = module.exports.START_YEAR = 1900;
|
|
9
|
+
const MAX_YEARS = module.exports.MAX_YEARS = 256;
|
|
10
|
+
|
|
11
|
+
const getBuffer = () => {
|
|
14
12
|
return {
|
|
15
13
|
buffer: Buffer.alloc(1472),
|
|
16
14
|
offset: 0
|
|
17
15
|
};
|
|
18
16
|
};
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
const getSignedLength = (value) => {
|
|
21
19
|
if ((value >= -128) && (value < 128)) return 1;
|
|
22
20
|
else if ((value >= -32768) && (value < 32768)) return 2;
|
|
23
21
|
else if ((value > -8388608) && (value < 8388608)) return 3;
|
|
24
22
|
else return 4;
|
|
25
23
|
};
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
const getUnsignedLength = (value) => {
|
|
28
26
|
if (value < 0x100) return 1;
|
|
29
27
|
else if (value < 0x10000) return 2;
|
|
30
28
|
else if (value < 0x1000000) return 3;
|
|
31
29
|
else return 4;
|
|
32
30
|
};
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
const getEncodingType = (encoding, decodingBuffer, decodingOffset) => {
|
|
35
33
|
switch (encoding) {
|
|
36
|
-
case baEnum.
|
|
37
|
-
return 'utf8';
|
|
38
|
-
case baEnum.CharacterStringEncodings.CHARACTER_UCS2:
|
|
34
|
+
case baEnum.CharacterStringEncoding.UCS_2:
|
|
39
35
|
if (decodingBuffer && decodingBuffer[decodingOffset] === 0xFF && decodingBuffer[decodingOffset + 1] === 0xFE) {
|
|
40
36
|
return 'ucs2';
|
|
41
37
|
}
|
|
42
38
|
return 'UTF-16BE'; // Default to big-endian
|
|
43
|
-
case baEnum.
|
|
39
|
+
case baEnum.CharacterStringEncoding.ISO_8859_1:
|
|
44
40
|
return 'latin1';
|
|
45
|
-
case baEnum.
|
|
46
|
-
return 'utf8'; // HACK: There is currently no support for UTF-32
|
|
47
|
-
case baEnum.CharacterStringEncodings.CHARACTER_MS_DBCS:
|
|
41
|
+
case baEnum.CharacterStringEncoding.MICROSOFT_DBCS:
|
|
48
42
|
return 'cp850';
|
|
49
|
-
case baEnum.
|
|
43
|
+
case baEnum.CharacterStringEncoding.JIS_X_0208:
|
|
50
44
|
return 'Shift_JIS';
|
|
51
45
|
default:
|
|
52
46
|
return 'utf8';
|
|
53
47
|
}
|
|
54
48
|
};
|
|
55
49
|
|
|
56
|
-
|
|
50
|
+
const encodeUnsigned = module.exports.encodeUnsigned = (buffer, value, length) => {
|
|
57
51
|
buffer.buffer.writeUIntBE(value, buffer.offset, length, true);
|
|
58
52
|
buffer.offset += length;
|
|
59
53
|
};
|
|
60
54
|
|
|
61
|
-
|
|
55
|
+
const encodeBacnetUnsigned = (buffer, value) => {
|
|
62
56
|
encodeUnsigned(buffer, value, getUnsignedLength(value));
|
|
63
57
|
};
|
|
64
58
|
|
|
65
|
-
|
|
59
|
+
const encodeSigned = (buffer, value, length) => {
|
|
66
60
|
buffer.buffer.writeIntBE(value, buffer.offset, length, true);
|
|
67
61
|
buffer.offset += length;
|
|
68
62
|
};
|
|
69
63
|
|
|
70
|
-
|
|
64
|
+
const encodeBacnetSigned = (buffer, value) => {
|
|
71
65
|
encodeSigned(buffer, value, getSignedLength(value));
|
|
72
66
|
};
|
|
73
67
|
|
|
74
|
-
|
|
68
|
+
const encodeBacnetReal = (buffer, value) => {
|
|
75
69
|
buffer.buffer.writeFloatBE(value, buffer.offset, true);
|
|
76
70
|
buffer.offset += 4;
|
|
77
71
|
};
|
|
78
72
|
|
|
79
|
-
|
|
73
|
+
const encodeBacnetDouble = (buffer, value) => {
|
|
80
74
|
buffer.buffer.writeDoubleBE(value, buffer.offset, true);
|
|
81
75
|
buffer.offset += 8;
|
|
82
76
|
};
|
|
83
77
|
|
|
84
|
-
|
|
78
|
+
const decodeUnsigned = module.exports.decodeUnsigned = (buffer, offset, length) => {
|
|
79
|
+
if (length === 0) {
|
|
80
|
+
return {
|
|
81
|
+
len: 0,
|
|
82
|
+
value: 0
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
85
|
return {
|
|
86
86
|
len: length,
|
|
87
87
|
value: buffer.readUIntBE(offset, length, true)
|
|
88
88
|
};
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
const decodeEnumerated = module.exports.decodeEnumerated = (buffer, offset, lenValue) => {
|
|
92
92
|
return decodeUnsigned(buffer, offset, lenValue);
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
const encodeBacnetObjectId = module.exports.encodeBacnetObjectId = (buffer, objectType, instance) => {
|
|
96
|
+
const value = (((objectType & baEnum.ASN1_MAX_OBJECT) << baEnum.ASN1_INSTANCE_BITS) | (instance & baEnum.ASN1_MAX_INSTANCE)) >>> 0;
|
|
97
97
|
encodeUnsigned(buffer, value, 4);
|
|
98
98
|
};
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
const encodeTag = module.exports.encodeTag = (buffer, tagNumber, contextSpecific, lenValueType) => {
|
|
101
|
+
let len = 1;
|
|
102
|
+
const tmp = new Array(3);
|
|
103
103
|
tmp[0] = 0;
|
|
104
104
|
if (contextSpecific) {
|
|
105
105
|
tmp[0] |= 0x8;
|
|
@@ -135,119 +135,119 @@ var encodeTag = module.exports.encodeTag = function(buffer, tagNumber, contextSp
|
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
const encodeBacnetEnumerated = (buffer, value) => {
|
|
139
139
|
encodeBacnetUnsigned(buffer, value);
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
const isExtendedTagNumber = (x) => {
|
|
143
143
|
return (x & 0xF0) === 0xF0;
|
|
144
144
|
};
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
const isExtendedValue = (x) => {
|
|
147
147
|
return (x & 0x07) === 5;
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
const isContextSpecific = (x) => {
|
|
151
151
|
return (x & 0x8) === 0x8;
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
const isOpeningTag = (x) => {
|
|
155
155
|
return (x & 0x07) === 6;
|
|
156
156
|
};
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
const isClosingTag = (x) => {
|
|
159
159
|
return (x & 0x07) === 7;
|
|
160
160
|
};
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
const encodeContextReal = module.exports.encodeContextReal = (buffer, tagNumber, value) => {
|
|
163
163
|
encodeTag(buffer, tagNumber, true, 4);
|
|
164
164
|
encodeBacnetReal(buffer, value);
|
|
165
165
|
};
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
const encodeContextUnsigned = module.exports.encodeContextUnsigned = (buffer, tagNumber, value) => {
|
|
168
168
|
encodeTag(buffer, tagNumber, true, getUnsignedLength(value));
|
|
169
169
|
encodeBacnetUnsigned(buffer, value);
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
const encodeContextEnumerated = module.exports.encodeContextEnumerated = (buffer, tagNumber, value) => {
|
|
173
173
|
encodeContextUnsigned(buffer, tagNumber, value);
|
|
174
174
|
};
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
const encodeOctetString = (buffer, octetString, octetOffset, octetCount) => {
|
|
177
177
|
if (octetString) {
|
|
178
|
-
for (
|
|
178
|
+
for (let i = octetOffset; i < (octetOffset + octetCount); i++) {
|
|
179
179
|
buffer.buffer[buffer.offset++] = octetString[i];
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
};
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
encodeTag(buffer, baEnum.
|
|
184
|
+
const encodeApplicationOctetString = module.exports.encodeApplicationOctetString = (buffer, octetString, octetOffset, octetCount) => {
|
|
185
|
+
encodeTag(buffer, baEnum.ApplicationTag.OCTET_STRING, false, octetCount);
|
|
186
186
|
encodeOctetString(buffer, octetString, octetOffset, octetCount);
|
|
187
187
|
};
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
buffer.buffer[buffer.offset++] = baEnum.
|
|
189
|
+
const encodeApplicationNull = (buffer) => {
|
|
190
|
+
buffer.buffer[buffer.offset++] = baEnum.ApplicationTag.NULL;
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
encodeTag(buffer, baEnum.
|
|
193
|
+
const encodeApplicationBoolean = module.exports.encodeApplicationBoolean = (buffer, booleanValue) => {
|
|
194
|
+
encodeTag(buffer, baEnum.ApplicationTag.BOOLEAN, false, booleanValue ? 1 : 0);
|
|
195
195
|
};
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
encodeTag(buffer, baEnum.
|
|
197
|
+
const encodeApplicationReal = (buffer, value) => {
|
|
198
|
+
encodeTag(buffer, baEnum.ApplicationTag.REAL, false, 4);
|
|
199
199
|
encodeBacnetReal(buffer, value);
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
encodeTag(buffer, baEnum.
|
|
202
|
+
const encodeApplicationDouble = (buffer, value) => {
|
|
203
|
+
encodeTag(buffer, baEnum.ApplicationTag.DOUBLE, false, 8);
|
|
204
204
|
encodeBacnetDouble(buffer, value);
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
const bitstringBytesUsed = (bitString) => {
|
|
208
|
+
let len = 0;
|
|
209
209
|
if (bitString.bitsUsed > 0) {
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
const lastBit = bitString.bitsUsed - 1;
|
|
211
|
+
const usedBytes = (lastBit / 8) + 1;
|
|
212
212
|
len = Math.floor(usedBytes);
|
|
213
213
|
}
|
|
214
214
|
return len;
|
|
215
215
|
};
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
const encodeApplicationObjectId = module.exports.encodeApplicationObjectId = (buffer, objectType, instance) => {
|
|
218
|
+
const tmp = getBuffer();
|
|
219
219
|
encodeBacnetObjectId(tmp, objectType, instance);
|
|
220
|
-
encodeTag(buffer, baEnum.
|
|
220
|
+
encodeTag(buffer, baEnum.ApplicationTag.OBJECTIDENTIFIER, false, tmp.offset);
|
|
221
221
|
tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset);
|
|
222
222
|
buffer.offset += tmp.offset;
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
const encodeApplicationUnsigned = module.exports.encodeApplicationUnsigned = (buffer, value) => {
|
|
226
|
+
const tmp = getBuffer();
|
|
227
227
|
encodeBacnetUnsigned(tmp, value);
|
|
228
|
-
encodeTag(buffer, baEnum.
|
|
228
|
+
encodeTag(buffer, baEnum.ApplicationTag.UNSIGNED_INTEGER, false, tmp.offset);
|
|
229
229
|
tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset);
|
|
230
230
|
buffer.offset += tmp.offset;
|
|
231
231
|
};
|
|
232
232
|
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
const encodeApplicationEnumerated = module.exports.encodeApplicationEnumerated = (buffer, value) => {
|
|
234
|
+
const tmp = getBuffer();
|
|
235
235
|
encodeBacnetEnumerated(tmp, value);
|
|
236
|
-
encodeTag(buffer, baEnum.
|
|
236
|
+
encodeTag(buffer, baEnum.ApplicationTag.ENUMERATED, false, tmp.offset);
|
|
237
237
|
tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset);
|
|
238
238
|
buffer.offset += tmp.offset;
|
|
239
239
|
};
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
const encodeApplicationSigned = module.exports.encodeApplicationSigned = (buffer, value) => {
|
|
242
|
+
const tmp = getBuffer();
|
|
243
243
|
encodeBacnetSigned(tmp, value);
|
|
244
|
-
encodeTag(buffer, baEnum.
|
|
244
|
+
encodeTag(buffer, baEnum.ApplicationTag.SIGNED_INTEGER, false, tmp.offset);
|
|
245
245
|
tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset);
|
|
246
246
|
buffer.offset += tmp.offset;
|
|
247
247
|
};
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
const byteReverseBits = (inByte) => {
|
|
250
|
+
let outByte = 0;
|
|
251
251
|
if ((inByte & 1) > 0) {
|
|
252
252
|
outByte |= 0x80;
|
|
253
253
|
}
|
|
@@ -275,37 +275,35 @@ var byteReverseBits = function(inByte) {
|
|
|
275
275
|
return outByte;
|
|
276
276
|
};
|
|
277
277
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (bitString.value) {
|
|
281
|
-
|
|
282
|
-
octet = bitString.value[octetIndex];
|
|
283
|
-
}
|
|
278
|
+
const bitstringOctet = (bitString, octetIndex) => {
|
|
279
|
+
let octet = 0;
|
|
280
|
+
if (bitString.value && octetIndex < baEnum.ASN1_MAX_BITSTRING_BYTES) {
|
|
281
|
+
octet = bitString.value[octetIndex];
|
|
284
282
|
}
|
|
285
283
|
return octet;
|
|
286
284
|
};
|
|
287
285
|
|
|
288
|
-
|
|
286
|
+
const encodeBitstring = (buffer, bitString) => {
|
|
289
287
|
if (bitString.bitsUsed === 0) {
|
|
290
288
|
buffer.buffer[buffer.offset++] = 0;
|
|
291
289
|
} else {
|
|
292
|
-
|
|
293
|
-
|
|
290
|
+
const usedBytes = bitstringBytesUsed(bitString);
|
|
291
|
+
const remainingUsedBits = bitString.bitsUsed - ((usedBytes - 1) * 8);
|
|
294
292
|
buffer.buffer[buffer.offset++] = 8 - remainingUsedBits;
|
|
295
|
-
for (
|
|
293
|
+
for (let i = 0; i < usedBytes; i++) {
|
|
296
294
|
buffer.buffer[buffer.offset++] = byteReverseBits(bitstringOctet(bitString, i));
|
|
297
295
|
}
|
|
298
296
|
}
|
|
299
297
|
};
|
|
300
298
|
|
|
301
|
-
|
|
302
|
-
|
|
299
|
+
const encodeApplicationBitstring = module.exports.encodeApplicationBitstring = (buffer, bitString) => {
|
|
300
|
+
let bitStringEncodedLength = 1;
|
|
303
301
|
bitStringEncodedLength += bitstringBytesUsed(bitString);
|
|
304
|
-
encodeTag(buffer, baEnum.
|
|
302
|
+
encodeTag(buffer, baEnum.ApplicationTag.BIT_STRING, false, bitStringEncodedLength);
|
|
305
303
|
encodeBitstring(buffer, bitString);
|
|
306
304
|
};
|
|
307
305
|
|
|
308
|
-
|
|
306
|
+
const encodeBacnetDate = module.exports.encodeBacnetDate = (buffer, value) => {
|
|
309
307
|
if (value === new Date(1, 1, 1)) {
|
|
310
308
|
buffer.buffer[buffer.offset++] = 0xFF;
|
|
311
309
|
buffer.buffer[buffer.offset++] = 0xFF;
|
|
@@ -313,50 +311,51 @@ var encodeBacnetDate = function(buffer, value) {
|
|
|
313
311
|
buffer.buffer[buffer.offset++] = 0xFF;
|
|
314
312
|
return;
|
|
315
313
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
314
|
+
|
|
315
|
+
if (value.getFullYear() >= START_YEAR) {
|
|
316
|
+
buffer.buffer[buffer.offset++] = (value.getFullYear() - START_YEAR);
|
|
317
|
+
} else if (value.getFullYear() < MAX_YEARS /* 1900 + 255 max */) {
|
|
319
318
|
buffer.buffer[buffer.offset++] = value.getFullYear();
|
|
320
319
|
} else {
|
|
321
|
-
|
|
320
|
+
throw new Error('invaide year: '+ value.getFullYear());
|
|
322
321
|
}
|
|
323
322
|
buffer.buffer[buffer.offset++] = value.getMonth();
|
|
324
323
|
buffer.buffer[buffer.offset++] = value.getDate();
|
|
325
324
|
buffer.buffer[buffer.offset++] = (value.getDay() === 0) ? 7 : value.getDay();
|
|
326
325
|
};
|
|
327
326
|
|
|
328
|
-
|
|
329
|
-
encodeTag(buffer, baEnum.
|
|
327
|
+
const encodeApplicationDate = module.exports.encodeApplicationDate = (buffer, value) => {
|
|
328
|
+
encodeTag(buffer, baEnum.ApplicationTag.DATE, false, 4);
|
|
330
329
|
encodeBacnetDate(buffer, value);
|
|
331
330
|
};
|
|
332
331
|
|
|
333
|
-
|
|
332
|
+
const encodeBacnetTime = (buffer, value) => {
|
|
334
333
|
buffer.buffer[buffer.offset++] = value.getHours();
|
|
335
334
|
buffer.buffer[buffer.offset++] = value.getMinutes();
|
|
336
335
|
buffer.buffer[buffer.offset++] = value.getSeconds();
|
|
337
336
|
buffer.buffer[buffer.offset++] = value.getMilliseconds() / 10;
|
|
338
337
|
};
|
|
339
338
|
|
|
340
|
-
|
|
341
|
-
encodeTag(buffer, baEnum.
|
|
339
|
+
const encodeApplicationTime = module.exports.encodeApplicationTime = (buffer, value) => {
|
|
340
|
+
encodeTag(buffer, baEnum.ApplicationTag.TIME, false, 4);
|
|
342
341
|
encodeBacnetTime(buffer, value);
|
|
343
342
|
};
|
|
344
343
|
|
|
345
|
-
|
|
344
|
+
const bacappEncodeDatetime = (buffer, value) => {
|
|
346
345
|
if (value !== new Date(1, 1, 1)) {
|
|
347
346
|
encodeApplicationDate(buffer, value);
|
|
348
347
|
encodeApplicationTime(buffer, value);
|
|
349
348
|
}
|
|
350
349
|
};
|
|
351
350
|
|
|
352
|
-
|
|
351
|
+
const encodeContextObjectId = module.exports.encodeContextObjectId = (buffer, tagNumber, objectType, instance) => {
|
|
353
352
|
encodeTag(buffer, tagNumber, true, 4);
|
|
354
353
|
encodeBacnetObjectId(buffer, objectType, instance);
|
|
355
354
|
};
|
|
356
355
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
356
|
+
const encodeOpeningTag = module.exports.encodeOpeningTag = (buffer, tagNumber) => {
|
|
357
|
+
let len = 1;
|
|
358
|
+
const tmp = new Array(2);
|
|
360
359
|
tmp[0] = 0x8;
|
|
361
360
|
if (tagNumber <= 14) {
|
|
362
361
|
tmp[0] |= (tagNumber << 4);
|
|
@@ -370,9 +369,9 @@ var encodeOpeningTag = module.exports.encodeOpeningTag = function(buffer, tagNum
|
|
|
370
369
|
buffer.offset += len;
|
|
371
370
|
};
|
|
372
371
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
372
|
+
const encodeClosingTag = module.exports.encodeClosingTag = (buffer, tagNumber) => {
|
|
373
|
+
let len = 1;
|
|
374
|
+
const tmp = new Array(2);
|
|
376
375
|
tmp[0] = 0x8;
|
|
377
376
|
if (tagNumber <= 14) {
|
|
378
377
|
tmp[0] |= (tagNumber << 4);
|
|
@@ -386,25 +385,25 @@ var encodeClosingTag = module.exports.encodeClosingTag = function(buffer, tagNum
|
|
|
386
385
|
buffer.offset += len;
|
|
387
386
|
};
|
|
388
387
|
|
|
389
|
-
|
|
388
|
+
const encodeReadAccessSpecification = module.exports.encodeReadAccessSpecification = (buffer, value) => {
|
|
390
389
|
encodeContextObjectId(buffer, 0, value.objectId.type, value.objectId.instance);
|
|
391
390
|
encodeOpeningTag(buffer, 1);
|
|
392
|
-
value.properties.forEach(
|
|
391
|
+
value.properties.forEach((p) => {
|
|
393
392
|
encodeContextEnumerated(buffer, 0, p.id);
|
|
394
|
-
if (p.index && p.index !==
|
|
393
|
+
if (p.index && p.index !== baEnum.ASN1_ARRAY_ALL) {
|
|
395
394
|
encodeContextUnsigned(buffer, 1, p.index);
|
|
396
395
|
}
|
|
397
396
|
});
|
|
398
397
|
encodeClosingTag(buffer, 1);
|
|
399
398
|
};
|
|
400
399
|
|
|
401
|
-
|
|
400
|
+
const encodeContextBoolean = module.exports.encodeContextBoolean = (buffer, tagNumber, booleanValue) => {
|
|
402
401
|
encodeTag(buffer, tagNumber, true, 1);
|
|
403
402
|
buffer.buffer.writeUInt8(booleanValue ? 1 : 0, buffer.offset, true);
|
|
404
403
|
buffer.offset += 1;
|
|
405
404
|
};
|
|
406
405
|
|
|
407
|
-
|
|
406
|
+
const encodeCovSubscription = (buffer, value) => {
|
|
408
407
|
encodeOpeningTag(buffer, 0);
|
|
409
408
|
encodeOpeningTag(buffer, 0);
|
|
410
409
|
encodeOpeningTag(buffer, 1);
|
|
@@ -421,7 +420,7 @@ var encodeCovSubscription = function(buffer, value) {
|
|
|
421
420
|
encodeOpeningTag(buffer, 1);
|
|
422
421
|
encodeContextObjectId(buffer, 0, value.monitoredObjectId.type, value.monitoredObjectId.instance);
|
|
423
422
|
encodeContextEnumerated(buffer, 1, value.monitoredProperty.id);
|
|
424
|
-
if (value.monitoredProperty.index !==
|
|
423
|
+
if (value.monitoredProperty.index !== baEnum.ASN1_ARRAY_ALL) {
|
|
425
424
|
encodeContextUnsigned(buffer, 2, value.monitoredProperty.index);
|
|
426
425
|
}
|
|
427
426
|
encodeClosingTag(buffer, 1);
|
|
@@ -432,129 +431,131 @@ var encodeCovSubscription = function(buffer, value) {
|
|
|
432
431
|
}
|
|
433
432
|
};
|
|
434
433
|
|
|
435
|
-
|
|
434
|
+
const bacappEncodeApplicationData = module.exports.bacappEncodeApplicationData = (buffer, value) => {
|
|
436
435
|
if (value.value === null) {
|
|
437
|
-
value.type = baEnum.
|
|
436
|
+
value.type = baEnum.ApplicationTag.NULL;
|
|
438
437
|
}
|
|
439
438
|
switch (value.type) {
|
|
440
|
-
case baEnum.
|
|
439
|
+
case baEnum.ApplicationTag.NULL:
|
|
441
440
|
encodeApplicationNull(buffer);
|
|
442
441
|
break;
|
|
443
|
-
case baEnum.
|
|
442
|
+
case baEnum.ApplicationTag.BOOLEAN:
|
|
444
443
|
encodeApplicationBoolean(buffer, value.value);
|
|
445
444
|
break;
|
|
446
|
-
case baEnum.
|
|
445
|
+
case baEnum.ApplicationTag.UNSIGNED_INTEGER:
|
|
447
446
|
encodeApplicationUnsigned(buffer, value.value);
|
|
448
447
|
break;
|
|
449
|
-
case baEnum.
|
|
448
|
+
case baEnum.ApplicationTag.SIGNED_INTEGER:
|
|
450
449
|
encodeApplicationSigned(buffer, value.value);
|
|
451
450
|
break;
|
|
452
|
-
case baEnum.
|
|
451
|
+
case baEnum.ApplicationTag.REAL:
|
|
453
452
|
encodeApplicationReal(buffer, value.value);
|
|
454
453
|
break;
|
|
455
|
-
case baEnum.
|
|
454
|
+
case baEnum.ApplicationTag.DOUBLE:
|
|
456
455
|
encodeApplicationDouble(buffer, value.value);
|
|
457
456
|
break;
|
|
458
|
-
case baEnum.
|
|
457
|
+
case baEnum.ApplicationTag.OCTET_STRING:
|
|
459
458
|
encodeApplicationOctetString(buffer, value.value, 0, value.value.length);
|
|
460
459
|
break;
|
|
461
|
-
case baEnum.
|
|
460
|
+
case baEnum.ApplicationTag.CHARACTER_STRING:
|
|
462
461
|
encodeApplicationCharacterString(buffer, value.value, value.encoding);
|
|
463
462
|
break;
|
|
464
|
-
case baEnum.
|
|
463
|
+
case baEnum.ApplicationTag.BIT_STRING:
|
|
465
464
|
encodeApplicationBitstring(buffer, value.value);
|
|
466
465
|
break;
|
|
467
|
-
case baEnum.
|
|
466
|
+
case baEnum.ApplicationTag.ENUMERATED:
|
|
468
467
|
encodeApplicationEnumerated(buffer, value.value);
|
|
469
468
|
break;
|
|
470
|
-
case baEnum.
|
|
469
|
+
case baEnum.ApplicationTag.DATE:
|
|
471
470
|
encodeApplicationDate(buffer, value.value);
|
|
472
471
|
break;
|
|
473
|
-
case baEnum.
|
|
472
|
+
case baEnum.ApplicationTag.TIME:
|
|
474
473
|
encodeApplicationTime(buffer, value.value);
|
|
475
474
|
break;
|
|
476
|
-
case baEnum.
|
|
475
|
+
case baEnum.ApplicationTag.TIMESTAMP:
|
|
477
476
|
bacappEncodeTimestamp(buffer, value.value);
|
|
478
477
|
break;
|
|
479
|
-
case baEnum.
|
|
478
|
+
case baEnum.ApplicationTag.DATETIME:
|
|
480
479
|
bacappEncodeDatetime(buffer, value.value);
|
|
481
480
|
break;
|
|
482
|
-
case baEnum.
|
|
481
|
+
case baEnum.ApplicationTag.OBJECTIDENTIFIER:
|
|
483
482
|
encodeApplicationObjectId(buffer, (value.value).type, (value.value).instance);
|
|
484
483
|
break;
|
|
485
|
-
case baEnum.
|
|
484
|
+
case baEnum.ApplicationTag.COV_SUBSCRIPTION:
|
|
486
485
|
encodeCovSubscription(buffer, value.value);
|
|
487
486
|
break;
|
|
488
|
-
case baEnum.
|
|
487
|
+
case baEnum.ApplicationTag.READ_ACCESS_RESULT:
|
|
489
488
|
encodeReadAccessResult(buffer, value.value);
|
|
490
489
|
break;
|
|
491
|
-
case baEnum.
|
|
490
|
+
case baEnum.ApplicationTag.READ_ACCESS_SPECIFICATION:
|
|
492
491
|
encodeReadAccessSpecification(buffer, value.value);
|
|
493
492
|
break;
|
|
493
|
+
case undefined:
|
|
494
|
+
throw new Error('Cannot encode a value if the type has not been specified');
|
|
494
495
|
default:
|
|
495
|
-
throw '
|
|
496
|
+
throw 'No encode for ApplicationTag type: ' + baEnum.getEnumName(baEnum.ApplicationTag, value.type);
|
|
496
497
|
}
|
|
497
498
|
};
|
|
498
499
|
|
|
499
|
-
|
|
500
|
+
const bacappEncodeDeviceObjPropertyRef = (buffer, value) => {
|
|
500
501
|
encodeContextObjectId(buffer, 0, value.objectId.type, value.objectId.instance);
|
|
501
502
|
encodeContextEnumerated(buffer, 1, value.id);
|
|
502
|
-
if (value.arrayIndex !==
|
|
503
|
+
if (value.arrayIndex !== baEnum.ASN1_ARRAY_ALL) {
|
|
503
504
|
encodeContextUnsigned(buffer, 2, value.arrayIndex);
|
|
504
505
|
}
|
|
505
|
-
if (value.deviceIndentifier.type === baEnum.
|
|
506
|
+
if (value.deviceIndentifier.type === baEnum.ObjectType.DEVICE) {
|
|
506
507
|
encodeContextObjectId(buffer, 3, value.deviceIndentifier.type, value.deviceIndentifier.instance);
|
|
507
508
|
}
|
|
508
509
|
};
|
|
509
510
|
|
|
510
|
-
|
|
511
|
+
const bacappEncodeContextDeviceObjPropertyRef = module.exports.bacappEncodeContextDeviceObjPropertyRef = (buffer, tagNumber, value) => {
|
|
511
512
|
encodeOpeningTag(buffer, tagNumber);
|
|
512
513
|
bacappEncodeDeviceObjPropertyRef(buffer, value);
|
|
513
514
|
encodeClosingTag(buffer, tagNumber);
|
|
514
515
|
};
|
|
515
516
|
|
|
516
|
-
|
|
517
|
+
const bacappEncodePropertyState = module.exports.bacappEncodePropertyState = (buffer, value) => {
|
|
517
518
|
switch (value.type) {
|
|
518
|
-
case baEnum.
|
|
519
|
-
encodeContextBoolean(buffer, 0, value.state === 1
|
|
519
|
+
case baEnum.PropertyStates.BOOLEAN_VALUE:
|
|
520
|
+
encodeContextBoolean(buffer, 0, value.state === 1);
|
|
520
521
|
break;
|
|
521
|
-
case baEnum.
|
|
522
|
+
case baEnum.PropertyStates.BINARY_VALUE:
|
|
522
523
|
encodeContextEnumerated(buffer, 1, value.state);
|
|
523
524
|
break;
|
|
524
|
-
case baEnum.
|
|
525
|
+
case baEnum.PropertyStates.EVENT_TYPE:
|
|
525
526
|
encodeContextEnumerated(buffer, 2, value.state);
|
|
526
527
|
break;
|
|
527
|
-
case baEnum.
|
|
528
|
+
case baEnum.PropertyStates.POLARITY:
|
|
528
529
|
encodeContextEnumerated(buffer, 3, value.state);
|
|
529
530
|
break;
|
|
530
|
-
case baEnum.
|
|
531
|
+
case baEnum.PropertyStates.PROGRAM_CHANGE:
|
|
531
532
|
encodeContextEnumerated(buffer, 4, value.state);
|
|
532
533
|
break;
|
|
533
|
-
case baEnum.
|
|
534
|
+
case baEnum.PropertyStates.PROGRAM_STATE:
|
|
534
535
|
encodeContextEnumerated(buffer, 5, value.state);
|
|
535
536
|
break;
|
|
536
|
-
case baEnum.
|
|
537
|
+
case baEnum.PropertyStates.REASON_FOR_HALT:
|
|
537
538
|
encodeContextEnumerated(buffer, 6, value.state);
|
|
538
539
|
break;
|
|
539
|
-
case baEnum.
|
|
540
|
+
case baEnum.PropertyStates.RELIABILITY:
|
|
540
541
|
encodeContextEnumerated(buffer, 7, value.state);
|
|
541
542
|
break;
|
|
542
|
-
case baEnum.
|
|
543
|
+
case baEnum.PropertyStates.STATE:
|
|
543
544
|
encodeContextEnumerated(buffer, 8, value.state);
|
|
544
545
|
break;
|
|
545
|
-
case baEnum.
|
|
546
|
+
case baEnum.PropertyStates.SYSTEM_STATUS:
|
|
546
547
|
encodeContextEnumerated(buffer, 9, value.state);
|
|
547
548
|
break;
|
|
548
|
-
case baEnum.
|
|
549
|
+
case baEnum.PropertyStates.UNITS:
|
|
549
550
|
encodeContextEnumerated(buffer, 10, value.state);
|
|
550
551
|
break;
|
|
551
|
-
case baEnum.
|
|
552
|
+
case baEnum.PropertyStates.UNSIGNED_VALUE:
|
|
552
553
|
encodeContextUnsigned(buffer, 11, value.state);
|
|
553
554
|
break;
|
|
554
|
-
case baEnum.
|
|
555
|
+
case baEnum.PropertyStates.LIFE_SAFETY_MODE:
|
|
555
556
|
encodeContextEnumerated(buffer, 12, value.state);
|
|
556
557
|
break;
|
|
557
|
-
case baEnum.
|
|
558
|
+
case baEnum.PropertyStates.LIFE_SAFETY_STATE:
|
|
558
559
|
encodeContextEnumerated(buffer, 13, value.state);
|
|
559
560
|
break;
|
|
560
561
|
default:
|
|
@@ -562,34 +563,36 @@ var bacappEncodePropertyState = module.exports.bacappEncodePropertyState = funct
|
|
|
562
563
|
}
|
|
563
564
|
};
|
|
564
565
|
|
|
565
|
-
|
|
566
|
-
|
|
566
|
+
const encodeContextBitstring = module.exports.encodeContextBitstring = (buffer, tagNumber, bitString) => {
|
|
567
|
+
let bitStringEncodedLength = 1;
|
|
567
568
|
bitStringEncodedLength += bitstringBytesUsed(bitString);
|
|
568
569
|
encodeTag(buffer, tagNumber, true, bitStringEncodedLength);
|
|
569
570
|
encodeBitstring(buffer, bitString);
|
|
570
571
|
};
|
|
571
572
|
|
|
572
|
-
|
|
573
|
+
const encodeContextSigned = module.exports.encodeContextSigned = (buffer, tagNumber, value) => {
|
|
573
574
|
encodeTag(buffer, tagNumber, true, getSignedLength(value));
|
|
574
575
|
encodeBacnetSigned(buffer, value);
|
|
575
576
|
};
|
|
576
577
|
|
|
577
|
-
|
|
578
|
+
const encodeContextTime = (buffer, tagNumber, value) => {
|
|
578
579
|
encodeTag(buffer, tagNumber, true, 4);
|
|
579
580
|
encodeBacnetTime(buffer, value);
|
|
580
581
|
};
|
|
581
582
|
|
|
582
|
-
|
|
583
|
+
const bacappEncodeContextDatetime = (buffer, tagNumber, value) => {
|
|
583
584
|
if (value !== new Date(1, 1, 1)) {
|
|
584
585
|
encodeOpeningTag(buffer, tagNumber);
|
|
585
586
|
bacappEncodeDatetime(buffer, value);
|
|
586
587
|
encodeClosingTag(buffer, tagNumber);
|
|
588
|
+
} else {
|
|
589
|
+
throw new Error('wrong Datetime while bacapp encoding context');
|
|
587
590
|
}
|
|
588
591
|
};
|
|
589
592
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
+
const decodeTagNumber = module.exports.decodeTagNumber = (buffer, offset) => {
|
|
594
|
+
let len = 1;
|
|
595
|
+
let tagNumber;
|
|
593
596
|
if (isExtendedTagNumber(buffer[offset])) {
|
|
594
597
|
tagNumber = buffer[offset + 1];
|
|
595
598
|
len++;
|
|
@@ -597,46 +600,46 @@ var decodeTagNumber = module.exports.decodeTagNumber = function(buffer, offset)
|
|
|
597
600
|
tagNumber = buffer[offset] >> 4;
|
|
598
601
|
}
|
|
599
602
|
return {
|
|
600
|
-
len
|
|
601
|
-
tagNumber
|
|
603
|
+
len,
|
|
604
|
+
tagNumber
|
|
602
605
|
};
|
|
603
606
|
};
|
|
604
607
|
|
|
605
|
-
|
|
606
|
-
|
|
608
|
+
const decodeIsContextTag = module.exports.decodeIsContextTag = (buffer, offset, tagNumber) => {
|
|
609
|
+
const result = decodeTagNumber(buffer, offset);
|
|
607
610
|
return isContextSpecific(buffer[offset]) && result.tagNumber === tagNumber;
|
|
608
611
|
};
|
|
609
612
|
|
|
610
|
-
|
|
611
|
-
|
|
613
|
+
const decodeIsOpeningTagNumber = module.exports.decodeIsOpeningTagNumber = (buffer, offset, tagNumber) => {
|
|
614
|
+
const result = decodeTagNumber(buffer, offset);
|
|
612
615
|
return isOpeningTag(buffer[offset]) && result.tagNumber === tagNumber;
|
|
613
616
|
};
|
|
614
617
|
|
|
615
|
-
|
|
616
|
-
|
|
618
|
+
const decodeIsClosingTagNumber = module.exports.decodeIsClosingTagNumber = (buffer, offset, tagNumber) => {
|
|
619
|
+
const result = decodeTagNumber(buffer, offset);
|
|
617
620
|
return isClosingTag(buffer[offset]) && result.tagNumber === tagNumber;
|
|
618
621
|
};
|
|
619
622
|
|
|
620
|
-
|
|
623
|
+
const decodeIsClosingTag = module.exports.decodeIsClosingTag = (buffer, offset) => {
|
|
621
624
|
return (buffer[offset] & 0x07) === 7;
|
|
622
625
|
};
|
|
623
626
|
|
|
624
|
-
|
|
627
|
+
const decodeIsOpeningTag = module.exports.decodeIsOpeningTag = (buffer, offset) => {
|
|
625
628
|
return (buffer[offset] & 0x07) === 6;
|
|
626
629
|
};
|
|
627
630
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
631
|
+
const decodeObjectId = module.exports.decodeObjectId = (buffer, offset) => {
|
|
632
|
+
const result = decodeUnsigned(buffer, offset, 4);
|
|
633
|
+
const objectType = (result.value >> baEnum.ASN1_INSTANCE_BITS) & baEnum.ASN1_MAX_OBJECT;
|
|
634
|
+
const instance = result.value & baEnum.ASN1_MAX_INSTANCE;
|
|
632
635
|
return {
|
|
633
636
|
len: result.len,
|
|
634
|
-
objectType
|
|
635
|
-
instance
|
|
637
|
+
objectType,
|
|
638
|
+
instance
|
|
636
639
|
};
|
|
637
640
|
};
|
|
638
641
|
|
|
639
|
-
|
|
642
|
+
const decodeObjectIdSafe = (buffer, offset, lenValue) => {
|
|
640
643
|
if (lenValue !== 4) {
|
|
641
644
|
return {
|
|
642
645
|
len: 0,
|
|
@@ -648,10 +651,10 @@ var decodeObjectIdSafe = function(buffer, offset, lenValue) {
|
|
|
648
651
|
}
|
|
649
652
|
};
|
|
650
653
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
654
|
+
const decodeTagNumberAndValue = module.exports.decodeTagNumberAndValue = (buffer, offset) => {
|
|
655
|
+
let value;
|
|
656
|
+
let result = decodeTagNumber(buffer, offset);
|
|
657
|
+
let len = result.len;
|
|
655
658
|
if (isExtendedValue(buffer[offset])) {
|
|
656
659
|
if (buffer[offset + len] === 255) {
|
|
657
660
|
len++;
|
|
@@ -675,20 +678,22 @@ var decodeTagNumberAndValue = module.exports.decodeTagNumberAndValue = function(
|
|
|
675
678
|
value = buffer[offset] & 0x07;
|
|
676
679
|
}
|
|
677
680
|
return {
|
|
678
|
-
len
|
|
681
|
+
len,
|
|
679
682
|
tagNumber: result.tagNumber,
|
|
680
|
-
value
|
|
683
|
+
value
|
|
681
684
|
};
|
|
682
685
|
};
|
|
683
686
|
|
|
684
|
-
|
|
687
|
+
const bacappDecodeApplicationData = module.exports.bacappDecodeApplicationData = (buffer, offset, maxOffset, objectType, propertyId) => {
|
|
685
688
|
if (!isContextSpecific(buffer[offset])) {
|
|
686
|
-
|
|
689
|
+
let result = decodeTagNumberAndValue(buffer, offset);
|
|
687
690
|
if (result) {
|
|
688
|
-
|
|
691
|
+
let len = result.len;
|
|
689
692
|
result = bacappDecodeData(buffer, offset + len, maxOffset, result.tagNumber, result.value);
|
|
690
|
-
if (!result)
|
|
691
|
-
|
|
693
|
+
if (!result) {
|
|
694
|
+
return undefined;
|
|
695
|
+
}
|
|
696
|
+
let resObj = {
|
|
692
697
|
len: len + result.len,
|
|
693
698
|
type: result.type,
|
|
694
699
|
value: result.value
|
|
@@ -702,12 +707,12 @@ var bacappDecodeApplicationData = module.exports.bacappDecodeApplicationData = f
|
|
|
702
707
|
}
|
|
703
708
|
};
|
|
704
709
|
|
|
705
|
-
|
|
710
|
+
const encodeReadAccessResult = module.exports.encodeReadAccessResult = (buffer, value) => {
|
|
706
711
|
encodeContextObjectId(buffer, 0, value.objectId.type, value.objectId.instance);
|
|
707
712
|
encodeOpeningTag(buffer, 1);
|
|
708
|
-
value.values.forEach(
|
|
713
|
+
value.values.forEach((item) => {
|
|
709
714
|
encodeContextEnumerated(buffer, 2, item.property.id);
|
|
710
|
-
if (item.property.index !==
|
|
715
|
+
if (item.property.index !== baEnum.ASN1_ARRAY_ALL) {
|
|
711
716
|
encodeContextUnsigned(buffer, 3, item.property.index);
|
|
712
717
|
}
|
|
713
718
|
if (item.value && item.value[0] && item.value[0].value && item.value[0].value.type === 'BacnetError') {
|
|
@@ -717,7 +722,7 @@ var encodeReadAccessResult = module.exports.encodeReadAccessResult = function(bu
|
|
|
717
722
|
encodeClosingTag(buffer, 5);
|
|
718
723
|
} else {
|
|
719
724
|
encodeOpeningTag(buffer, 4);
|
|
720
|
-
item.value.forEach(
|
|
725
|
+
item.value.forEach((subItem) => {
|
|
721
726
|
bacappEncodeApplicationData(buffer, subItem);
|
|
722
727
|
});
|
|
723
728
|
encodeClosingTag(buffer, 4);
|
|
@@ -726,30 +731,36 @@ var encodeReadAccessResult = module.exports.encodeReadAccessResult = function(bu
|
|
|
726
731
|
encodeClosingTag(buffer, 1);
|
|
727
732
|
};
|
|
728
733
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if (!decodeIsContextTag(buffer, offset + len, 0))
|
|
734
|
+
const decodeReadAccessResult = module.exports.decodeReadAccessResult = (buffer, offset, apduLen) => {
|
|
735
|
+
let len = 0;
|
|
736
|
+
let value = {};
|
|
737
|
+
if (!decodeIsContextTag(buffer, offset + len, 0)) {
|
|
738
|
+
return undefined;
|
|
739
|
+
}
|
|
733
740
|
len++;
|
|
734
|
-
|
|
741
|
+
let result = decodeObjectId(buffer, offset + len);
|
|
735
742
|
value.objectId = {
|
|
736
743
|
type: result.objectType,
|
|
737
744
|
instance: result.instance
|
|
738
745
|
};
|
|
739
746
|
len += result.len;
|
|
740
|
-
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1))
|
|
747
|
+
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1)) {
|
|
748
|
+
return -1; // TODO: why?
|
|
749
|
+
}
|
|
741
750
|
len++;
|
|
742
751
|
|
|
743
|
-
|
|
752
|
+
const values = [];
|
|
744
753
|
while ((apduLen - len) > 0) {
|
|
745
|
-
|
|
754
|
+
let newEntry = {};
|
|
746
755
|
if (decodeIsClosingTagNumber(buffer, offset + len, 1)) {
|
|
747
756
|
len++;
|
|
748
757
|
break;
|
|
749
758
|
}
|
|
750
759
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
751
760
|
len += result.len;
|
|
752
|
-
if (result.tagNumber !== 2)
|
|
761
|
+
if (result.tagNumber !== 2) {
|
|
762
|
+
return undefined;
|
|
763
|
+
}
|
|
753
764
|
result = decodeEnumerated(buffer, offset + len, result.value);
|
|
754
765
|
newEntry.id = result.value;
|
|
755
766
|
len += result.len;
|
|
@@ -761,17 +772,19 @@ var decodeReadAccessResult = module.exports.decodeReadAccessResult = function(bu
|
|
|
761
772
|
newEntry.index = result.value;
|
|
762
773
|
len += result.len;
|
|
763
774
|
} else {
|
|
764
|
-
newEntry.index =
|
|
775
|
+
newEntry.index = baEnum.ASN1_ARRAY_ALL;
|
|
765
776
|
}
|
|
766
777
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
767
778
|
len += result.len;
|
|
768
779
|
if (result.tagNumber === 4) {
|
|
769
|
-
|
|
780
|
+
const localValues = [];
|
|
770
781
|
while ((len + offset) <= buffer.length && !decodeIsClosingTagNumber(buffer, offset + len, 4)) {
|
|
771
|
-
|
|
772
|
-
if (!localResult)
|
|
782
|
+
let localResult = bacappDecodeApplicationData(buffer, offset + len, apduLen + offset - 1, value.objectId.type, newEntry.id);
|
|
783
|
+
if (!localResult) {
|
|
784
|
+
return undefined;
|
|
785
|
+
}
|
|
773
786
|
len += localResult.len;
|
|
774
|
-
|
|
787
|
+
let resObj = {
|
|
775
788
|
value: localResult.value,
|
|
776
789
|
type: localResult.type
|
|
777
790
|
};
|
|
@@ -779,20 +792,22 @@ var decodeReadAccessResult = module.exports.decodeReadAccessResult = function(bu
|
|
|
779
792
|
if (localResult.encoding !== undefined) resObj.encoding = localResult.encoding;
|
|
780
793
|
localValues.push(resObj);
|
|
781
794
|
}
|
|
782
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 4))
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
795
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 4)) {
|
|
796
|
+
return undefined;
|
|
797
|
+
}
|
|
798
|
+
if ((localValues.count === 2) && (localValues[0].type === baEnum.ApplicationTag.DATE) && (localValues[1].type === baEnum.ApplicationTag.TIME)) {
|
|
799
|
+
const date = localValues[0].value;
|
|
800
|
+
const time = localValues[1].value;
|
|
801
|
+
const bdatetime = new Date(date.year, date.month, date.day, time.hour, time.minute, time.second, time.millisecond);
|
|
787
802
|
newEntry.value = [
|
|
788
|
-
{type: baEnum.
|
|
803
|
+
{type: baEnum.ApplicationTag.DATETIME, value: bdatetime}
|
|
789
804
|
];
|
|
790
805
|
} else {
|
|
791
806
|
newEntry.value = localValues;
|
|
792
807
|
}
|
|
793
808
|
len++;
|
|
794
809
|
} else if (result.tagNumber === 5) {
|
|
795
|
-
|
|
810
|
+
let err = {};
|
|
796
811
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
797
812
|
len += result.len;
|
|
798
813
|
result = decodeEnumerated(buffer, offset + len, result.value);
|
|
@@ -803,37 +818,39 @@ var decodeReadAccessResult = module.exports.decodeReadAccessResult = function(bu
|
|
|
803
818
|
result = decodeEnumerated(buffer, offset + len, result.value);
|
|
804
819
|
len += result.len;
|
|
805
820
|
err.errorCode = result.value;
|
|
806
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 5))
|
|
821
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 5)) {
|
|
822
|
+
return undefined;
|
|
823
|
+
}
|
|
807
824
|
len++;
|
|
808
|
-
newEntry.value = {
|
|
809
|
-
type: baEnum.
|
|
825
|
+
newEntry.value = [{
|
|
826
|
+
type: baEnum.ApplicationTag.ERROR,
|
|
810
827
|
value: err
|
|
811
|
-
};
|
|
828
|
+
}];
|
|
812
829
|
}
|
|
813
830
|
values.push(newEntry);
|
|
814
831
|
}
|
|
815
832
|
value.values = values;
|
|
816
833
|
return {
|
|
817
|
-
len
|
|
818
|
-
value
|
|
834
|
+
len,
|
|
835
|
+
value
|
|
819
836
|
};
|
|
820
837
|
};
|
|
821
838
|
|
|
822
|
-
|
|
839
|
+
const decodeSigned = module.exports.decodeSigned = (buffer, offset, length) => {
|
|
823
840
|
return {
|
|
824
841
|
len: length,
|
|
825
842
|
value: buffer.readIntBE(offset, length, true)
|
|
826
843
|
};
|
|
827
844
|
};
|
|
828
845
|
|
|
829
|
-
|
|
846
|
+
const decodeReal = module.exports.decodeReal = (buffer, offset) => {
|
|
830
847
|
return {
|
|
831
848
|
len: 4,
|
|
832
849
|
value: buffer.readFloatBE(offset, true)
|
|
833
850
|
};
|
|
834
851
|
};
|
|
835
852
|
|
|
836
|
-
|
|
853
|
+
const decodeRealSafe = (buffer, offset, lenValue) => {
|
|
837
854
|
if (lenValue !== 4) {
|
|
838
855
|
return {
|
|
839
856
|
len: lenValue,
|
|
@@ -844,14 +861,14 @@ var decodeRealSafe = function(buffer, offset, lenValue) {
|
|
|
844
861
|
}
|
|
845
862
|
};
|
|
846
863
|
|
|
847
|
-
|
|
864
|
+
const decodeDouble = (buffer, offset) => {
|
|
848
865
|
return {
|
|
849
866
|
len: 8,
|
|
850
867
|
value: buffer.readDoubleBE(offset, true)
|
|
851
868
|
};
|
|
852
869
|
};
|
|
853
870
|
|
|
854
|
-
|
|
871
|
+
const decodeDoubleSafe = (buffer, offset, lenValue) => {
|
|
855
872
|
if (lenValue !== 8) {
|
|
856
873
|
return {
|
|
857
874
|
len: lenValue,
|
|
@@ -862,9 +879,9 @@ var decodeDoubleSafe = function(buffer, offset, lenValue) {
|
|
|
862
879
|
}
|
|
863
880
|
};
|
|
864
881
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
for (
|
|
882
|
+
const decodeOctetString = module.exports.decodeOctetString = (buffer, offset, maxLength, octetStringOffset, octetStringLength) => {
|
|
883
|
+
const octetString = [];
|
|
884
|
+
for (let i = octetStringOffset; i < (octetStringOffset + octetStringLength); i++) {
|
|
868
885
|
octetString.push(buffer[offset + i]);
|
|
869
886
|
}
|
|
870
887
|
return {
|
|
@@ -873,73 +890,52 @@ var decodeOctetString = function(buffer, offset, maxLength, octetStringOffset, o
|
|
|
873
890
|
};
|
|
874
891
|
};
|
|
875
892
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
var result = decodeTagNumberAndValue(buffer, offset);
|
|
879
|
-
return {
|
|
880
|
-
len: result.lenValue + result.len,
|
|
881
|
-
value: Buffer.from(buffer.slice(offset, result.lenValue))
|
|
882
|
-
};
|
|
883
|
-
} else {
|
|
884
|
-
return;
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
|
|
888
|
-
var multiCharsetCharacterstringDecode = function(buffer, offset, maxLength, encoding, length) {
|
|
889
|
-
var stringBuf = Buffer.alloc(length);
|
|
893
|
+
const multiCharsetCharacterstringDecode = (buffer, offset, maxLength, encoding, length) => {
|
|
894
|
+
const stringBuf = Buffer.alloc(length);
|
|
890
895
|
buffer.copy(stringBuf, 0, offset, offset + length);
|
|
891
896
|
return {
|
|
892
897
|
value: iconv.decode(stringBuf, getEncodingType(encoding, buffer, offset)),
|
|
893
898
|
len: length + 1,
|
|
894
|
-
encoding
|
|
899
|
+
encoding
|
|
895
900
|
};
|
|
896
901
|
};
|
|
897
902
|
|
|
898
|
-
|
|
903
|
+
const decodeCharacterString = module.exports.decodeCharacterString = (buffer, offset, maxLength, lenValue) => {
|
|
899
904
|
return multiCharsetCharacterstringDecode(buffer, offset + 1, maxLength, buffer[offset], lenValue - 1);
|
|
900
905
|
};
|
|
901
906
|
|
|
902
|
-
|
|
903
|
-
var status = false;
|
|
904
|
-
if (index < MAX_BITSTRING_BYTES) {
|
|
905
|
-
bitString.value[index] = octet;
|
|
906
|
-
status = true;
|
|
907
|
-
}
|
|
908
|
-
return status;
|
|
909
|
-
};
|
|
910
|
-
|
|
911
|
-
var bitstringSetBitsUsed = function(bitString, bytesUsed, unusedBits) {
|
|
907
|
+
const bitstringSetBitsUsed = (bitString, bytesUsed, unusedBits) => {
|
|
912
908
|
bitString.bitsUsed = bytesUsed * 8;
|
|
913
909
|
bitString.bitsUsed -= unusedBits;
|
|
914
910
|
};
|
|
915
911
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
912
|
+
const decodeBitstring = module.exports.decodeBitstring = (buffer, offset, lenValue) => {
|
|
913
|
+
let len = 0;
|
|
914
|
+
let bitString = {};
|
|
919
915
|
bitString.value = [];
|
|
920
916
|
if (lenValue > 0) {
|
|
921
|
-
|
|
922
|
-
if (bytesUsed <=
|
|
917
|
+
const bytesUsed = lenValue - 1;
|
|
918
|
+
if (bytesUsed <= baEnum.ASN1_MAX_BITSTRING_BYTES) {
|
|
923
919
|
len = 1;
|
|
924
|
-
for (
|
|
920
|
+
for (let i = 0; i < bytesUsed; i++) {
|
|
925
921
|
bitString.value.push(byteReverseBits(buffer[offset + len++]));
|
|
926
922
|
}
|
|
927
|
-
|
|
923
|
+
const unusedBits = buffer[offset] & 0x07;
|
|
928
924
|
bitstringSetBitsUsed(bitString, bytesUsed, unusedBits);
|
|
929
925
|
}
|
|
930
926
|
}
|
|
931
927
|
return {
|
|
932
|
-
len
|
|
928
|
+
len,
|
|
933
929
|
value: bitString
|
|
934
930
|
};
|
|
935
931
|
};
|
|
936
932
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
933
|
+
const decodeDate = module.exports.decodeDate = (buffer, offset) => {
|
|
934
|
+
let date;
|
|
935
|
+
const year = buffer[offset] + 1900;
|
|
936
|
+
const month = buffer[offset + 1];
|
|
937
|
+
const day = buffer[offset + 2];
|
|
938
|
+
const wday = buffer[offset + 3];
|
|
943
939
|
if (month === 0xFF && day === 0xFF && wday === 0xFF && (year - 1900) === 0xFF) {
|
|
944
940
|
date = new Date(1, 1, 1);
|
|
945
941
|
} else {
|
|
@@ -951,7 +947,7 @@ var decodeDate = module.exports.decodeDate = function(buffer, offset) {
|
|
|
951
947
|
};
|
|
952
948
|
};
|
|
953
949
|
|
|
954
|
-
|
|
950
|
+
const decodeDateSafe = (buffer, offset, lenValue) => {
|
|
955
951
|
if (lenValue !== 4) {
|
|
956
952
|
return {
|
|
957
953
|
len: lenValue,
|
|
@@ -962,25 +958,24 @@ var decodeDateSafe = function(buffer, offset, lenValue) {
|
|
|
962
958
|
}
|
|
963
959
|
};
|
|
964
960
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
if (result.tagNumber === baEnum.
|
|
968
|
-
|
|
961
|
+
const decodeApplicationDate = module.exports.decodeApplicationDate = (buffer, offset) => {
|
|
962
|
+
const result = decodeTagNumber(buffer, offset);
|
|
963
|
+
if (result.tagNumber === baEnum.ApplicationTag.DATE) {
|
|
964
|
+
const value = decodeDate(buffer, offset + 1);
|
|
969
965
|
return {
|
|
970
966
|
len: value.len + 1,
|
|
971
|
-
value
|
|
967
|
+
value
|
|
972
968
|
};
|
|
973
|
-
} else {
|
|
974
|
-
return;
|
|
975
969
|
}
|
|
970
|
+
return undefined;
|
|
976
971
|
};
|
|
977
972
|
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
973
|
+
const decodeBacnetTime = module.exports.decodeBacnetTime = (buffer, offset) => {
|
|
974
|
+
let value;
|
|
975
|
+
const hour = buffer[offset + 0];
|
|
976
|
+
const min = buffer[offset + 1];
|
|
977
|
+
const sec = buffer[offset + 2];
|
|
978
|
+
let hundredths = buffer[offset + 3];
|
|
984
979
|
if (hour === 0xFF && min === 0xFF && sec === 0xFF && hundredths === 0xFF) {
|
|
985
980
|
value = new Date(1, 1, 1);
|
|
986
981
|
} else {
|
|
@@ -989,11 +984,11 @@ var decodeBacnetTime = module.exports.decodeBacnetTime = function(buffer, offset
|
|
|
989
984
|
}
|
|
990
985
|
return {
|
|
991
986
|
len: 4,
|
|
992
|
-
value
|
|
987
|
+
value
|
|
993
988
|
};
|
|
994
989
|
};
|
|
995
990
|
|
|
996
|
-
|
|
991
|
+
const decodeBacnetTimeSafe = (buffer, offset, lenValue) => {
|
|
997
992
|
if (lenValue !== 4) {
|
|
998
993
|
return {
|
|
999
994
|
len: lenValue,
|
|
@@ -1004,96 +999,95 @@ var decodeBacnetTimeSafe = function(buffer, offset, lenValue) {
|
|
|
1004
999
|
}
|
|
1005
1000
|
};
|
|
1006
1001
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
if (result.tagNumber === baEnum.
|
|
1010
|
-
|
|
1002
|
+
const decodeApplicationTime = module.exports.decodeApplicationTime = (buffer, offset) => {
|
|
1003
|
+
const result = decodeTagNumber(buffer, offset);
|
|
1004
|
+
if (result.tagNumber === baEnum.ApplicationTag.TIME) {
|
|
1005
|
+
const value = decodeBacnetTime(buffer, offset + 1);
|
|
1011
1006
|
return {
|
|
1012
1007
|
len: value.len + 1,
|
|
1013
|
-
value
|
|
1008
|
+
value
|
|
1014
1009
|
};
|
|
1015
|
-
} else {
|
|
1016
|
-
return;
|
|
1017
1010
|
}
|
|
1011
|
+
return undefined;
|
|
1018
1012
|
};
|
|
1019
1013
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1014
|
+
const decodeBacnetDatetime = (buffer, offset) => {
|
|
1015
|
+
let len = 0;
|
|
1016
|
+
const date = decodeApplicationDate(buffer, offset + len);
|
|
1023
1017
|
len += date.len;
|
|
1024
|
-
|
|
1018
|
+
const time = decodeApplicationTime(buffer, offset + len);
|
|
1025
1019
|
len += time.len;
|
|
1026
1020
|
return {
|
|
1027
|
-
len
|
|
1021
|
+
len,
|
|
1028
1022
|
value: new Date(date.year, date.month, date.day, time.hour, time.minute, time.second, time.millisecond)
|
|
1029
1023
|
};
|
|
1030
1024
|
};
|
|
1031
1025
|
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1026
|
+
const bacappDecodeData = (buffer, offset, maxLength, tagDataType, lenValueType) => {
|
|
1027
|
+
let result;
|
|
1028
|
+
let value = {
|
|
1035
1029
|
len: 0,
|
|
1036
1030
|
type: tagDataType
|
|
1037
1031
|
};
|
|
1038
1032
|
switch (tagDataType) {
|
|
1039
|
-
case baEnum.
|
|
1033
|
+
case baEnum.ApplicationTag.NULL:
|
|
1040
1034
|
value.value = null;
|
|
1041
1035
|
break;
|
|
1042
|
-
case baEnum.
|
|
1043
|
-
value.value = lenValueType > 0
|
|
1036
|
+
case baEnum.ApplicationTag.BOOLEAN:
|
|
1037
|
+
value.value = lenValueType > 0;
|
|
1044
1038
|
break;
|
|
1045
|
-
case baEnum.
|
|
1039
|
+
case baEnum.ApplicationTag.UNSIGNED_INTEGER:
|
|
1046
1040
|
result = decodeUnsigned(buffer, offset, lenValueType);
|
|
1047
1041
|
value.len += result.len;
|
|
1048
1042
|
value.value = result.value;
|
|
1049
1043
|
break;
|
|
1050
|
-
case baEnum.
|
|
1044
|
+
case baEnum.ApplicationTag.SIGNED_INTEGER:
|
|
1051
1045
|
result = decodeSigned(buffer, offset, lenValueType);
|
|
1052
1046
|
value.len += result.len;
|
|
1053
1047
|
value.value = result.value;
|
|
1054
1048
|
break;
|
|
1055
|
-
case baEnum.
|
|
1049
|
+
case baEnum.ApplicationTag.REAL:
|
|
1056
1050
|
result = decodeRealSafe(buffer, offset, lenValueType);
|
|
1057
1051
|
value.len += result.len;
|
|
1058
1052
|
value.value = result.value;
|
|
1059
1053
|
break;
|
|
1060
|
-
case baEnum.
|
|
1054
|
+
case baEnum.ApplicationTag.DOUBLE:
|
|
1061
1055
|
result = decodeDoubleSafe(buffer, offset, lenValueType);
|
|
1062
1056
|
value.len += result.len;
|
|
1063
1057
|
value.value = result.value;
|
|
1064
1058
|
break;
|
|
1065
|
-
case baEnum.
|
|
1059
|
+
case baEnum.ApplicationTag.OCTET_STRING:
|
|
1066
1060
|
result = decodeOctetString(buffer, offset, maxLength, 0, lenValueType);
|
|
1067
1061
|
value.len += result.len;
|
|
1068
1062
|
value.value = result.value;
|
|
1069
1063
|
break;
|
|
1070
|
-
case baEnum.
|
|
1064
|
+
case baEnum.ApplicationTag.CHARACTER_STRING:
|
|
1071
1065
|
result = decodeCharacterString(buffer, offset, maxLength, lenValueType);
|
|
1072
1066
|
value.len += result.len;
|
|
1073
1067
|
value.value = result.value;
|
|
1074
1068
|
value.encoding = result.encoding;
|
|
1075
1069
|
break;
|
|
1076
|
-
case baEnum.
|
|
1070
|
+
case baEnum.ApplicationTag.BIT_STRING:
|
|
1077
1071
|
result = decodeBitstring(buffer, offset, lenValueType);
|
|
1078
1072
|
value.len += result.len;
|
|
1079
1073
|
value.value = result.value;
|
|
1080
1074
|
break;
|
|
1081
|
-
case baEnum.
|
|
1075
|
+
case baEnum.ApplicationTag.ENUMERATED:
|
|
1082
1076
|
result = decodeEnumerated(buffer, offset, lenValueType);
|
|
1083
1077
|
value.len += result.len;
|
|
1084
1078
|
value.value = result.value;
|
|
1085
1079
|
break;
|
|
1086
|
-
case baEnum.
|
|
1080
|
+
case baEnum.ApplicationTag.DATE:
|
|
1087
1081
|
result = decodeDateSafe(buffer, offset, lenValueType);
|
|
1088
1082
|
value.len += result.len;
|
|
1089
1083
|
value.value = result.value;
|
|
1090
1084
|
break;
|
|
1091
|
-
case baEnum.
|
|
1085
|
+
case baEnum.ApplicationTag.TIME:
|
|
1092
1086
|
result = decodeBacnetTimeSafe(buffer, offset, lenValueType);
|
|
1093
1087
|
value.len += result.len;
|
|
1094
1088
|
value.value = result.value;
|
|
1095
1089
|
break;
|
|
1096
|
-
case baEnum.
|
|
1090
|
+
case baEnum.ApplicationTag.OBJECTIDENTIFIER:
|
|
1097
1091
|
result = decodeObjectIdSafe(buffer, offset, lenValueType);
|
|
1098
1092
|
value.len += result.len;
|
|
1099
1093
|
value.value = {type: result.objectType, instance: result.instance};
|
|
@@ -1104,115 +1098,115 @@ var bacappDecodeData = function(buffer, offset, maxLength, tagDataType, lenValue
|
|
|
1104
1098
|
return value;
|
|
1105
1099
|
};
|
|
1106
1100
|
|
|
1107
|
-
|
|
1108
|
-
|
|
1101
|
+
const bacappContextTagType = (property, tagNumber) => {
|
|
1102
|
+
let tag = 0;
|
|
1109
1103
|
switch (property) {
|
|
1110
|
-
case baEnum.
|
|
1111
|
-
case baEnum.
|
|
1112
|
-
case baEnum.
|
|
1104
|
+
case baEnum.PropertyIdentifier.ACTUAL_SHED_LEVEL:
|
|
1105
|
+
case baEnum.PropertyIdentifier.REQUESTED_SHED_LEVEL:
|
|
1106
|
+
case baEnum.PropertyIdentifier.EXPECTED_SHED_LEVEL:
|
|
1113
1107
|
switch (tagNumber) {
|
|
1114
1108
|
case 0:
|
|
1115
1109
|
case 1:
|
|
1116
|
-
tag = baEnum.
|
|
1110
|
+
tag = baEnum.ApplicationTag.UNSIGNED_INTEGER;
|
|
1117
1111
|
break;
|
|
1118
1112
|
case 2:
|
|
1119
|
-
tag = baEnum.
|
|
1113
|
+
tag = baEnum.ApplicationTag.REAL;
|
|
1120
1114
|
break;
|
|
1121
1115
|
default:
|
|
1122
1116
|
break;
|
|
1123
1117
|
}
|
|
1124
1118
|
break;
|
|
1125
|
-
case baEnum.
|
|
1119
|
+
case baEnum.PropertyIdentifier.ACTION:
|
|
1126
1120
|
switch (tagNumber) {
|
|
1127
1121
|
case 0:
|
|
1128
1122
|
case 1:
|
|
1129
|
-
tag = baEnum.
|
|
1123
|
+
tag = baEnum.ApplicationTag.OBJECTIDENTIFIER;
|
|
1130
1124
|
break;
|
|
1131
1125
|
case 2:
|
|
1132
|
-
tag = baEnum.
|
|
1126
|
+
tag = baEnum.ApplicationTag.ENUMERATED;
|
|
1133
1127
|
break;
|
|
1134
1128
|
case 3:
|
|
1135
1129
|
case 5:
|
|
1136
1130
|
case 6:
|
|
1137
|
-
tag = baEnum.
|
|
1131
|
+
tag = baEnum.ApplicationTag.UNSIGNED_INTEGER;
|
|
1138
1132
|
break;
|
|
1139
1133
|
case 7:
|
|
1140
1134
|
case 8:
|
|
1141
|
-
tag = baEnum.
|
|
1135
|
+
tag = baEnum.ApplicationTag.BOOLEAN;
|
|
1142
1136
|
break;
|
|
1143
1137
|
default:
|
|
1144
1138
|
break;
|
|
1145
1139
|
}
|
|
1146
1140
|
break;
|
|
1147
|
-
case baEnum.
|
|
1141
|
+
case baEnum.PropertyIdentifier.LIST_OF_GROUP_MEMBERS:
|
|
1148
1142
|
switch (tagNumber) {
|
|
1149
1143
|
case 0:
|
|
1150
|
-
tag = baEnum.
|
|
1144
|
+
tag = baEnum.ApplicationTag.OBJECTIDENTIFIER;
|
|
1151
1145
|
break;
|
|
1152
1146
|
default:
|
|
1153
1147
|
break;
|
|
1154
1148
|
}
|
|
1155
1149
|
break;
|
|
1156
|
-
case baEnum.
|
|
1150
|
+
case baEnum.PropertyIdentifier.EXCEPTION_SCHEDULE:
|
|
1157
1151
|
switch (tagNumber) {
|
|
1158
1152
|
case 1:
|
|
1159
|
-
tag = baEnum.
|
|
1153
|
+
tag = baEnum.ApplicationTag.OBJECTIDENTIFIER;
|
|
1160
1154
|
break;
|
|
1161
1155
|
case 3:
|
|
1162
|
-
tag = baEnum.
|
|
1156
|
+
tag = baEnum.ApplicationTag.UNSIGNED_INTEGER;
|
|
1163
1157
|
break;
|
|
1164
1158
|
default:
|
|
1165
1159
|
break;
|
|
1166
1160
|
}
|
|
1167
1161
|
break;
|
|
1168
|
-
case baEnum.
|
|
1162
|
+
case baEnum.PropertyIdentifier.LOG_DEVICE_OBJECT_PROPERTY:
|
|
1169
1163
|
switch (tagNumber) {
|
|
1170
1164
|
case 0:
|
|
1171
1165
|
case 3:
|
|
1172
|
-
tag = baEnum.
|
|
1166
|
+
tag = baEnum.ApplicationTag.OBJECTIDENTIFIER;
|
|
1173
1167
|
break;
|
|
1174
1168
|
case 1:
|
|
1175
|
-
tag = baEnum.
|
|
1169
|
+
tag = baEnum.ApplicationTag.ENUMERATED;
|
|
1176
1170
|
break;
|
|
1177
1171
|
case 2:
|
|
1178
|
-
tag = baEnum.
|
|
1172
|
+
tag = baEnum.ApplicationTag.UNSIGNED_INTEGER;
|
|
1179
1173
|
break;
|
|
1180
1174
|
default:
|
|
1181
1175
|
break;
|
|
1182
1176
|
}
|
|
1183
1177
|
break;
|
|
1184
|
-
case baEnum.
|
|
1178
|
+
case baEnum.PropertyIdentifier.SUBORDINATE_LIST:
|
|
1185
1179
|
switch (tagNumber) {
|
|
1186
1180
|
case 0:
|
|
1187
1181
|
case 1:
|
|
1188
|
-
tag = baEnum.
|
|
1182
|
+
tag = baEnum.ApplicationTag.OBJECTIDENTIFIER;
|
|
1189
1183
|
break;
|
|
1190
1184
|
default:
|
|
1191
1185
|
break;
|
|
1192
1186
|
}
|
|
1193
1187
|
break;
|
|
1194
|
-
case baEnum.
|
|
1188
|
+
case baEnum.PropertyIdentifier.RECIPIENT_LIST:
|
|
1195
1189
|
switch (tagNumber) {
|
|
1196
1190
|
case 0:
|
|
1197
|
-
tag = baEnum.
|
|
1191
|
+
tag = baEnum.ApplicationTag.OBJECTIDENTIFIER;
|
|
1198
1192
|
break;
|
|
1199
1193
|
default:
|
|
1200
1194
|
break;
|
|
1201
1195
|
}
|
|
1202
1196
|
break;
|
|
1203
|
-
case baEnum.
|
|
1197
|
+
case baEnum.PropertyIdentifier.ACTIVE_COV_SUBSCRIPTIONS:
|
|
1204
1198
|
switch (tagNumber) {
|
|
1205
1199
|
case 0:
|
|
1206
1200
|
case 1:
|
|
1207
1201
|
break;
|
|
1208
1202
|
case 2:
|
|
1209
|
-
tag = baEnum.
|
|
1203
|
+
tag = baEnum.ApplicationTag.BOOLEAN;
|
|
1210
1204
|
break;
|
|
1211
1205
|
case 3:
|
|
1212
|
-
tag = baEnum.
|
|
1206
|
+
tag = baEnum.ApplicationTag.UNSIGNED_INTEGER;
|
|
1213
1207
|
break;
|
|
1214
1208
|
case 4:
|
|
1215
|
-
tag = baEnum.
|
|
1209
|
+
tag = baEnum.ApplicationTag.REAL;
|
|
1216
1210
|
break;
|
|
1217
1211
|
default:
|
|
1218
1212
|
break;
|
|
@@ -1224,17 +1218,21 @@ var bacappContextTagType = function(property, tagNumber) {
|
|
|
1224
1218
|
return tag;
|
|
1225
1219
|
};
|
|
1226
1220
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
if (!decodeIsContextTag(buffer, offset + len, 0))
|
|
1221
|
+
const decodeDeviceObjPropertyRef = (buffer, offset) => {
|
|
1222
|
+
let len = 0;
|
|
1223
|
+
let arrayIndex = baEnum.ASN1_ARRAY_ALL;
|
|
1224
|
+
if (!decodeIsContextTag(buffer, offset + len, 0)) {
|
|
1225
|
+
return undefined;
|
|
1226
|
+
}
|
|
1231
1227
|
len++;
|
|
1232
|
-
|
|
1228
|
+
let objectId = decodeObjectId(buffer, offset + len);
|
|
1233
1229
|
len += objectId.len;
|
|
1234
|
-
|
|
1230
|
+
let result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1235
1231
|
len += result.len;
|
|
1236
|
-
if (result.tagNumber !== 1)
|
|
1237
|
-
|
|
1232
|
+
if (result.tagNumber !== 1) {
|
|
1233
|
+
return undefined;
|
|
1234
|
+
}
|
|
1235
|
+
let id = decodeEnumerated(buffer, offset + len, result.value);
|
|
1238
1236
|
len += id.len;
|
|
1239
1237
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1240
1238
|
if (result.tagNumber === 2) {
|
|
@@ -1250,7 +1248,7 @@ var decodeDeviceObjPropertyRef = function(buffer, offset) {
|
|
|
1250
1248
|
}
|
|
1251
1249
|
}
|
|
1252
1250
|
return {
|
|
1253
|
-
len
|
|
1251
|
+
len,
|
|
1254
1252
|
value: {
|
|
1255
1253
|
objectId: objectId,
|
|
1256
1254
|
id: id
|
|
@@ -1258,36 +1256,48 @@ var decodeDeviceObjPropertyRef = function(buffer, offset) {
|
|
|
1258
1256
|
};
|
|
1259
1257
|
};
|
|
1260
1258
|
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
if (!decodeIsContextTag(buffer, offset + len, 0))
|
|
1259
|
+
const decodeReadAccessSpecification = module.exports.decodeReadAccessSpecification = (buffer, offset, apduLen) => {
|
|
1260
|
+
let len = 0;
|
|
1261
|
+
let value = {};
|
|
1262
|
+
if (!decodeIsContextTag(buffer, offset + len, 0)) {
|
|
1263
|
+
return undefined;
|
|
1264
|
+
}
|
|
1265
1265
|
len++;
|
|
1266
|
-
|
|
1266
|
+
let decodedValue = decodeObjectId(buffer, offset + len);
|
|
1267
1267
|
value.objectId = {
|
|
1268
1268
|
type: decodedValue.objectType,
|
|
1269
1269
|
instance: decodedValue.instance
|
|
1270
1270
|
};
|
|
1271
1271
|
len += decodedValue.len;
|
|
1272
|
-
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1))
|
|
1272
|
+
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1)) {
|
|
1273
|
+
return undefined;
|
|
1274
|
+
}
|
|
1273
1275
|
len++;
|
|
1274
|
-
|
|
1276
|
+
const propertyIdAndArrayIndex = [];
|
|
1275
1277
|
while ((apduLen - len) > 1 && !decodeIsClosingTagNumber(buffer, offset + len, 1)) {
|
|
1276
|
-
|
|
1277
|
-
if (!isContextSpecific(buffer[offset + len]))
|
|
1278
|
-
|
|
1278
|
+
let propertyRef = {};
|
|
1279
|
+
if (!isContextSpecific(buffer[offset + len])) {
|
|
1280
|
+
return undefined;
|
|
1281
|
+
}
|
|
1282
|
+
let result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1279
1283
|
len += result.len;
|
|
1280
|
-
if (result.tagNumber !== 0)
|
|
1281
|
-
|
|
1284
|
+
if (result.tagNumber !== 0) {
|
|
1285
|
+
return undefined;
|
|
1286
|
+
}
|
|
1287
|
+
if ((len + result.value) >= apduLen) {
|
|
1288
|
+
return undefined;
|
|
1289
|
+
}
|
|
1282
1290
|
decodedValue = decodeEnumerated(buffer, offset + len, result.value);
|
|
1283
1291
|
propertyRef.id = decodedValue.value;
|
|
1284
1292
|
len += decodedValue.len;
|
|
1285
|
-
propertyRef.index =
|
|
1293
|
+
propertyRef.index = baEnum.ASN1_ARRAY_ALL;
|
|
1286
1294
|
if (isContextSpecific(buffer[offset + len]) && !isClosingTag(buffer[offset + len])) {
|
|
1287
|
-
|
|
1295
|
+
const tmp = decodeTagNumberAndValue(buffer, offset + len);
|
|
1288
1296
|
if (tmp.tagNumber === 1) {
|
|
1289
1297
|
len += tmp.len;
|
|
1290
|
-
if ((len + tmp.value) >= apduLen)
|
|
1298
|
+
if ((len + tmp.value) >= apduLen) {
|
|
1299
|
+
return undefined;
|
|
1300
|
+
}
|
|
1291
1301
|
decodedValue = decodeUnsigned(buffer, offset + len, tmp.value);
|
|
1292
1302
|
propertyRef.index = decodedValue.value;
|
|
1293
1303
|
len += decodedValue.len;
|
|
@@ -1295,56 +1305,80 @@ var decodeReadAccessSpecification = module.exports.decodeReadAccessSpecification
|
|
|
1295
1305
|
}
|
|
1296
1306
|
propertyIdAndArrayIndex.push(propertyRef);
|
|
1297
1307
|
}
|
|
1298
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 1))
|
|
1308
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 1)) {
|
|
1309
|
+
return undefined;
|
|
1310
|
+
}
|
|
1299
1311
|
len++;
|
|
1300
1312
|
value.properties = propertyIdAndArrayIndex;
|
|
1301
1313
|
return {
|
|
1302
|
-
len
|
|
1303
|
-
value
|
|
1314
|
+
len,
|
|
1315
|
+
value
|
|
1304
1316
|
};
|
|
1305
1317
|
};
|
|
1306
1318
|
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1319
|
+
const decodeCovSubscription = (buffer, offset, apduLen) => {
|
|
1320
|
+
let len = 0;
|
|
1321
|
+
let value = {};
|
|
1322
|
+
let result;
|
|
1323
|
+
let decodedValue;
|
|
1312
1324
|
value.recipient = {};
|
|
1313
|
-
if (!decodeIsOpeningTagNumber(buffer, offset + len, 0))
|
|
1325
|
+
if (!decodeIsOpeningTagNumber(buffer, offset + len, 0)) {
|
|
1326
|
+
return undefined;
|
|
1327
|
+
}
|
|
1314
1328
|
len++;
|
|
1315
|
-
if (!decodeIsOpeningTagNumber(buffer, offset + len, 0))
|
|
1329
|
+
if (!decodeIsOpeningTagNumber(buffer, offset + len, 0)) {
|
|
1330
|
+
return undefined;
|
|
1331
|
+
}
|
|
1316
1332
|
len++;
|
|
1317
|
-
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1))
|
|
1333
|
+
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1)) {
|
|
1334
|
+
return undefined;
|
|
1335
|
+
}
|
|
1318
1336
|
len++;
|
|
1319
1337
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1320
1338
|
len += result.len;
|
|
1321
|
-
if (result.tagNumber !== baEnum.
|
|
1339
|
+
if (result.tagNumber !== baEnum.ApplicationTag.UNSIGNED_INTEGER) {
|
|
1340
|
+
return undefined;
|
|
1341
|
+
}
|
|
1322
1342
|
decodedValue = decodeUnsigned(buffer, offset + len, result.value);
|
|
1323
1343
|
len += decodedValue.len;
|
|
1324
1344
|
value.recipient.net = decodedValue.value;
|
|
1325
1345
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1326
1346
|
len += result.len;
|
|
1327
|
-
if (result.tagNumber !== baEnum.
|
|
1347
|
+
if (result.tagNumber !== baEnum.ApplicationTag.OCTET_STRING) {
|
|
1348
|
+
return undefined;
|
|
1349
|
+
}
|
|
1328
1350
|
decodedValue = decodeOctetString(buffer, offset + len, apduLen, 0, result.value);
|
|
1329
1351
|
len += decodedValue.len;
|
|
1330
1352
|
value.recipient.adr = decodedValue.value;
|
|
1331
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 1))
|
|
1353
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 1)) {
|
|
1354
|
+
return undefined;
|
|
1355
|
+
}
|
|
1332
1356
|
len++;
|
|
1333
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 0))
|
|
1357
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 0)) {
|
|
1358
|
+
return undefined;
|
|
1359
|
+
}
|
|
1334
1360
|
len++;
|
|
1335
1361
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1336
1362
|
len += result.len;
|
|
1337
|
-
if (result.tagNumber !== 1)
|
|
1363
|
+
if (result.tagNumber !== 1) {
|
|
1364
|
+
return undefined;
|
|
1365
|
+
}
|
|
1338
1366
|
decodedValue = decodeUnsigned(buffer, offset + len, result.value);
|
|
1339
1367
|
len += decodedValue.len;
|
|
1340
1368
|
value.subscriptionProcessId = decodedValue.value;
|
|
1341
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 0))
|
|
1369
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 0)) {
|
|
1370
|
+
return undefined;
|
|
1371
|
+
}
|
|
1342
1372
|
len++;
|
|
1343
|
-
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1))
|
|
1373
|
+
if (!decodeIsOpeningTagNumber(buffer, offset + len, 1)) {
|
|
1374
|
+
return undefined;
|
|
1375
|
+
}
|
|
1344
1376
|
len++;
|
|
1345
1377
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1346
1378
|
len += result.len;
|
|
1347
|
-
if (result.tagNumber !== 0)
|
|
1379
|
+
if (result.tagNumber !== 0) {
|
|
1380
|
+
return undefined;
|
|
1381
|
+
}
|
|
1348
1382
|
decodedValue = decodeObjectId(buffer, offset + len);
|
|
1349
1383
|
len += decodedValue.len;
|
|
1350
1384
|
value.monitoredObjectId = {
|
|
@@ -1353,7 +1387,9 @@ var decodeCovSubscription = function(buffer, offset, apduLen) {
|
|
|
1353
1387
|
};
|
|
1354
1388
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1355
1389
|
len += result.len;
|
|
1356
|
-
if (result.tagNumber !== 1)
|
|
1390
|
+
if (result.tagNumber !== 1) {
|
|
1391
|
+
return undefined;
|
|
1392
|
+
}
|
|
1357
1393
|
decodedValue = decodeEnumerated(buffer, offset + len, result.value);
|
|
1358
1394
|
len += decodedValue.len;
|
|
1359
1395
|
value.monitoredProperty = {};
|
|
@@ -1365,36 +1401,44 @@ var decodeCovSubscription = function(buffer, offset, apduLen) {
|
|
|
1365
1401
|
len += decodedValue.len;
|
|
1366
1402
|
value.monitoredProperty.index = decodedValue.value;
|
|
1367
1403
|
} else {
|
|
1368
|
-
value.monitoredProperty.index =
|
|
1404
|
+
value.monitoredProperty.index = baEnum.ASN1_ARRAY_ALL;
|
|
1405
|
+
}
|
|
1406
|
+
if (!decodeIsClosingTagNumber(buffer, offset + len, 1)) {
|
|
1407
|
+
return undefined;
|
|
1369
1408
|
}
|
|
1370
|
-
if (!decodeIsClosingTagNumber(buffer, offset + len, 1)) return;
|
|
1371
1409
|
len++;
|
|
1372
1410
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1373
1411
|
len += result.len;
|
|
1374
|
-
if (result.tagNumber !== 2)
|
|
1375
|
-
|
|
1412
|
+
if (result.tagNumber !== 2) {
|
|
1413
|
+
return undefined;
|
|
1414
|
+
}
|
|
1415
|
+
value.issueConfirmedNotifications = buffer[offset + len] > 0;
|
|
1376
1416
|
len++;
|
|
1377
1417
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1378
1418
|
len += result.len;
|
|
1379
|
-
if (result.tagNumber !== 3)
|
|
1419
|
+
if (result.tagNumber !== 3) {
|
|
1420
|
+
return undefined;
|
|
1421
|
+
}
|
|
1380
1422
|
decodedValue = decodeUnsigned(buffer, offset + len, result.value);
|
|
1381
1423
|
len += decodedValue.len;
|
|
1382
1424
|
value.timeRemaining = decodedValue.value;
|
|
1383
1425
|
if (len < apduLen && !isClosingTag(buffer[offset + len])) {
|
|
1384
1426
|
result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1385
1427
|
len += result.len;
|
|
1386
|
-
if (result.tagNumber !== 4)
|
|
1428
|
+
if (result.tagNumber !== 4) {
|
|
1429
|
+
return undefined;
|
|
1430
|
+
}
|
|
1387
1431
|
decodedValue = decodeReal(buffer, offset + len);
|
|
1388
1432
|
len += decodedValue.len;
|
|
1389
1433
|
value.covIncrement = decodedValue.value;
|
|
1390
1434
|
}
|
|
1391
1435
|
return {
|
|
1392
|
-
len
|
|
1393
|
-
value
|
|
1436
|
+
len,
|
|
1437
|
+
value
|
|
1394
1438
|
};
|
|
1395
1439
|
};
|
|
1396
1440
|
|
|
1397
|
-
|
|
1441
|
+
const decodeCalendarDate = (buffer, offset) => {
|
|
1398
1442
|
return {
|
|
1399
1443
|
len: 4,
|
|
1400
1444
|
year: buffer[offset],
|
|
@@ -1404,20 +1448,20 @@ var decodeCalendarDate = function(buffer, offset) {
|
|
|
1404
1448
|
};
|
|
1405
1449
|
};
|
|
1406
1450
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1451
|
+
const decodeCalendarDateRange = (buffer, offset) => {
|
|
1452
|
+
let len = 1;
|
|
1453
|
+
const startDate = decodeDate(buffer, offset + len);
|
|
1410
1454
|
len += startDate.len + 1;
|
|
1411
|
-
|
|
1455
|
+
const endDate = decodeDate(buffer, offset + len);
|
|
1412
1456
|
len += endDate.len + 1;
|
|
1413
1457
|
return {
|
|
1414
|
-
len
|
|
1415
|
-
startDate
|
|
1416
|
-
endDate
|
|
1458
|
+
len,
|
|
1459
|
+
startDate,
|
|
1460
|
+
endDate
|
|
1417
1461
|
};
|
|
1418
1462
|
};
|
|
1419
1463
|
|
|
1420
|
-
|
|
1464
|
+
const decodeCalendarWeekDay = (buffer, offset) => {
|
|
1421
1465
|
return {
|
|
1422
1466
|
len: 3,
|
|
1423
1467
|
month: buffer[offset],
|
|
@@ -1426,12 +1470,12 @@ var decodeCalendarWeekDay = function(buffer, offset) {
|
|
|
1426
1470
|
};
|
|
1427
1471
|
};
|
|
1428
1472
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1473
|
+
const decodeCalendar = (buffer, offset, apduLen) => {
|
|
1474
|
+
let len = 0;
|
|
1475
|
+
const entries = [];
|
|
1476
|
+
let decodedValue;
|
|
1433
1477
|
while (len < apduLen) {
|
|
1434
|
-
|
|
1478
|
+
const result = decodeTagNumber(buffer, offset + len);
|
|
1435
1479
|
len += result.len;
|
|
1436
1480
|
switch (result.tagNumber) {
|
|
1437
1481
|
case 0:
|
|
@@ -1458,100 +1502,116 @@ var decodeCalendar = function(buffer, offset, apduLen) {
|
|
|
1458
1502
|
}
|
|
1459
1503
|
};
|
|
1460
1504
|
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1505
|
+
const bacappDecodeContextApplicationData = (buffer, offset, maxOffset, objectType, propertyId) => {
|
|
1506
|
+
let len = 0;
|
|
1507
|
+
let result;
|
|
1464
1508
|
if (isContextSpecific(buffer[offset])) {
|
|
1465
|
-
if (propertyId === baEnum.
|
|
1509
|
+
if (propertyId === baEnum.PropertyIdentifier.LIST_OF_GROUP_MEMBERS) {
|
|
1466
1510
|
result = decodeReadAccessSpecification(buffer, offset, maxOffset);
|
|
1467
|
-
if (!result)
|
|
1511
|
+
if (!result) {
|
|
1512
|
+
return undefined;
|
|
1513
|
+
}
|
|
1468
1514
|
return {
|
|
1469
|
-
type: baEnum.
|
|
1515
|
+
type: baEnum.ApplicationTag.READ_ACCESS_SPECIFICATION,
|
|
1470
1516
|
value: result.value,
|
|
1471
1517
|
len: result.len
|
|
1472
1518
|
};
|
|
1473
|
-
} else if (propertyId === baEnum.
|
|
1519
|
+
} else if (propertyId === baEnum.PropertyIdentifier.ACTIVE_COV_SUBSCRIPTIONS) {
|
|
1474
1520
|
result = decodeCovSubscription(buffer, offset, maxOffset);
|
|
1475
|
-
if (!result)
|
|
1521
|
+
if (!result) {
|
|
1522
|
+
return undefined;
|
|
1523
|
+
}
|
|
1476
1524
|
return {
|
|
1477
|
-
type: baEnum.
|
|
1525
|
+
type: baEnum.ApplicationTag.COV_SUBSCRIPTION,
|
|
1478
1526
|
value: result.value,
|
|
1479
1527
|
len: result.len
|
|
1480
1528
|
};
|
|
1481
|
-
} else if (objectType === baEnum.
|
|
1529
|
+
} else if (objectType === baEnum.ObjectType.GROUP && propertyId === baEnum.PropertyIdentifier.PRESENT_VALUE) {
|
|
1482
1530
|
result = decodeReadAccessResult(buffer, offset, maxOffset);
|
|
1483
|
-
if (!result)
|
|
1531
|
+
if (!result) {
|
|
1532
|
+
return undefined;
|
|
1533
|
+
}
|
|
1484
1534
|
return {
|
|
1485
|
-
type: baEnum.
|
|
1535
|
+
type: baEnum.ApplicationTag.READ_ACCESS_RESULT,
|
|
1486
1536
|
value: result.value,
|
|
1487
1537
|
len: result.len
|
|
1488
1538
|
};
|
|
1489
|
-
} else if (propertyId === baEnum.
|
|
1539
|
+
} else if (propertyId === baEnum.PropertyIdentifier.LIST_OF_OBJECT_PROPERTY_REFERENCES || propertyId === baEnum.PropertyIdentifier.LOG_DEVICE_OBJECT_PROPERTY || propertyId === baEnum.PropertyIdentifier.OBJECT_PROPERTY_REFERENCE) {
|
|
1490
1540
|
result = decodeDeviceObjPropertyRef(buffer, offset, maxOffset);
|
|
1491
|
-
if (!result)
|
|
1541
|
+
if (!result) {
|
|
1542
|
+
return undefined;
|
|
1543
|
+
}
|
|
1492
1544
|
return {
|
|
1493
|
-
type: baEnum.
|
|
1545
|
+
type: baEnum.ApplicationTag.OBJECT_PROPERTY_REFERENCE,
|
|
1494
1546
|
value: result.value,
|
|
1495
1547
|
len: result.len
|
|
1496
1548
|
};
|
|
1497
|
-
} else if (propertyId === baEnum.
|
|
1549
|
+
} else if (propertyId === baEnum.PropertyIdentifier.DATE_LIST) {
|
|
1498
1550
|
result = decodeCalendar(buffer, offset, maxOffset);
|
|
1499
|
-
if (!result)
|
|
1551
|
+
if (!result) {
|
|
1552
|
+
return undefined;
|
|
1553
|
+
}
|
|
1500
1554
|
return {
|
|
1501
|
-
type: baEnum.
|
|
1555
|
+
type: baEnum.ApplicationTag.CONTEXT_SPECIFIC_DECODED,
|
|
1502
1556
|
value: result.value,
|
|
1503
1557
|
len: result.len
|
|
1504
1558
|
};
|
|
1505
|
-
} else if (propertyId === baEnum.
|
|
1506
|
-
|
|
1507
|
-
|
|
1559
|
+
} else if (propertyId === baEnum.PropertyIdentifier.EVENT_TIME_STAMPS) {
|
|
1560
|
+
let subEvtResult;
|
|
1561
|
+
let evtResult = decodeTagNumberAndValue(buffer, offset + len);
|
|
1508
1562
|
len += 1;
|
|
1509
1563
|
if (evtResult.tagNumber === 0) {
|
|
1510
1564
|
subEvtResult = decodeBacnetTime(buffer, offset + 1);
|
|
1511
1565
|
return {
|
|
1512
|
-
type: baEnum.
|
|
1566
|
+
type: baEnum.ApplicationTag.TIMESTAMP,
|
|
1513
1567
|
value: subEvtResult.value,
|
|
1514
1568
|
len: subEvtResult.len + 1
|
|
1515
1569
|
};
|
|
1516
1570
|
} else if (evtResult.tagNumber === 1) {
|
|
1517
1571
|
subEvtResult = decodeUnsigned(buffer, offset + len, evtResult.value);
|
|
1518
1572
|
return {
|
|
1519
|
-
type: baEnum.
|
|
1573
|
+
type: baEnum.ApplicationTag.UNSIGNED_INTEGER,
|
|
1520
1574
|
value: subEvtResult.value,
|
|
1521
1575
|
len: subEvtResult.len + 1
|
|
1522
1576
|
};
|
|
1523
1577
|
} else if (evtResult.tagNumber === 2) {
|
|
1524
1578
|
subEvtResult = decodeBacnetDatetime(buffer, offset + len);
|
|
1525
1579
|
return {
|
|
1526
|
-
type: baEnum.
|
|
1580
|
+
type: baEnum.ApplicationTag.TIMESTAMP,
|
|
1527
1581
|
value: subEvtResult.value,
|
|
1528
1582
|
len: subEvtResult.len + 2
|
|
1529
1583
|
};
|
|
1530
1584
|
} else {
|
|
1531
|
-
return;
|
|
1585
|
+
return undefined;
|
|
1532
1586
|
}
|
|
1533
1587
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1588
|
+
const list = [];
|
|
1589
|
+
let tagResult = decodeTagNumberAndValue(buffer, offset + len);
|
|
1590
|
+
let multipleValues = isOpeningTag(buffer[offset + len]);
|
|
1537
1591
|
while (((len + offset) <= maxOffset) && !isClosingTag(buffer[offset + len])) {
|
|
1538
|
-
|
|
1539
|
-
if (!subResult)
|
|
1592
|
+
let subResult = decodeTagNumberAndValue(buffer, offset + len);
|
|
1593
|
+
if (!subResult) {
|
|
1594
|
+
return undefined;
|
|
1595
|
+
}
|
|
1540
1596
|
if (subResult.value === 0) {
|
|
1541
1597
|
len += subResult.len;
|
|
1542
|
-
result = bacappDecodeApplicationData(buffer, offset + len, maxOffset, baEnum.
|
|
1543
|
-
if (!result)
|
|
1598
|
+
result = bacappDecodeApplicationData(buffer, offset + len, maxOffset, baEnum.ASN1_MAX_OBJECT_TYPE, baEnum.ASN1_MAX_PROPERTY_ID);
|
|
1599
|
+
if (!result) {
|
|
1600
|
+
return undefined;
|
|
1601
|
+
}
|
|
1544
1602
|
list.push(result);
|
|
1545
1603
|
len += result.len;
|
|
1546
1604
|
} else {
|
|
1547
|
-
|
|
1548
|
-
if (overrideTagNumber !== baEnum.
|
|
1605
|
+
const overrideTagNumber = bacappContextTagType(propertyId, subResult.tagNumber);
|
|
1606
|
+
if (overrideTagNumber !== baEnum.ASN1_MAX_APPLICATION_TAG) {
|
|
1549
1607
|
subResult.tagNumber = overrideTagNumber;
|
|
1550
1608
|
}
|
|
1551
|
-
|
|
1552
|
-
if (!bacappResult)
|
|
1609
|
+
let bacappResult = bacappDecodeData(buffer, offset + len + subResult.len, maxOffset, subResult.tagNumber, subResult.value);
|
|
1610
|
+
if (!bacappResult) {
|
|
1611
|
+
return undefined;
|
|
1612
|
+
}
|
|
1553
1613
|
if (bacappResult.len === subResult.value) {
|
|
1554
|
-
|
|
1614
|
+
let resObj = {
|
|
1555
1615
|
value: bacappResult.value,
|
|
1556
1616
|
type: bacappResult.type
|
|
1557
1617
|
};
|
|
@@ -1562,152 +1622,110 @@ var bacappDecodeContextApplicationData = function(buffer, offset, maxOffset, obj
|
|
|
1562
1622
|
} else {
|
|
1563
1623
|
list.push({
|
|
1564
1624
|
value: buffer.slice(offset + len + subResult.len, offset + len + subResult.len + subResult.value),
|
|
1565
|
-
type: baEnum.
|
|
1625
|
+
type: baEnum.ApplicationTag.CONTEXT_SPECIFIC_ENCODED
|
|
1566
1626
|
});
|
|
1567
1627
|
len += subResult.len + subResult.value;
|
|
1568
1628
|
}
|
|
1569
1629
|
}
|
|
1570
1630
|
if (multipleValues === false) {
|
|
1571
1631
|
return {
|
|
1572
|
-
len
|
|
1632
|
+
len,
|
|
1573
1633
|
value: list[0],
|
|
1574
|
-
type: baEnum.
|
|
1634
|
+
type: baEnum.ApplicationTag.CONTEXT_SPECIFIC_DECODED
|
|
1575
1635
|
};
|
|
1576
1636
|
}
|
|
1577
1637
|
}
|
|
1578
|
-
if ((len + offset) > maxOffset)
|
|
1638
|
+
if ((len + offset) > maxOffset) {
|
|
1639
|
+
return undefined;
|
|
1640
|
+
}
|
|
1579
1641
|
if (decodeIsClosingTagNumber(buffer, offset + len, tagResult.tagNumber)) {
|
|
1580
1642
|
len++;
|
|
1581
1643
|
}
|
|
1582
1644
|
return {
|
|
1583
|
-
len
|
|
1645
|
+
len,
|
|
1584
1646
|
value: list,
|
|
1585
|
-
type: baEnum.
|
|
1647
|
+
type: baEnum.ApplicationTag.CONTEXT_SPECIFIC_DECODED
|
|
1586
1648
|
};
|
|
1587
|
-
} else {
|
|
1588
|
-
return;
|
|
1589
1649
|
}
|
|
1650
|
+
return undefined;
|
|
1590
1651
|
};
|
|
1591
1652
|
|
|
1592
|
-
|
|
1653
|
+
const bacappEncodeTimestamp = module.exports.bacappEncodeTimestamp = (buffer, value) => {
|
|
1593
1654
|
switch (value.type) {
|
|
1594
|
-
case baEnum.
|
|
1655
|
+
case baEnum.TimeStamp.TIME:
|
|
1595
1656
|
encodeContextTime(buffer, 0, value.value);
|
|
1596
1657
|
break;
|
|
1597
|
-
case baEnum.
|
|
1658
|
+
case baEnum.TimeStamp.SEQUENCE_NUMBER:
|
|
1598
1659
|
encodeContextUnsigned(buffer, 1, value.value);
|
|
1599
1660
|
break;
|
|
1600
|
-
case baEnum.
|
|
1661
|
+
case baEnum.TimeStamp.DATETIME:
|
|
1601
1662
|
bacappEncodeContextDatetime(buffer, 2, value.value);
|
|
1602
1663
|
break;
|
|
1603
|
-
case baEnum.TimestampTags.TIME_STAMP_NONE:
|
|
1604
|
-
break;
|
|
1605
1664
|
default:
|
|
1606
1665
|
throw new Error('NOT_IMPLEMENTED');
|
|
1607
1666
|
}
|
|
1608
1667
|
};
|
|
1609
1668
|
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
encodeClosingTag(buffer, tagNumber);
|
|
1615
|
-
}
|
|
1669
|
+
const bacappEncodeContextTimestamp = module.exports.bacappEncodeContextTimestamp = (buffer, tagNumber, value) => {
|
|
1670
|
+
encodeOpeningTag(buffer, tagNumber);
|
|
1671
|
+
bacappEncodeTimestamp(buffer, value);
|
|
1672
|
+
encodeClosingTag(buffer, tagNumber);
|
|
1616
1673
|
};
|
|
1617
1674
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
if (!decodeIsContextTag(buffer, offset + len, tagNumber))
|
|
1621
|
-
|
|
1675
|
+
const decodeContextCharacterString = module.exports.decodeContextCharacterString = (buffer, offset, maxLength, tagNumber) => {
|
|
1676
|
+
let len = 0;
|
|
1677
|
+
if (!decodeIsContextTag(buffer, offset + len, tagNumber)) {
|
|
1678
|
+
return undefined;
|
|
1679
|
+
}
|
|
1680
|
+
const result = decodeTagNumberAndValue(buffer, offset + len);
|
|
1622
1681
|
len += result.len;
|
|
1623
|
-
|
|
1624
|
-
if (!decodedValue)
|
|
1682
|
+
const decodedValue = multiCharsetCharacterstringDecode(buffer, offset + 1 + len, maxLength, buffer[offset + len], result.value - 1);
|
|
1683
|
+
if (!decodedValue) {
|
|
1684
|
+
return undefined;
|
|
1685
|
+
}
|
|
1625
1686
|
len += result.value;
|
|
1626
1687
|
return {
|
|
1627
|
-
len
|
|
1688
|
+
len,
|
|
1628
1689
|
value: decodedValue.value,
|
|
1629
1690
|
encoding: decodedValue.encoding
|
|
1630
1691
|
};
|
|
1631
1692
|
};
|
|
1632
1693
|
|
|
1633
|
-
|
|
1634
|
-
|
|
1694
|
+
const decodeIsContextTagWithLength = (buffer, offset, tagNumber) => {
|
|
1695
|
+
const result = decodeTagNumber(buffer, offset);
|
|
1635
1696
|
return {
|
|
1636
1697
|
len: result.len,
|
|
1637
1698
|
value: isContextSpecific(buffer[offset]) && (result.tagNumber === tagNumber)
|
|
1638
1699
|
};
|
|
1639
1700
|
};
|
|
1640
1701
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
if (!result.value)
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
value: decodedValue.value
|
|
1648
|
-
};
|
|
1649
|
-
};
|
|
1650
|
-
|
|
1651
|
-
var decodeContextDate = function(buffer, offset, tagNumber) {
|
|
1652
|
-
var result = decodeIsContextTagWithLength(buffer, offset, tagNumber);
|
|
1653
|
-
if (!result.value) return;
|
|
1654
|
-
var decodedValue = decodeDate(buffer, offset + result.len);
|
|
1655
|
-
return {
|
|
1656
|
-
len: result.len + decodedValue.len,
|
|
1657
|
-
value: decodedValue.value
|
|
1658
|
-
};
|
|
1659
|
-
};
|
|
1660
|
-
|
|
1661
|
-
module.exports.decodeContextObjectId = function(buffer, offset, tagNumber) {
|
|
1662
|
-
var result = decodeIsContextTagWithLength(buffer, offset, tagNumber);
|
|
1663
|
-
if (!result.value) return;
|
|
1664
|
-
var decodedValue = decodeObjectId(buffer, offset + result.len);
|
|
1702
|
+
module.exports.decodeContextObjectId = (buffer, offset, tagNumber) => {
|
|
1703
|
+
const result = decodeIsContextTagWithLength(buffer, offset, tagNumber);
|
|
1704
|
+
if (!result.value) {
|
|
1705
|
+
return undefined;
|
|
1706
|
+
}
|
|
1707
|
+
const decodedValue = decodeObjectId(buffer, offset + result.len);
|
|
1665
1708
|
decodedValue.len = decodedValue.len + result.len;
|
|
1666
1709
|
return decodedValue;
|
|
1667
1710
|
};
|
|
1668
1711
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
var decodedValue;
|
|
1672
|
-
if (isContextSpecific(buffer[offset])) {
|
|
1673
|
-
var result = decodeTagNumberAndValue(buffer, offset);
|
|
1674
|
-
len = result.len;
|
|
1675
|
-
if (len > 0 && (len <= maxApduLen) && !decodeIsClosingTagNumber(buffer, offset + len, result.tagNumber)) {
|
|
1676
|
-
if (propertyTag < baEnum.ApplicationTags.MAX_BACNET_APPLICATION_TAG) {
|
|
1677
|
-
decodedValue = bacappDecodeData(buffer, offset + len, maxApduLen, propertyTag, result.value);
|
|
1678
|
-
len += decodedValue.len;
|
|
1679
|
-
} else if (result.value > 0) {
|
|
1680
|
-
len += result.value;
|
|
1681
|
-
} else {
|
|
1682
|
-
return;
|
|
1683
|
-
}
|
|
1684
|
-
} else if (len === 1) {
|
|
1685
|
-
len = 0;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
return {
|
|
1689
|
-
len: len,
|
|
1690
|
-
value: decodedValue ? decodedValue.value : decodedValue
|
|
1691
|
-
};
|
|
1692
|
-
};
|
|
1693
|
-
|
|
1694
|
-
var encodeBacnetCharacterString = function(buffer, value, encoding) {
|
|
1695
|
-
encoding = encoding || baEnum.CharacterStringEncodings.CHARACTER_UTF8;
|
|
1712
|
+
const encodeBacnetCharacterString = (buffer, value, encoding) => {
|
|
1713
|
+
encoding = encoding || baEnum.CharacterStringEncoding.UTF_8;
|
|
1696
1714
|
buffer.buffer[buffer.offset++] = encoding;
|
|
1697
|
-
|
|
1715
|
+
const bufEncoded = iconv.encode(value, getEncodingType(encoding));
|
|
1698
1716
|
buffer.offset += bufEncoded.copy(buffer.buffer, buffer.offset);
|
|
1699
1717
|
};
|
|
1700
1718
|
|
|
1701
|
-
|
|
1702
|
-
|
|
1719
|
+
const encodeApplicationCharacterString = module.exports.encodeApplicationCharacterString = (buffer, value, encoding) => {
|
|
1720
|
+
const tmp = getBuffer();
|
|
1703
1721
|
encodeBacnetCharacterString(tmp, value, encoding);
|
|
1704
|
-
encodeTag(buffer, baEnum.
|
|
1722
|
+
encodeTag(buffer, baEnum.ApplicationTag.CHARACTER_STRING, false, tmp.offset);
|
|
1705
1723
|
tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset);
|
|
1706
1724
|
buffer.offset += tmp.offset;
|
|
1707
1725
|
};
|
|
1708
1726
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1727
|
+
const encodeContextCharacterString = module.exports.encodeContextCharacterString = (buffer, tagNumber, value, encoding) => {
|
|
1728
|
+
const tmp = getBuffer();
|
|
1711
1729
|
encodeBacnetCharacterString(tmp, value, encoding);
|
|
1712
1730
|
encodeTag(buffer, tagNumber, true, tmp.offset);
|
|
1713
1731
|
tmp.buffer.copy(buffer.buffer, buffer.offset, 0, tmp.offset);
|