Nasty OTAA connect
After getting basic connectivity for my Seeedstudio LoRa-E5 Development Kit and STM32F691DISCOVERY test rig working I wanted to see if I could get the device connected to The Things Industries(TTI).

My Over the Air Activation (OTAA) implementation is very “nasty” as it is assumed that there are no timeouts or failures and it only sends one BCD message “01020304”.
public class Program
{
private const string SerialPortId = "COM6";
private const string AppKey = "................................";
private const string AppEui = "................";
private const byte MessagePort = 15;
//private const string Payload = "48656c6c6f204c6f526157414e"; // Hello LoRaWAN
private const string Payload = "01020304"; // AQIDBA==
//private const string Payload = "04030201"; // BAMCAQ==
public static void Main()
{
SerialDevice serialDevice;
uint bytesWritten;
uint txByteCount;
uint bytesRead;
Debug.WriteLine("devMobile.IoT.SeeedLoRaE5.NetworkJoinOTAA starting");
Debug.WriteLine($"Ports available: {Windows.Devices.SerialCommunication.SerialDevice.GetDeviceSelector()}");
try
{
serialDevice = SerialDevice.FromId(SerialPortId);
// set parameters
serialDevice.BaudRate = 9600;
serialDevice.Parity = SerialParity.None;
serialDevice.StopBits = SerialStopBitCount.One;
serialDevice.Handshake = SerialHandshake.None;
serialDevice.DataBits = 8;
serialDevice.ReadTimeout = new TimeSpan(0, 0, 5);
serialDevice.WriteTimeout = new TimeSpan(0, 0, 4);
DataWriter outputDataWriter = new DataWriter(serialDevice.OutputStream);
DataReader inputDataReader = new DataReader(serialDevice.InputStream);
// set a watch char to be notified when it's available in the input stream
serialDevice.WatchChar = '\n';
// clear out the RX buffer
bytesRead = inputDataReader.Load(128);
while (bytesRead > 0)
{
string response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
bytesRead = inputDataReader.Load(128);
}
// Set the Region to AS923
bytesWritten = outputDataWriter.WriteString("AT+DR=AS923\r\n");
Debug.WriteLine($"TX: region {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response
bytesRead = inputDataReader.Load(128);
if (bytesRead > 0)
{
String response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
}
// Set the Join mode
bytesWritten = outputDataWriter.WriteString("AT+MODE=LWOTAA\r\n");
Debug.WriteLine($"TX: mode {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response
bytesRead = inputDataReader.Load(128);
if (bytesRead > 0)
{
string response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
}
// Set the appEUI
bytesWritten = outputDataWriter.WriteString($"AT+ID=AppEui,\"{AppEui}\"\r\n");
Debug.WriteLine($"TX: AppEui {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response
bytesRead = inputDataReader.Load(128);
if (bytesRead > 0)
{
String response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
}
// Set the appKey
bytesWritten = outputDataWriter.WriteString($"AT+KEY=APPKEY,{AppKey}\r\n");
Debug.WriteLine($"TX: AppKey {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response
bytesRead = inputDataReader.Load(128);
if (bytesRead > 0)
{
String response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
}
// Set the port number
bytesWritten = outputDataWriter.WriteString($"AT+PORT={MessagePort}\r\n");
Debug.WriteLine($"TX: port {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response
bytesRead = inputDataReader.Load(128);
if (bytesRead > 0)
{
String response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
}
// Join the network
bytesWritten = outputDataWriter.WriteString("AT+JOIN\r\n");
Debug.WriteLine($"TX: join {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response, need loop as multi line response
bytesRead = inputDataReader.Load(128);
while (bytesRead > 0)
{
String response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
bytesRead = inputDataReader.Load(128);
}
while (true)
{
bytesWritten = outputDataWriter.WriteString($"AT+MSGHEX=\"{Payload}\"\r\n");
Debug.WriteLine($"TX: send {outputDataWriter.UnstoredBufferLength} bytes to output stream.");
txByteCount = outputDataWriter.Store();
Debug.WriteLine($"TX: {txByteCount} bytes via {serialDevice.PortName}");
// Read the response, need loop as multi line response
bytesRead = inputDataReader.Load(128);
while (bytesRead > 0)
{
String response = inputDataReader.ReadString(bytesRead);
Debug.WriteLine($"RX :{response}");
bytesRead = inputDataReader.Load(128);
}
Thread.Sleep(300000);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
The code is not suitable for production but it confirmed my software and hardware configuration worked.
The thread '<No Name>' (0x2) has exited with code 0 (0x0).
devMobile.IoT.SeeedE5.NetworkJoinOTAA starting
TX: DR 13 bytes
RX :+DR: AS923
TX: MODE 16 bytes
RX :+MODE: LWOTAA
TX: ID=AppEui 40 bytes
RX :+ID: AppEui, ..:..:.:.:.:.:.:.
TX: KEY=APPKEY 48 bytes
RX :+KEY: APPKEY ................................
TX: PORT 11 bytes
RX :+PORT: 1
TX: JOIN 9 bytes
RX :+JOIN: Start
+JOIN: NORMAL
+JOIN: Network joined
+JOIN: NetID 000013 DevAddr ..:..:..:..
+JOIN: Done
TX: MSGHEX 22 bytes
RX :+MSGHEX: Start
+MSGHEX: FPENDING
+MSGHEX: RXWIN1, RSSI -41, SNR 9.0
+MSGHEX: Done
TX: MSGHEX 22 bytes
RX :+MSGHEX: Start
+MSGHEX: Done
In the Visual Studio 2019 debug output I could see messages getting sent and then after a short delay they were visible in the TTI console.