예제 #1
0
        public static int Decode(byte[] buffer, int offset, int max_length, out BacnetMstpFrameTypes frame_type, out byte destination_address, out byte source_address, out int msg_length)
        {
            frame_type          = (BacnetMstpFrameTypes)buffer[offset + 2];
            destination_address = buffer[offset + 3];
            source_address      = buffer[offset + 4];
            msg_length          = (buffer[offset + 5] << 8) | (buffer[offset + 6] << 0);
            byte   crc_header = buffer[offset + 7];
            ushort crc_data   = 0;

            if (max_length < MSTP_HEADER_LENGTH)
            {
                return(-1);                                     //not enough data
            }
            if (msg_length > 0)
            {
                crc_data = (ushort)((buffer[offset + 8 + msg_length + 1] << 8) | (buffer[offset + 8 + msg_length + 0] << 0));
            }
            if (buffer[offset + 0] != MSTP_PREAMBLE1)
            {
                return(-1);
            }
            if (buffer[offset + 1] != MSTP_PREAMBLE2)
            {
                return(-1);
            }
            if (CRC_Calc_Header(buffer, offset + 2, 5) != crc_header)
            {
                return(-1);
            }
            if (msg_length > 0 && max_length >= (MSTP_HEADER_LENGTH + msg_length + 2) && CRC_Calc_Data(buffer, offset + 8, msg_length) != crc_data)
            {
                return(-1);
            }
            return(8 + (msg_length) + (msg_length > 0 ? 2 : 0));
        }
예제 #2
0
        public int Send(byte[] buffer, int offset, int data_length, BacnetAddress address, bool wait_for_transmission, int timeout)
        {
            if (m_TS == -1)
            {
                throw new Exception("Source address must be set up before sending messages");
            }

            //add to queue
            BacnetNpduControls   function   = NPDU.DecodeFunction(buffer, offset);
            BacnetMstpFrameTypes frame_type = (function & BacnetNpduControls.ExpectingReply) == BacnetNpduControls.ExpectingReply ? BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY : BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;

            byte[] copy = new byte[data_length + MSTP.MSTP_HEADER_LENGTH + 2];
            Array.Copy(buffer, offset, copy, MSTP.MSTP_HEADER_LENGTH, data_length);
            MessageFrame f = new MessageFrame(frame_type, address.adr[0], copy, data_length);

            lock (m_send_queue)
                m_send_queue.AddLast(f);
            if (m_reply == null)
            {
                m_reply = f;
                m_reply_mutex.Set();
            }

            //wait for message to be sent
            if (wait_for_transmission)
            {
                if (!f.send_mutex.WaitOne(timeout))
                {
                    return(-ETIMEDOUT);
                }
            }

            return(data_length);
        }
예제 #3
0
 public MessageFrame(BacnetMstpFrameTypes frameType, byte destinationAddress, byte[] data, int dataLength)
 {
     FrameType          = frameType;
     DestinationAddress = destinationAddress;
     Data       = data;
     DataLength = dataLength;
     SendMutex  = new ManualResetEvent(false);
 }
예제 #4
0
 public MessageFrame(BacnetMstpFrameTypes frame_type, byte destination_address, byte[] data, int data_length)
 {
     this.frame_type          = frame_type;
     this.destination_address = destination_address;
     this.data        = data;
     this.data_length = data_length;
     send_mutex       = new ManualResetEvent(false);
 }
