// public static 메서드 #region 패킷 샘플 // 0C 00 10 00 09 1E 29 55 4E 44 40 0E 14 7B 4F 1F // 0C 00 12 00 05 1E 29 55 4E 44 41 11 99 9A 4F 1F // 0C 00 12 00 06 1E 29 55 4E 44 42 20 00 00 4F 1F // 0C 00 12 00 07 1E 29 55 4E 44 44 83 E0 00 4F 1F // 0C 00 12 00 08 1E 29 55 4E 44 3F 78 51 EC 4F 1F // 0C 00 12 00 09 1E 29 55 4E 44 3F 4F 5C 29 4F 1F // 0C 01 08 00 02 1E 29 55 4E 91 00 4F 1F // 0C 01 0A 00 02 1E 29 55 4E 91 00 4F 1F // 0C 01 0C 00 02 1E 29 55 4E 91 00 4F 1F #endregion #region 패킷 샘플(priority-array. priority 8에 Real 100.0) // 0C 00 40 00 01 // 1E 29 57 // 4E // 00 00 00 00 // 00 00 00 44 42 C8 00 00 // 00 00 00 00 // 00 00 00 00 // 4F // 1F #endregion // 수정 2015-02-06 // 기존 PRESENT_VALUE 외에 priority-array 처리 기능 추가 public static BACnetReadAccessResult GetResult(byte[] packet, int startIndex, out int index) { BACnetReadAccessResult rtn = new BACnetReadAccessResult(); int idx = startIndex; byte nowTag; byte[] nowData; nowTag = ReadTag(packet, ref idx); if (nowTag != 0x0c) { throw new BACnetPacketException("SD Context Tag 0 (Object Identifer, L=4) Tag값이 0x0C 가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } nowData = ReadValue(packet, ref idx, 4); rtn.m_ObjectIdentifier = Convert.ToUInt32((nowData[0] * 0x01000000) + (nowData[1] * 0x00010000) + (nowData[2] * 0x00000100) + (nowData[3] * 0x00000001)); nowTag = ReadTag(packet, ref idx); if (nowTag != 0x1e) { throw new BACnetPacketException("PD Opening Tag 1 (List Of Result) Tag 값이 0x1E 가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } nowTag = ReadTag(packet, ref idx); if (nowTag != 0x29) { throw new BACnetPacketException("SD Context Tag 2 (Property Identifier, L=1) Tag 값이 0x29 가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } nowData = ReadValue(packet, ref idx, 1); rtn.m_PropertyID = nowData[0]; if (rtn.m_PropertyID == 0x55) { // 0x55 = 85 = PRESENT_VALUE } else if (rtn.m_PropertyID == 0x57) { // 0x57 = 87 = priority-array } else { throw new BACnetPacketException("PropertyID 값이 0x55 (PRESENT_VALUE), 0x57 (priority-array)가 아닌 0x" + rtn.m_PropertyID.ToString("X2") + " 입니다."); } nowTag = ReadTag(packet, ref idx); if (nowTag == 0x4e) { // Property Array Index (Optional) 는 없는 것으로 가정 rtn.m_HasError = false; List <double?> listValues = new List <double?>(16); int cntValues = 1; if (rtn.m_PropertyID == 0x55) { // 0x55 = 85 = PRESENT_VALUE cntValues = 1; } else if (rtn.m_PropertyID == 0x57) { // 0x57 = 87 = priority-array cntValues = 16; } for (int idxValues = 0; idxValues < cntValues; idxValues++) { nowTag = ReadTag(packet, ref idx); if (nowTag == 0x00) { // NULL listValues.Add(null); } else if (nowTag == 0x91) { //(Enumerated, L=1) nowData = ReadValue(packet, ref idx, 1); listValues.Add((double)nowData[0]); } else if (nowTag == 0x44) { //(Real, L=4) nowData = ReadValue(packet, ref idx, 4); byte[] tempData = new byte[] { nowData[3], nowData[2], nowData[1], nowData[0] }; listValues.Add(Convert.ToDouble(BitConverter.ToSingle(tempData, 0))); } else if (nowTag == 0x21) { //(unsigned int, L=1) nowData = ReadValue(packet, ref idx, 1); listValues.Add(Convert.ToInt32(nowData[0])); } else if (nowTag == 0x22) { //(unsigned int, L=2) nowData = ReadValue(packet, ref idx, 2); byte[] tempData = new byte[] { nowData[1], nowData[0] }; listValues.Add(Convert.ToInt32(BitConverter.ToUInt16(tempData, 0))); } else { throw new BACnetPacketException("Application Tag 값이 0x91 (Enumerated, L=1), 0x44 (Real, L=4), 0x21 (unsigned int, L=1), 0x22 (unsigned int, L=2)가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } } if (rtn.m_PropertyID == 0x55) { // 0x55 = 85 = PRESENT_VALUE rtn.m_Value = (double)listValues[0]; } else if (rtn.m_PropertyID == 0x57) { // 0x57 = 87 = priority-array for (int idxValues = 0; idxValues < Math.Min(listValues.Count, rtn.m_Values.Length); idxValues++) { rtn.m_Values[idxValues] = listValues[idxValues]; } } nowTag = ReadTag(packet, ref idx); if (nowTag == 0x4f) { // PD Closing Tag 4 (Property Value) } else { throw new BACnetPacketException("PD Closing Tag 4 (Property Value) Tag 값이 0x4F 가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } } else if (nowTag == 0x5e) { rtn.m_HasError = true; nowTag = ReadTag(packet, ref idx); if (nowTag == 0x91) { nowData = ReadValue(packet, ref idx, 1); rtn.m_ErrorClass = nowData[0]; } else { throw new BACnetPacketException("Error Class 의 Application Tag 값이 0x91 (Enumerated, L=1)이 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } nowTag = ReadTag(packet, ref idx); if (nowTag == 0x91) { nowData = ReadValue(packet, ref idx, 1); rtn.m_ErrorCode = nowData[0]; } else { throw new BACnetPacketException("Error Code 의 Application Tag 값이 0x91 (Enumerated, L=1)이 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } nowTag = ReadTag(packet, ref idx); if (nowTag == 0x5f) { // PD Closing Tag 5 (Property Access Error) } else { throw new BACnetPacketException("PD Closing Tag 5 (Property Access Error) Tag 값이 0x5F 가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } } else { throw new BACnetPacketException("PD Opening Tag 값이 0x4E (Property Value), 0x5E (Property Access Error)가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } nowTag = ReadTag(packet, ref idx); if (nowTag == 0x1f) { } else { throw new BACnetPacketException("PD Closing Tag 1 (List Of Result) Tag 값이 0x1F 가 아닌 0x" + nowTag.ToString("X2") + " 입니다."); } index = idx; return(rtn); }
// public static 메서드 public static BACnetReceive ReadPacket(byte[] packet, int startIdx, out int nextIdx) { BACnetReceive rtn = new BACnetReceive(); int idx = startIdx; rtn.m_BVLCI = new BACnetVirtualLinkControlInformation(packet, idx, out idx); if (rtn.m_BVLCI.Type != 0x81) { rtn.m_IsPacketError = true; throw new BACnetPacketException("BVLCI Type 값이 0x81 이 아닙니다"); } rtn.m_HasBVLCI = true; nextIdx = startIdx + rtn.m_BVLCI.Length; if (rtn.m_BVLCI.Function != BACnetFunction.OriginalUnicastNPDU) { // Unicast 아님 rtn.m_IsUnicastNPDU = false; return(rtn); } else { rtn.m_IsUnicastNPDU = true; } rtn.m_NPCI = new NetworkProtocolControlInformation(packet, idx, out idx); rtn.m_HasNPCI = true; if ((rtn.m_NPCI.Control & 0x80) > 0) { // Network Layer Message rtn.m_IsNetworkLayerMessage = true; return(rtn); } try { rtn.m_PDUType = (BACnetPDUType)(packet[idx] & 0xf0); } catch (IndexOutOfRangeException) { throw new BACnetPacketException("PDUType 을 읽는 중 패킷의 배열 범위를 벗어났습니다."); } switch (rtn.m_PDUType) { default: case BACnetPDUType.BACnetComfirmedRequestPDU: case BACnetPDUType.BACnetUnconfirmedRequestPDU: case BACnetPDUType.SegmentACK: case BACnetPDUType.AbortPDU: rtn.m_IsInterestingAPDU = false; return(rtn); case BACnetPDUType.BACnetSimpleACKPDU: { BACnetSimpleACK simpleACK = new BACnetSimpleACK(packet, idx, out idx); rtn.m_APDU = simpleACK; rtn.m_IsInterestingAPDU = true; rtn.m_HasServiceChoice = true; rtn.m_ServiceChoice = (BACnetService)simpleACK.ServiceChoice; } break; case BACnetPDUType.BACnetComplexACKPDU: { BACnetComplexACK complexACK = new BACnetComplexACK(packet, idx, out idx); rtn.m_APDU = complexACK; rtn.m_IsInterestingAPDU = true; rtn.m_HasServiceChoice = true; rtn.m_ServiceChoice = (BACnetService)complexACK.ServiceChoice; } break; case BACnetPDUType.ErrorPDU: { BACnetErrorPDU errorPDU = new BACnetErrorPDU(packet, idx, out idx); rtn.m_APDU = errorPDU; rtn.m_IsInterestingAPDU = true; rtn.m_HasServiceChoice = true; rtn.m_ServiceChoice = (BACnetService)errorPDU.ServiceChoice; } break; case BACnetPDUType.RejectPDU: { BACnetRejectPDU rejectPDU = new BACnetRejectPDU(packet, idx, out idx); rtn.m_APDU = rejectPDU; rtn.m_IsInterestingAPDU = true; rtn.m_HasServiceChoice = false; } break; } if (rtn.m_PDUType == BACnetPDUType.BACnetComplexACKPDU) { if ((rtn.m_APDU.PDUType & 0x08) > 0) { // Has Segment // 현재, 분할 응답에 대한 처리는 되어있지 않음 rtn.m_HasSegment = true; } rtn.m_Results = new List <BACnetReadAccessResult>(20); rtn.m_HasReadAccessResult = true; try { while (idx < nextIdx) { BACnetReadAccessResult nowResult = BACnetReadAccessResult.GetResult(packet, idx, out idx); rtn.m_Results.Add(nowResult); } } catch { rtn.m_IsPacketError = true; throw; } } if (idx != nextIdx) { throw new BACnetPacketException("패킷 내용의 길이가 BVLCI 의 Length 와 일치하지 않습니다."); } return(rtn); }
public bool CheckReceiceData(byte invokeId, IList <BACnetReadAccessResult> listResult, IPEndPoint remoteEP, bool hasSNet, ushort snet, byte[] sadr) { if (m_InvokeId != invokeId) { return(false); } if (IPEndPoint.Equals(m_RemoteEP, remoteEP) != true) { return(false); } if (m_Device.HasNET != hasSNet) { return(false); } if (m_Device.HasNET == true) { if (sadr == null) { sadr = new byte[0]; } if (m_Device.NET != snet) { return(false); } if (m_Device.ADR.Length != sadr.Length) { return(false); } for (int idx = 0; idx < sadr.Length; idx++) { if (m_Device.ADR[idx] != sadr[idx]) { return(false); } } } if (listResult == null) { listResult = new BACnetReadAccessResult[0]; } if (m_Items.Count != listResult.Count) { return(false); } for (int idx = 0; idx < listResult.Count; idx++) { if (m_Items[idx].ObjectIdentifier != listResult[idx].ObjectIdentifier) { return(false); } } return(true); }