@bitpoolos/edge-bacnet 1.1.7 → 1.2.1

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.
Files changed (123) hide show
  1. package/README.md +2 -2
  2. package/bacnet_client.js +331 -168
  3. package/bacnet_device.js +50 -16
  4. package/bacnet_gateway.html +119 -15
  5. package/bacnet_gateway.js +388 -395
  6. package/bacnet_read.html +32 -11
  7. package/bacnet_read.js +1 -1
  8. package/bacnet_server.js +86 -24
  9. package/common.js +26 -19
  10. package/examples/1-Discover-Read.json +1 -1
  11. package/examples/2-Discover-Write.json +1 -1
  12. package/examples/3-Discover-Read-Write.json +1 -1
  13. package/package.json +3 -3
  14. package/resources/{node-bacnet/LICENSE.md → node-bacstack-ts/LICENSE} +3 -4
  15. package/resources/node-bacstack-ts/README.md +75 -0
  16. package/resources/{node-bacnet → node-bacstack-ts/dist}/index.js +0 -2
  17. package/resources/node-bacstack-ts/dist/lib/apdu.js +193 -0
  18. package/resources/node-bacstack-ts/dist/lib/asn1.js +1660 -0
  19. package/resources/node-bacstack-ts/dist/lib/bvlc.js +47 -0
  20. package/resources/node-bacstack-ts/dist/lib/client.js +1454 -0
  21. package/resources/node-bacstack-ts/dist/lib/enum.js +2114 -0
  22. package/resources/node-bacstack-ts/dist/lib/npdu.js +112 -0
  23. package/resources/node-bacstack-ts/dist/lib/services/add-list-element.js +58 -0
  24. package/resources/node-bacstack-ts/dist/lib/services/alarm-acknowledge.js +93 -0
  25. package/resources/node-bacstack-ts/dist/lib/services/alarm-summary.js +42 -0
  26. package/resources/node-bacstack-ts/dist/lib/services/atomic-read-file.js +157 -0
  27. package/resources/node-bacstack-ts/dist/lib/services/atomic-write-file.js +136 -0
  28. package/resources/node-bacstack-ts/dist/lib/services/cov-notify.js +119 -0
  29. package/resources/node-bacstack-ts/dist/lib/services/create-object.js +104 -0
  30. package/resources/node-bacstack-ts/dist/lib/services/delete-object.js +21 -0
  31. package/resources/node-bacstack-ts/dist/lib/services/device-communication-control.js +46 -0
  32. package/resources/node-bacstack-ts/dist/lib/services/error.js +27 -0
  33. package/resources/node-bacstack-ts/dist/lib/services/event-information.js +100 -0
  34. package/resources/node-bacstack-ts/dist/lib/services/event-notify-data.js +219 -0
  35. package/resources/node-bacstack-ts/dist/lib/services/get-enrollment-summary.js +172 -0
  36. package/resources/node-bacstack-ts/dist/lib/services/get-event-information.js +135 -0
  37. package/resources/node-bacstack-ts/dist/lib/services/i-am-broadcast.js +59 -0
  38. package/resources/node-bacstack-ts/dist/lib/services/i-have-broadcast.js +34 -0
  39. package/resources/node-bacstack-ts/dist/lib/services/index.js +32 -0
  40. package/resources/node-bacstack-ts/dist/lib/services/life-safety-operation.js +40 -0
  41. package/resources/node-bacstack-ts/dist/lib/services/private-transfer.js +43 -0
  42. package/resources/node-bacstack-ts/dist/lib/services/read-property-multiple.js +44 -0
  43. package/resources/node-bacstack-ts/dist/lib/services/read-property.js +122 -0
  44. package/resources/node-bacstack-ts/dist/lib/services/read-range.js +201 -0
  45. package/resources/node-bacstack-ts/dist/lib/services/reinitialize-device.js +35 -0
  46. package/resources/node-bacstack-ts/dist/lib/services/subscribe-cov.js +55 -0
  47. package/resources/node-bacstack-ts/dist/lib/services/subscribe-property.js +93 -0
  48. package/resources/node-bacstack-ts/dist/lib/services/time-sync.js +31 -0
  49. package/resources/node-bacstack-ts/dist/lib/services/who-has.js +56 -0
  50. package/resources/node-bacstack-ts/dist/lib/services/who-is.js +45 -0
  51. package/resources/node-bacstack-ts/dist/lib/services/write-property-multiple.js +105 -0
  52. package/resources/node-bacstack-ts/dist/lib/services/write-property.js +90 -0
  53. package/resources/node-bacstack-ts/dist/lib/transport.js +49 -0
  54. package/resources/node-bacstack-ts/dist/lib/types.js +2 -0
  55. package/resources/node-bacstack-ts/package.json +94 -0
  56. package/resources/node-bacnet/CHANGELOG.md +0 -481
  57. package/resources/node-bacnet/README.md +0 -91
  58. package/resources/node-bacnet/docs/Client.html +0 -4422
  59. package/resources/node-bacnet/docs/bacnet-icon-quad.png +0 -0
  60. package/resources/node-bacnet/docs/bacnet-icon-quad128.png +0 -0
  61. package/resources/node-bacnet/docs/bacnet-icon-quad64.png +0 -0
  62. package/resources/node-bacnet/docs/bacnet-icon-small.xcf +0 -0
  63. package/resources/node-bacnet/docs/bacnet-icon.xcf +0 -0
  64. package/resources/node-bacnet/docs/bacnet.html +0 -7032
  65. package/resources/node-bacnet/docs/client.js.html +0 -1759
  66. package/resources/node-bacnet/docs/enum.js.html +0 -2530
  67. package/resources/node-bacnet/docs/global.html +0 -2068
  68. package/resources/node-bacnet/docs/images/mocha-logo.svg +0 -65
  69. package/resources/node-bacnet/docs/index.html +0 -283
  70. package/resources/node-bacnet/docs/scripts/collapse.js +0 -11
  71. package/resources/node-bacnet/docs/scripts/jquery-3.1.1.min.js +0 -4
  72. package/resources/node-bacnet/docs/scripts/linenumber.js +0 -26
  73. package/resources/node-bacnet/docs/scripts/prettify/Apache-License-2.0.txt +0 -202
  74. package/resources/node-bacnet/docs/scripts/prettify/lang-css.js +0 -2
  75. package/resources/node-bacnet/docs/scripts/prettify/prettify.js +0 -28
  76. package/resources/node-bacnet/docs/scripts/search.js +0 -47
  77. package/resources/node-bacnet/docs/services_i-am.js.html +0 -157
  78. package/resources/node-bacnet/docs/services_time-sync.js.html +0 -118
  79. package/resources/node-bacnet/docs/services_who-is.js.html +0 -138
  80. package/resources/node-bacnet/docs/styles/jsdoc.css +0 -683
  81. package/resources/node-bacnet/docs/styles/prettify.css +0 -82
  82. package/resources/node-bacnet/examples/discover-devices.js +0 -66
  83. package/resources/node-bacnet/examples/read-device.js +0 -510
  84. package/resources/node-bacnet/examples/subscribe-cov.js +0 -75
  85. package/resources/node-bacnet/lib/apdu.js +0 -209
  86. package/resources/node-bacnet/lib/asn1.js +0 -1733
  87. package/resources/node-bacnet/lib/bvlc.js +0 -90
  88. package/resources/node-bacnet/lib/client.js +0 -1695
  89. package/resources/node-bacnet/lib/enum.js +0 -2463
  90. package/resources/node-bacnet/lib/npdu.js +0 -123
  91. package/resources/node-bacnet/lib/services/add-list-element.js +0 -64
  92. package/resources/node-bacnet/lib/services/alarm-acknowledge.js +0 -90
  93. package/resources/node-bacnet/lib/services/alarm-summary.js +0 -42
  94. package/resources/node-bacnet/lib/services/atomic-read-file.js +0 -162
  95. package/resources/node-bacnet/lib/services/atomic-write-file.js +0 -138
  96. package/resources/node-bacnet/lib/services/cov-notify.js +0 -126
  97. package/resources/node-bacnet/lib/services/create-object.js +0 -106
  98. package/resources/node-bacnet/lib/services/delete-object.js +0 -23
  99. package/resources/node-bacnet/lib/services/device-communication-control.js +0 -48
  100. package/resources/node-bacnet/lib/services/error.js +0 -33
  101. package/resources/node-bacnet/lib/services/event-information.js +0 -99
  102. package/resources/node-bacnet/lib/services/event-notify-data.js +0 -229
  103. package/resources/node-bacnet/lib/services/get-enrollment-summary.js +0 -178
  104. package/resources/node-bacnet/lib/services/get-event-information.js +0 -144
  105. package/resources/node-bacnet/lib/services/i-am.js +0 -90
  106. package/resources/node-bacnet/lib/services/i-have.js +0 -34
  107. package/resources/node-bacnet/lib/services/index.js +0 -34
  108. package/resources/node-bacnet/lib/services/life-safety-operation.js +0 -40
  109. package/resources/node-bacnet/lib/services/private-transfer.js +0 -43
  110. package/resources/node-bacnet/lib/services/read-property-multiple.js +0 -50
  111. package/resources/node-bacnet/lib/services/read-property.js +0 -130
  112. package/resources/node-bacnet/lib/services/read-range.js +0 -201
  113. package/resources/node-bacnet/lib/services/register-foreign-device.js +0 -18
  114. package/resources/node-bacnet/lib/services/reinitialize-device.js +0 -37
  115. package/resources/node-bacnet/lib/services/subscribe-cov.js +0 -57
  116. package/resources/node-bacnet/lib/services/subscribe-property.js +0 -97
  117. package/resources/node-bacnet/lib/services/time-sync.js +0 -51
  118. package/resources/node-bacnet/lib/services/who-has.js +0 -54
  119. package/resources/node-bacnet/lib/services/who-is.js +0 -71
  120. package/resources/node-bacnet/lib/services/write-property-multiple.js +0 -117
  121. package/resources/node-bacnet/lib/services/write-property.js +0 -94
  122. package/resources/node-bacnet/lib/transport.js +0 -82
  123. package/resources/node-bacnet/package.json +0 -92
