Exemplo n.º 1
0
        /// <summary>
        ///     Read Property.
        /// </summary>
        /// <param name="recipient">The recipient.</param>
        /// <param name="arrayidx">The arrayidx.</param>
        /// <param name="objtype">The objtype.</param>
        /// <param name="objprop">The objprop.</param>
        /// <param name="property">The property.</param>
        /// <returns></returns>
        public bool SendReadProperty(
            Device recipient,
            int arrayidx,
            BacnetEnums.BacnetObjectType objtype,
            BacnetEnums.BacnetPropertyId objprop,
            Property property)
        {
            // Create and send an Confirmed Request

            //value = "(none)";
            if (recipient == null)
            {
                return(false);
            }

            if (property == null)
            {
                return(false);
            }

            //uint instance = BACnetData.Devices[deviceidx].Instance;

            var sendBytes = new byte[50];

            // BVLL
            sendBytes[0] = Bvlc.BacnetBvlcTypeBip;
            sendBytes[1] = Bvlc.BacnetBvlcFuncUnicastNpdu;
            sendBytes[2] = 0x00;
            sendBytes[3] = 0x00; // BVLL Length, fix later (24?)

            // NPDU
            sendBytes[4] = BacnetEnums.BacnetProtocolVersion;
            if (recipient.SourceLength == 0)
            {
                sendBytes[5] = 0x04; // Control flags, no destination address
            }
            else
            {
                sendBytes[5] = 0x24; // Control flags, with broadcast or destination address
            }
            uint len = 6;

            if (recipient.SourceLength > 0)
            {
                // Get the (MSTP) Network number (2001)
                var temp2 = BitConverter.GetBytes(recipient.Network);
                sendBytes[len++] = temp2[1];
                sendBytes[len++] = temp2[0];

                // Get the MAC address (0x0D)
                var temp4 = BitConverter.GetBytes(recipient.MacAddress);

                sendBytes[len++] = 0x01; // MAC address length - adjust for other lengths ...
                sendBytes[len++] = temp4[0];
                sendBytes[len++] = 0xFF; // Hop count = 255
            }

            // APDU
            sendBytes[len++] = 0x00; // Control flags
            sendBytes[len++] = 0x05; // Max APDU length (1476)

            // Create invoke counter
            sendBytes[len++] = (byte)(invokeCounter);
            invokeCounter    = ((invokeCounter + 1) & 0xFF);

            sendBytes[len++] = 0x0C; // Service Choice: Read Property request

            // Service Request (var part of APDU):
            // Set up Object ID (Context Tag)
            len = Apdu.SetObjectId(ref sendBytes, len, objtype, recipient.Instance);

            // Set up Property ID (Context Tag)
            len = Apdu.SetPropertyId(ref sendBytes, len, objprop);

            // Optional array index goes here
            if (arrayidx >= 0)
            {
                len = Apdu.SetArrayIdx(ref sendBytes, len, arrayidx);
            }

            // Fix the BVLL length
            sendBytes[3] = (byte)len;

            var getResponse = false;
            var count       = 0;

            while (count < BacnetUnicastRequestRepeatCount && !getResponse)
            {
                sendUdp.EnableBroadcast = false;
                sendUdp.Send(sendBytes, (int)len, recipient.ServerEp);

                while (!getResponse)
                {
                    if (sendUdp.Client.Available <= 0)
                    {
                        continue;
                    }
                    //recvBytes = SendUDP.Receive(ref RemoteEP);
                    var sendTo    = recipient.ServerEp;
                    var recvBytes = sendUdp.Receive(ref sendTo);

                    var apduOffset = Npdu.Parse(recvBytes, Bvlc.BacnetBvlcHeaderLen); // BVLL is always 4 bytes

                    // Check for APDU response
                    // 0x - Confirmed Request
                    // 1x - Un-Confirmed Request
                    // 2x - Simple ACK
                    // 3x - Complex ACK
                    // 4x - Segment ACK
                    // 5x - Error
                    // 6x - Reject
                    // 7x - Abort
                    if (recvBytes[apduOffset] != 0x30)
                    {
                        continue;
                    }
                    // Verify the Invoke ID is the same
                    var ic = (byte)(invokeCounter == 0 ? 255 : invokeCounter - 1);
                    if (ic != recvBytes[apduOffset + 1])
                    {
                        continue;
                    }
                    Apdu.ParseProperty(ref recvBytes, apduOffset, property);
                    getResponse = true; // This will still execute the finally
                }

                count++;
            }
            return(getResponse);
        }