LoRaWAN-Gateway does not receive messages using LoRaSender Example

Hello everyone,

I am trying to send LoRaWAN messages from a Heltec Wifi LoRa v3 to a Milesight Gateway connected via Semtech UDP with The Things Network.

I need to send LoRaWAN messages with specific payloads and on defined freqs/sf in order to test some common vulnerabilities for a practical part in my master thesis.

Sending messages with the code example LoRaWan_OLED_sender.ino works fine, but I have problems using the example LoRaSender.ino and the library lora-packet to generate the PHYPayloads.

I have also a CatSniffer from ElectronicCats to sniff all messages.
CatSniffer can receive both - the LoRaWAN MAC implementation of Heltec (LoRaWan_APP) and the custom implementation with manual PHYPayload generation (RadioLib). And the PhyPayloads are valid.

Example generated PhyPayload (Join Request) with Fake IDs: 00F7F885B1569199A901010000009199A9DD63099FC5BB

I tried also to analyse the UDP packets sent from Gateway to TTN with Wireshark - but the Gateway does not receive any packets.

Does anyone have an idea?

Is there a better way to set the public sync word instead Radio.SetSyncWord(52);?

Library for PHYPayloads: https://github.com/anthonykirby/lora-packet

Example LoRaSender.ino: https://github.com/HelTecAutomation/Heltec_ESP32/blob/master/examples/LoRa/LoRaSender/LoRaSender.ino

Custom Code to send HEX based PHYPayloads:

#define SERIALCOMMAND_HARDWAREONLY

#include “HT_SSD1306Wire.h”
#include “LoRaWan_APP.h”
#include <RadioLib.h>
#include “Arduino.h”

SSD1306Wire display1(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr , freq , i2c group , resolution , rst

#define RF_FREQUENCY 867300000 // Hz

#define TX_OUTPUT_POWER 20 // dBm

#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7…SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false

#define BUFFER_SIZE 100

char rxpacket[BUFFER_SIZE];

bool lora_idle = true;
bool rx_on = false;
int rx_progress = 0;
int16_t rssi, rxSize;

static RadioEvents_t RadioEvents;
void OnTxDone(void);
void OnTxTimeout(void);
void OnRxError(void);

void setup() {
Serial.begin(115200);
Mcu.begin();
VextON();

display1.init();
displayText(“Setup LoRa Rx/Tx…”);

RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxDone = OnRxDone;
RadioEvents.RxError = OnRxError;

Radio.Init(&RadioEvents);
Radio.SetChannel(RF_FREQUENCY);
Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, 3000);
Radio.SetSyncWord(52);

rssi = 0;

displayText(“Waiting For Cmd…”);
}

void VextON(void) {
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
}

void loop() {
if (Serial.available()) {
String command = Serial.readStringUntil(’\n’);

if (command.startsWith("tx ")) {
  displayText("Got Tx Cmd......");
  tx_sent(command.substring(3));
} else {
  displayText("Cmd not found......");
  showDisplayStartView();
}

}

if (rx_on) {
if (rx_progress == 100) {
rx_on = false;
rx_progress = 0;

  displayText("Waiting For Cmd.........");
  return;
}

drawRxProgress();
rx_progress++;
delay(80);

}

Radio.IrqProcess();
}

void OnTxDone(void) {
displayText(“TX done…”);

listenToRxTemporarily();

lora_idle = true;
}

void OnTxTimeout(void) {
Radio.Sleep();
displayText(“TX Timeout…”);
showDisplayStartView();

lora_idle = true;
}

void OnRxDone(uint8_t* payload, uint16_t size, int16_t rssi, int8_t snr) {
rssi = rssi;
rxSize = size;

memcpy(rxpacket, payload, size);
rxpacket[size] = ‘\0’;

Radio.Sleep();

Serial.printf("\r\nreceived packet “%s” with rssi %d , length %d\r\n", rxpacket, rssi, rxSize);
displayText(“Received Packet… :/”);
showDisplayStartView();

lora_idle = true;
}

void OnRxError(void) {
displayText(“RX Error… :/”);
showDisplayStartView();

lora_idle = true;
}

void tx_sent(String message) {
if (lora_idle == true) {
int message_len = message.length() + 1;
char char_array[message_len];
message.toCharArray(char_array, message_len);

int outDataLength = (sizeof(char_array) - 1) / 2;
byte outData[outDataLength];

Serial.printf("\r\nsending packet \"%s\" , length %d, bytes %d\r\n", char_array, strlen(char_array), outDataLength);

hexCharacterStringToBytes(outData, char_array);

Radio.Send(outData, outDataLength);
displayText("Sending Package......");

lora_idle = false;

} else {
displayText(“LoRa is NOT idle…”);
}
}

void displayText(String text) {
Serial.println(text);

display1.clear();
display1.setFont(ArialMT_Plain_10);
display1.setTextAlignment(TEXT_ALIGN_LEFT);
display1.drawString(0, 26, text);
display1.display();
}

void drawRxProgress() {
display1.clear();
display1.drawProgressBar(0, 32, 120, 10, rx_progress);

display1.setTextAlignment(TEXT_ALIGN_CENTER);
display1.drawString(64, 15, “RX mode on”);
display1.display();
}

void showDisplayStartView() {
delay(1000);
displayText(“Waiting For Cmd…”);
}

void listenToRxTemporarily(void) {
rx_on = true;
Serial.println(“Listen to Rx for 8 Seconds”);
Radio.Rx(8000);
}

void hexCharacterStringToBytes(byte* byteArray, const char* hexString) {
bool oddLength = strlen(hexString) & 1;

byte currentByte = 0;
byte byteIndex = 0;

for (byte charIndex = 0; charIndex < strlen(hexString); charIndex++) {
bool oddCharIndex = charIndex & 1;

if (oddLength) {
  // If the length is odd
  if (oddCharIndex) {
    // odd characters go in high nibble
    currentByte = nibble(hexString[charIndex]) << 4;
  } else {
    // Even characters go into low nibble
    currentByte |= nibble(hexString[charIndex]);
    byteArray[byteIndex++] = currentByte;
    currentByte = 0;
  }
} else {
  // If the length is even
  if (!oddCharIndex) {
    // Odd characters go into the high nibble
    currentByte = nibble(hexString[charIndex]) << 4;
  } else {
    // Odd characters go into low nibble
    currentByte |= nibble(hexString[charIndex]);
    byteArray[byteIndex++] = currentByte;
    currentByte = 0;
  }
}

}
}

byte nibble(char c) {
if (c >= ‘0’ && c <= ‘9’)
return c - ‘0’;

if (c >= ‘a’ && c <= ‘f’)
return c - ‘a’ + 10;

if (c >= ‘A’ && c <= ‘F’)
return c - ‘A’ + 10;

return 0; // Not a valid hexadecimal character
}

You should refer to the Lorawan instance instead of Lora point-to-point