Here’s what I do for talking to XBees with API mode. You want all data handling to be done on the main thread, not on the Serial Connection’s thread, so use a timer to move it to the main thread. I make a subclass of SerialConnection and call it “XBeeDevice” or some such. I give it a timer property and initialize the timer in the class constructor:
// Polltimer is a one-shot, fired by DataReceived, and serves simply to get the buffer parsing code out of the
// DataReceived event.
PollTimer = new Timer
PollTimer.Period = PollTime // 2ms typ
PollTimer.Mode = timer.ModeSingle
PollTimer.Enabled = True
AddHandler PollTimer.Action, WeakAddressOf ParseRX
The DataReceived event handler is simply:
RXBuffer = RXBuffer + Me.ReadAll(Encodings.ASCII)
PollTimer.Reset // PollTimer.Action is handled by ParseRX
I have a class APIpacket which encapsulates all the properties of an API packet, with a constructor that takes a string parameter. The ParseRX method of the SerialConnection class looks like this:
// This is the handler for PollTimer, which is a one-shot fired by our DataReceived event.
// AT Response Packet
// <SOX><Len MSB><Len LSB><FrameType 0x88><FrameID><Cmd1><Cmd2><Status><data><Checksum>
// Receive Packet Packet
// <SOX><Len MSB><Len LSB><FrameType 0x90><Source MAC><Source Net Addr><ReceiveOptions><Payload><Checksum>
Dim PacketStart, PacketLen As Integer
Dim ResponseStatus As Integer
Dim Packet As APIpacket
// Align buffer with SOX at start
PacketStart = RXBuffer.IndexOfBytes(0,ChrB(SOX))
RXBuffer = RXBuffer.MiddleBytes(PacketStart)
If LenB(RXBuffer) >= 3 Then // We have enough length to try parsing, i.e. we have the Length field.
PacketLen = AscB(MidB(RXBuffer,3,1)) // Ignore MSByte, we don't get messages > 255 bytes.
If LenB(RXBuffer) >= PacketLen + 4 Then // We have all the bytes of the packet as specified by its length field
Packet = New APIpacket(RXBuffer)
If Packet.Checksum = 0 Then // Got a packet, but note that it could be a ZigBee Status message
RXBuffer = RXBuffer.MidB(PacketLen+5) // Remove the handled packet from the buffer, leaving anything that might have come in since.
If Packet.FrameType = FrameType_ATresponse Or (Packet.FrameType = FrameType_ReceivePacket and Packet.Command = CMD_WirelessAT) Or Packet.FrameType = FrameType_RemoteATresponse Then // Not a ZigBee message, we need to handle it
// Handle the message
RaiseEvent PacketAvailable(Packet)
In my system, all received messages are in response to commands transmitted from the host Xojo app, and RXBuffer is cleared every time a new message is sent, because I never send another message to the device until I get a response to the previous one. The above code will need some tweaking if you expect to receive messages at random from the XBee, as it looks like it assumes a cleared RXBuffer.