예제 #5
0
파일: MSTP.cs 프로젝트: tomyqg/BACnet-1
        public static int Decode(byte[] buffer, int offset, int maxLength, out BacnetMstpFrameTypes frameType, out byte destinationAddress, out byte sourceAddress, out int msgLength)
        {
            if (maxLength < MSTP_HEADER_LENGTH)                                                   //not enough data
            {
                frameType          = BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; // don't care
                destinationAddress = sourceAddress = 0;                                           // don't care
                msgLength          = 0;
                return(-1);
            }

            frameType          = (BacnetMstpFrameTypes)buffer[offset + 2];
            destinationAddress = buffer[offset + 3];
            sourceAddress      = buffer[offset + 4];
            msgLength          = (buffer[offset + 5] << 8) | (buffer[offset + 6] << 0);
            var    crcHeader = buffer[offset + 7];
            ushort crcData   = 0;

            if (msgLength > 0)
            {
                if (offset + 8 + msgLength + 1 >= buffer.Length)
                {
                    return(-1);
                }

                crcData = (ushort)((buffer[offset + 8 + msgLength + 1] << 8) | (buffer[offset + 8 + msgLength + 0] << 0));
            }

            if (buffer[offset + 0] != MSTP_PREAMBLE1)
            {
                return(-1);
            }

            if (buffer[offset + 1] != MSTP_PREAMBLE2)
            {
                return(-1);
            }

            if (CRC_Calc_Header(buffer, offset + 2, 5) != crcHeader)
            {
                return(-1);
            }

            if (msgLength > 0 && maxLength >= MSTP_HEADER_LENGTH + msgLength + 2 && CRC_Calc_Data(buffer, offset + 8, msgLength) != crcData)
            {
                return(-1);
            }

            return(8 + msgLength + (msgLength > 0 ? 2 : 0));
        }
예제 #6
0
파일: MSTP.cs 프로젝트: tomyqg/BACnet-1
 public static int Encode(byte[] buffer, int offset, BacnetMstpFrameTypes frameType, byte destinationAddress, byte sourceAddress, int msgLength)
 {
     buffer[offset + 0] = MSTP_PREAMBLE1;
     buffer[offset + 1] = MSTP_PREAMBLE2;
     buffer[offset + 2] = (byte)frameType;
     buffer[offset + 3] = destinationAddress;
     buffer[offset + 4] = sourceAddress;
     buffer[offset + 5] = (byte)((msgLength & 0xFF00) >> 8);
     buffer[offset + 6] = (byte)((msgLength & 0x00FF) >> 0);
     buffer[offset + 7] = CRC_Calc_Header(buffer, offset + 2, 5);
     if (msgLength > 0)
     {
         //calculate data crc
         var dataCrc = CRC_Calc_Data(buffer, offset + 8, msgLength);
         buffer[offset + 8 + msgLength + 0] = (byte)(dataCrc & 0xFF);  //LSB first!
         buffer[offset + 8 + msgLength + 1] = (byte)(dataCrc >> 8);
     }
     //optional pad (0xFF)
     return(MSTP_HEADER_LENGTH + msgLength + (msgLength > 0 ? 2 : 0));
 }
