private BacnetMstpProtocolTransport.GetMessageStatus GetNextMessage(byte[]buffer, ref int offset, int timeout_ms, out BacnetPtpFrameTypes frame_type, out int msg_length)
{
BacnetMstpProtocolTransport.GetMessageStatus status;
int timeout = timeout_ms;
frame_type = BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XOFF;
msg_length = 0;
bool compliment_next = false;
//fetch header
while (offset < PTP.PTP_HEADER_LENGTH)
{
if (m_port == null) return BacnetMstpProtocolTransport.GetMessageStatus.ConnectionClose;
if (offset > 0)
timeout = T_FRAME_ABORT; //set sub timeout
else
timeout = timeout_ms; //set big silence timeout
//read
int rx = m_port.Read(buffer, offset, PTP.PTP_HEADER_LENGTH - offset, timeout);
status = ProcessRxStatus(buffer, ref offset, rx);
if (status != BacnetMstpProtocolTransport.GetMessageStatus.Good) return status;
//remove XON/XOFF
int new_offset = offset + rx;
RemoveXonOff(buffer, offset, ref new_offset, ref compliment_next);
offset = new_offset;
//remove garbage
RemoveGarbage(buffer, ref offset);
}
//greeting
if (IsGreeting(buffer, 0, offset))
{
//get last byte
int rx = m_port.Read(buffer, offset, 1, timeout);
status = ProcessRxStatus(buffer, ref offset, rx);
if (status != BacnetMstpProtocolTransport.GetMessageStatus.Good) return status;
offset += 1;
if (IsGreeting(buffer, 0, offset))
{
frame_type = BacnetPtpFrameTypes.FRAME_TYPE_GREETING;
if (StateLogging) Trace.WriteLine(frame_type, null);
return BacnetMstpProtocolTransport.GetMessageStatus.Good;
}
else
{
//drop message
buffer[0] = 0xFF;
RemoveGarbage(buffer, ref offset);
return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError;
}
}
//decode
if (PTP.Decode(buffer, 0, offset, out frame_type, out msg_length) < 0)
{
//drop message
buffer[0] = 0xFF;
RemoveGarbage(buffer, ref offset);
return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError;
}
//valid length?
int full_msg_length = msg_length + PTP.PTP_HEADER_LENGTH + (msg_length > 0 ? 2 : 0);
if (msg_length > MaxBufferLength)
{
//drop message
buffer[0] = 0xFF;
RemoveGarbage(buffer, ref offset);
return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError;
}
//fetch data
if (msg_length > 0)
{
timeout = T_FRAME_ABORT; //set sub timeout
while (offset < full_msg_length)
{
//read
int rx = m_port.Read(buffer, offset, full_msg_length - offset, timeout);
status = ProcessRxStatus(buffer, ref offset, rx);
if (status != BacnetMstpProtocolTransport.GetMessageStatus.Good) return status;
//remove XON/XOFF
int new_offset = offset + rx;
RemoveXonOff(buffer, offset, ref new_offset, ref compliment_next);
offset = new_offset;
}
//verify data crc
if (PTP.Decode(buffer, 0, offset, out frame_type, out msg_length) < 0)
{
//drop message
buffer[0] = 0xFF;
RemoveGarbage(buffer, ref offset);
return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError;
}
}
//debug
if (StateLogging)
Trace.WriteLine(frame_type, null);
//done
return BacnetMstpProtocolTransport.GetMessageStatus.Good;
}