Fix setting illegal LoRaWan frequencies (#23388)

This commit is contained in:
Theo Arends 2025-05-07 12:26:45 +02:00
parent 502cdfb9ea
commit 5475fcc8f3
2 changed files with 61 additions and 54 deletions

View File

@ -69,27 +69,45 @@ For Others, same Uplink/Downlink (TX/RX) frequencies may not be allowed.
See: https://lora-alliance.org/wp-content/uploads/2020/11/RP_2-1.0.2.pdf See: https://lora-alliance.org/wp-content/uploads/2020/11/RP_2-1.0.2.pdf
*/ */
// Determines the channel from the current Uplink LoraSettings uint32_t LoraWanFrequencyToChannel(void) {
// return 0..71 // Determines the channel from the current Uplink LoraSettings
uint32_t LoraWanChannel(void) { uint32_t channel = 0;
float fFrequencyDiff;
uint8_t uChannel = 0;
switch (Lora->settings.region) { switch (Lora->settings.region) {
case TAS_LORA_REGION_AU915: case TAS_LORA_REGION_AU915:
if (125.0 == Lora->settings.bandwidth) { // Return 0 .. 71
fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP1; if ((Lora->settings.frequency < 915.2) || (Lora->settings.frequency > 927.8)) {
uChannel = (0.01 + (fFrequencyDiff / 0.2)); // 0.01 to fix rounding errors Lora->settings.frequency = TAS_LORAWAN_AU915_FREQUENCY_UP1; // Fix initial frequency
Lora->settings.bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_UP1; // Fix initial bandwidth
}
else if (125.0 == Lora->settings.bandwidth) {
float fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP1;
channel = (0.01 + (fFrequencyDiff / 0.2)); // 0.01 to fix rounding errors
} else { } else {
fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP2; float fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP2;
uChannel = 64 + ((0.01 + (fFrequencyDiff / 1.6))); channel = 64 + ((0.01 + (fFrequencyDiff / 1.6)));
} }
break; break;
default: // TAS_LORA_REGION_EU868
//default: // EU863-870 (EU868) JoinReq message frequencies are 868.1, 868.3 and 868.5
//not implemented uint32_t frequency = (Lora->settings.frequency * 10);
uint32_t channel = 250;
if (8681 == frequency) {
channel = 0;
}
else if (8683 == frequency) {
channel = 1;
}
else if (8685 == frequency) {
channel = 2;
}
if (250 == channel) {
Lora->settings.frequency = 868.1;
Lora->Config();
channel = 0;
}
} }
return uChannel; return channel;
} }
/***************************************************************************** /*****************************************************************************
@ -103,7 +121,7 @@ uint32_t LoraWanChannel(void) {
const uint8_t RX1DRs[] PROGMEM = {8,9,10,11,12,13,13}; // DR0..6 const uint8_t RX1DRs[] PROGMEM = {8,9,10,11,12,13,13}; // DR0..6
const uint8_t SF[] PROGMEM = {12,11,10,9,8,7,8,0,12,11,10,9,8,7}; // DR0..13 const uint8_t SF[] PROGMEM = {12,11,10,9,8,7,8,0,12,11,10,9,8,7}; // DR0..13
void LoraWanRadioInfo(uint8_t mode, void* pInfo) { void LoraWanRadioInfo(uint8_t mode, void* pInfo, uint32_t uChannel = 0) {
LoRaWanRadioInfo_t* pResult = (LoRaWanRadioInfo_t*) pInfo; LoRaWanRadioInfo_t* pResult = (LoRaWanRadioInfo_t*) pInfo;
switch (Lora->settings.region) { switch (Lora->settings.region) {
@ -166,8 +184,7 @@ void LoraWanRadioInfo(uint8_t mode, void* pInfo) {
Tasmota does not support different RX1 & RX2 DRs (yet), so just use DR8 and rely on RX2 arriving at end device OK. Tasmota does not support different RX1 & RX2 DRs (yet), so just use DR8 and rely on RX2 arriving at end device OK.
*/ */
uint32_t uChannel = LoraWanChannel(); uint8_t UplinkChannelBand = LoraWanFrequencyToChannel() %8; // 0..7
uint8_t UplinkChannelBand = uChannel %8; //0..7
switch (mode) { switch (mode) {
case TAS_LORAWAN_RADIO_UPLINK: { case TAS_LORAWAN_RADIO_UPLINK: {
// if (uChannel > 71) uChannel = 71; See note above // if (uChannel > 71) uChannel = 71; See note above
@ -224,11 +241,8 @@ bool LoraWanDefaults(uint32_t region = TAS_LORA_REGION_EU868, LoRaWanRadioMode_t
// TO DO: Need 3 profiles: Uplink, RX1, RX2 // TO DO: Need 3 profiles: Uplink, RX1, RX2
// Works OK for now as RX2 always received by end device. // Works OK for now as RX2 always received by end device.
multi_profile = true; multi_profile = true;
if ((Lora->settings.frequency < 915.2) || (Lora->settings.frequency > 927.8)) {
Lora->settings.frequency = TAS_LORAWAN_AU915_FREQUENCY_UP1;
}
LoRaWanRadioInfo_t RadioInfo; LoRaWanRadioInfo_t RadioInfo;
LoraWanRadioInfo(mode, &RadioInfo); // Region specific LoraWanRadioInfo(mode, &RadioInfo, LoraWanFrequencyToChannel()); // Region specific
Lora->settings.frequency = RadioInfo.frequency; Lora->settings.frequency = RadioInfo.frequency;
Lora->settings.bandwidth = RadioInfo.bandwidth; Lora->settings.bandwidth = RadioInfo.bandwidth;
Lora->settings.spreading_factor = RadioInfo.spreading_factor; Lora->settings.spreading_factor = RadioInfo.spreading_factor;
@ -405,7 +419,7 @@ size_t LoraWanCFList(uint8_t * CFList, size_t uLen) {
case TAS_LORA_REGION_AU915: { case TAS_LORA_REGION_AU915: {
if (uLen < 16) return 0; if (uLen < 16) return 0;
uint8_t uChannel = LoraWanChannel(); // 0..71 uint8_t uChannel = LoraWanFrequencyToChannel(); // 0..71
uint8_t uMaskByte = uChannel /8; // 0..8 uint8_t uMaskByte = uChannel /8; // 0..8
// Add first 10 bytes // Add first 10 bytes
@ -455,27 +469,6 @@ uint32_t LoraWanSpreadingFactorToDataRate(bool downlink) {
} }
} }
uint32_t LoraWanFrequencyToChannel(void) {
// EU863-870 (EU868) JoinReq message frequencies are 868.1, 868.3 and 868.5
uint32_t frequency = (Lora->settings.frequency * 10);
uint32_t channel = 250;
if (8681 == frequency) {
channel = 0;
}
else if (8683 == frequency) {
channel = 1;
}
else if (8685 == frequency) {
channel = 2;
}
if (250 == channel) {
Lora->settings.frequency = 868.1;
Lora->Config();
channel = 0;
}
return channel;
}
/*********************************************************************************************/ /*********************************************************************************************/
void LoraWanSendLinkADRReq(uint32_t node) { void LoraWanSendLinkADRReq(uint32_t node) {
@ -500,9 +493,9 @@ void LoraWanSendLinkADRReq(uint32_t node) {
case TAS_LORA_REGION_AU915: { case TAS_LORA_REGION_AU915: {
//Ref: https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf //Ref: https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
// page 39 // page 39
uint8_t uChannel = LoraWanChannel(); // 0..71 uint8_t uChannel = LoraWanFrequencyToChannel(); // 0..71
uint8_t ChMaskCntl = uChannel/16.0; // 0..4 uint8_t ChMaskCntl = uChannel /16.0; // 0..4
uChannel = uChannel%16; // 0..15 uChannel = uChannel %16; // 0..15
uint16_t uMask = 0x01 << uChannel; uint16_t uMask = 0x01 << uChannel;
data[9] = LoraWanSpreadingFactorToDataRate(false) << 4 | 0x0F; // Uplink DataRate_TXPower Should be 'DR2' for & 'unchanged' = 0x2F data[9] = LoraWanSpreadingFactorToDataRate(false) << 4 | 0x0F; // Uplink DataRate_TXPower Should be 'DR2' for & 'unchanged' = 0x2F

View File

@ -48,17 +48,17 @@ void LoraSettings2Json(bool show = false) {
#ifdef USE_LORAWAN_BRIDGE #ifdef USE_LORAWAN_BRIDGE
if (show && (Lora->settings.region == TAS_LORA_REGION_AU915)) { if (show && (Lora->settings.region == TAS_LORA_REGION_AU915)) {
LoRaWanRadioInfo_t Rx1Info; LoRaWanRadioInfo_t Rx1Info;
LoraWanRadioInfo(TAS_LORAWAN_RADIO_RX1, &Rx1Info); // Get Rx1Info with values used for RX1 transmit window. (Region specific, calculated from Uplink radio settings) LoraWanRadioInfo(TAS_LORAWAN_RADIO_RX1, &Rx1Info, LoraWanFrequencyToChannel()); // Get Rx1Info with values used for RX1 transmit window. (Region specific, calculated from Uplink radio settings)
LoRaWanRadioInfo_t Rx2Info; LoRaWanRadioInfo_t Rx2Info;
LoraWanRadioInfo(TAS_LORAWAN_RADIO_RX2, &Rx2Info); // Get Rx2Info LoraWanRadioInfo(TAS_LORAWAN_RADIO_RX2, &Rx2Info, LoraWanFrequencyToChannel()); // Get Rx2Info
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":[%1_f,%1_f,%1_f]"), &Lora->settings.frequency, &Rx1Info.frequency, &Rx2Info.frequency); // xxx.x MHz ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":[%1_f,%1_f,%1_f]"), &Lora->settings.frequency, &Rx1Info.frequency, &Rx2Info.frequency); // xxx.x MHz
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":[%1_f,%1_f,%1_f]"), &Lora->settings.bandwidth, &Rx1Info.bandwidth, &Rx2Info.bandwidth); // xxx.x kHz ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":[%1_f,%1_f,%1_f]"), &Lora->settings.bandwidth, &Rx1Info.bandwidth, &Rx2Info.bandwidth); // xxx.x kHz
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":[%d,%d,%d]"), Lora->settings.spreading_factor, Rx1Info.spreading_factor, Rx2Info.spreading_factor); ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":[%d,%d,%d]"), Lora->settings.spreading_factor, Rx1Info.spreading_factor, Rx2Info.spreading_factor);
} else } else
#endif // USE_LORAWAN_BRIDGE #endif // USE_LORAWAN_BRIDGE
{ {
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%1_f"), &Lora->settings.frequency); // xxx.x MHz ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%1_f"), &Lora->settings.frequency); // xxx.x MHz
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &Lora->settings.bandwidth); // xxx.x kHz ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &Lora->settings.bandwidth); // xxx.x kHz
ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":%d"), Lora->settings.spreading_factor); ResponseAppend_P(PSTR(",\"" D_JSON_SPREADING_FACTOR "\":%d"), Lora->settings.spreading_factor);
} }
ResponseAppend_P(PSTR(",\"" D_JSON_CODINGRATE4 "\":%d"), Lora->settings.coding_rate); ResponseAppend_P(PSTR(",\"" D_JSON_CODINGRATE4 "\":%d"), Lora->settings.coding_rate);
@ -443,19 +443,33 @@ void CmndLoraConfig(void) {
// LoRaConfig 1 - Set EU868 default parameters // LoRaConfig 1 - Set EU868 default parameters
// LoRaConfig 2 - Set EU868 default LoRaWan bridge parameters // LoRaConfig 2 - Set EU868 default LoRaWan bridge parameters
// LoRaConfig 41 - Set AU915 default parameters // LoRaConfig 41 - Set AU915 default parameters
// LoRaConfig 42 - Set AU915 default LoRaWan bridge parameters // LoRaConfig 42 - Set AU915 default LoRaWan bridge parameters with channel 0
// LoRaConfig 42,10 - Set AU915 default LoRaWan bridge parameters with channel 10
// LoRaConfig {"Frequency":868.0,"Bandwidth":125.0} - Enter float parameters // LoRaConfig {"Frequency":868.0,"Bandwidth":125.0} - Enter float parameters
// LoRaConfig {"SyncWord":18} - Enter decimal parameter (=0x12) // LoRaConfig {"SyncWord":18} - Enter decimal parameter (=0x12)
if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.data_len > 0) {
if (XdrvMailbox.payload > 0) { if (XdrvMailbox.payload > 0) {
uint32_t region = XdrvMailbox.payload / 10; uint32_t region = (XdrvMailbox.payload / 10) &0x0F; // 0 .. 15
uint32_t option = ((XdrvMailbox.payload -1) &1) +1; // Option 1 or 2 if (region > 9) { region = 0; } // 0 .. 9
uint32_t option = ((XdrvMailbox.payload -1) &0x01) +1; // Option 1 or 2
switch (option) { switch (option) {
case 1: case 1:
LoraDefaults(region); // Default region LoRa values LoraDefaults(region); // Default region LoRa values
break; break;
#ifdef USE_LORAWAN_BRIDGE #ifdef USE_LORAWAN_BRIDGE
case 2: case 2:
switch (region) {
case TAS_LORA_REGION_AU915:
uint32_t parm[2] = { 0, 0 };
ParseParameters(2, parm); // parm[1] will hold channel
Lora->settings.region = region; // Need valid region for LoraWanRadioInfo()
LoRaWanRadioInfo_t UpInfo;
LoraWanRadioInfo(TAS_LORAWAN_RADIO_UPLINK, &UpInfo, parm[1]); // Set uplink frequency based on channel
Lora->settings.frequency = UpInfo.frequency;
break;
// default:
// not implemented
}
LoraWanDefaults(region); // Default region LoRaWan values LoraWanDefaults(region); // Default region LoRaWan values
break; break;
#endif // USE_LORAWAN_BRIDGE #endif // USE_LORAWAN_BRIDGE