예제 #7
0
        private GetMessageStatus GetNextMessage(int timeout_ms, out BacnetMstpFrameTypes frame_type, out byte destination_address, out byte source_address, out int msg_length)
        {
            int timeout;

            frame_type = BacnetMstpFrameTypes.FRAME_TYPE_TOKEN;
            destination_address = 0;
            source_address = 0;
            msg_length = 0;

            //fetch header
            while (m_local_offset < MSTP.MSTP_HEADER_LENGTH)
            {
                if (m_port == null) return GetMessageStatus.ConnectionClose;

                if (m_local_offset > 0)
                    timeout = T_FRAME_ABORT;    //set sub timeout
                else
                    timeout = timeout_ms;       //set big silence timeout

                //read
                int rx = m_port.Read(m_local_buffer, m_local_offset, MSTP.MSTP_HEADER_LENGTH - m_local_offset, timeout);
                if (rx == -ETIMEDOUT)
                {
                    //drop message
                    GetMessageStatus status = m_local_offset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout;
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return status;
                }
                else if (rx < 0)
                {
                    //drop message
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return GetMessageStatus.ConnectionError;
                }
                else if (rx == 0)
                {
                    //drop message
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return GetMessageStatus.ConnectionClose;
                }
                m_local_offset += rx;

                //remove paddings & garbage
                RemoveGarbage();
            }

            //decode
            if (MSTP.Decode(m_local_buffer, 0, m_local_offset, out frame_type, out destination_address, out source_address, out msg_length) < 0)
            {
                //drop message
                m_local_buffer[0] = 0xFF;
                RemoveGarbage();
                return GetMessageStatus.DecodeError;
            }

            //valid length?
            int full_msg_length = msg_length + MSTP.MSTP_HEADER_LENGTH + (msg_length > 0 ? 2 : 0);
            if (msg_length > MaxBufferLength)
            {
                //drop message
                m_local_buffer[0] = 0xFF;
                RemoveGarbage();
                return GetMessageStatus.DecodeError;
            }

            //fetch data
            if (msg_length > 0)
            {
                timeout = T_FRAME_ABORT;    //set sub timeout
                while (m_local_offset < full_msg_length)
                {
                    //read
                    int rx = m_port.Read(m_local_buffer, m_local_offset, full_msg_length - m_local_offset, timeout);
                    if (rx == -ETIMEDOUT)
                    {
                        //drop message
                        GetMessageStatus status = m_local_offset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout;
                        m_local_buffer[0] = 0xFF;
                        RemoveGarbage();
                        return status;
                    }
                    else if (rx < 0)
                    {
                        //drop message
                        m_local_buffer[0] = 0xFF;
                        RemoveGarbage();
                        return GetMessageStatus.ConnectionError;
                    }
                    else if (rx == 0)
                    {
                        //drop message
                        m_local_buffer[0] = 0xFF;
                        RemoveGarbage();
                        return GetMessageStatus.ConnectionClose;
                    }
                    m_local_offset += rx;
                }

                //verify data crc
                if (MSTP.Decode(m_local_buffer, 0, m_local_offset, out frame_type, out destination_address, out source_address, out msg_length) < 0)
                {
                    //drop message
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return GetMessageStatus.DecodeError;
                }
            }

            //signal frame event
            if (FrameRecieved != null)
            {
                BacnetMstpFrameTypes _frame_type = frame_type;
                byte _destination_address = destination_address;
                byte _source_address = source_address;
                int _msg_length = msg_length;
                System.Threading.ThreadPool.QueueUserWorkItem((o) => { FrameRecieved(this, _frame_type, _destination_address, _source_address, _msg_length); }, null);
            }

            if(StateLogging) Trace.WriteLine("" + frame_type + " " + destination_address.ToString("X2") + " ");

            //done
            return GetMessageStatus.Good;
        }
예제 #8
0
 public MessageFrame(BacnetMstpFrameTypes frame_type, byte destination_address, byte[] data, int data_length)
 {
     this.frame_type = frame_type;
     this.destination_address = destination_address;
     this.data = data;
     this.data_length = data_length;
     send_mutex = new Threading.ManualResetEvent(false);
 }
예제 #9
0
 private void SendFrame(BacnetMstpFrameTypes frame_type, byte destination_address)
 {
     SendFrame(new MessageFrame(frame_type, destination_address, null, 0));
 }
예제 #10
0
 private void QueueFrame(BacnetMstpFrameTypes frame_type, byte destination_address)
 {
     m_send_queue.AddLast(new MessageFrame(frame_type, destination_address, null, 0));
 }