@@ -1,1695 +0,0 @@
1
- 'use strict';
2
-
3
- // Util Modules
4
- const EventEmitter = require('events').EventEmitter;
5
- const debug = require('debug')('bacnet:client:debug');
6
- const trace = require('debug')('bacnet:client:trace');
7
- const usc = require('underscore');
8
-
9
- // Local Modules
10
- const baTransport = require('./transport');
11
- const baServices = require('./services');
12
- const baAsn1 = require('./asn1');
13
- const baApdu = require('./apdu');
14
- const baNpdu = require('./npdu');
15
- const baBvlc = require('./bvlc');
16
- const baEnum = require('./enum');
17
-
18
- const ALL_INTERFACES = '0.0.0.0';
19
- const LOCALHOST_INTERFACES_IPV4 = '127.0.0.1';
20
- const BROADCAST_ADDRESS = '255.255.255.255';
21
- const DEFAULT_HOP_COUNT = 0xFF;
22
- const BVLC_HEADER_LENGTH = 4;
23
- const BVLC_FWD_HEADER_LENGTH = 10; // FORWARDED_NPDU
24
-
25
- const beU = baEnum.UnconfirmedServiceChoice;
26
- const unconfirmedServiceMap = {
27
- [beU.I_AM]: 'iAm',
28
- [beU.WHO_IS]: 'whoIs',
29
- [beU.WHO_HAS]: 'whoHas',
30
- [beU.UNCONFIRMED_COV_NOTIFICATION]: 'covNotifyUnconfirmed',
31
- [beU.TIME_SYNCHRONIZATION]: 'timeSync',
32
- [beU.UTC_TIME_SYNCHRONIZATION]: 'timeSyncUTC',
33
- [beU.UNCONFIRMED_EVENT_NOTIFICATION]: 'eventNotify',
34
- [beU.I_HAVE]: 'iHave',
35
- [beU.UNCONFIRMED_PRIVATE_TRANSFER]: 'privateTransfer',
36
- };
37
- const beC = baEnum.ConfirmedServiceChoice;
38
- const confirmedServiceMap = {
39
- [beC.READ_PROPERTY]: 'readProperty',
40
- [beC.WRITE_PROPERTY]: 'writeProperty',
41
- [beC.READ_PROPERTY_MULTIPLE]: 'readPropertyMultiple',
42
- [beC.WRITE_PROPERTY_MULTIPLE]: 'writePropertyMultiple',
43
- [beC.CONFIRMED_COV_NOTIFICATION]: 'covNotify',
44
- [beC.ATOMIC_WRITE_FILE]: 'atomicWriteFile',
45
- [beC.ATOMIC_READ_FILE]: 'atomicReadFile',
46
- [beC.SUBSCRIBE_COV]: 'subscribeCov',
47
- [beC.SUBSCRIBE_COV_PROPERTY]: 'subscribeProperty',
48
- [beC.DEVICE_COMMUNICATION_CONTROL]: 'deviceCommunicationControl',
49
- [beC.REINITIALIZE_DEVICE]: 'reinitializeDevice',
50
- [beC.CONFIRMED_EVENT_NOTIFICATION]: 'eventNotify',
51
- [beC.READ_RANGE]: 'readRange',
52
- [beC.CREATE_OBJECT]: 'createObject',
53
- [beC.DELETE_OBJECT]: 'deleteObject',
54
- [beC.ACKNOWLEDGE_ALARM]: 'alarmAcknowledge',
55
- [beC.GET_ALARM_SUMMARY]: 'getAlarmSummary',
56
- [beC.GET_ENROLLMENT_SUMMARY]: 'getEnrollmentSummary',
57
- [beC.GET_EVENT_INFORMATION]: 'getEventInformation',
58
- [beC.LIFE_SAFETY_OPERATION]: 'lifeSafetyOperation',
59
- [beC.ADD_LIST_ELEMENT]: 'addListElement',
60
- [beC.REMOVE_LIST_ELEMENT]: 'removeListElement',
61
- [beC.CONFIRMED_PRIVATE_TRANSFER]: 'privateTransfer',
62
- };
63
-
64
- /**
65
- * To be able to communicate to BACNET devices, you have to initialize a new bacnet instance.
66
- * @class bacnet
67
- * @param {object=} this._settings - The options object used for parameterizing the bacnet.
68
- * @param {number=} [options.port=47808] - BACNET communication port for listening and sending.
69
- * @param {string=} options.interface - Specific BACNET communication interface if different from primary one.
70
- * @param {string=} [options.broadcastAddress=255.255.255.255] - The address used for broadcast messages.
71
- * @param {number=} [options.apduTimeout=3000] - The timeout in milliseconds until a transaction should be interpreted as error.
72
- * @example
73
- * const bacnet = require('node-bacnet');
74
- *
75
- * const client = new bacnet({
76
- * port: 47809, // Use BAC1 as communication port
77
- * interface: '192.168.251.10', // Listen on a specific interface
78
- * broadcastAddress: '192.168.251.255', // Use the subnet broadcast address
79
- * apduTimeout: 6000 // Wait twice as long for response
80
- * });
81
- */
82
- class Client extends EventEmitter {
83
- /**
84
- *
85
- * @param options
86
- */
87
- constructor(options) {
88
- super();
89
-
90
- options = options || {};
91
-
92
- this._invokeCounter = 1;
93
- this._invokeStore = {};
94
-
95
- this._lastSequenceNumber = 0;
96
- this._segmentStore = [];
97
-
98
- this._settings = {
99
- port: options.port || 47808,
100
- interface: options.interface || ALL_INTERFACES,
101
- transport: options.transport,
102
- broadcastAddress: options.broadcastAddress || BROADCAST_ADDRESS,
103
- apduTimeout: options.apduTimeout || 3000
104
- };
105
-
106
- options.reuseAddr = options.reuseAddr === undefined ? true : !!options.reuseAddr;
107
-
108
- this._transport = this._settings.transport || new baTransport({
109
- port: this._settings.port,
110
- interface: this._settings.interface,
111
- broadcastAddress: this._settings.broadcastAddress,
112
- reuseAddr: options.reuseAddr
113
- });
114
-
115
- // Setup code
116
- this._transport.on('message', this._receiveData.bind(this));
117
- this._transport.on('error', this._receiveError.bind(this));
118
- this._transport.on('listening', () => this.emit('listening'));
119
- this._transport.open();
120
- }
121
-
122
- /**
123
- *
124
- * @returns {number}
125
- * @private
126
- */
127
- _getInvokeId() {
128
- const id = this._invokeCounter++;
129
- if (id >= 256) this._invokeCounter = 1;
130
- return id - 1;
131
- }
132
-
133
- /**
134
- *
135
- * @param id
136
- * @param err
137
- * @param result
138
- * @returns {*}
139
- * @private
140
- */
141
- _invokeCallback(id, err, result) {
142
- const callback = this._invokeStore[id];
143
- if (callback) {
144
- return void callback(err, result);
145
- }
146
- debug('InvokeId', id, 'not found -> drop package');
147
- }
148
-
149
- /**
150
- *
151
- * @param id
152
- * @param callback
153
- * @private
154
- */
155
- _addCallback(id, callback) {
156
- const timeout = setTimeout(() => {
157
- delete this._invokeStore[id];
158
- callback(new Error('ERR_TIMEOUT'));
159
- }, this._settings.apduTimeout);
160
- this._invokeStore[id] = (err, data) => {
161
- clearTimeout(timeout);
162
- delete this._invokeStore[id];
163
- callback(err, data);
164
- };
165
- }
166
-
167
- /**
168
- *
169
- * @param isForwarded
170
- * @returns {{offset: (number), buffer: *}}
171
- * @private
172
- */
173
- _getBuffer(isForwarded) {
174
- return Object.assign({}, {
175
- buffer: Buffer.alloc(this._transport.getMaxPayload()),
176
- offset: isForwarded ? BVLC_FWD_HEADER_LENGTH : BVLC_HEADER_LENGTH
177
- });
178
- }
179
-
180
- /**
181
- *
182
- * @param invokeId
183
- * @param buffer
184
- * @param offset
185
- * @param length
186
- * @returns {*}
187
- * @private
188
- */
189
- _processError(invokeId, buffer, offset, length) {
190
- const result = baServices.error.decode(buffer, offset, length);
191
- trace('Received error:', result);
192
- if (!result) {
193
- return debug('Couldn`t decode Error');
194
- }
195
- const err = new Error(baServices.error.buildMessage(result));
196
- err.bacnetErrorClass = result.class;
197
- err.bacnetErrorCode = result.code;
198
- this._invokeCallback(invokeId, err);
199
- }
200
-
201
- /**
202
- *
203
- * @param invokeId
204
- * @param reason
205
- * @private
206
- */
207
- _processAbort(invokeId, reason) {
208
- const err = new Error('BacnetAbort - Reason:' + reason);
209
- err.bacnetAbortReason = reason;
210
- this._invokeCallback(invokeId, err);
211
- }
212
-
213
- /**
214
- *
215
- * @param receiver
216
- * @param negative
217
- * @param server
218
- * @param originalInvokeId
219
- * @param sequencenumber
220
- * @param actualWindowSize
221
- * @private
222
- */
223
- _segmentAckResponse(receiver, negative, server, originalInvokeId, sequencenumber, actualWindowSize) {
224
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
225
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0);
226
- baApdu.encodeSegmentAck(buffer, baEnum.PduType.SEGMENT_ACK | (negative ? baEnum.PduSegAckBit.NEGATIVE_ACK : 0) | (server ? baEnum.PduSegAckBit.SERVER : 0), originalInvokeId, sequencenumber, actualWindowSize);
227
- this.sendBvlc(receiver, buffer);
228
- }
229
-
230
- /**
231
- *
232
- * @param msg
233
- * @param first
234
- * @param moreFollows
235
- * @param buffer
236
- * @param offset
237
- * @param length
238
- * @private
239
- */
240
- _performDefaultSegmentHandling(msg, first, moreFollows, buffer, offset, length) {
241
- if (first) {
242
- this._segmentStore = [];
243
- msg.type &= ~baEnum.PduConReqBit.SEGMENTED_MESSAGE;
244
- let apduHeaderLen = 3;
245
- if ((msg.type & baEnum.PDU_TYPE_MASK) === baEnum.PduType.CONFIRMED_REQUEST) {
246
- apduHeaderLen = 4;
247
- }
248
- const apdubuffer = this._getBuffer();
249
- apdubuffer.offset = 0;
250
- buffer.copy(apdubuffer.buffer, apduHeaderLen, offset, offset + length);
251
- if ((msg.type & baEnum.PDU_TYPE_MASK) === baEnum.PduType.CONFIRMED_REQUEST) {
252
- baApdu.encodeConfirmedServiceRequest(
253
- apdubuffer,
254
- msg.type,
255
- msg.service,
256
- msg.maxSegments,
257
- msg.maxApdu,
258
- msg.invokeId,
259
- 0,
260
- 0
261
- );
262
- } else {
263
- baApdu.encodeComplexAck(apdubuffer, msg.type, msg.service, msg.invokeId, 0, 0);
264
- }
265
- this._segmentStore.push(apdubuffer.buffer.slice(0, length + apduHeaderLen));
266
- } else {
267
- this._segmentStore.push(buffer.slice(offset, offset + length));
268
- }
269
- if (!moreFollows) {
270
- const apduBuffer = Buffer.concat(this._segmentStore);
271
- this._segmentStore = [];
272
- msg.type &= ~baEnum.PduConReqBit.SEGMENTED_MESSAGE;
273
- this._handlePdu(apduBuffer, 0, apduBuffer.length, msg.header);
274
- }
275
- }
276
-
277
- /**
278
- *
279
- * @param msg
280
- * @param server
281
- * @param buffer
282
- * @param offset
283
- * @param length
284
- * @private
285
- */
286
- _processSegment(msg, server, buffer, offset, length) {
287
- let first = false;
288
- if (msg.sequencenumber === 0 && this._lastSequenceNumber === 0) {
289
- first = true;
290
- } else {
291
- if (msg.sequencenumber !== this._lastSequenceNumber + 1) {
292
- return this._segmentAckResponse(msg.header.address, true, server, msg.invokeId, this._lastSequenceNumber, msg.proposedWindowNumber);
293
- }
294
- }
295
- this._lastSequenceNumber = msg.sequencenumber;
296
- const moreFollows = msg.type & baEnum.PduConReqBit.MORE_FOLLOWS;
297
- if (!moreFollows) {
298
- this._lastSequenceNumber = 0;
299
- }
300
- if ((msg.sequencenumber % msg.proposedWindowNumber) === 0 || !moreFollows) {
301
- this._segmentAckResponse(msg.header.address, false, server, msg.invokeId, msg.sequencenumber, msg.proposedWindowNumber);
302
- }
303
- this._performDefaultSegmentHandling(msg, first, moreFollows, buffer, offset, length);
304
- }
305
-
306
- /**
307
- *
308
- * @param serviceMap
309
- * @param content
310
- * @param buffer
311
- * @param offset
312
- * @param length
313
- * @returns {*}
314
- * @private
315
- */
316
- _processServiceRequest(serviceMap, content, buffer, offset, length) {
317
- let result;
318
-
319
- const sender = content.header.sender;
320
- if (sender.address === LOCALHOST_INTERFACES_IPV4) {
321
- debug('Received and skipped localhost service request:', content.service);
322
- return;
323
- }
324
-
325
- const name = serviceMap[content.service];
326
- if (!name) {
327
- debug('Received unsupported service request:', content.service);
328
- return;
329
- }
330
-
331
- const id = content.invokeId ? '@' + content.invokeId : '';
332
- trace(`Received service request${id}:`, name);
333
-
334
- // Find a function to decode the packet.
335
- const serviceHandler = baServices[name];
336
- if (serviceHandler) {
337
- try {
338
- content.payload = serviceHandler.decode(buffer, offset, length);
339
- trace(`Handled service request${id}:`, name, JSON.stringify(content));
340
- } catch (e) {
341
- // Sometimes incomplete or corrupted messages will cause exceptions
342
- // during decoding, but we don't want these to terminate the program, so
343
- // we'll just log them and ignore them.
344
- debug('Exception thrown when processing message:', e);
345
- debug('Original message was', name + ':', content);
346
- return;
347
- }
348
- if (!content.payload) {
349
- return debug('Received invalid', name, 'message');
350
- }
351
- } else {
352
- debug('No serviceHandler defined for:', name);
353
- // Call the callback anyway, just with no payload.
354
- }
355
- //trace('Passing payload over to callback:', content);
356
-
357
- // Call the user code, if they've defined a callback.
358
- if (this.listenerCount(name)) {
359
- trace('listener count by name emits ' + name + ' with content');
360
- this.emit(name, content);
361
- } else {
362
- if (this.listenerCount('unhandledEvent')) {
363
- trace('unhandled event emiting with content');
364
- this.emit('unhandledEvent', content);
365
- } else {
366
- // No 'unhandled event' handler, so respond with an error ourselves.
367
- // This is better than doing nothing, which can often make the other
368
- // device think we have gone offline.
369
- trace('no unhandled event handler with header: ' + JSON.stringify(content.header));
370
- if (content.header.expectingReply) {
371
- debug('Replying with error for unhandled service:', name);
372
- // Make sure we don't reply pretending to be the caller, if we got a
373
- // forwarded message! Really this should be overridden to be your
374
- // own IP, but only if it's not null/undefined to begin with.
375
- content.header.sender.forwardedFrom = null;
376
- this.errorResponse(
377
- content.header.sender,
378
- content.service,
379
- content.invokeId,
380
- baEnum.ErrorClass.SERVICES,
381
- baEnum.ErrorCode.REJECT_UNRECOGNIZED_SERVICE
382
- );
383
- }
384
- }
385
- }
386
- }
387
-
388
- /**
389
- *
390
- * @param buffer
391
- * @param offset
392
- * @param length
393
- * @param header
394
- * @private
395
- */
396
- _handlePdu(buffer, offset, length, header) {
397
- let msg;
398
- trace('handlePdu Header: ', header);
399
- // Handle different PDU types
400
- switch (header.apduType & baEnum.PDU_TYPE_MASK) {
401
- case baEnum.PduType.UNCONFIRMED_REQUEST:
402
- msg = baApdu.decodeUnconfirmedServiceRequest(buffer, offset);
403
- msg.header = header;
404
- msg.header.confirmedService = false;
405
- this._processServiceRequest(unconfirmedServiceMap, msg, buffer, offset + msg.len, length - msg.len);
406
- break;
407
- case baEnum.PduType.SIMPLE_ACK:
408
- msg = baApdu.decodeSimpleAck(buffer, offset);
409
- offset += msg.len;
410
- length -= msg.len;
411
- this._invokeCallback(msg.invokeId, null, {msg: msg, buffer: buffer, offset: offset + msg.len, length: length - msg.len});
412
- break;
413
- case baEnum.PduType.COMPLEX_ACK:
414
- msg = baApdu.decodeComplexAck(buffer, offset);
415
- msg.header = header;
416
- if ((header.apduType & baEnum.PduConReqBit.SEGMENTED_MESSAGE) === 0) {
417
- this._invokeCallback(msg.invokeId, null, {msg: msg, buffer: buffer, offset: offset + msg.len, length: length - msg.len});
418
- } else {
419
- this._processSegment(msg, true, buffer, offset + msg.len, length - msg.len);
420
- }
421
- break;
422
- case baEnum.PduType.SEGMENT_ACK:
423
- msg = baApdu.decodeSegmentAck(buffer, offset);
424
- msg.header = header;
425
- this._processSegment(msg, true, buffer, offset + msg.len, length - msg.len);
426
- break;
427
- case baEnum.PduType.ERROR:
428
- msg = baApdu.decodeError(buffer, offset);
429
- this._processError(msg.invokeId, buffer, offset + msg.len, length - msg.len);
430
- break;
431
- case baEnum.PduType.REJECT:
432
- case baEnum.PduType.ABORT:
433
- msg = baApdu.decodeAbort(buffer, offset);
434
- this._processAbort(msg.invokeId, msg.reason);
435
- break;
436
- case baEnum.PduType.CONFIRMED_REQUEST:
437
- msg = baApdu.decodeConfirmedServiceRequest(buffer, offset);
438
- msg.header = header;
439
- msg.header.confirmedService = true;
440
- if ((header.apduType & baEnum.PduConReqBit.SEGMENTED_MESSAGE) === 0) {
441
- this._processServiceRequest(confirmedServiceMap, msg, buffer, offset + msg.len, length - msg.len);
442
- } else {
443
- this._processSegment(msg, true, buffer, offset + msg.len, length - msg.len);
444
- }
445
- break;
446
- default:
447
- debug(`Received unknown PDU type ${header.apduType} -> Drop packet`);
448
- break;
449
- }
450
- }
451
-
452
- /**
453
- *
454
- * @param buffer
455
- * @param offset
456
- * @param msgLength
457
- * @param header
458
- * @returns {*}
459
- * @private
460
- */
461
- _handleNpdu(buffer, offset, msgLength, header) {
462
- // Check data length
463
- if (msgLength <= 0) {
464
- return trace('No NPDU data -> Drop package');
465
- }
466
- // Parse baNpdu header
467
- const result = baNpdu.decode(buffer, offset);
468
- if (!result) {
469
- return trace('Received invalid NPDU header -> Drop package');
470
- }
471
- if (result.funct & baEnum.NpduControlBit.NETWORK_LAYER_MESSAGE) {
472
- return trace('Received network layer message -> Drop package');
473
- }
474
- if(result.source && result.source.net && result.source.adr) {
475
- header.source = result.source;
476
- }
477
- offset += result.len;
478
- msgLength -= result.len;
479
- if (msgLength <= 0) {
480
- return trace('No APDU data -> Drop package');
481
- }
482
- header.apduType = baApdu.getDecodedType(buffer, offset);
483
- header.expectingReply = !!(result.funct & baEnum.NpduControlBit.EXPECTING_REPLY);
484
- this._handlePdu(buffer, offset, msgLength, header);
485
- }
486
-
487
- /**
488
- *
489
- * @param buffer
490
- * @param remoteAddress
491
- * @returns {*}
492
- * @private
493
- */
494
- _receiveData(buffer, remoteAddress) {
495
- // Check data length
496
- if (buffer.length < baEnum.BVLC_HEADER_LENGTH) {
497
- return trace('Received invalid data -> Drop package');
498
- }
499
- // Parse BVLC header
500
- const result = baBvlc.decode(buffer, 0);
501
- if (!result) {
502
- return trace('Received invalid BVLC header -> Drop package');
503
- }
504
- let header = {
505
- // Which function the packet came in on, so later code can distinguish
506
- // between ORIGINAL_BROADCAST_NPDU and DISTRIBUTE_BROADCAST_TO_NETWORK.
507
- func: result.func,
508
- sender: {
509
- // Address of the host we are directly connected to. String, IP:port.
510
- address: remoteAddress,
511
- // If the host is a BBMD passing messages along to another node, this
512
- // is the address of the distant BACnet node. String, IP:port.
513
- // Typically we won't have network connectivity to this address, but
514
- // we have to include it in replies so the host we are connect to knows
515
- // where to forward the messages.
516
- forwardedFrom: null,
517
- },
518
- };
519
- // Check BVLC function
520
- switch (result.func) {
521
- case baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU:
522
- case baEnum.BvlcResultPurpose.ORIGINAL_BROADCAST_NPDU:
523
- this._handleNpdu(buffer, result.len, buffer.length - result.len, header);
524
- break;
525
- case baEnum.BvlcResultPurpose.FORWARDED_NPDU:
526
- // Preserve the IP of the node behind the BBMD so we know where to send
527
- // replies back to.
528
- header.sender.forwardedFrom = result.originatingIP;
529
- this._handleNpdu(buffer, result.len, buffer.length - result.len, header);
530
- break;
531
- case baEnum.BvlcResultPurpose.REGISTER_FOREIGN_DEVICE:
532
- let decodeResult = baServices.registerForeignDevice.decode(buffer, result.len, buffer.length - result.len);
533
- if (!decodeResult) {
534
- return trace('Received invalid registerForeignDevice message');
535
- }
536
- this.emit('registerForeignDevice', {
537
- header: header,
538
- payload: decodeResult,
539
- });
540
- break;
541
- case baEnum.BvlcResultPurpose.DISTRIBUTE_BROADCAST_TO_NETWORK:
542
- this._handleNpdu(buffer, result.len, buffer.length - result.len, header);
543
- break;
544
- default:
545
- debug('Received unknown BVLC function ' + result.func + ' -> Drop package');
546
- break;
547
- }
548
- }
549
-
550
- /**
551
- * @event bacnet.error
552
- * @param {error} err - The error object thrown by the underlying transport layer.
553
- * @example
554
- * const bacnet = require('node-bacnet');
555
- * const client = new bacnet();
556
- *
557
- * client.on('error', (err) => {
558
- * console.log('Error occurred: ', err);
559
- * client.close();
560
- * });
561
- */
562
- _receiveError(err) {
563
- this.emit('error', err);
564
- }
565
-
566
- /**
567
- * The whoIs command discovers all BACNET devices in a network.
568
- * @function bacnet.whoIs
569
- * @param {string} receiver - IP address of the target device.
570
- * @param {object=} options
571
- * @param {number=} options.lowLimit - Minimal device instance number to search for.
572
- * @param {number=} options.highLimit - Maximal device instance number to search for.
573
- * @fires bacnet.iAm
574
- * @example
575
- * const bacnet = require('node-bacnet');
576
- * const client = new bacnet();
577
- *
578
- * client.whoIs();
579
- */
580
- whoIs(receiver, options) {
581
- if (!options) {
582
- if (
583
- receiver &&
584
- typeof receiver === 'object' &&
585
- receiver.address === undefined &&
586
- receiver.forwardedFrom === undefined &&
587
- (receiver.lowLimit !== undefined || receiver.highLimit !== undefined)
588
- ) {
589
- // receiver seems to be an options object
590
- options = receiver;
591
- receiver = undefined;
592
- }
593
- }
594
- options = options || {};
595
-
596
- const settings = {
597
- lowLimit: options.lowLimit,
598
- highLimit: options.highLimit,
599
- };
600
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
601
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0);
602
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.WHO_IS);
603
- baServices.whoIs.encode(buffer, settings.lowLimit, settings.highLimit);
604
- this.sendBvlc(receiver, buffer);
605
- }
606
-
607
- /**
608
- * The timeSync command sets the time of a target device.
609
- * @function bacnet.timeSync
610
- * @param {string} receiver - IP address of the target device.
611
- * @param {date} dateTime - The date and time to set on the target device.
612
- * @example
613
- * const bacnet = require('node-bacnet');
614
- * const client = new bacnet();
615
- *
616
- * client.timeSync('192.168.1.43', new Date());
617
- */
618
- timeSync(receiver, dateTime) {
619
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
620
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
621
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.TIME_SYNCHRONIZATION);
622
- baServices.timeSync.encode(buffer, dateTime);
623
- this.sendBvlc(receiver, buffer);
624
- }
625
-
626
- /**
627
- * The timeSyncUTC command sets the UTC time of a target device.
628
- * @function bacnet.timeSyncUTC
629
- * @param {string} receiver - IP address of the target device.
630
- * @param {date} dateTime - The date and time to set on the target device.
631
- * @example
632
- * const bacnet = require('node-bacnet');
633
- * const client = new bacnet();
634
- *
635
- * client.timeSyncUTC('192.168.1.43', new Date());
636
- */
637
- timeSyncUTC(receiver, dateTime) {
638
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
639
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
640
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.UTC_TIME_SYNCHRONIZATION);
641
- baServices.timeSync.encode(buffer, dateTime);
642
- this.sendBvlc(receiver, buffer);
643
- }
644
-
645
- /**
646
- * The readProperty command reads a single property of an object from a device.
647
- * @function bacnet.readProperty
648
- * @param {string} receiver - IP address of the target device.
649
- * @param {object} objectId - The BACNET object ID to read.
650
- * @param {number} objectId.type - The BACNET object type to read.
651
- * @param {number} objectId.instance - The BACNET object instance to read.
652
- * @param {number} propertyId - The BACNET property id in the specified object to read.
653
- * @param {object=} options
654
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
655
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
656
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
657
- * @param {number=} options.arrayIndex - The array index of the property to be read.
658
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
659
- * @example
660
- * const bacnet = require('node-bacnet');
661
- * const client = new bacnet();
662
- *
663
- * client.readProperty('192.168.1.43', {type: 8, instance: 44301}, 28, (err, value) => {
664
- * console.log('value: ', value);
665
- * });
666
- */
667
- readProperty(receiver, objectId, propertyId, options, next) {
668
- next = next || options;
669
- const settings = {
670
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
671
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
672
- invokeId: options.invokeId || this._getInvokeId(),
673
- arrayIndex: (options.arrayIndex || options.arrayIndex === 0) ? options.arrayIndex : baEnum.ASN1_ARRAY_ALL
674
- };
675
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
676
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0);
677
- const type = baEnum.PduType.CONFIRMED_REQUEST | (settings.maxSegments !== baEnum.MaxSegmentsAccepted.SEGMENTS_0 ? baEnum.PduConReqBit.SEGMENTED_RESPONSE_ACCEPTED : 0);
678
- baApdu.encodeConfirmedServiceRequest(buffer, type, baEnum.ConfirmedServiceChoice.READ_PROPERTY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
679
- baServices.readProperty.encode(buffer, objectId.type, objectId.instance, propertyId, settings.arrayIndex);
680
- this.sendBvlc(receiver, buffer);
681
- this._addCallback(settings.invokeId, (err, data) => {
682
- if (err) {
683
- return void next(err);
684
- }
685
- const result = baServices.readProperty.decodeAcknowledge(data.buffer, data.offset, data.length);
686
- if (!result) {
687
- return void next(new Error('INVALID_DECODING'));
688
- }
689
- next(null, result);
690
- });
691
- }
692
-
693
- /**
694
- * The writeProperty command writes a single property of an object to a device.
695
- * @function bacnet.writeProperty
696
- * @param {string} receiver - IP address of the target device.
697
- * @param {object} objectId - The BACNET object ID to write.
698
- * @param {number} objectId.type - The BACNET object type to write.
699
- * @param {number} objectId.instance - The BACNET object instance to write.
700
- * @param {number} propertyId - The BACNET property id in the specified object to write.
701
- * @param {object[]} values - A list of values to be written to the specified property.
702
- * @param {ApplicationTag} values.type - The data-type of the value to be written.
703
- * @param {number} values.value - The actual value to be written.
704
- * @param {object=} options
705
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
706
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
707
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
708
- * @param {number=} options.arrayIndex - The array index of the property to be read.
709
- * @param {number=} options.priority - The priority of the value to be written.
710
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
711
- * @example
712
- * const bacnet = require('node-bacnet');
713
- * const client = new bacnet();
714
- *
715
- * client.writeProperty('192.168.1.43', {type: 8, instance: 44301}, 28, [
716
- * {type: bacnet.enum.ApplicationTag.REAL, value: 100}
717
- * ], (err, value) => {
718
- * console.log('value: ', value);
719
- * });
720
- */
721
- writeProperty(receiver, objectId, propertyId, values, options, next) {
722
- next = next || options;
723
- const settings = {
724
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
725
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
726
- invokeId: options.invokeId || this._getInvokeId(),
727
- arrayIndex: options.arrayIndex || baEnum.ASN1_ARRAY_ALL,
728
- priority: options.priority || baEnum.ASN1_NO_PRIORITY
729
- };
730
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
731
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0);
732
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.WRITE_PROPERTY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
733
- baServices.writeProperty.encode(buffer, objectId.type, objectId.instance, propertyId, settings.arrayIndex, settings.priority, values);
734
- this.sendBvlc(receiver, buffer);
735
- this._addCallback(settings.invokeId, (err, data) => {
736
- next(err);
737
- });
738
- }
739
-
740
- /**
741
- * The readPropertyMultiple command reads multiple properties in multiple objects from a device.
742
- * @function bacnet.readPropertyMultiple
743
- * @param {string} receiver - IP address of the target device.
744
- * @param {object[]} propertiesArray - List of object and property specifications to be read.
745
- * @param {object} propertiesArray.objectId - Specifies which object to read.
746
- * @param {number} propertiesArray.objectId.type - The BACNET object type to read.
747
- * @param {number} propertiesArray.objectId.instance - The BACNET object instance to read.
748
- * @param {object[]} propertiesArray.properties - List of properties to be read.
749
- * @param {number} propertiesArray.properties.id - The BACNET property id in the specified object to read. Also supports 8 for all properties.
750
- * @param {object=} options
751
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
752
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
753
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
754
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
755
- * @example
756
- * const bacnet = require('node-bacnet');
757
- * const client = new bacnet();
758
- *
759
- * const requestArray = [
760
- * {objectId: {type: 8, instance: 4194303}, properties: [{id: 8}]}
761
- * ];
762
- * client.readPropertyMultiple('192.168.1.43', requestArray, (err, value) => {
763
- * console.log('value: ', value);
764
- * });
765
- */
766
- readPropertyMultiple(receiver, propertiesArray, options, next) {
767
- next = next || options;
768
- const settings = {
769
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
770
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
771
- invokeId: options.invokeId || this._getInvokeId()
772
- };
773
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
774
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0);
775
- const type = baEnum.PduType.CONFIRMED_REQUEST | (settings.maxSegments !== baEnum.MaxSegmentsAccepted.SEGMENTS_0 ? baEnum.PduConReqBit.SEGMENTED_RESPONSE_ACCEPTED : 0);
776
- baApdu.encodeConfirmedServiceRequest(buffer, type, baEnum.ConfirmedServiceChoice.READ_PROPERTY_MULTIPLE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
777
- baServices.readPropertyMultiple.encode(buffer, propertiesArray);
778
- this.sendBvlc(receiver, buffer);
779
- this._addCallback(settings.invokeId, (err, data) => {
780
- if (err) {
781
- return void next(err);
782
- }
783
- const result = baServices.readPropertyMultiple.decodeAcknowledge(data.buffer, data.offset, data.length);
784
- if (!result) {
785
- return void next(new Error('INVALID_DECODING'));
786
- }
787
- next(null, result);
788
- });
789
- }
790
-
791
- /**
792
- * The writePropertyMultiple command writes multiple properties in multiple objects to a device.
793
- * @function bacnet.writePropertyMultiple
794
- * @param {string} receiver - IP address of the target device.
795
- * @param {object[]} values - List of object and property specifications to be written.
796
- * @param {object} values.objectId - Specifies which object to read.
797
- * @param {number} values.objectId.type - The BACNET object type to read.
798
- * @param {number} values.objectId.instance - The BACNET object instance to read.
799
- * @param {object[]} values.values - List of properties to be written.
800
- * @param {object} values.values.property - Property specifications to be written.
801
- * @param {number} values.values.property.id - The BACNET property id in the specified object to write.
802
- * @param {number} values.values.property.index - The array index of the property to be written.
803
- * @param {object[]} values.values.value - A list of values to be written to the specified property.
804
- * @param {ApplicationTag} values.values.value.type - The data-type of the value to be written.
805
- * @param {object} values.values.value.value - The actual value to be written.
806
- * @param {number} values.values.priority - The priority to be used for writing to the property.
807
- * @param {object=} options
808
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
809
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
810
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
811
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
812
- * @example
813
- * const bacnet = require('node-bacnet');
814
- * const client = new bacnet();
815
- *
816
- * const values = [
817
- * {objectId: {type: 8, instance: 44301}, values: [
818
- * {property: {id: 28, index: 12}, value: [{type: bacnet.enum.ApplicationTag.BOOLEAN, value: true}], priority: 8}
819
- * ]}
820
- * ];
821
- * client.writePropertyMultiple('192.168.1.43', values, (err, value) => {
822
- * console.log('value: ', value);
823
- * });
824
- */
825
- writePropertyMultiple(receiver, values, options, next) {
826
- next = next || options;
827
- const settings = {
828
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
829
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
830
- invokeId: options.invokeId || this._getInvokeId()
831
- };
832
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
833
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
834
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.WRITE_PROPERTY_MULTIPLE, settings.maxSegments, settings.maxApdu, settings.invokeId);
835
- baServices.writePropertyMultiple.encodeObject(buffer, values);
836
- this.sendBvlc(receiver, buffer);
837
- this._addCallback(settings.invokeId, (err, data) => {
838
- next(err);
839
- });
840
- }
841
-
842
- /**
843
- * The confirmedCOVNotification command is used to push notifications to other
844
- * systems that have registered with us via a subscribeCOV message.
845
- * @function bacnet.confirmedCOVNotification
846
- * @param {string} receiver - IP address of the target device.
847
- * @param {object} monitoredObject - The object being monitored, from subscribeCOV.
848
- * @param {number} monitoredObject.type - Object type.
849
- * @param {number} monitoredObject.instance - Object instance.
850
- * @param {number} subscribeId - Subscriber ID from subscribeCOV,
851
- * @param {number} initiatingDeviceId - Our BACnet device ID.
852
- * @param {number} lifetime - Number of seconds left until the subscription expires.
853
- * @param {array} values - values for the monitored object. See example.
854
- * @param {object=} options
855
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
856
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
857
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
858
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
859
- * @example
860
- * const bacnet = require('node-bacnet');
861
- * const client = new bacnet();
862
- *
863
- * const settings = {deviceId: 123}; // our BACnet device
864
- *
865
- * // Items saved from subscribeCOV message
866
- * const monitoredObject = {type: 1, instance: 1};
867
- * const subscriberProcessId = 123;
868
- *
869
- * client.confirmedCOVNotification(
870
- * '192.168.1.43',
871
- * monitoredObject,
872
- * subscriberProcessId,
873
- * settings.deviceId,
874
- * 30, // should be lifetime of subscription really
875
- * [
876
- * {
877
- * property: { id: bacnet.enum.PropertyIdentifier.PRESENT_VALUE },
878
- * value: [
879
- * {value: 123, type: bacnet.enum.ApplicationTag.REAL},
880
- * ],
881
- * },
882
- * ],
883
- * (err) => {
884
- * console.log('error: ', err);
885
- * }
886
- * );
887
- */
888
- confirmedCOVNotification(receiver, monitoredObject, subscribeId, initiatingDeviceId, lifetime, values, options, next) {
889
- next = next || options;
890
- const settings = {
891
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
892
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
893
- invokeId: options.invokeId || this._getInvokeId()
894
- };
895
- const buffer = this._getBuffer();
896
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
897
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CONFIRMED_COV_NOTIFICATION, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
898
- baServices.covNotify.encode(buffer, subscribeId, initiatingDeviceId, monitoredObject, lifetime, values);
899
- baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
900
- this.sendBvlc(receiver, buffer);
901
- this._addCallback(settings.invokeId, (err, data) => {
902
- if (err) {
903
- return void next(err);
904
- }
905
- next();
906
- });
907
- }
908
-
909
- /**
910
- * The deviceCommunicationControl command enables or disables network communication of the target device.
911
- * @function bacnet.deviceCommunicationControl
912
- * @param {string} receiver - IP address of the target device.
913
- * @param {number} timeDuration - The time to hold the network communication state in seconds. 0 for infinite.
914
- * @param {EnableDisable} enableDisable - The network communication state to set.
915
- * @param {object=} options
916
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
917
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
918
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
919
- * @param {string=} options.password - The optional password used to set the network communication state.
920
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
921
- * @example
922
- * const bacnet = require('node-bacnet');
923
- * const client = new bacnet();
924
- *
925
- * client.deviceCommunicationControl('192.168.1.43', 0, bacnet.enum.EnableDisable.DISABLE, (err) => {
926
- * console.log('error: ', err);
927
- * });
928
- */
929
- deviceCommunicationControl(receiver, timeDuration, enableDisable, options, next) {
930
- next = next || options;
931
- const settings = {
932
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
933
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
934
- invokeId: options.invokeId || this._getInvokeId(),
935
- password: options.password
936
- };
937
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
938
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
939
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.DEVICE_COMMUNICATION_CONTROL, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
940
- baServices.deviceCommunicationControl.encode(buffer, timeDuration, enableDisable, settings.password);
941
- this.sendBvlc(receiver, buffer);
942
- this._addCallback(settings.invokeId, (err, data) => {
943
- next(err);
944
- });
945
- }
946
-
947
- /**
948
- * The reinitializeDevice command initiates a restart of the target device.
949
- * @function bacnet.reinitializeDevice
950
- * @param {string} receiver - IP address of the target device.
951
- * @param {ReinitializedState} state - The type of restart to be initiated.
952
- * @param {object=} options
953
- * @param {MaxSegmentsAccepted=} options.maxSegments - The maximimal allowed number of segments.
954
- * @param {MaxApduLengthAccepted=} options.maxApdu - The maximal allowed APDU size.
955
- * @param {number=} options.invokeId - The invoke ID of the confirmed service telegram.
956
- * @param {string=} options.password - The optional password used to restart the device.
957
- * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
958
- * @example
959
- * const bacnet = require('node-bacnet');
960
- * const client = new bacnet();
961
- *
962
- * client.reinitializeDevice('192.168.1.43', bacnet.enum.ReinitializedState.COLDSTART, (err, value) => {
963
- * console.log('value: ', value);
964
- * });
965
- */
966
- reinitializeDevice(receiver, state, options, next) {
967
- next = next || options;
968
- const settings = {
969
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
970
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
971
- invokeId: options.invokeId || this._getInvokeId(),
972
- password: options.password
973
- };
974
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
975
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
976
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.REINITIALIZE_DEVICE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
977
- baServices.reinitializeDevice.encode(buffer, state, settings.password);
978
- this.sendBvlc(receiver, buffer);
979
- this._addCallback(settings.invokeId, (err, data) => {
980
- next(err);
981
- });
982
- }
983
-
984
- /**
985
- *
986
- * @param receiver
987
- * @param objectId
988
- * @param position
989
- * @param fileBuffer
990
- * @param options
991
- * @param next
992
- */
993
- writeFile(receiver, objectId, position, fileBuffer, options, next) {
994
- next = next || options;
995
- const settings = {
996
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
997
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
998
- invokeId: options.invokeId || this._getInvokeId()
999
- };
1000
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1001
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1002
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ATOMIC_WRITE_FILE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1003
- baServices.atomicWriteFile.encode(buffer, false, objectId, position, fileBuffer);
1004
- this.sendBvlc(receiver, buffer);
1005
- this._addCallback(settings.invokeId, (err, data) => {
1006
- if (err) {
1007
- return void next(err);
1008
- }
1009
- const result = baServices.atomicWriteFile.decodeAcknowledge(data.buffer, data.offset, data.length);
1010
- if (!result) {
1011
- return void next(new Error('INVALID_DECODING'));
1012
- }
1013
- next(null, result);
1014
- });
1015
- }
1016
-
1017
- /**
1018
- *
1019
- * @param receiver
1020
- * @param objectId
1021
- * @param position
1022
- * @param count
1023
- * @param options
1024
- * @param next
1025
- */
1026
- readFile(receiver, objectId, position, count, options, next) {
1027
- next = next || options;
1028
- const settings = {
1029
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1030
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1031
- invokeId: options.invokeId || this._getInvokeId()
1032
- };
1033
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1034
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1035
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ATOMIC_READ_FILE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1036
- baServices.atomicReadFile.encode(buffer, true, objectId, position, count);
1037
- this.sendBvlc(receiver, buffer);
1038
- this._addCallback(settings.invokeId, (err, data) => {
1039
- if (err) {
1040
- return void next(err);
1041
- }
1042
- const result = baServices.atomicReadFile.decodeAcknowledge(data.buffer, data.offset, data.length);
1043
- if (!result) {
1044
- return void next(new Error('INVALID_DECODING'));
1045
- }
1046
- next(null, result);
1047
- });
1048
- }
1049
-
1050
- /**
1051
- *
1052
- * @param receiver
1053
- * @param objectId
1054
- * @param idxBegin
1055
- * @param quantity
1056
- * @param options
1057
- * @param next
1058
- */
1059
- readRange(receiver, objectId, idxBegin, quantity, options, next) {
1060
- next = next || options;
1061
- const settings = {
1062
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1063
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1064
- invokeId: options.invokeId || this._getInvokeId()
1065
- };
1066
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1067
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1068
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.READ_RANGE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1069
- baServices.readRange.encode(buffer, objectId, baEnum.PropertyIdentifier.LOG_BUFFER, baEnum.ASN1_ARRAY_ALL, baEnum.ReadRangeType.BY_POSITION, idxBegin, new Date(), quantity);
1070
- this.sendBvlc(receiver, buffer);
1071
- this._addCallback(settings.invokeId, (err, data) => {
1072
- if (err) {
1073
- return void next(err);
1074
- }
1075
- const result = baServices.readRange.decodeAcknowledge(data.buffer, data.offset, data.length);
1076
- if (!result) {
1077
- return void next(new Error('INVALID_DECODING'));
1078
- }
1079
- next(null, result);
1080
- });
1081
- }
1082
-
1083
- /**
1084
- *
1085
- * @param receiver
1086
- * @param objectId
1087
- * @param subscribeId
1088
- * @param cancel
1089
- * @param issueConfirmedNotifications
1090
- * @param lifetime
1091
- * @param options
1092
- * @param next
1093
- */
1094
- subscribeCov(receiver, objectId, subscribeId, cancel, issueConfirmedNotifications, lifetime, options, next) {
1095
- next = next || options;
1096
- const settings = {
1097
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1098
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1099
- invokeId: options.invokeId || this._getInvokeId()
1100
- };
1101
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1102
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1103
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.SUBSCRIBE_COV, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1104
- baServices.subscribeCov.encode(buffer, subscribeId, objectId, cancel, issueConfirmedNotifications, lifetime);
1105
- this.sendBvlc(receiver, buffer);
1106
- this._addCallback(settings.invokeId, (err, data) => {
1107
- if (err) {
1108
- return void next(err);
1109
- }
1110
- next();
1111
- });
1112
- }
1113
-
1114
- /**
1115
- *
1116
- * @param receiver
1117
- * @param objectId
1118
- * @param monitoredProperty
1119
- * @param subscribeId
1120
- * @param cancel
1121
- * @param issueConfirmedNotifications
1122
- * @param options
1123
- * @param next
1124
- */
1125
- subscribeProperty(receiver, objectId, monitoredProperty, subscribeId, cancel, issueConfirmedNotifications, options, next) {
1126
- next = next || options;
1127
- const settings = {
1128
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1129
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1130
- invokeId: options.invokeId || this._getInvokeId()
1131
- };
1132
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1133
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1134
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.SUBSCRIBE_COV_PROPERTY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1135
- baServices.subscribeProperty.encode(buffer, subscribeId, objectId, cancel, issueConfirmedNotifications, 0, monitoredProperty, false, 0x0f);
1136
- this.sendBvlc(receiver, buffer);
1137
- this._addCallback(settings.invokeId, (err, data) => {
1138
- if (err) {
1139
- return void next(err);
1140
- }
1141
- next();
1142
- });
1143
- }
1144
-
1145
- /**
1146
- * The unconfirmedCOVNotification command sends an unconfirmed COV notification to a device
1147
- * @function bacnet.unconfirmedCOVNotification
1148
- * @param {string} receiver - IP address of the target device.
1149
- * @param {number} subscriberProcessId - The process id which was used by a target device in the subscription.
1150
- * @param {number} initiatingDeviceId - The id of this device.
1151
- * @param {object} monitoredObjectId - Specifies about which object the notification is.
1152
- * @param {number} monitoredObjectId.type - The BACNET object type of the notification.
1153
- * @param {number} monitoredObjectId.instance - The BACNET object instance of the notification.
1154
- * @param {number} timeRemaining - How long the subscription is still active in seconds.
1155
- * @param {object[]} values - List of properties with updated values.
1156
- * @param {object} values.property - Property specifications.
1157
- * @param {number} values.property.id - The updated BACNET property id.
1158
- * @param {number} values.property.index - The array index of the updated property.
1159
- * @param {object[]} values.value - A list of updated values.
1160
- * @param {ApplicationTag} values.value.type - The data-type of the updated value.
1161
- * @param {object} values.value.value - The actual updated value.
1162
- * @param {number} values.priority - The priority of the updated property.
1163
- * @example
1164
- * const bacnet = require('node-bacnet');
1165
- * const client = new bacnet();
1166
- *
1167
- * client.unconfirmedCOVNotification(
1168
- * '127.0.0.1',
1169
- * 3,
1170
- * 433,
1171
- * {type: 2, instance: 122},
1172
- * 120,
1173
- * [
1174
- * {
1175
- * property: {id: 85},
1176
- * value: [{type: baEnum.ApplicationTag.REAL, value: 12.3}]
1177
- * },
1178
- * {
1179
- * property: {id: 111},
1180
- * value: [{type: baEnum.ApplicationTag.BIT_STRING, value: 0xFFFF}]
1181
- * }
1182
- * ]);
1183
- */
1184
- unconfirmedCOVNotification(receiver, subscriberProcessId, initiatingDeviceId, monitoredObjectId, timeRemaining, values) {
1185
- const buffer = this._getBuffer();
1186
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1187
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.UNCONFIRMED_COV_NOTIFICATION);
1188
- baServices.covNotify.encode(buffer, subscriberProcessId, initiatingDeviceId, monitoredObjectId, timeRemaining, values);
1189
- baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
1190
- this._transport.send(buffer.buffer, buffer.offset, receiver);
1191
- }
1192
-
1193
- /**
1194
- *
1195
- * @param receiver
1196
- * @param objectId
1197
- * @param values
1198
- * @param options
1199
- * @param next
1200
- */
1201
- createObject(receiver, objectId, values, options, next) {
1202
- next = next || options;
1203
- const settings = {
1204
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1205
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1206
- invokeId: options.invokeId || this._getInvokeId()
1207
- };
1208
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1209
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1210
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CREATE_OBJECT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1211
- baServices.createObject.encode(buffer, objectId, values);
1212
- this.sendBvlc(receiver, buffer);
1213
- this._addCallback(settings.invokeId, (err, data) => {
1214
- if (err) {
1215
- return void next(err);
1216
- }
1217
- next();
1218
- });
1219
- }
1220
-
1221
- /**
1222
- *
1223
- * @param receiver
1224
- * @param objectId
1225
- * @param options
1226
- * @param next
1227
- */
1228
- deleteObject(receiver, objectId, options, next) {
1229
- next = next || options;
1230
- const settings = {
1231
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1232
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1233
- invokeId: options.invokeId || this._getInvokeId()
1234
- };
1235
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1236
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1237
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.DELETE_OBJECT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1238
- baServices.deleteObject.encode(buffer, objectId);
1239
- this.sendBvlc(receiver, buffer);
1240
- this._addCallback(settings.invokeId, (err, data) => {
1241
- if (err) {
1242
- return void next(err);
1243
- }
1244
- next();
1245
- });
1246
- }
1247
-
1248
- /**
1249
- *
1250
- * @param receiver
1251
- * @param objectId
1252
- * @param reference
1253
- * @param values
1254
- * @param options
1255
- * @param next
1256
- */
1257
- removeListElement(receiver, objectId, reference, values, options, next) {
1258
- next = next || options;
1259
- const settings = {
1260
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1261
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1262
- invokeId: options.invokeId || this._getInvokeId()
1263
- };
1264
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1265
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1266
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.REMOVE_LIST_ELEMENT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1267
- baServices.addListElement.encode(buffer, objectId, reference.id, reference.index, values);
1268
- this.sendBvlc(receiver, buffer);
1269
- this._addCallback(settings.invokeId, (err, data) => {
1270
- if (err) {
1271
- return void next(err);
1272
- }
1273
- next();
1274
- });
1275
- }
1276
-
1277
- /**
1278
- *
1279
- * @param receiver
1280
- * @param objectId
1281
- * @param reference
1282
- * @param values
1283
- * @param options
1284
- * @param next
1285
- */
1286
- addListElement(receiver, objectId, reference, values, options, next) {
1287
- next = next || options;
1288
- const settings = {
1289
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1290
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1291
- invokeId: options.invokeId || this._getInvokeId()
1292
- };
1293
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1294
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1295
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ADD_LIST_ELEMENT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1296
- baServices.addListElement.encode(buffer, objectId, reference.id, reference.index, values);
1297
- this.sendBvlc(receiver, buffer);
1298
- this._addCallback(settings.invokeId, (err, data) => {
1299
- if (err) {
1300
- return void next(err);
1301
- }
1302
- next();
1303
- });
1304
- }
1305
-
1306
- /**
1307
- *
1308
- * @param receiver
1309
- * @param options
1310
- * @param next
1311
- */
1312
- getAlarmSummary(receiver, options, next) {
1313
- next = next || options;
1314
- const settings = {
1315
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1316
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1317
- invokeId: options.invokeId || this._getInvokeId()
1318
- };
1319
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1320
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1321
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.GET_ALARM_SUMMARY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1322
- this.sendBvlc(receiver, buffer);
1323
- this._addCallback(settings.invokeId, (err, data) => {
1324
- if (err) {
1325
- return void next(err);
1326
- }
1327
- const result = baServices.alarmSummary.decode(data.buffer, data.offset, data.length);
1328
- if (!result) {
1329
- return void next(new Error('INVALID_DECODING'));
1330
- }
1331
- next(null, result);
1332
- });
1333
- }
1334
-
1335
- /**
1336
- *
1337
- * @param receiver
1338
- * @param objectId
1339
- * @param options
1340
- * @param next
1341
- */
1342
- getEventInformation(receiver, objectId, options, next) {
1343
- next = next || options;
1344
- const settings = {
1345
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1346
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1347
- invokeId: options.invokeId || this._getInvokeId()
1348
- };
1349
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1350
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1351
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.GET_EVENT_INFORMATION, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1352
- baAsn1.encodeContextObjectId(buffer, 0, objectId.type, objectId.instance);
1353
- this.sendBvlc(receiver, buffer);
1354
- this._addCallback(settings.invokeId, (err, data) => {
1355
- if (err) {
1356
- return void next(err);
1357
- }
1358
- const result = baServices.eventInformation.decode(data.buffer, data.offset, data.length);
1359
- if (!result) {
1360
- return void next(new Error('INVALID_DECODING'));
1361
- }
1362
- next(null, result);
1363
- });
1364
- }
1365
-
1366
- /**
1367
- *
1368
- * @param receiver
1369
- * @param objectId
1370
- * @param eventState
1371
- * @param ackText
1372
- * @param evTimeStamp
1373
- * @param ackTimeStamp
1374
- * @param options
1375
- * @param next
1376
- */
1377
- acknowledgeAlarm(receiver, objectId, eventState, ackText, evTimeStamp, ackTimeStamp, options, next) {
1378
- next = next || options;
1379
- const settings = {
1380
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1381
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1382
- invokeId: options.invokeId || this._getInvokeId()
1383
- };
1384
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1385
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1386
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ACKNOWLEDGE_ALARM, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1387
- baServices.alarmAcknowledge.encode(buffer, 57, objectId, eventState, ackText, evTimeStamp, ackTimeStamp);
1388
- this.sendBvlc(receiver, buffer);
1389
- this._addCallback(settings.invokeId, (err, data) => {
1390
- if (err) {
1391
- return void next(err);
1392
- }
1393
- next();
1394
- });
1395
- }
1396
-
1397
- /**
1398
- *
1399
- * @param receiver
1400
- * @param vendorId
1401
- * @param serviceNumber
1402
- * @param data
1403
- * @param options
1404
- * @param next
1405
- */
1406
- confirmedPrivateTransfer(receiver, vendorId, serviceNumber, data, options, next) {
1407
- next = next || options;
1408
- const settings = {
1409
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1410
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1411
- invokeId: options.invokeId || this._getInvokeId()
1412
- };
1413
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1414
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1415
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CONFIRMED_PRIVATE_TRANSFER, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1416
- baServices.privateTransfer.encode(buffer, vendorId, serviceNumber, data);
1417
- this.sendBvlc(receiver, buffer);
1418
- this._addCallback(settings.invokeId, (err, data) => {
1419
- if (err) {
1420
- return void next(err);
1421
- }
1422
- next();
1423
- });
1424
- }
1425
-
1426
- /**
1427
- *
1428
- * @param receiver
1429
- * @param vendorId
1430
- * @param serviceNumber
1431
- * @param data
1432
- */
1433
- unconfirmedPrivateTransfer(receiver, vendorId, serviceNumber, data) {
1434
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1435
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1436
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.UNCONFIRMED_PRIVATE_TRANSFER);
1437
- baServices.privateTransfer.encode(buffer, vendorId, serviceNumber, data);
1438
- this.sendBvlc(receiver, buffer);
1439
- }
1440
-
1441
- /**
1442
- *
1443
- * @param receiver
1444
- * @param acknowledgmentFilter
1445
- * @param options
1446
- * @param next
1447
- */
1448
- getEnrollmentSummary(receiver, acknowledgmentFilter, options, next) {
1449
- next = next || options;
1450
- const settings = {
1451
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1452
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1453
- invokeId: options.invokeId || this._getInvokeId()
1454
- };
1455
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1456
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1457
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.GET_ENROLLMENT_SUMMARY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1458
- baServices.getEnrollmentSummary.encode(buffer, acknowledgmentFilter, options.enrollmentFilter, options.eventStateFilter, options.eventTypeFilter, options.priorityFilter, options.notificationClassFilter);
1459
- this.sendBvlc(receiver, buffer);
1460
- this._addCallback(settings.invokeId, (err, data) => {
1461
- if (err) {
1462
- return void next(err);
1463
- }
1464
- const result = baServices.getEnrollmentSummary.decodeAcknowledge(data.buffer, data.offset, data.length);
1465
- if (!result) {
1466
- return void next(new Error('INVALID_DECODING'));
1467
- }
1468
- next(null, result);
1469
- });
1470
- }
1471
-
1472
- /**
1473
- *
1474
- * @param receiver
1475
- * @param eventNotification
1476
- */
1477
- unconfirmedEventNotification(receiver, eventNotification) {
1478
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1479
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1480
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.UNCONFIRMED_EVENT_NOTIFICATION);
1481
- baServices.eventNotifyData.encode(buffer, eventNotification);
1482
- this.sendBvlc(receiver, buffer);
1483
- }
1484
-
1485
- /**
1486
- *
1487
- * @param receiver
1488
- * @param eventNotification
1489
- * @param options
1490
- * @param next
1491
- */
1492
- confirmedEventNotification(receiver, eventNotification, options, next) {
1493
- next = next || options;
1494
- const settings = {
1495
- maxSegments: options.maxSegments || baEnum.MaxSegmentsAccepted.SEGMENTS_65,
1496
- maxApdu: options.maxApdu || baEnum.MaxApduLengthAccepted.OCTETS_1476,
1497
- invokeId: options.invokeId || this._getInvokeId()
1498
- };
1499
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1500
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBit.EXPECTING_REPLY, receiver);
1501
- baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduType.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CONFIRMED_EVENT_NOTIFICATION, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0);
1502
- baServices.eventNotifyData.encode(buffer, eventNotification);
1503
- this.sendBvlc(receiver, buffer);
1504
- this._addCallback(settings.invokeId, (err, data) => {
1505
- if (err) {
1506
- return void next(err);
1507
- }
1508
- next();
1509
- });
1510
- }
1511
-
1512
- /**
1513
- * The readPropertyResponse call sends a response with information about one of our properties.
1514
- * @function bacnet.readPropertyResponse
1515
- * @param {string} receiver - IP address of the target device.
1516
- * @param {number} invokeId - ID of the original readProperty request.
1517
- * @param {object} objectId - objectId from the original request,
1518
- * @param {object} property - property being read, taken from the original request.
1519
- * @param {object=} options varying behaviour for special circumstances
1520
- * @param {string=} options.forwardedFrom - If functioning as a BBMD, the IP address this message originally came from.
1521
- */
1522
- readPropertyResponse(receiver, invokeId, objectId, property, value, options = {}) {
1523
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1524
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1525
- baApdu.encodeComplexAck(buffer, baEnum.PduType.COMPLEX_ACK, baEnum.ConfirmedServiceChoice.READ_PROPERTY, invokeId);
1526
- baServices.readProperty.encodeAcknowledge(buffer, objectId, property.id, property.index, value);
1527
- this.sendBvlc(receiver, buffer);
1528
- }
1529
-
1530
- readPropertyMultipleResponse(receiver, invokeId, values) {
1531
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1532
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1533
- baApdu.encodeComplexAck(buffer, baEnum.PduType.COMPLEX_ACK, baEnum.ConfirmedServiceChoice.READ_PROPERTY_MULTIPLE, invokeId);
1534
- baServices.readPropertyMultiple.encodeAcknowledge(buffer, values);
1535
- this.sendBvlc(receiver, buffer);
1536
- }
1537
-
1538
- /**
1539
- * The iAmResponse command is sent as a reply to a whoIs request.
1540
- * @function bacnet.iAmResponse
1541
- * @param {object} receiver - address to send packet to, null for local broadcast.
1542
- * @param {number} deviceId - Our device ID.
1543
- * @param {number} segmentation - an enum.Segmentation value.
1544
- * @param {number} vendorId - The numeric ID assigned to the organisation providing this application.
1545
- */
1546
- iAmResponse(receiver, deviceId, segmentation, vendorId) {
1547
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1548
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1549
- baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.I_AM);
1550
- baServices.iAm.encode(buffer, deviceId, this._transport.getMaxPayload(), segmentation, vendorId);
1551
- this.sendBvlc(receiver, buffer);
1552
- }
1553
-
1554
- /**
1555
- *
1556
- * @param receiver
1557
- * @param deviceId
1558
- * @param objectId
1559
- * @param objectName
1560
- */
1561
- iHaveResponse(receiver, deviceId, objectId, objectName) {
1562
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1563
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1564
- baApdu.EecodeUnconfirmedServiceRequest(buffer, baEnum.PduType.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.I_HAVE);
1565
- baServices.iHave(buffer, deviceId, objectId, objectName);
1566
- this.sendBvlc(receiver, buffer);
1567
- }
1568
-
1569
- /**
1570
- *
1571
- * @param receiver
1572
- * @param service
1573
- * @param invokeId
1574
- */
1575
- simpleAckResponse(receiver, service, invokeId) {
1576
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1577
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1578
- baApdu.encodeSimpleAck(buffer, baEnum.PduType.SIMPLE_ACK, service, invokeId);
1579
- this.sendBvlc(receiver, buffer);
1580
- }
1581
-
1582
- /**
1583
- *
1584
- * @param receiver
1585
- * @param service
1586
- * @param invokeId
1587
- * @param errorClass
1588
- * @param errorCode
1589
- */
1590
- errorResponse(receiver, service, invokeId, errorClass, errorCode) {
1591
- trace(`error response on ${JSON.stringify(receiver)} service: ${JSON.stringify(service)} invokeId: ${invokeId} errorClass: ${errorClass} errorCode: ${errorCode}`);
1592
- trace(`error message ${baServices.error.buildMessage({ 'class': errorClass, 'code': errorCode })}`);
1593
- const buffer = this._getBuffer(receiver && receiver.forwardedFrom);
1594
- baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver);
1595
- baApdu.encodeError(buffer, baEnum.PduType.ERROR, service, invokeId);
1596
- baServices.error.encode(buffer, errorClass, errorCode);
1597
- this.sendBvlc(receiver, buffer);
1598
- }
1599
-
1600
- /**
1601
- *
1602
- * @param receiver
1603
- * @param buffer
1604
- */
1605
- sendBvlc(receiver, buffer) {
1606
- if (typeof receiver === 'string') {
1607
- receiver = {
1608
- address: receiver
1609
- };
1610
- }
1611
- if (receiver && receiver.forwardedFrom) {
1612
- // Remote node address given, forward to BBMD
1613
- baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.FORWARDED_NPDU, buffer.offset, receiver.forwardedFrom);
1614
- } else if (receiver && receiver.address) {
1615
- // Specific address, unicast
1616
- baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset);
1617
- } else {
1618
- // No address, broadcast
1619
- baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_BROADCAST_NPDU, buffer.offset);
1620
- }
1621
- this._transport.send(
1622
- buffer.buffer,
1623
- buffer.offset,
1624
- (receiver && receiver.address) || null
1625
- );
1626
- }
1627
-
1628
- /**
1629
- * The resultResponse is a BVLC-Result message used to respond to certain events, such as BBMD registration.
1630
- * This message cannot be wrapped for passing through a BBMD, as it is used as a BBMD control message.
1631
- * @function bacnet.resultResponse
1632
- * @param {string} receiver - IP address of the target device.
1633
- * @param {number} resultCode - Single value from BvlcResultFormat enum.
1634
- */
1635
- resultResponse(receiver, resultCode) {
1636
- const buffer = this._getBuffer();
1637
- baApdu.encodeResult(buffer, resultCode);
1638
- baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.BVLC_RESULT, buffer.offset);
1639
- this._transport.send(buffer.buffer, buffer.offset, receiver.address);
1640
- }
1641
-
1642
- /**
1643
- * Unloads the current bacnet instance and closes the underlying UDP socket.
1644
- * @function bacnet.close
1645
- * @example
1646
- * const bacnet = require('node-bacnet');
1647
- * const client = new bacnet();
1648
- *
1649
- * client.close();
1650
- */
1651
- close() {
1652
- this._transport.close();
1653
- }
1654
-
1655
- /**
1656
- * Helper function to take an array of enums and produce a bitstring suitable
1657
- * for inclusion as a property.
1658
- *
1659
- * @example
1660
- * [bacnet.enum.PropertyIdentifier.PROTOCOL_OBJECT_TYPES_SUPPORTED]: [
1661
- * {value: bacnet.createBitstring([
1662
- * bacnet.enum.ObjectTypesSupported.ANALOG_INPUT,
1663
- * bacnet.enum.ObjectTypesSupported.ANALOG_OUTPUT,
1664
- * ]),
1665
- * type: bacnet.enum.ApplicationTag.BIT_STRING},
1666
- * ],
1667
- */
1668
- static createBitstring(items) {
1669
- let offset = 0;
1670
- let bytes = [];
1671
- let bitsUsed = 0;
1672
- while (items.length) {
1673
- // Find any values between offset and offset+8, for the next byte
1674
- let value = 0;
1675
- items = items.filter(i => {
1676
- if (i >= offset + 8) {
1677
- return true;
1678
- } // leave for future iteration
1679
- value |= 1 << (i - offset);
1680
- bitsUsed = Math.max(bitsUsed, i);
1681
- return false; // remove from list
1682
- });
1683
- bytes.push(value);
1684
- offset += 8;
1685
- }
1686
- bitsUsed++;
1687
-
1688
- return {
1689
- value: bytes,
1690
- bitsUsed,
1691
- };
1692
- }
1693
-
1694
- }
1695
- module.exports = Client;