private BacnetMstpProtocolTransport.GetMessageStatus ProcessRxStatus(byte[] buffer, ref int offset, int rx) { if (rx == -BacnetMstpProtocolTransport.ETIMEDOUT) { //drop message BacnetMstpProtocolTransport.GetMessageStatus status = offset == 0 ? BacnetMstpProtocolTransport.GetMessageStatus.Timeout : BacnetMstpProtocolTransport.GetMessageStatus.SubTimeout; buffer[0] = 0xFF; RemoveGarbage(buffer, ref offset); return(status); } if (rx < 0) { //drop message buffer[0] = 0xFF; RemoveGarbage(buffer, ref offset); return(BacnetMstpProtocolTransport.GetMessageStatus.ConnectionError); } if (rx == 0) { //drop message buffer[0] = 0xFF; RemoveGarbage(buffer, ref offset); return(BacnetMstpProtocolTransport.GetMessageStatus.ConnectionClose); } return(BacnetMstpProtocolTransport.GetMessageStatus.Good); }
private void ptp_thread() { byte[] buffer = new byte[MaxBufferLength]; try { while (m_port != null) { //connect if needed if (!m_is_connected) { if (!Reconnect()) { Thread.Sleep(1000); continue; } } //read message int offset = 0; BacnetPtpFrameTypes frame_type; int msg_length; BacnetMstpProtocolTransport.GetMessageStatus status = GetNextMessage(buffer, ref offset, T_HEARTBEAT, out frame_type, out msg_length); //action switch (status) { case BacnetMstpProtocolTransport.GetMessageStatus.ConnectionClose: case BacnetMstpProtocolTransport.GetMessageStatus.ConnectionError: Trace.TraceWarning("Connection disturbance"); Reconnect(); break; case BacnetMstpProtocolTransport.GetMessageStatus.DecodeError: Trace.TraceWarning("PTP decode error"); break; case BacnetMstpProtocolTransport.GetMessageStatus.SubTimeout: Trace.TraceWarning("PTP frame abort"); break; case BacnetMstpProtocolTransport.GetMessageStatus.Timeout: SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); //both server and client will send this break; case BacnetMstpProtocolTransport.GetMessageStatus.Good: //action switch (frame_type) { case BacnetPtpFrameTypes.FRAME_TYPE_GREETING: //request connection SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_REQUEST); break; case BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON: m_may_send.Set(); break; case BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XOFF: m_may_send.Reset(); break; case BacnetPtpFrameTypes.FRAME_TYPE_DATA0: //send confirm SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK0_XON); //notify the sky! if (MessageRecieved != null) { MessageRecieved(this, buffer, PTP.PTP_HEADER_LENGTH, msg_length, GetBroadcastAddress()); } break; case BacnetPtpFrameTypes.FRAME_TYPE_DATA1: //send confirm SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK1_XON); //notify the sky! if (MessageRecieved != null) { MessageRecieved(this, buffer, PTP.PTP_HEADER_LENGTH, msg_length, GetBroadcastAddress()); } break; case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK0_XOFF: case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK1_XOFF: //so, the other one got the message, eh? m_may_send.Reset(); break; case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK0_XON: case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK1_XON: //so, the other one got the message, eh? m_may_send.Set(); break; case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK0_XOFF: case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK1_XOFF: m_may_send.Reset(); //denial, eh? break; case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK0_XON: case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK1_XON: m_may_send.Set(); //denial, eh? break; case BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_REQUEST: //also send a password perhaps? if (!string.IsNullOrEmpty(m_password)) { byte[] pass = Encoding.ASCII.GetBytes(m_password); byte[] tmp_buffer = new byte[PTP.PTP_HEADER_LENGTH + pass.Length + 2]; Array.Copy(pass, 0, tmp_buffer, PTP.PTP_HEADER_LENGTH, pass.Length); SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_RESPONSE, tmp_buffer, pass.Length); } else { SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_RESPONSE); } //we're ready SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); break; case BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_RESPONSE: if (msg_length > 0 && !string.IsNullOrEmpty(m_password)) { string password = Encoding.ASCII.GetString(buffer, PTP.PTP_HEADER_LENGTH, msg_length); if (password != m_password) { SendDisconnect(BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_REQUEST, BacnetPtpDisconnectReasons.PTP_DISCONNECT_INVALID_PASSWORD); } else { SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); //we're ready } } else { //we're ready SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); } break; case BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_REQUEST: BacnetPtpDisconnectReasons reason = BacnetPtpDisconnectReasons.PTP_DISCONNECT_OTHER; if (msg_length > 0) { reason = (BacnetPtpDisconnectReasons)buffer[PTP.PTP_HEADER_LENGTH]; } SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_RESPONSE); Trace.WriteLine("Disconnect requested: " + reason, null); Reconnect(); break; case BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_RESPONSE: m_may_send.Reset(); //hopefully we'll be closing down now break; case BacnetPtpFrameTypes.FRAME_TYPE_TEST_REQUEST: SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_TEST_RESPONSE, buffer, msg_length); break; case BacnetPtpFrameTypes.FRAME_TYPE_TEST_RESPONSE: //good break; } break; } } Trace.WriteLine("PTP thread is closing down", null); } catch (Exception ex) { Trace.TraceError("Exception in PTP thread: " + ex.Message); } }