altera2015 / usbserial

Flutter Android USB Serial plugin
BSD 3-Clause "New" or "Revised" License
124 stars 83 forks source link

Add support for synchronous write/read sequence #3

Closed WolfMoestl closed 5 years ago

WolfMoestl commented 5 years ago

In version 0.1.1 usb_serial supports asynchronous communications, but not synchronous ones.

In my case I need kind of a handshake-type synchronous communication: whenever something is written to the attached USB device I need to know the response from the device for that specific command.

The feature request is the following: When sending a String in synchronous manner...

  1. empty the input buffer if there is still some content
  2. write the given String to the device
  3. wait until the return message is available in the input buffer (e.g. when a configureable "STOP" sequence is fetched like "\r\n") or the maximum amount of milliseconds (configureable) has elapsed
  4. return the fetched message as byte array or NULL if the device did not response in time

The point is: I have to wait for the response prior to sending the next command.

So I would like so see interfaces in the UsbPort class like:

byte[] writeWithRead(String message, [byte[] stopSequence, int maximumWaitTime]);

byte[] writeWithRead(String message, [byte[] stopSequence]);

byte[] writeWithRead(String message, [int maximumWaitTime]);

void setDefaultStopSequence(byte[] defaultStopSequence);

void setDefaultMaximumWaitTime(int maximumWaitTime);

defaultStopSequence and maximumWaitTime should have reasonable defaults (e.g. "\n" and 100).

In my case I need different maximumWaitTimes for different calls to de attached device, thus I need the option to specify it in the writeWithRead call when sending commands which are taking more time on the attached device (e.g. "RESET" needs much more time then "GET_STATUS").

A mixture of sync/async USB communications should be suppored as well: Code using this library should be able to:

In fact what I need to do is:

altera2015 commented 5 years ago

Hey WolfMoestl,

Thanks for your detailed request. I understand you would like to be able to use the library in a synchronous fashion. Dart is single threaded and locking that thread while waiting for serial communications is not optimal.

Looking at this request I would approach it with:

The StreamTransformer allows you to split incoming data on desired terminator and StreamQueue allows you to use await to get the next available full message.

If I have time I'll poke at it, but maybe this gets you started?

altera2015 commented 5 years ago

Have a look at the https://github.com/altera2015/usbserial/tree/transaction branch. It should do just what you are looking for. I haven't been able to test this with a real serial device yet as I had none at hand, so all my tests were done with the EchoPort instead of UsbPort.

Example on how to use are in the code and in the tests. https://github.com/altera2015/usbserial/blob/transaction/test/test.dart

altera2015 commented 5 years ago

Version 0.2.0 now has support for a 'synchronous', using the await keyword, way of interacting with the underlying serial device.

WolfMoestl commented 5 years ago

Thanks for implementing this!

Just 2 things:

  1. transaction.dart lines 13 & 14: it's usually '\r\n\', not the other way round as you used it. If one just copies the String you will never get any message back as the usual combination probably used by the device is '\r\n'.

  2. IMHO the returned message should not contain the delimter used (e.g. '\r\n'), so please strip it.

Beside that: works great!