@@ -15,6 +15,7 @@ const baEnum = require('./enum');
1515
1616const DEFAULT_HOP_COUNT = 0xFF ;
1717const BVLC_HEADER_LENGTH = 4 ;
18+ const BVLC_FWD_HEADER_LENGTH = 10 ; // FORWARDED_NPDU
1819
1920/**
2021 * To be able to communicate to BACNET devices, you have to initialize a new bacstack instance.
@@ -91,10 +92,10 @@ class Client extends EventEmitter {
9192 } ;
9293 }
9394
94- _getBuffer ( ) {
95+ _getBuffer ( isForwarded ) {
9596 return {
9697 buffer : Buffer . alloc ( this . _transport . getMaxPayload ( ) ) ,
97- offset : BVLC_HEADER_LENGTH
98+ offset : isForwarded ? BVLC_FWD_HEADER_LENGTH : BVLC_HEADER_LENGTH
9899 } ;
99100 }
100101
@@ -797,13 +798,15 @@ class Client extends EventEmitter {
797798 const settings = {
798799 maxSegments : options . maxSegments || baEnum . MaxSegmentsAccepted . SEGMENTS_65 ,
799800 maxApdu : options . maxApdu || baEnum . MaxApduLengthAccepted . OCTETS_1476 ,
800- invokeId : options . invokeId || this . _getInvokeId ( )
801+ invokeId : options . invokeId || this . _getInvokeId ( ) ,
802+ isForwarded : ! ! options . forwardedFrom ,
803+ forwardedFrom : options . forwardedFrom || null ,
801804 } ;
802- const buffer = this . _getBuffer ( ) ;
805+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
803806 baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE | baEnum . NpduControlBits . EXPECTING_REPLY , address ) ;
804807 baApdu . encodeConfirmedServiceRequest ( buffer , baEnum . PduTypes . CONFIRMED_REQUEST , baEnum . ConfirmedServiceChoice . CONFIRMED_COV_NOTIFICATION , settings . maxSegments , settings . maxApdu , settings . invokeId , 0 , 0 ) ;
805808 baServices . covNotify . encode ( buffer , subscribeId , initiatingDeviceId , monitoredObject , lifetime , values ) ;
806- baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset ) ;
809+ baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset , settings . forwardedFrom ) ;
807810 this . _transport . send ( buffer . buffer , buffer . offset , address ) ;
808811 this . _addCallback ( settings . invokeId , ( err , data ) => {
809812 if ( err ) return next ( err ) ;
@@ -1203,63 +1206,130 @@ class Client extends EventEmitter {
12031206 }
12041207
12051208 // Public Device Functions
1206- readPropertyResponse ( receiver , invokeId , objectId , property , value ) {
1207- const buffer = this . _getBuffer ( ) ;
1209+
1210+ /**
1211+ * The readPropertyResponse call sends a response with information about one of our properties.
1212+ * @function bacstack.readPropertyResponse
1213+ * @param {string } receiver - IP address of the target device.
1214+ * @param {number } invokeId - ID of the original readProperty request.
1215+ * @param {object } objectId - objectId from the original request,
1216+ * @param {object } property - property being read, taken from the original request.
1217+ * @param {object= } options varying behaviour for special circumstances
1218+ * @param {string= } options.forwardedFrom - If functioning as a BBMD, the IP address this message originally came from.
1219+ */
1220+ readPropertyResponse ( receiver , invokeId , objectId , property , value , options = { } ) {
1221+ const settings = {
1222+ isForwarded : ! ! options . forwardedFrom ,
1223+ forwardedFrom : options . forwardedFrom || null ,
1224+ } ;
1225+
1226+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
12081227 baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE , receiver ) ;
12091228 baApdu . encodeComplexAck ( buffer , baEnum . PduTypes . COMPLEX_ACK , baEnum . ConfirmedServiceChoice . READ_PROPERTY , invokeId ) ;
12101229 baServices . readProperty . encodeAcknowledge ( buffer , objectId , property . id , property . index , value ) ;
1211- baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset ) ;
1230+ baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset , settings . forwardedFrom ) ;
12121231 this . _transport . send ( buffer . buffer , buffer . offset , receiver ) ;
12131232 }
12141233
1215- readPropertyMultipleResponse ( receiver , invokeId , values ) {
1216- const buffer = this . _getBuffer ( ) ;
1234+ readPropertyMultipleResponse ( receiver , invokeId , values , options = { } ) {
1235+ const settings = {
1236+ isForwarded : ! ! options . forwardedFrom ,
1237+ forwardedFrom : options . forwardedFrom || null ,
1238+ } ;
1239+
1240+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
12171241 baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE , receiver ) ;
12181242 baApdu . encodeComplexAck ( buffer , baEnum . PduTypes . COMPLEX_ACK , baEnum . ConfirmedServiceChoice . READ_PROPERTY_MULTIPLE , invokeId ) ;
12191243 baServices . readPropertyMultiple . encodeAcknowledge ( buffer , values ) ;
1220- baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset ) ;
1244+ baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset , settings . forwardedFrom ) ;
12211245 this . _transport . send ( buffer . buffer , buffer . offset , receiver ) ;
12221246 }
12231247
1224- iAmResponse ( deviceId , segmentation , vendorId ) {
1225- const buffer = this . _getBuffer ( ) ;
1226- baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE , this . _transport . getBroadcastAddress ( ) ) ;
1248+ /**
1249+ * The iAmResponse command is sent as a reply to a whoIs request.
1250+ * @function bacstack.iAmResponse
1251+ * @param {number } deviceId - Our device ID.
1252+ * @param {number } segmentation - an enum.Segmentation value.
1253+ * @param {number } vendorId - The numeric ID assigned to the organisation providing this application.
1254+ * @param {object= } options varying behaviour for special circumstances
1255+ * @param {string= } options.forwardedFrom - If functioning as a BBMD, the IP address this message originally came from.
1256+ * @param {string= } options.receiver - If functioning as a BBMD, the upstream device to send this message to. By default it is broadcasted to the local subnet, but this can be overridden here. An object like {net: 65535} is also permitted.
1257+ * @param {number= } options.hops - Number of hops until packet should be dropped, default 255.
1258+ */
1259+ iAmResponse ( deviceId , segmentation , vendorId , options ) {
1260+ const settings = {
1261+ isForwarded : ! ! options . forwardedFrom ,
1262+ forwardedFrom : options . forwardedFrom || null ,
1263+ receiver : options . receiver || this . _transport . getBroadcastAddress ( ) ,
1264+ hops : options . hops || DEFAULT_HOP_COUNT ,
1265+ } ;
1266+
1267+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
1268+ baNpdu . encode (
1269+ buffer ,
1270+ baEnum . NpduControlPriority . NORMAL_MESSAGE ,
1271+ settings . receiver ,
1272+ undefined ,
1273+ settings . hops
1274+ ) ;
12271275 baApdu . encodeUnconfirmedServiceRequest ( buffer , baEnum . PduTypes . UNCONFIRMED_REQUEST , baEnum . UnconfirmedServiceChoice . I_AM ) ;
12281276 baServices . iAmBroadcast . encode ( buffer , deviceId , this . _transport . getMaxPayload ( ) , segmentation , vendorId ) ;
1229- baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_BROADCAST_NPDU , buffer . offset ) ;
1230- this . _transport . send ( buffer . buffer , buffer . offset , this . _transport . getBroadcastAddress ( ) ) ;
1277+ baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_BROADCAST_NPDU , buffer . offset , settings . forwardedFrom ) ;
1278+ this . _transport . send ( buffer . buffer , buffer . offset , settings . receiver ) ;
12311279 }
12321280
1233- iHaveResponse ( deviceId , objectId , objectName ) {
1234- const buffer = this . _getBuffer ( ) ;
1281+ iHaveResponse ( deviceId , objectId , objectName , options = { } ) {
1282+ const settings = {
1283+ isForwarded : ! ! options . forwardedFrom ,
1284+ forwardedFrom : options . forwardedFrom || null ,
1285+ } ;
1286+
1287+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
12351288 baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE , this . _transport . getBroadcastAddress ( ) ) ;
12361289 baApdu . EecodeUnconfirmedServiceRequest ( buffer , baEnum . PduTypes . UNCONFIRMED_REQUEST , baEnum . UnconfirmedServiceChoice . I_HAVE ) ;
12371290 baServices . EncodeIhaveBroadcast ( buffer , deviceId , objectId , objectName ) ;
12381291 baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_BROADCAST_NPDU , buffer . offset ) ;
12391292 this . _transport . send ( buffer . buffer , buffer . offset , this . _transport . getBroadcastAddress ( ) ) ;
12401293 }
12411294
1242- simpleAckResponse ( receiver , service , invokeId ) {
1243- const buffer = this . _getBuffer ( ) ;
1295+ simpleAckResponse ( receiver , service , invokeId , options = { } ) {
1296+ const settings = {
1297+ isForwarded : ! ! options . forwardedFrom ,
1298+ forwardedFrom : options . forwardedFrom || null ,
1299+ } ;
1300+
1301+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
12441302 baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE , receiver ) ;
12451303 baApdu . encodeSimpleAck ( buffer , baEnum . PduTypes . SIMPLE_ACK , service , invokeId ) ;
1246- baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset ) ;
1304+ baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset , settings . forwardedFrom ) ;
12471305 this . _transport . send ( buffer . buffer , buffer . offset , receiver ) ;
12481306 }
12491307
1308+ /**
1309+ * The resultResponse is a BVLC-Result message used to respond to certain events, such as BBMD registration.
1310+ * This message cannot be wrapped for passing through a BBMD, as it is used as a BBMD control message.
1311+ * @function bacstack.resultResponse
1312+ * @param {string } receiver - IP address of the target device.
1313+ * @param {number } resultCode - Single value from BvlcResultFormat enum.
1314+ */
12501315 resultResponse ( receiver , resultCode ) {
12511316 const buffer = this . _getBuffer ( ) ;
12521317 baApdu . encodeResult ( buffer , resultCode ) ;
12531318 baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . BVLC_RESULT , buffer . offset ) ;
12541319 this . _transport . send ( buffer . buffer , buffer . offset , receiver ) ;
12551320 }
12561321
1257- errorResponse ( receiver , service , invokeId , errorClass , errorCode ) {
1258- const buffer = this . _getBuffer ( ) ;
1322+ errorResponse ( receiver , service , invokeId , errorClass , errorCode , options = { } ) {
1323+ const settings = {
1324+ isForwarded : ! ! options . forwardedFrom ,
1325+ forwardedFrom : options . forwardedFrom || null ,
1326+ } ;
1327+
1328+ const buffer = this . _getBuffer ( settings . isForwarded ) ;
12591329 baNpdu . encode ( buffer , baEnum . NpduControlPriority . NORMAL_MESSAGE , receiver ) ;
12601330 baApdu . encodeError ( buffer , baEnum . PduTypes . ERROR , service , invokeId ) ;
12611331 baServices . error . encode ( buffer , errorClass , errorCode ) ;
1262- baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset ) ;
1332+ baBvlc . encode ( buffer . buffer , baEnum . BvlcResultPurpose . ORIGINAL_UNICAST_NPDU , buffer . offset , settings . forwardedFrom ) ;
12631333 this . _transport . send ( buffer . buffer , buffer . offset , receiver ) ;
12641334 }
12651335
0 commit comments