public void EncodeBACnetNew(byte[] outbuf, ref int optr) { int startBACnetPacket = optr; // BVLC Part // http://www.bacnetwiki.com/wiki/index.php?title=BACnet_Virtual_Link_Control outbuf[optr++] = BACnetEnums.BACNET_BVLC_TYPE_BIP; if (npdu.isBroadcast) { outbuf[optr++] = (byte)BACnetEnums.BACNET_BVLC_FUNCTION.BVLC_ORIGINAL_BROADCAST_NPDU; } else { outbuf[optr++] = (byte)BACnetEnums.BACNET_BVLC_FUNCTION.BVLC_ORIGINAL_UNICAST_NPDU; } int store_length_here = optr; optr += 2; // Start of NPDU // http://www.bacnetwiki.com/wiki/index.php?title=NPDU outbuf[optr++] = 0x01; // Always 1 int store_NPCI = optr; outbuf[optr++] = 0x00; // Control if (npdu.isNPDUmessage) { outbuf[store_NPCI] |= 0x80; // Indicating Network Layer Message } if (npdu.expectingReply) { outbuf[store_NPCI] |= 0x04; // todo- magic number } if (npdu.isBroadcast) { outbuf[store_NPCI] |= 0x20; // Control byte - indicate DADR present outbuf[optr++] = 0xff; // DNET Network - B'cast outbuf[optr++] = 0xff; outbuf[optr++] = 0x00; // DLEN } else { // insert dadr - but only if the device is NOT directly coupled. See page 59. If the device is directly coupled // then the ethernet address in the packet will suffice. if (!dadr.directlyConnected) { // need to insert destination DADR here outbuf[store_NPCI] |= 0x20; // Control byte - indidate DADR present dadr.Encode(outbuf, ref optr); } } // we are a router, so we need to add source address under most circumstances. (not broadcast who-is) if (srcDevice.adr != null) { outbuf[store_NPCI] |= 0x08; // Control byte - indidate SADR present srcDevice.adr.Encode(outbuf, ref optr); } if (npdu.isBroadcast || !dadr.directlyConnected) { // insert hopcount here. hopcount -= 10; outbuf[optr++] = (byte)hopcount; } // APDU start // http://www.bacnetwiki.com/wiki/index.php?title=APDU if (apdu_present) { // APDU start // http://www.bacnetwiki.com/wiki/index.php?title=APDU for (int i = 0; i < apdu_length; i++) { outbuf[optr++] = buffer[apdu_offset + i]; // Encoded APDU type == 01 == Unconfirmed Request } } else if (npdu.isNPDUmessage) { // Build the Nsdu // http://www.bacnetwiki.com/wiki/index.php?title=Network_Layer_Message outbuf[optr++] = (byte)npdu.function; switch (npdu.function) { case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK: break; case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_INIT_RT_TABLE: outbuf[optr++] = 0x00; // Number of port mappings break; case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: if (numberList != null) { foreach (uint i in numberList) { BACnetLibraryCL.InsertUint16(outbuf, ref optr, i); } } break; default: _apm.MessageTodo("m0023 Implement " + npdu.function.ToString()); break; } } else { // build an APDU. switch (this.pduType) { case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: switch (this.unconfirmedServiceChoice) { case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM: // APDU start // http://www.bacnetwiki.com/wiki/index.php?title=APDU outbuf[optr++] = 0x10; // Encoded APDU type == 01 == Unconfirmed Request outbuf[optr++] = 0x00; // Unconfirmed Service Choice: I-Am // object identifier, device object BACnetObjectIdentifier bnoid = new BACnetObjectIdentifier(); bnoid.SetType(BACnetEnums.BACNET_OBJECT_TYPE.OBJECT_DEVICE); _apm.MessageTodo("m0038 - Establish a mechanism to determine our OWN Device ID"); bnoid.SetInstance(_apm.ourDeviceId); bnoid.EncodeApplicationTag(outbuf, ref optr); // Maximum APDU length (Application Tag, Integer) Unsigned apdulen = new Unsigned(1476); apdulen.Encode(outbuf, ref optr); // Segmentation supported, (Application Tag, Enum) BACnetSegmentation bsg = new BACnetSegmentation(); bsg.Encode(outbuf, ref optr); // Vendor ID, (Application Tag, Integer) BACnetLibraryCL.InsertApplicationTagUint16(outbuf, ref optr, _apm.ourVendorID); break; default: _apm.MessageTodo("m0022 Build missing service type"); break; } break; default: _apm.MessageTodo("m0021 Build missing PDU type"); break; } } outbuf[store_length_here] = (byte)(((optr - startBACnetPacket) >> 8) & 0xff); outbuf[store_length_here + 1] = (byte)((optr - startBACnetPacket) & 0xff); }
// the better method is to populate the pkt structure, then call encode... public static void ReadPropertyObjectList_deprecated(BACnetManager bnm, Device device) { byte[] data = new byte[1024]; int optr = 0; // BVLC Part // http://www.bacnetwiki.com/wiki/index.php?title=BACnet_Virtual_Link_Control data[optr++] = BACnetEnums.BACNET_BVLC_TYPE_BIP; // 81 data[optr++] = (byte)BACnetEnums.BACNET_BVLC_FUNCTION.BVLC_ORIGINAL_UNICAST_NPDU; //0a int store_length_here = optr; optr += 2; // Start of NPDU // http://www.bacnetwiki.com/wiki/index.php?title=NPDU data[optr++] = 0x01; // Version data[optr++] = 0x24; // NCPI - Dest present, expecting reply if (device.adr != null) { device.adr.Encode(data, ref optr); } else { // this means we have an ethernet/IP address for a MAC address. At present // we then dont know the network number // todo - resolve the network number issue ADR tempAdr = new ADR(0, device.directlyConnectedIPEndPointOfDevice); tempAdr.Encode(data, ref optr); } data[optr++] = 0xff; // Hopcount // APDU start // http://www.bacnetwiki.com/wiki/index.php?title=APDU // Unconfirmed Request // Structure described here http://www.bacnetwiki.com/wiki/index.php?title=BACnet-Confirmed-Request-PDU data[optr++] = 0x02; // PDU Type=0 and SA=1 data[optr++] = 0x04; // Max Resp (Encoded) data[optr++] = 0x01; // Invoke ID data[optr++] = 0x0c; // Service Choice 12 = ReadProperty // Service Request // Object type, instance (Device Object) device.deviceObjectID.Encode(data, ref optr); // Property Identifier (Object List) data[optr++] = 0x19; // 19 Context Tag: 1, Length/Value/Type: 1 data[optr++] = 0x4c; // 4c Property Identifier: object-list (76) BACnetUtil.InsertInt16(data, ref store_length_here, optr); bnm.insideSocket.OurSendTo(data, optr, device.packet.directlyConnectedIPEndPointOfDevice); }