I'm doing a WPF application that reads from and sends messages to a USB LoRaWAN dongle.
Here's a quick resume of what the app should do:
With this application, the user should be able to connect the "server", that is to say, open the serial port and start consuming messages (for now, I'm just trying to show them on the console). To do this, the user clicks on a menu option.
The user then should also be able to send messages, or "commands", to the dongle. When this happens, the dongle sends a "message received" signal (in the form of a message, as well).
Finally, the user also has to be able to close the server, with another menu option.
Every message has to end with a newline character.
This is my code for the "Start Server" button click command and read async command:
private async void ConnectServerCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
#if DEBUG
Debug.Print("ConnectServer");
#endif
cts = new CancellationTokenSource();
//CancellationToken ct = cts.Token;
// Se llama al método OpenPort() de MySerialPort que intenta abrir el puerto, hace un SET del VERBOSITY y controla las excepciones
MySerialPort.OpenPort();
await ConnectServer(cts.Token);
}
private async Task ConnectServer(CancellationToken ct)
{
// ENTRAR AL BUCLE PARA RECIBIR/ENVIAR MENSAJES
byte[] recBuffer = new byte[1024];
int result;
while ((!ct.IsCancellationRequested) && (MySerialPort.SerialPort.IsOpen))
{
try
{
result = await MySerialPort.SerialPort.BaseStream.ReadAsync(recBuffer, 0, 1024, ct);
if (result > 0)
{
Debug.Print("{0} - {1} ", DateTime.Now, Encoding.Default.GetString(recBuffer));
}
Debug.Print("IsCancellationRequested: {0}", ct.IsCancellationRequested);
/*if (Encoding.Default.GetString(recBuffer).Contains("\n")) {
msg = (Encoding.Default.GetString(recBuffer)).Split('\n')[0];
return msg;
}*/
if (ct.IsCancellationRequested)
{
MySerialPort.ClosePort();
return;
}
}
catch (Exception ex)
{
MessageBox.Show("Error in ReadSerialBytesAsync: " + ex.ToString());
}
}
}
And this, my "Close Server" button command:
private void DisconnectServerCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
#if DEBUG
Debug.Print("DisconnectServer");
#endif
// ROMPER EL BUCLE DE CONNECTSERVER
if (cts != null)
{
cts.Cancel();
}
}
For now I was able to connect the server and start reading asynchronously some messages, but I currently have two issues.
1. Whenever I try to cancel the task, it doesn't happen immediately. I have to try to send another command for the app to know that the cancellation token was requested, and then it does close the port. I tried to close the port in my close server command, but it then throws an IOException, and I don't know if that is the correct way of doing it.
2. I receive messages multiple times. Whenever I send a command, the dongle sends the received signal more than just one time. I don't understand why does this happen.
I also want to process the messages only when the newline delimiter is found, but I still don't understand the logic to do this.
This is an example output:
ConnectServer
Trying to open SerialPort COM3.
03/11/2019 11:14:30 - RIsCancellationRequested: False
03/11/2019 11:14:30 - SET 0 SUCCESS VERBOSE=LONG,DEVPORT,OFF,OFF
IsCancellationRequested: False
LoadDeviceListFile
03/11/2019 11:14:32 - RET 0 SUCCESS VERBOSE=LONG,DEVPORT,OFF,OFF
IsCancellationRequested: False
03/11/2019 11:14:32 - GET 0 SUCCESS DEV_PROV_LIST=\
0,70B3D5E75E00IsCancellationRequested: False
03/11/2019 11:14:32 - 4ET 0 SUCCESS DEV_PROV_LIST=\
0,70B3D5E75E00IsCancellationRequested: False
03/11/2019 11:14:32 - 275,ABP,C,0,00004275,2B7E151628AED2A6ABF7158809CF4F3C,2B7E151628AED2A6ABF7158809CF4F3C,70B3D5E75F600000,2B7E151628AED2A6ABF7158809CF4F3CIsCancellationRequested: False
03/11/2019 11:14:32 -
75,ABP,C,0,00004275,2B7E151628AED2A6ABF7158809CF4F3C,2B7E151628AED2A6ABF7158809CF4F3C,70B3D5E75F600000,2B7E151628AED2A6ABF7158809CF4F3CIsCancellationRequested: False
GetFromDeviceCommand
COMPort de MySerialPort: COM3
03/11/2019 11:14:38 - R75,ABP,C,0,00004275,2B7E151628AED2A6ABF7158809CF4F3C,2B7E151628AED2A6ABF7158809CF4F3C,70B3D5E75F600000,2B7E151628AED2A6ABF7158809CF4F3CIsCancellationRequested: False
03/11/2019 11:14:38 - GET 0 SUCCESS FIRMWARE_INFO=LWCServer:0.3(beta), Kernel:3.4.0.3924,\
FWName:3.4.0.3924.lwc-server.lwcs.ClassC.lrctm.EU.chkpt.wdt2-dfp-br-F5437A
IsCancellationRequested: False
DisconnectServer
GetFromDeviceCommand
COMPort de MySerialPort: COM3
03/11/2019 11:14:44 - RET 0 SUCCESS FIRMWARE_INFO=LWCServer:0.3(beta), Kernel:3.4.0.3924,\
FWName:3.4.0.3924.lwc-server.lwcs.ClassC.lrctm.EU.chkpt.wdt2-dfp-br-F5437A
IsCancellationRequested: True
SerialPort COM3 open. Closing it.
The thread 0x3b14 has exited with code 0 (0x0).
The program '[10580] LWCConfig_02.exe' has exited with code 0 (0x0).
ConnectServermethod is called synchronously. It is markedasync, returns aTask, but it is notawaited. - dymanoidMySerialPort.SerialPort.BaseStream? - AckdariCancellationTokento theReadAsync, so it should abort if you trigger a cancel. You may found somekind of bug in .net - Ackdari