diff --git a/lib/asn1.js b/lib/asn1.js index 6579798a..7d2eb2ab 100644 --- a/lib/asn1.js +++ b/lib/asn1.js @@ -1077,7 +1077,7 @@ const bacappDecodeData = (buffer, offset, maxLength, tagDataType, lenValueType) }; const bacappContextTagType = (property, tagNumber) => { - let tag = 0; + let tag = tagNumber; switch (property) { case baEnum.PropertyIdentifier.ACTUAL_SHED_LEVEL: case baEnum.PropertyIdentifier.REQUESTED_SHED_LEVEL: diff --git a/lib/client.js b/lib/client.js index be8f21e1..92b2519c 100644 --- a/lib/client.js +++ b/lib/client.js @@ -44,20 +44,27 @@ class Client extends EventEmitter { this._invokeStore = {}; this._lastSequenceNumber = 0; + this._sequenceTimeout = null this._segmentStore = []; this._settings = { port: options.port || 47808, + listenPort: options.listenPort || options.port || 47808, interface: options.interface, transport: options.transport, broadcastAddress: options.broadcastAddress || '255.255.255.255', apduTimeout: options.apduTimeout || 3000 + }; + options.reuseAddr = options.reuseAddr == null ? true: options.reuseAddr; + this._transport = this._settings.transport || new baTransport({ port: this._settings.port, + listenPort: this._settings.listenPort, interface: this._settings.interface, - broadcastAddress: this._settings.broadcastAddress + broadcastAddress: this._settings.broadcastAddress, + reuseAddr: options.reuseAddr }); // Setup code @@ -146,6 +153,13 @@ class Client extends EventEmitter { } } + _handleSequenceTimeout(invokeId){ + if(this._sequenceTimeout){ + clearInterval(this._sequenceTimeout); + } + this._sequenceTimeout = setTimeout(()=>{this._lastSequenceNumber = 0},this._settings.apduTimeout); + } + _processSegment(receiver, type, service, invokeId, maxSegments, maxApdu, server, sequencenumber, proposedWindowNumber, buffer, offset, length) { let first = false; if (sequencenumber === 0 && this._lastSequenceNumber === 0) { @@ -156,6 +170,7 @@ class Client extends EventEmitter { } } this._lastSequenceNumber = sequencenumber; + this._handleSequenceTimeout(); const moreFollows = type & baEnum.PduConReqBits.MORE_FOLLOWS; if (!moreFollows) { this._lastSequenceNumber = 0; @@ -166,99 +181,99 @@ class Client extends EventEmitter { this._performDefaultSegmentHandling(this, receiver, type, service, invokeId, maxSegments, maxApdu, sequencenumber, first, moreFollows, buffer, offset, length); } - _processConfirmedServiceRequest(address, type, service, maxSegments, maxApdu, invokeId, buffer, offset, length) { + _processConfirmedServiceRequest(address, type, service, maxSegments, maxApdu, invokeId, buffer, offset, length, srcAddress,destAddress) { let result; debug('Handle this._processConfirmedServiceRequest'); if (service === baEnum.ConfirmedServiceChoice.READ_PROPERTY) { result = baServices.readProperty.decode(buffer, offset, length); if (!result) return debug('Received invalid readProperty message'); - this.emit('readProperty', {address: address, invokeId: invokeId, request: result}); + this.emit('readProperty', {address: address, invokeId: invokeId, request: result, srcAddress: srcAddress, destAddress:destAddress}); } else if (service === baEnum.ConfirmedServiceChoice.WRITE_PROPERTY) { result = baServices.writeProperty.decode(buffer, offset, length); if (!result) return debug('Received invalid writeProperty message'); - this.emit('writeProperty', {address: address, invokeId: invokeId, request: result}); + this.emit('writeProperty', {address: address, invokeId: invokeId, request: result, srcAddress: srcAddress, destAddress:destAddress}); } else if (service === baEnum.ConfirmedServiceChoice.READ_PROPERTY_MULTIPLE) { result = baServices.readPropertyMultiple.decode(buffer, offset, length); if (!result) return debug('Received invalid readPropertyMultiple message'); - this.emit('readPropertyMultiple', {address: address, invokeId: invokeId, request: result}); + this.emit('readPropertyMultiple', {address: address, invokeId: invokeId, request: result, srcAddress: srcAddress, destAddress:destAddress}); } else if (service === baEnum.ConfirmedServiceChoice.WRITE_PROPERTY_MULTIPLE) { result = baServices.writePropertyMultiple.decode(buffer, offset, length); if (!result) return debug('Received invalid writePropertyMultiple message'); - this.emit('writePropertyMultiple', {address: address, invokeId: invokeId, request: result}); + this.emit('writePropertyMultiple', {address: address, invokeId: invokeId, request: result, srcAddress: srcAddress, destAddress:destAddress}); } else if (service === baEnum.ConfirmedServiceChoice.CONFIRMED_COV_NOTIFICATION) { result = baServices.covNotify.decode(buffer, offset, length); if (!result) return debug('Received invalid covNotify message'); - this.emit('covNotify', {address: address, invokeId: invokeId, request: result}); + this.emit('covNotify', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.ATOMIC_WRITE_FILE) { result = baServices.atomicWriteFile.decode(buffer, offset, length); if (!result) return debug('Received invalid atomicWriteFile message'); - this.emit('atomicWriteFile', {address: address, invokeId: invokeId, request: result}); + this.emit('atomicWriteFile', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.ATOMIC_READ_FILE) { result = baServices.atomicReadFile.decode(buffer, offset, length); if (!result) return debug('Received invalid atomicReadFile message'); - this.emit('atomicReadFile', {address: address, invokeId: invokeId, request: result}); + this.emit('atomicReadFile', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.SUBSCRIBE_COV) { result = baServices.subscribeCov.decode(buffer, offset, length); if (!result) return debug('Received invalid subscribeCOV message'); - this.emit('subscribeCOV', {address: address, invokeId: invokeId, request: result}); + this.emit('subscribeCOV', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.SUBSCRIBE_COV_PROPERTY) { result = baServices.subscribeProperty.decode(buffer, offset, length); if (!result) return debug('Received invalid subscribeProperty message'); - this.emit('subscribeProperty', {address: address, invokeId: invokeId, request: result}); + this.emit('subscribeProperty', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.DEVICE_COMMUNICATION_CONTROL) { result = baServices.deviceCommunicationControl.decode(buffer, offset, length); if (!result) return debug('Received invalid deviceCommunicationControl message'); - this.emit('deviceCommunicationControl', {address: address, invokeId: invokeId, request: result}); + this.emit('deviceCommunicationControl', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.REINITIALIZE_DEVICE) { result = baServices.reinitializeDevice.decode(buffer, offset, length); if (!result) return debug('Received invalid reinitializeDevice message'); - this.emit('reinitializeDevice', {address: address, invokeId: invokeId, request: result}); + this.emit('reinitializeDevice', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.CONFIRMED_EVENT_NOTIFICATION) { result = baServices.eventNotifyData.decode(buffer, offset, length); if (!result) return debug('Received invalid eventNotifyData message'); - this.emit('eventNotifyData', {address: address, invokeId: invokeId, request: result}); + this.emit('eventNotifyData', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.READ_RANGE) { result = baServices.readRange.decode(buffer, offset, length); if (!result) return debug('Received invalid readRange message'); - this.emit('readRange', {address: address, invokeId: invokeId, request: result}); + this.emit('readRange', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.CREATE_OBJECT) { result = baServices.createObject.decode(buffer, offset, length); if (!result) return debug('Received invalid createObject message'); - this.emit('createObject', {address: address, invokeId: invokeId, request: result}); + this.emit('createObject', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.DELETE_OBJECT) { result = baServices.deleteObject.decode(buffer, offset, length); if (!result) return debug('Received invalid deleteObject message'); - this.emit('deleteObject', {address: address, invokeId: invokeId, request: result}); + this.emit('deleteObject', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.ACKNOWLEDGE_ALARM) { result = baServices.alarmAcknowledge.decode(buffer, offset, length); if (!result) return debug('Received invalid alarmAcknowledge message'); - this.emit('alarmAcknowledge', {address: address, invokeId: invokeId, request: result}); + this.emit('alarmAcknowledge', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.GET_ALARM_SUMMARY) { this.emit('getAlarmSummary', {address: address, invokeId: invokeId}); } else if (service === baEnum.ConfirmedServiceChoice.GET_ENROLLMENT_SUMMARY) { result = baServices.getEnrollmentSummary.decode(buffer, offset, length); if (!result) return debug('Received invalid getEntrollmentSummary message'); - this.emit('getEntrollmentSummary', {address: address, invokeId: invokeId, request: result}); + this.emit('getEntrollmentSummary', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.GET_EVENT_INFORMATION) { result = baServices.getEventInformation.decode(buffer, offset, length); if (!result) return debug('Received invalid getEventInformation message'); - this.emit('getEventInformation', {address: address, invokeId: invokeId, request: result}); + this.emit('getEventInformation', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.LIFE_SAFETY_OPERATION) { result = baServices.lifeSafetyOperation.decode(buffer, offset, length); if (!result) return debug('Received invalid lifeSafetyOperation message'); - this.emit('lifeSafetyOperation', {address: address, invokeId: invokeId, request: result}); + this.emit('lifeSafetyOperation', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.ADD_LIST_ELEMENT) { result = baServices.addListElement.decode(buffer, offset, length); if (!result) return debug('Received invalid addListElement message'); - this.emit('addListElement', {address: address, invokeId: invokeId, request: result}); + this.emit('addListElement', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.REMOVE_LIST_ELEMENT) { result = baServices.addListElement.decode(buffer, offset, length); if (!result) return debug('Received invalid removeListElement message'); - this.emit('removeListElement', {address: address, invokeId: invokeId, request: result}); + this.emit('removeListElement', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else if (service === baEnum.ConfirmedServiceChoice.CONFIRMED_PRIVATE_TRANSFER) { result = baServices.privateTransfer.decode(buffer, offset, length); if (!result) return debug('Received invalid privateTransfer message'); - this.emit('privateTransfer', {address: address, invokeId: invokeId, request: result}); + this.emit('privateTransfer', {address: address, invokeId: invokeId, request: result, srcAddress:srcAddress}); } else { debug('Received unsupported confirmed service request'); } @@ -374,7 +389,7 @@ class Client extends EventEmitter { } } - _handlePdu(address, type, buffer, offset, length, addressObject) { + _handlePdu(address, type, buffer, offset, length, addressObject, destAddressObject) { let result; // Handle different PDU types switch (type & baEnum.PDU_TYPE_MASK) { @@ -413,7 +428,7 @@ class Client extends EventEmitter { case baEnum.PduTypes.CONFIRMED_REQUEST: result = baApdu.decodeConfirmedServiceRequest(buffer, offset); if ((type & baEnum.PduConReqBits.SEGMENTED_MESSAGE) === 0) { - this._processConfirmedServiceRequest(address, result.type, result.service, result.maxSegments, result.maxApdu, result.invokeId, buffer, offset + result.len, length - result.len); + this._processConfirmedServiceRequest(address, result.type, result.service, result.maxSegments, result.maxApdu, result.invokeId, buffer, offset + result.len, length - result.len, addressObject , destAddressObject ); } else { this._processSegment(address, result.type, result.service, result.invokeId, result.maxSegments, result.maxApdu, true, result.sequencenumber, result.proposedWindowNumber, buffer, offset + result.len, length - result.len); } @@ -429,13 +444,21 @@ class Client extends EventEmitter { if (msgLength <= 0) return debug('No NPDU data -> Drop package'); // Parse baNpdu header const result = baNpdu.decode(buffer, offset); - var addressObject; + var addressObject, destAddress; + // @todo a MSTP Dest & Source could occur. this case is not handled. if(typeof(result.source) != 'undefined'){ addressObject = result.source; addressObject.ip = remoteAddress; - }else{ + }else{ addressObject = remoteAddress; - } + } + + if(typeof(result.destination) != 'undefined'){ + destAddress = result.destination; + destAddress.ip = remoteAddress; + }else{ + destAddress = remoteAddress; + } if (!result) return debug('Received invalid NPDU header -> Drop package'); if (result.funct & baEnum.NpduControlBits.NETWORK_LAYER_MESSAGE) { @@ -445,7 +468,7 @@ class Client extends EventEmitter { msgLength -= result.len; if (msgLength <= 0) return debug('No APDU data -> Drop package'); const apduType = baApdu.getDecodedType(buffer, offset); - this._handlePdu(remoteAddress, apduType, buffer, offset, msgLength,addressObject); + this._handlePdu(remoteAddress, apduType, buffer, offset, msgLength,addressObject,destAddress); } _receiveData(buffer, remoteAddress) { @@ -583,6 +606,9 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId(), arrayIndex: options.arrayIndex || baEnum.ASN1_ARRAY_ALL }; + if(options.arrayIndex != undefined){ + settings.arrayIndex = options.arrayIndex; + } const buffer = this._getBuffer(); baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); const type = baEnum.PduTypes.CONFIRMED_REQUEST | (settings.maxSegments !== baEnum.MaxSegmentsAccepted.SEGMENTS_0 ? baEnum.PduConReqBits.SEGMENTED_RESPONSE_ACCEPTED : 0); @@ -779,7 +805,7 @@ class Client extends EventEmitter { password: options.password }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.DEVICE_COMMUNICATION_CONTROL, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.deviceCommunicationControl.encode(buffer, timeDuration, enableDisable, settings.password); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); @@ -817,11 +843,12 @@ class Client extends EventEmitter { password: options.password }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0 ); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.REINITIALIZE_DEVICE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.reinitializeDevice.encode(buffer, state, settings.password); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { next(err); }); @@ -835,11 +862,13 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0 ); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ATOMIC_WRITE_FILE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); - baServices.atomicWriteFile.encode(buffer, false, objectId, position, fileBuffer); + // Edit, enforcing 'stream' + baServices.atomicWriteFile.encode(buffer, true, objectId, position, fileBuffer); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); const result = baServices.atomicWriteFile.decodeAcknowledge(data.buffer, data.offset, data.length); @@ -856,11 +885,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ATOMIC_READ_FILE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.atomicReadFile.encode(buffer, true, objectId, position, count); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); const result = baServices.atomicReadFile.decodeAcknowledge(data.buffer, data.offset, data.length); @@ -877,11 +907,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.READ_RANGE, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.readRange.encode(buffer, objectId, baEnum.PropertyIdentifier.LOG_BUFFER, baEnum.ASN1_ARRAY_ALL, baEnum.ReadRangeType.BY_POSITION, idxBegin, new Date(), quantity); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); const result = baServices.readRange.decodeAcknowledge(data.buffer, data.offset, data.length); @@ -898,11 +929,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.SUBSCRIBE_COV, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.subscribeCov.encode(buffer, subscribeId, objectId, cancel, issueConfirmedNotifications, lifetime); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -917,11 +949,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.SUBSCRIBE_COV_PROPERTY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.subscribeProperty.encode(buffer, subscribeId, objectId, cancel, issueConfirmedNotifications, 0, monitoredProperty, false, 0x0f); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -936,11 +969,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, null , DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CREATE_OBJECT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.createObject.encode(buffer, objectId, values); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -955,11 +989,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.DELETE_OBJECT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.deleteObject.encode(buffer, objectId); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -974,11 +1009,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.REMOVE_LIST_ELEMENT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.addListElement.encode(buffer, objectId, reference.id, reference.index, values); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -993,11 +1029,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ADD_LIST_ELEMENT, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.addListElement.encode(buffer, objectId, reference.id, reference.index, values); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -1012,10 +1049,11 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.GET_ALARM_SUMMARY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); const result = baServices.alarmSummary.decode(data.buffer, data.offset, data.length); @@ -1032,11 +1070,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.GET_EVENT_INFORMATION, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baAsn1.encodeContextObjectId(buffer, 0, objectId.type, objectId.instance); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); const result = baServices.eventInformation.decode(data.buffer, data.offset, data.length); @@ -1053,11 +1092,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.ACKNOWLEDGE_ALARM, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.alarmAcknowledge.encode(buffer, 57, objectId, eventState, ackText, evTimeStamp, ackTimeStamp); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -1072,11 +1112,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CONFIRMED_PRIVATE_TRANSFER, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.privateTransfer.encode(buffer, vendorId, serviceNumber, data); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); next(); @@ -1085,11 +1126,12 @@ class Client extends EventEmitter { unconfirmedPrivateTransfer(address, vendorId, serviceNumber, data) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduTypes.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.UNCONFIRMED_PRIVATE_TRANSFER); baServices.privateTransfer.encode(buffer, vendorId, serviceNumber, data); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); } getEnrollmentSummary(address, acknowledgmentFilter, options, next) { @@ -1100,11 +1142,12 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.GET_ENROLLMENT_SUMMARY, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.getEnrollmentSummary.encode(buffer, acknowledgmentFilter, options.enrollmentFilter, options.eventStateFilter, options.eventTypeFilter, options.priorityFilter, options.notificationClassFilter); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); const result = baServices.getEnrollmentSummary.decodeAcknowledge(data.buffer, data.offset, data.length); @@ -1115,11 +1158,12 @@ class Client extends EventEmitter { unconfirmedEventNotification(address, eventNotification) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduTypes.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.UNCONFIRMED_EVENT_NOTIFICATION); baServices.eventNotifyData.encode(buffer, eventNotification); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, address); + var sendAddress = typeof(address) != 'string' ? address.ip : address; + this._transport.send(buffer.buffer, buffer.offset, sendAddress); } confirmedEventNotification(address, eventNotification, options, next) { @@ -1130,10 +1174,11 @@ class Client extends EventEmitter { invokeId: options.invokeId || this._getInvokeId() }; const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE | baEnum.NpduControlBits.EXPECTING_REPLY, address, DEFAULT_HOP_COUNT, baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK, 0); baApdu.encodeConfirmedServiceRequest(buffer, baEnum.PduTypes.CONFIRMED_REQUEST, baEnum.ConfirmedServiceChoice.CONFIRMED_EVENT_NOTIFICATION, settings.maxSegments, settings.maxApdu, settings.invokeId, 0, 0); baServices.eventNotifyData.encode(buffer, eventNotification); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); + var sendAddress = typeof(address) != 'string' ? address.ip : address; this._transport.send(buffer.buffer, buffer.offset, address); this._addCallback(settings.invokeId, (err, data) => { if (err) return next(err); @@ -1142,31 +1187,37 @@ class Client extends EventEmitter { } // Public Device Functions - readPropertyResponse(receiver, invokeId, objectId, property, value) { + readPropertyResponse(receiver, invokeId, objectId, property, value,source) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE,receiver,source); baApdu.encodeComplexAck(buffer, baEnum.PduTypes.COMPLEX_ACK, baEnum.ConfirmedServiceChoice.READ_PROPERTY, invokeId); baServices.readProperty.encodeAcknowledge(buffer, objectId, property.id, property.index, value); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); this._transport.send(buffer.buffer, buffer.offset, receiver); } - readPropertyMultipleResponse(receiver, invokeId, values) { + readPropertyMultipleResponse(receiver, invokeId, values,source) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver,source); baApdu.encodeComplexAck(buffer, baEnum.PduTypes.COMPLEX_ACK, baEnum.ConfirmedServiceChoice.READ_PROPERTY_MULTIPLE, invokeId); baServices.readPropertyMultiple.encodeAcknowledge(buffer, values); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); this._transport.send(buffer.buffer, buffer.offset, receiver); } - iAmResponse(deviceId, segmentation, vendorId) { + /** + * Responds to both broadcast and unicast I-AM responses + * @function bacstack.iAmResponse + */ + iAmResponse(deviceId, segmentation, vendorId, destAddress,srcAddress) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, this._transport.getBroadcastAddress()); + var dAddress = destAddress == undefined ? this._transport.getBroadcastAddress() : destAddress; + var sAddress = srcAddress == undefined ? this._transport.getBroadcastAddress() : srcAddress; + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, dAddress , sAddress ); baApdu.encodeUnconfirmedServiceRequest(buffer, baEnum.PduTypes.UNCONFIRMED_REQUEST, baEnum.UnconfirmedServiceChoice.I_AM); baServices.iAmBroadcast.encode(buffer, deviceId, this._transport.getMaxPayload(), segmentation, vendorId); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_BROADCAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, this._transport.getBroadcastAddress()); + this._transport.send(buffer.buffer, buffer.offset, dAddress); } iHaveResponse(deviceId, objectId, objectName) { @@ -1180,15 +1231,16 @@ class Client extends EventEmitter { simpleAckResponse(receiver, service, invokeId) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver); + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver, null, DEFAULT_HOP_COUNT); baApdu.encodeSimpleAck(buffer, baEnum.PduTypes.SIMPLE_ACK, service, invokeId); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); - this._transport.send(buffer.buffer, buffer.offset, receiver); + this._transport.send(buffer.buffer, buffer.offset, receiver.ip || receiver.address ); } - errorResponse(receiver, service, invokeId, errorClass, errorCode) { + errorResponse(receiver, service, invokeId, errorClass, errorCode,srcAddress) { const buffer = this._getBuffer(); - baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver); + var sAddress = srcAddress == undefined ? this._transport.getBroadcastAddress() : srcAddress; + baNpdu.encode(buffer, baEnum.NpduControlPriority.NORMAL_MESSAGE, receiver,sAddress); baApdu.encodeError(buffer, baEnum.PduTypes.ERROR, service, invokeId); baServices.error.encode(buffer, errorClass, errorCode); baBvlc.encode(buffer.buffer, baEnum.BvlcResultPurpose.ORIGINAL_UNICAST_NPDU, buffer.offset); diff --git a/lib/services/read-property.js b/lib/services/read-property.js index 63e877cb..9db37ab1 100644 --- a/lib/services/read-property.js +++ b/lib/services/read-property.js @@ -11,7 +11,9 @@ module.exports.encode = (buffer, objectType, objectInstance, propertyId, arrayIn baAsn1.encodeContextEnumerated(buffer, 1, propertyId); } if (arrayIndex !== baEnum.ASN1_ARRAY_ALL) { - baAsn1.encodeContextUnsigned(buffer, 2, arrayIndex || baEnum.ASN1_ARRAY_ALL); + //baAsn1.encodeContextUnsigned(buffer, 2, arrayIndex || baEnum.ASN1_ARRAY_ALL); + // Want to encode 0 + baAsn1.encodeContextUnsigned(buffer, 2, arrayIndex) } }; diff --git a/lib/services/write-property-multiple.js b/lib/services/write-property-multiple.js index 6f5dd4d3..bb3536c6 100644 --- a/lib/services/write-property-multiple.js +++ b/lib/services/write-property-multiple.js @@ -84,6 +84,9 @@ module.exports.decode = (buffer, offset, apduLen) => { } newEntry.priority = priority; _values.push(newEntry); + if (baAsn1.decodeIsClosingTagNumber(buffer, offset + len, 1)){ + len++; + } } if (!baAsn1.decodeIsClosingTagNumber(buffer, offset + len, 1)) return; len++; diff --git a/lib/transport.js b/lib/transport.js index 721574d9..6a3c9c83 100644 --- a/lib/transport.js +++ b/lib/transport.js @@ -7,9 +7,15 @@ class Transport extends EventEmitter { constructor(settings) { super(); this._settings = settings; - this._server = createSocket({type: 'udp4', reuseAddr: true}); + this._server = createSocket({type: 'udp4', reuseAddr: settings.reuseAddr}); this._server.on('message', (msg, rinfo) => this.emit('message', msg, rinfo.address)); - this._server.on('error', (err) => this.emit('message', err)); + this._server.on('error', (err) => { + if(err.message.includes('bind') || err.message.includes('EADDRINUSE')){ + console.log('Error, failed to bind bacnet port',err); + throw(err); + } + this.emit('message', err); + }); } getBroadcastAddress() { @@ -25,7 +31,7 @@ class Transport extends EventEmitter { } open() { - this._server.bind(this._settings.port, this._settings.interface, () => { + this._server.bind(this._settings.listenPort, this._settings.interface, () => { this._server.setBroadcast(true); }); } diff --git a/package.json b/package.json index efad8fca..6742e6cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "natezimmer_bacstack", - "version": "0.0.1-beta.19", + "version": "0.0.1-beta.26", "description": "A BACnet protocol stack written in pure JavaScript.", "main": "index.js", "scripts": {