Inspired by the Arduino Library
After successful proof of concept projects I have build a nanoFramwork library “inspired” by the RakWireless Arduino library.
The initial version only supports my RAK811 LPWAN Evaluation Board(EVB) and STM32F691DISCOVERY based test rig It handles failures, displays error codes/messages, but doesn’t handle all timeouts.
If the RAK811 module is initialised, then connects to the network successfully, the application sends “48656c6c6f204c6f526157414e” (“hello LoRaWAN”) every 20 seconds.

The code application code is now a lot smaller & simpler
public class Program
{
#if ST_STM32F769I_DISCOVERY
private const string SerialPortId = "COM6";
#endif
#if OTAA
private const string DevEui = "...";
private const string AppEui = "...";
private const string AppKey = "...";
#endif
#if ABP
private const string devAddress = "...";
private const string nwksKey = "...";
private const string appsKey = "...";
#endif
private const byte MessagePort = 1;
private const string Payload = "48656c6c6f204c6f526157414e"; // Hello LoRaWAN
public static void Main()
{
Result result;
Debug.WriteLine(" devMobile.IoT.Rak811LoRaWanDeviceClient starting");
Debug.WriteLine(Windows.Devices.SerialCommunication.SerialDevice.GetDeviceSelector());
try
{
using ( Rak811LoRaWanDevice device = new Rak811LoRaWanDevice())
{
result = device.Initialise(SerialPortId, SerialParity.None, 8, SerialStopBitCount.One);
if (result != Result.Success)
{
Debug.WriteLine($"Initialise failed {result}");
return;
}
result = device.Region("AS923");
if (result != Result.Success)
{
Debug.WriteLine($"Region failed {result}");
return;
}
#if OTAA
result = device.OtaaInitialise(DevEui, AppEui, AppKey);
if (result != Result.Success)
{
Debug.WriteLine($"OTAA Initialise failed {result}");
return;
}
#endif
#if ABP
result = device.AbpInitialise(devAddress, nwksKey, appsKey);
if (result != Result.Success)
{
Debug.WriteLine($"ABP Initialise failed {result}");
return;
}
#endif
result = device.Join(new TimeSpan(0,0,10));
if (result != Result.Success)
{
Debug.WriteLine($"Join failed {result}");
return;
}
while (true)
{
result = device.Send(MessagePort, Payload);
if (result != Result.Success)
{
Debug.WriteLine($"Send failed {result}");
}
result = device.Sleep();
if (result != Result.Success)
{
Debug.WriteLine($"Sleep failed {result}");
return;
}
Thread.Sleep(20000);
result = device.Wakeup();
if (result != Result.Success)
{
Debug.WriteLine($"Wakeup failed {result}");
return;
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
I compared the debugging output with confirmations off
The thread '<No Name>' (0x2) has exited with code 0 (0x0).
devMobile.IoT.Rak811LoRaWanDeviceClient starting
COM5,COM6
01:11:13 lora:work_mode
TX: send 32 bytes 32 via COM6
RX 01:11:14:UART1 work mode: RUI_UART_NORAMAL
Current work_mode:LoRaWAN, join_mode:OTAA, Class: A
Initialization OK
01:11:15 lora:region
TX: send 33 bytes 33 via COM6
RX 01:11:16:OK
01:11:16 lora:join_mode
TX: send 32 bytes 32 via COM6
RX 01:11:17:OK
01:11:18 lora:dev_eui
TX: send 45 bytes 45 via COM6
RX 01:11:19:OK
01:11:19 lora:app_eui
TX: send 45 bytes 45 via COM6
RX 01:11:20:OK
01:11:21 lora:app_key
TX: send 61 bytes 61 via COM6
RX 01:11:22:OK
01:11:22 join
TX: send 9 bytes 9 via COM6
RX 01:11:29:OK Join Success
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
RX :OK
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
RX :OK
at+recv=1,-54,9,5:48656c6c6f
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
RX :OK
at+recv=2,-51,7,5:48656c6c6f
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
Then with confirmations on (note the at+recv=0,-59,7,0) and received messages (at+recv=23,-53,8,5:48656c6c6f)
devMobile.IoT.Rak811LoRaWanDeviceClient starting
COM5,COM6
01:20:54 lora:work_mode
TX: send 32 bytes 32 via COM6
RX 01:20:56:UART1 work mode: RUI_UART_NORAMAL
Current work_mode:LoRaWAN, join_mode:OTAA, Class: A
Initialization OK
01:20:56 lora:region
TX: send 33 bytes 33 via COM6
RX 01:20:57:OK
01:20:58 lora:join_mode
TX: send 32 bytes 32 via COM6
RX 01:20:59:OK
01:20:59 lora:dev_eui
TX: send 45 bytes 45 via COM6
RX 01:21:00:OK
01:21:01 lora:app_eui
TX: send 45 bytes 45 via COM6
RX 01:21:02:OK
01:21:02 lora:app_key
TX: send 61 bytes 61 via COM6
RX 01:21:03:OK
01:21:04 join
TX: send 9 bytes 9 via COM6
RX 01:21:11:OK Join Success
01:21:11 lora:confirm
TX: send 30 bytes 30 via COM6
RX 01:21:12:OK
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
RX :OK
at+recv=23,-53,8,5:48656c6c6f
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
TX: send 43 bytes to output stream.
TX: 43 bytes via COM6
RX :OK
at+recv=0,-59,7,0
In the Visual Studio 2019 debug output I could see the responses to the AT Commands and especially the lack of handling of downlink messages and confirmations from the network.
The next step is to implement timeouts for when operations fail or the module doesn’t respond. Then extend the code to support the receiving of messages as a class A device (missing for the RAK arduino library). I wonder how this will work for when the module is configured as a class C device which can receive messages at any time.
Some commands are quite quick to respond e.g. setting the Region, Sleep, and Wakeup so are most probably ok running synchronously. Other commands can take quite a while e.g. Join, Send, WorkMode so maybe these need to be asynchronous (along with the receiving of confirmations and messages ).
The code is not suitable for production but it confirmed my new approach worked.
Pingback: nanoFramework RAK811 LoRaWAN library Part7 | devMobile's blog