private void ptp_thread()
{
byte[] buffer = new byte[MaxBufferLength];
try
{
while (m_port != null)
{
//connect if needed
if (!m_is_connected)
{
if (!Reconnect())
{
System.Threading.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 = System.Text.ASCIIEncoding.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 = System.Text.ASCIIEncoding.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.ToString(), 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);
}
}