예제 #11
0
        private GetMessageStatus GetNextMessage(int timeoutMs, out BacnetMstpFrameTypes frameType,
                                                out byte destinationAddress, out byte sourceAddress, out int msgLength)
        {
            int timeout;

            frameType          = BacnetMstpFrameTypes.FRAME_TYPE_TOKEN;
            destinationAddress = 0;
            sourceAddress      = 0;
            msgLength          = 0;

            //fetch header
            while (_localOffset < MSTP.MSTP_HEADER_LENGTH)
            {
                if (_port == null)
                {
                    return(GetMessageStatus.ConnectionClose);
                }

                timeout = _localOffset > 0
                                        ? T_FRAME_ABORT // set sub timeout
                                        : timeoutMs;    // set big silence timeout

                //read
                var rx = _port.Read(_localBuffer, _localOffset, MSTP.MSTP_HEADER_LENGTH - _localOffset, timeout);
                if (rx == -ETIMEDOUT)
                {
                    //drop message
                    var status = _localOffset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout;
                    _localBuffer[0] = 0xFF;
                    RemoveGarbage();
                    return(status);
                }
                if (rx < 0)
                {
                    //drop message
                    _localBuffer[0] = 0xFF;
                    RemoveGarbage();
                    return(GetMessageStatus.ConnectionError);
                }
                if (rx == 0)
                {
                    //drop message
                    _localBuffer[0] = 0xFF;
                    RemoveGarbage();
                    return(GetMessageStatus.ConnectionClose);
                }
                _localOffset += rx;

                //remove paddings & garbage
                RemoveGarbage();
            }

            //decode
            if (MSTP.Decode(_localBuffer, 0, _localOffset, out frameType, out destinationAddress,
                            out sourceAddress, out msgLength) < 0)
            {
                //drop message
                _localBuffer[0] = 0xFF;
                RemoveGarbage();
                return(GetMessageStatus.DecodeError);
            }

            //valid length?
            var fullMsgLength = msgLength + MSTP.MSTP_HEADER_LENGTH + (msgLength > 0 ? 2 : 0);

            if (msgLength > MaxBufferLength)
            {
                //drop message
                _localBuffer[0] = 0xFF;
                RemoveGarbage();
                return(GetMessageStatus.DecodeError);
            }

            //fetch data
            if (msgLength > 0)
            {
                timeout = T_FRAME_ABORT;                 //set sub timeout
                while (_localOffset < fullMsgLength)
                {
                    //read
                    var rx = _port.Read(_localBuffer, _localOffset, fullMsgLength - _localOffset, timeout);
                    if (rx == -ETIMEDOUT)
                    {
                        //drop message
                        var status = _localOffset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout;
                        _localBuffer[0] = 0xFF;
                        RemoveGarbage();
                        return(status);
                    }
                    if (rx < 0)
                    {
                        //drop message
                        _localBuffer[0] = 0xFF;
                        RemoveGarbage();
                        return(GetMessageStatus.ConnectionError);
                    }
                    if (rx == 0)
                    {
                        //drop message
                        _localBuffer[0] = 0xFF;
                        RemoveGarbage();
                        return(GetMessageStatus.ConnectionClose);
                    }
                    _localOffset += rx;
                }

                //verify data crc
                if (
                    MSTP.Decode(_localBuffer, 0, _localOffset, out frameType, out destinationAddress,
                                out sourceAddress, out msgLength) < 0)
                {
                    //drop message
                    _localBuffer[0] = 0xFF;
                    RemoveGarbage();
                    return(GetMessageStatus.DecodeError);
                }
            }

            //signal frame event
            if (FrameRecieved != null)
            {
                var frameTypeCopy          = frameType;
                var destinationAddressCopy = destinationAddress;
                var sourceAddressCopy      = sourceAddress;
                var msgLengthCopy          = msgLength;

                ThreadPool.QueueUserWorkItem(
                    o => { FrameRecieved(this, frameTypeCopy, destinationAddressCopy, sourceAddressCopy, msgLengthCopy); }, null);
            }

            Log.Debug($"{frameType} {destinationAddress:X2}");

            //done
            return(GetMessageStatus.Good);
        }
예제 #12
0
 private void SendFrame(BacnetMstpFrameTypes frameType, byte destinationAddress)
 {
     SendFrame(new MessageFrame(frameType, destinationAddress, null, 0));
 }
예제 #13
0
 private void QueueFrame(BacnetMstpFrameTypes frameType, byte destinationAddress)
 {
     lock (_sendQueue)
         _sendQueue.AddLast(new MessageFrame(frameType, destinationAddress, null, 0));
 }
