Ejemplo n.º 1
0
        // 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);
        }
Ejemplo n.º 2
0
        // 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);
        }