I am pretty new to serial comms, but would like advise on how to best achieve a robust application which speak to and listens to a serial device.
I have managed to make use of System.IO.SerialPort
, and successfully connected to, sent data to and recieved from my device. The way things work is this.
My application connects to the Com Port and opens the port.... I then connect my device to the com port, and it detects a connection to the PC, so sends a bit of text. it's really just copyright info, as well as the version of the firmware. I don't do anything with that, except display it in my 'activity' window.
The device then waits.
I can then query information, but sending a command such as 'QUERY PARAMETER1'. It then replies with something like:
'QUERY PARAMETER1\r\n\r\n76767\r\n\r\n'
I then process that. I can then update it by sending 'SET PARAMETER1 12345', and it will reply with 'QUERY PARAMETER1\r\n\r\n12345\r\n\r\n'.
All pretty basic.
So, what I have done is created a Communication Class. this call is called in it's own thread, and sends data back to the main form... and also allows me to send messages to it.
Sending data is easy. Recieving is a bit more tricky. I have employed the use of the datarecieved event, and when ever data comes in, I echo that to my screen. My problem is this:
When I send a command, I feel I am being very dodgy in my handling. What I am doing is, lets say I am sending 'QUERY PARAMETER1'. I send the command to the device, I then put 'PARAMETER1' into a global variable, and I do a Thread.Sleep(100).
On the data received, I then have a bit of logic that checks the incoming data, and sees if the string CONTAINS the value in the global variable. As the reply may be 'QUERY PARAMETER1\r\n\r\n76767\r\n\r\n', it sees that it contains my parameter, parses the string, and returns the value I am looking for, but placing it into another global variable.
My sending method was sleeping for 100ms. It then wakes, and checks the returned global variable. If it has data... then I'm happy, and I process the data. Problem is... if the sleep is too short.. it will fail. And I feel it's flaky.. putting stuff into variables.. then waiting...
The other option is to use ReadLine
instead, but that's very blocking. So I remove the data received method, and instead... just send the data... then call ReadLine()
. That may give me better results. There's no time, except when we connect initially, that data comes from the device, without me requesting it. So, maybe ReadLine
will be simpler and safer? Is this known as 'Blocking' reads? Also, can I set a timeout?
Hopefully someone can guide me.