private void DecodeConfirmedService(byte[] apdu_buf) { if ((apdu_buf[0] & 0x08) != 0) { _apm.MessageTodo("m0002 Need to implement confirmed service types with seg=1 still"); return; } int iptr = 3; confirmedServiceChoice = (BACnetEnums.BACNET_CONFIRMED_SERVICE)apdu_buf[iptr++]; apduConfirmedServiceTypeFlag = true; switch (confirmedServiceChoice) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: // Expecting 2-3 context tags. // First, mandatory, context 0, object ID objectID = new BACnetObjectIdentifier(); objectID.DecodeContextTag(apdu_buf, ref iptr); // Second, mandatory, Property ID propertyID = (BACnetEnums.BACNET_PROPERTY_ID)BACnetEncoding.DecodeTagContextUint(apdu_buf, ref iptr, 1); // Third, Array Index, Optional if (iptr < apdu_length) { arrayIndex = (int)BACnetEncoding.DecodeTagContextUint(apdu_buf, ref iptr, 2); arrayIndexDecoded = true; } break; default: _apm.MessageTodo("m0024 all the other service types"); break; } }
void DecodeComplexACK(byte[] buf, int offset) { if ((buf[offset] & 0x0f) != 0) { throw new Exception("m0020 - Not ready to handle segmented messages yet"); } // invoke ID - ignoring for now // Service ACK choice BACnetEnums.BACNET_CONFIRMED_SERVICE sc = (BACnetEnums.BACNET_CONFIRMED_SERVICE)buf[offset + 2]; switch (sc) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: offset += 3; // Decode Object ID of the object whos property we are reading BACnetObjectIdentifier oid = new BACnetObjectIdentifier(buf, ref offset, BACnetEnums.TAG.CONTEXT, 0); // Decode the property ID propertyID = (BACnetEnums.BACNET_PROPERTY_ID)BACnetEncoding.DecodeTagContextUint(buf, ref offset, 1); // Now decode the Property Value itself. Variable encoding, variable length, etc.... switch (oid.objectType) { case BACnetEnums.BACNET_OBJECT_TYPE.OBJECT_DEVICE: switch (propertyID) { case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_LIST: // decode the list of objects // process the opening context tag, 0x3e if (buffer[offset++] != 0x3e) { throw new Exception("m0033 - Opening context tag not found " + buffer[offset - 1].ToString()); } objectList = new List <BACnetObjectIdentifier>(); // now loop until closing tag found while (buffer[offset] != 0x3f) { // we should get a list of object IDs, add these to our backnet packet object as they are discovered. objectList.Add(new BACnetObjectIdentifier(buffer, ref offset, BACnetEnums.TAG.APPLICATION, BACnetEnums.BACNET_APPLICATION_TAG.BACNET_APPLICATION_TAG_OBJECT_ID)); } break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_NAME: _apm.MessageTodo("m0032 - Decode object name"); break; default: _apm.MessageTodo("m0026 Unimplemented Property ID " + propertyID.ToString()); break; } break; default: _apm.MessageTodo("m0061 Unhandled object type " + oid.objectType.ToString()); break; } break; default: _apm.MessageTodo("m0028 - Not ready to deal with this service yet " + sc.ToString()); return; } }
private bool DecodeUnconfirmedService(byte[] apdu_buf, int apduLen) { // todo, this code assumes that the service is encoded in postion number one. This is not always the case. Resolve if ((apdu_buf[0] & 0x0f) != 0) { _apm.MessageProtocolError("m0025 this nibble should be zero for Unconfirmed services"); return(false); } if (apdu_buf[1] == (byte)BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_WHO_IS) { // http://www.bacnetwiki.com/wiki/index.php?title=Who-Is apduUnconfirmedServiceFlag = true; unconfirmedServiceChoice = BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_WHO_IS; if (apduLen != 2) { int offset = 2; // means we must have a low and high range.. lowRange = BACnetEncoding.DecodeTagContextUint(apdu_buf, ref offset, 0); highRange = BACnetEncoding.DecodeTagContextUint(apdu_buf, ref offset, 1); } // and for now, we will assume only workstations issue who-is messages. this.srcDevice.type = BACnetEnums.DEVICE_TYPE.Workstation; } else if (apdu_buf[1] == (byte)BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM) { apduUnconfirmedServiceFlag = true; unconfirmedServiceChoice = BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM; // I-Am described right here: http://www.bacnetwiki.com/wiki/index.php?title=I-Am // first encoded entity is the Device Identifier... // Encoding described here: http://www.bacnetwiki.com/wiki/index.php?title=Encoding // Decode Device Identifier int offset = 2; srcDevice.deviceObjectID.DecodeApplicationTag(apdu_buf, ref offset); Console.WriteLine("This is device: " + srcDevice.deviceObjectID); // todo, for now, we will ignore device insance xxx if received // and we are the client (bacnet browser ) srcDevice.packet = this; uint maxAPDULen; offset += BACnetEncoding.BACnetDecode_uint(apdu_buf, offset, out maxAPDULen); Console.WriteLine("Max APDU length accepted: " + maxAPDULen); uint segmentation_supported; offset += BACnetEncoding.BACnetDecode_uint(apdu_buf, offset, out segmentation_supported); Console.WriteLine("Segmentation Supported: " + segmentation_supported); srcDevice.SegmentationSupported = (BACnetEnums.BACNET_SEGMENTATION)segmentation_supported; uint vendorId; offset += BACnetEncoding.BACnetDecode_uint(apdu_buf, offset, out vendorId); Console.WriteLine("VendorId: " + vendorId); srcDevice.VendorId = vendorId; } return(true); }