예제 #14
0
        private GetMessageStatus GetNextMessage(int timeout_ms, out BacnetMstpFrameTypes frame_type, out byte destination_address, out byte source_address, out int msg_length)
        {
            int timeout;

            frame_type          = BacnetMstpFrameTypes.FRAME_TYPE_TOKEN;
            destination_address = 0;
            source_address      = 0;
            msg_length          = 0;

            //fetch header
            while (m_local_offset < MSTP.MSTP_HEADER_LENGTH)
            {
                if (m_port == null)
                {
                    return(GetMessageStatus.ConnectionClose);
                }

                if (m_local_offset > 0)
                {
                    timeout = T_FRAME_ABORT;    //set sub timeout
                }
                else
                {
                    timeout = timeout_ms;       //set big silence timeout
                }
                //read
                int rx = m_port.Read(m_local_buffer, m_local_offset, MSTP.MSTP_HEADER_LENGTH - m_local_offset, timeout);
                if (rx == -ETIMEDOUT)
                {
                    //drop message
                    GetMessageStatus status = m_local_offset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout;
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return(status);
                }
                if (rx < 0)
                {
                    //drop message
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return(GetMessageStatus.ConnectionError);
                }
                if (rx == 0)
                {
                    //drop message
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return(GetMessageStatus.ConnectionClose);
                }
                m_local_offset += rx;

                //remove paddings & garbage
                RemoveGarbage();
            }

            //decode
            if (MSTP.Decode(m_local_buffer, 0, m_local_offset, out frame_type, out destination_address, out source_address, out msg_length) < 0)
            {
                //drop message
                m_local_buffer[0] = 0xFF;
                RemoveGarbage();
                return(GetMessageStatus.DecodeError);
            }

            //valid length?
            int full_msg_length = msg_length + MSTP.MSTP_HEADER_LENGTH + (msg_length > 0 ? 2 : 0);

            if (msg_length > MaxBufferLength)
            {
                //drop message
                m_local_buffer[0] = 0xFF;
                RemoveGarbage();
                return(GetMessageStatus.DecodeError);
            }

            //fetch data
            if (msg_length > 0)
            {
                timeout = T_FRAME_ABORT;    //set sub timeout
                while (m_local_offset < full_msg_length)
                {
                    //read
                    int rx = m_port.Read(m_local_buffer, m_local_offset, full_msg_length - m_local_offset, timeout);
                    if (rx == -ETIMEDOUT)
                    {
                        //drop message
                        GetMessageStatus status = m_local_offset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout;
                        m_local_buffer[0] = 0xFF;
                        RemoveGarbage();
                        return(status);
                    }
                    if (rx < 0)
                    {
                        //drop message
                        m_local_buffer[0] = 0xFF;
                        RemoveGarbage();
                        return(GetMessageStatus.ConnectionError);
                    }
                    if (rx == 0)
                    {
                        //drop message
                        m_local_buffer[0] = 0xFF;
                        RemoveGarbage();
                        return(GetMessageStatus.ConnectionClose);
                    }
                    m_local_offset += rx;
                }

                //verify data crc
                if (MSTP.Decode(m_local_buffer, 0, m_local_offset, out frame_type, out destination_address, out source_address, out msg_length) < 0)
                {
                    //drop message
                    m_local_buffer[0] = 0xFF;
                    RemoveGarbage();
                    return(GetMessageStatus.DecodeError);
                }
            }

            //signal frame event
            if (FrameRecieved != null)
            {
                BacnetMstpFrameTypes _frame_type = frame_type;
                byte _destination_address        = destination_address;
                byte _source_address             = source_address;
                int  _msg_length = msg_length;
                ThreadPool.QueueUserWorkItem((o) => { FrameRecieved(this, _frame_type, _destination_address, _source_address, _msg_length); }, null);
            }

            if (StateLogging)
            {
                Trace.WriteLine("" + frame_type + " " + destination_address.ToString("X2") + " ");
            }

            //done
            return(GetMessageStatus.Good);
        }