nanoframework / Home

:house: The landing page for .NET nanoFramework repositories.
https://www.nanoframework.net
MIT License
860 stars 79 forks source link

DataRead.Load doesn't return immediately if watchChar present in received data #624

Closed KiwiBryn closed 2 years ago

KiwiBryn commented 4 years ago

DataRead.Load doesn't return immediately if watchChar present in received data stream. Comment on watchChar in SerialDevices library indicates that it should.

When calling in the the operation will return immediately if this character is received in the incoming data stream. No matter if the requested quantity of bytes hasn't been read. Also if this character is received in the incoming data stream, the event is fired with it's parameter set to .

ST_STM32F769I_DISCOVERY

1.5.0-preview.1

Don't know if has worked before this is new library

I'm using a serial port to send & receive short strings (AT commands for LoRaWAN modem). I wanted to use the WatchChar feature + DataRead.Load(uint count) to retrieve the response messages from the modem (they are all terminated with \r\n).

Sample code here https://github.com/KiwiBryn/RAK811LoRaWAN-NetNF

  1. add #define SERIAL_SYNC_READ at top of file

  2. Use jumper to join TX to RX pins of your board (D0 & D1 of Arduino headers on 769 I'm using)

  3. Download and run code, note uint bytesRead = inputDataReader.Load(50); round line takes 30 sec to timeout.

Expected behaviour is that inputDataReader.Load should promptly return with "at+version\r\n" at inputDataReader.ReadString call.

I followed execution down through nanoFramework.Windows.Devices.SerialCommunication implementation appears to be down in native code.

AdrianSoundy commented 4 years ago

The problem is when you process the WatchChar event. You need to do a Load using the SerialDevice.BytesToRead but more characters could have been received after the watch character by time event is handled.

What we need is new field in the SerialDataReceivedEventArgs which contains the number of bytes to load to the event watch character in stream. Something like "BytesToWatchChar"

Then you can load / read 1 message at a time.

Ellerbach commented 3 years ago

@KiwiBryn there is now System.IO.Ports available and that should, at least partially, solve your issue. You have a ReadLine() function where you can determine with the NewLine property the string that is the end of line. so in your case you can just do something like this:

using System.IO.Ports;
SerialPort port = new SerialPort("COM2");
port.Open();
port.ReadTimeout = 30000; // 30 seconds timeout for example as per your example
port.NewLine = "\r\n";
string readLine;
while(mycondition)
{
  try
  {
    readLine = port.ReadLine();
    // Do whatever you want
  }
  catch (TimeoutException)
  {
     // 
  }
  catch(Exception)
  {
    // Other exceptions like if the string is malformed
  }
}
KiwiBryn commented 3 years ago

Thanks @Ellerbach I'll give it go once I have got Seeed-LoRaWAN module going.

networkfusion commented 3 years ago

@KiwiBryn , did this fix the issue?

josesimoes commented 2 years ago

Closing this as Win.Devices.SerialCommunication has been deprecated. Hopefully this is fixed in the new Sys.IO.Ports.