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;
}