From b4a20c19f8bde6413b34be67725cd429b62b8347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Wed, 19 Nov 2025 12:38:34 +0100 Subject: [PATCH 01/39] Add a new frequency range for EU SRD area with adaptive DC --- src/DisplayFormatters.cpp | 3 ++ src/airtime.cpp | 7 ++-- src/graphics/draw/MenuHandler.cpp | 2 +- src/mesh/MeshRadio.h | 9 +++++- src/mesh/RadioInterface.cpp | 54 +++++++++++++++++++++++++++---- src/mesh/Router.cpp | 7 ++-- src/modules/AdminModule.cpp | 2 +- 7 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/DisplayFormatters.cpp b/src/DisplayFormatters.cpp index d88f9fc9fe7..e22c9ca301c 100644 --- a/src/DisplayFormatters.cpp +++ b/src/DisplayFormatters.cpp @@ -37,6 +37,9 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: return useShortName ? "LongM" : "LongMod"; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: + return useShortName ? "LiteF" : "LiteFast"; + break; default: return useShortName ? "Custom" : "Invalid"; break; diff --git a/src/airtime.cpp b/src/airtime.cpp index a7736d66711..0e0d72e20e9 100644 --- a/src/airtime.cpp +++ b/src/airtime.cpp @@ -133,11 +133,12 @@ bool AirTime::isTxAllowedChannelUtil(bool polite) bool AirTime::isTxAllowedAirUtil() { - if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) { - if (utilizationTXPercent() < myRegion->dutyCycle * polite_duty_cycle_percent / 100) { + float effectiveDutyCycle = getEffectiveDutyCycle(); + if (!config.lora.override_duty_cycle && effectiveDutyCycle < 100) { + if (utilizationTXPercent() < effectiveDutyCycle * polite_duty_cycle_percent / 100) { return true; } else { - LOG_WARN("TX air util. >%f%%. Skip send", myRegion->dutyCycle * polite_duty_cycle_percent / 100); + LOG_WARN("TX air util. >%f%%. Skip send", effectiveDutyCycle * polite_duty_cycle_percent / 100); return false; } } diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 586bdd4a66c..9b1de37c4c0 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -173,7 +173,7 @@ void menuHandler::LoraRegionPicker(uint32_t duration) #endif config.lora.tx_enabled = true; initRegion(); - if (myRegion->dutyCycle < 100) { + if (getEffectiveDutyCycle() < 100) { config.lora.ignore_mqtt = true; // Ignore MQTT by default if region has a duty cycle limit } diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index f2514eea1a2..1eed7559b8b 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -22,4 +22,11 @@ struct RegionInfo { extern const RegionInfo regions[]; extern const RegionInfo *myRegion; -extern void initRegion(); \ No newline at end of file +extern void initRegion(); + +/** + * Get the effective duty cycle for the current region based on device role. + * For EU_866, returns 10% for fixed devices (ROUTER, ROUTER_LATE) and 2.5% for mobile devices. + * For other regions, returns the standard duty cycle. + */ +extern float getEffectiveDutyCycle(); \ No newline at end of file diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index f7daf11228c..ac18ae025f3 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -187,6 +187,13 @@ const RegionInfo regions[] = { */ RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false), + /* + EU 866MHz RFID band (ETSI EN 302 208): 4 channels at 865.7/866.3/866.9/867.5 MHz + 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) + https://www.etsi.org/deliver/etsi_en/302200_302299/302208/03.04.01_60/en_302208v030401p.pdf + */ + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false), + /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ @@ -219,6 +226,23 @@ void initRegion() myRegion = r; } +/** + * Get duty cycle for current region. EU_866: 10% for routers, 2.5% for mobile. + */ +float getEffectiveDutyCycle() +{ + if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866) { + if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER || + config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) { + return 10.0f; + } else { + return 2.5f; + } + } + // For all other regions, return the standard duty cycle + return myRegion->dutyCycle; +} + /** * ## LoRaWAN for North America @@ -518,6 +542,11 @@ void RadioInterface::applyModemConfig() cr = 8; sf = 12; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: + bw = 125; + cr = 5; + sf = 9; + break; } } else { sf = loraConfig.spread_factor; @@ -564,6 +593,19 @@ void RadioInterface::applyModemConfig() // Set to default modem preset loraConfig.use_preset = true; loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { + static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; + LOG_ERROR(err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + sprintf(cn->message, err_string); + service->sendClientNotification(cn); + + // Set to LiteFast preset which is compliant + loraConfig.use_preset = true; + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; } else { validConfig = true; } @@ -582,8 +624,9 @@ void RadioInterface::applyModemConfig() // Set final tx_power back onto config loraConfig.tx_power = (int8_t)power; // cppcheck-suppress assignmentAddressToInteger - // Calculate the number of channels - uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000))); + // Calculate number of channels: spacing = gap between channels (0 for continuous spectrum) + float channelSpacing = myRegion->spacing + (bw / 1000); + uint32_t numChannels = round((myRegion->freqEnd - myRegion->freqStart + myRegion->spacing) / channelSpacing); // If user has manually specified a channel num, then use that, otherwise generate one by hashing the name const char *channelName = channels.getName(channels.getPrimaryIndex()); @@ -595,11 +638,8 @@ void RadioInterface::applyModemConfig() channel_num == hash(DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false, config.lora.use_preset)) % numChannels; - // Old frequency selection formula - // float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num); - - // New frequency selection formula - float freq = myRegion->freqStart + (bw / 2000) + (channel_num * (bw / 1000)); + // Calculate frequency: freqStart is band edge, add half bandwidth to get first channel center + float freq = myRegion->freqStart + (bw / 2000) + (channel_num * channelSpacing); // override if we have a verbatim frequency if (loraConfig.override_frequency) { diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 47ed0c85a44..115079147a0 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -294,10 +294,11 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) } // should have already been handled by sendLocal // Abort sending if we are violating the duty cycle - if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) { + float effectiveDutyCycle = getEffectiveDutyCycle(); + if (!config.lora.override_duty_cycle && effectiveDutyCycle < 100) { float hourlyTxPercent = airTime->utilizationTXPercent(); - if (hourlyTxPercent > myRegion->dutyCycle) { - uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle); + if (hourlyTxPercent > effectiveDutyCycle) { + uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, effectiveDutyCycle); LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d mins", silentMinutes); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 5f0c27fffa2..a3a3278c725 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -798,7 +798,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) #endif config.lora.tx_enabled = true; initRegion(); - if (myRegion->dutyCycle < 100) { + if (getEffectiveDutyCycle() < 100) { config.lora.ignore_mqtt = true; // Ignore MQTT by default if region has a duty cycle limit } // Compare the entire string, we are sure of the length as a topic has never been set From b1a06336103dc5f2c5fe50ab3d8d7529c0fb75bb Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 20 Dec 2025 01:26:58 +0000 Subject: [PATCH 02/39] new presets yo --- protobufs | 2 +- src/DisplayFormatters.cpp | 12 ++++++++++++ src/graphics/draw/MenuHandler.cpp | 12 ++++++++++-- src/mesh/RadioInterface.cpp | 11 +++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/protobufs b/protobufs index 9beb80f1d30..e2d639a59b6 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 9beb80f1d302f70d05f9c4bc9dd543b8f7bc8796 +Subproject commit e2d639a59b61e9a4bed5bb3b76c4adc8f6add036 diff --git a/src/DisplayFormatters.cpp b/src/DisplayFormatters.cpp index e22c9ca301c..1d53d4da479 100644 --- a/src/DisplayFormatters.cpp +++ b/src/DisplayFormatters.cpp @@ -40,6 +40,18 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: return useShortName ? "LiteF" : "LiteFast"; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: + return useShortName ? "LiteS" : "LiteSlow"; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: + return useShortName ? "NarF" : "NarrowFast"; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: + return useShortName ? "NarS" : "NarrowSlow"; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: + return useShortName ? "HamF" : "HamFast"; + break; default: return useShortName ? "Custom" : "Invalid"; break; diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 9b1de37c4c0..e7e3f1921f0 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -132,7 +132,10 @@ void menuHandler::LoraRegionPicker(uint32_t duration) "KZ_433", "KZ_863", "NP_865", - "BR_902"}; + "BR_902", + "EU_866", + "NARROW_868", + "HAM_US433"}; BannerOverlayOptions bannerOptions; #if defined(M5STACK_UNITC6L) bannerOptions.message = "LoRa Region"; @@ -141,7 +144,7 @@ void menuHandler::LoraRegionPicker(uint32_t duration) #endif bannerOptions.durationMs = duration; bannerOptions.optionsArrayPtr = optionsArray; - bannerOptions.optionsCount = 27; + bannerOptions.optionsCount = 30; bannerOptions.InitialSelected = 0; bannerOptions.bannerCallback = [](int selected) -> void { if (selected != 0 && config.lora.region != _meshtastic_Config_LoRaConfig_RegionCode(selected)) { @@ -236,6 +239,11 @@ void menuHandler::RadioPresetPicker() {"ShortSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW}, {"ShortFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST}, {"ShortTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO}, + {"NarrowFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST}, + {"NarrowSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW}, + {"NarrowFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST}, + {"NarrowSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}, + {"HamFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST}, }; constexpr size_t presetCount = sizeof(presetOptions) / sizeof(presetOptions[0]); diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index ac18ae025f3..6d154e7689e 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -194,6 +194,17 @@ const RegionInfo regions[] = { */ RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false), + /* + EU 868MHz band: 3 channels at 868.415/868.4925/868.570 MHz + 15 kHz gap between channels, 27 dBm, duty cycle 10% + */ + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false), + + /* + HAM 433MHz band + */ + RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false), + /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ From d6b58c7b500f2e112e28f9c9f060aae863a533a5 Mon Sep 17 00:00:00 2001 From: NomDeTom <116762865+NomDeTom@users.noreply.github.com> Date: Sat, 20 Dec 2025 01:36:46 +0000 Subject: [PATCH 03/39] Update protobufs --- src/mesh/generated/meshtastic/config.pb.h | 39 +++++++++-- src/mesh/generated/meshtastic/mesh.pb.cpp | 5 ++ src/mesh/generated/meshtastic/mesh.pb.h | 75 +++++++++++++++++++++ src/mesh/generated/meshtastic/portnums.pb.h | 5 ++ 4 files changed, 118 insertions(+), 6 deletions(-) diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index d4ef5bee49a..848a53a99c3 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -285,7 +285,13 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode { /* Nepal 865MHz */ meshtastic_Config_LoRaConfig_RegionCode_NP_865 = 25, /* Brazil 902MHz */ - meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26 + meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26, + /* EU 866MHz RFID band (ETSI EN 302 208) */ + meshtastic_Config_LoRaConfig_RegionCode_EU_866 = 27, + /* EU 866MHz RFID band (ETSI EN 302 208) */ + meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 = 28, + /* EU 866MHz RFID band (ETSI EN 302 208) */ + meshtastic_Config_LoRaConfig_RegionCode_HAM_US433 = 29 } meshtastic_Config_LoRaConfig_RegionCode; /* Standard predefined channel settings @@ -315,7 +321,28 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset { meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO = 8, /* Long Range - Turbo This preset performs similarly to LongFast, but with 500Khz bandwidth. */ - meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO = 9 + meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO = 9, + /* Lite Fast + Medium range preset optimized for EU 866MHz RFID band with 125kHz bandwidth. + Comparable link budget to MEDIUM_FAST but compliant with ETSI EN 302 208. */ + meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST = 10, + /* Lite Slow + Medium-to-moderate range preset optimized for EU 866MHz RFID band with 125kHz bandwidth. + Comparable link budget to LONG_FAST but compliant with ETSI EN 302 208. */ + meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW = 11, + /* Narrow Fast + Medium-to-moderate range preset optimized for EU 868MHz band with 62.5kHz bandwidth. + Comparable link budget to SHORT_SLOW, but with half the data rate. + Intended to avoid interference with other devices. */ + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST = 12, + /* Narrow Slow + Moderate range preset optimized for EU 868MHz band with 62.5kHz bandwidth. + Comparable link budget and data rate to LONG_FAST. */ + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW = 13, + /* Ham Fast + Short range preset optimized for 433MHz band with wide bandwidth. + Intended for use in amateur radio bands. */ + meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST = 14 } meshtastic_Config_LoRaConfig_ModemPreset; typedef enum _meshtastic_Config_BluetoothConfig_PairingMode { @@ -689,12 +716,12 @@ extern "C" { #define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1)) #define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET -#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_BR_902 -#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_BR_902+1)) +#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_HAM_US433 +#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_HAM_US433+1)) #define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST -#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO -#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO+1)) +#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST +#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST+1)) #define _meshtastic_Config_BluetoothConfig_PairingMode_MIN meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN #define _meshtastic_Config_BluetoothConfig_PairingMode_MAX meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp index 9966e52f8da..d8eee120336 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.cpp +++ b/src/mesh/generated/meshtastic/mesh.pb.cpp @@ -24,6 +24,9 @@ PB_BIND(meshtastic_Data, meshtastic_Data, 2) PB_BIND(meshtastic_KeyVerification, meshtastic_KeyVerification, AUTO) +PB_BIND(meshtastic_StoreForwardPlusPlus, meshtastic_StoreForwardPlusPlus, 2) + + PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO) @@ -121,6 +124,8 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU + + diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 0c48a789128..6f2c755bed2 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -478,6 +478,22 @@ typedef enum _meshtastic_Routing_Error { meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38 } meshtastic_Routing_Error; +/* Enum of message types */ +typedef enum _meshtastic_StoreForwardPlusPlus_SFPP_message_type { + /* Send an announcement of the canonical tip of a chain */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE = 0, + /* Query whether a specific link is on the chain */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type_CHAIN_QUERY = 1, + /* Request the next link in the chain */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_REQUEST = 3, + /* Provide a link to add to the chain */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE = 4, + /* If we must fragment, send the first half */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_FIRSTHALF = 5, + /* If we must fragment, send the second half */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF = 6 +} meshtastic_StoreForwardPlusPlus_SFPP_message_type; + /* The priority of this message for sending. Higher priorities are sent first (when managing the transmit queue). This field is never sent over the air, it is only used internally inside of a local device node. @@ -782,6 +798,32 @@ typedef struct _meshtastic_KeyVerification { meshtastic_KeyVerification_hash2_t hash2; } meshtastic_KeyVerification; +typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_message_hash_t; +typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_commit_hash_t; +typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_root_hash_t; +typedef PB_BYTES_ARRAY_T(240) meshtastic_StoreForwardPlusPlus_message_t; +/* The actual over-the-mesh message doing store and forward++ */ +typedef struct _meshtastic_StoreForwardPlusPlus { + /* Which message type is this */ + meshtastic_StoreForwardPlusPlus_SFPP_message_type sfpp_message_type; + /* The hash of the specific message */ + meshtastic_StoreForwardPlusPlus_message_hash_t message_hash; + /* The hash of a link on a chain */ + meshtastic_StoreForwardPlusPlus_commit_hash_t commit_hash; + /* the root hash of a chain */ + meshtastic_StoreForwardPlusPlus_root_hash_t root_hash; + /* The encrypted bytes from a message */ + meshtastic_StoreForwardPlusPlus_message_t message; + /* Message ID of the contained message */ + uint32_t encapsulated_id; + /* Destination of the contained message */ + uint32_t encapsulated_to; + /* Sender of the contained message */ + uint32_t encapsulated_from; + /* The receive time of the message in question */ + uint32_t encapsulated_rxtime; +} meshtastic_StoreForwardPlusPlus; + /* Waypoint message, used to share arbitrary locations across the mesh */ typedef struct _meshtastic_Waypoint { /* Id of the waypoint */ @@ -1310,6 +1352,10 @@ extern "C" { #define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED #define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED+1)) +#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE +#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF +#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1)) + #define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET #define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX #define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1)) @@ -1338,6 +1384,8 @@ extern "C" { #define meshtastic_Data_portnum_ENUMTYPE meshtastic_PortNum +#define meshtastic_StoreForwardPlusPlus_sfpp_message_type_ENUMTYPE meshtastic_StoreForwardPlusPlus_SFPP_message_type + #define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority @@ -1380,6 +1428,7 @@ extern "C" { #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} +#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} @@ -1411,6 +1460,7 @@ extern "C" { #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} +#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} @@ -1489,6 +1539,15 @@ extern "C" { #define meshtastic_KeyVerification_nonce_tag 1 #define meshtastic_KeyVerification_hash1_tag 2 #define meshtastic_KeyVerification_hash2_tag 3 +#define meshtastic_StoreForwardPlusPlus_sfpp_message_type_tag 1 +#define meshtastic_StoreForwardPlusPlus_message_hash_tag 2 +#define meshtastic_StoreForwardPlusPlus_commit_hash_tag 3 +#define meshtastic_StoreForwardPlusPlus_root_hash_tag 4 +#define meshtastic_StoreForwardPlusPlus_message_tag 5 +#define meshtastic_StoreForwardPlusPlus_encapsulated_id_tag 6 +#define meshtastic_StoreForwardPlusPlus_encapsulated_to_tag 7 +#define meshtastic_StoreForwardPlusPlus_encapsulated_from_tag 8 +#define meshtastic_StoreForwardPlusPlus_encapsulated_rxtime_tag 9 #define meshtastic_Waypoint_id_tag 1 #define meshtastic_Waypoint_latitude_i_tag 2 #define meshtastic_Waypoint_longitude_i_tag 3 @@ -1705,6 +1764,19 @@ X(a, STATIC, SINGULAR, BYTES, hash2, 3) #define meshtastic_KeyVerification_CALLBACK NULL #define meshtastic_KeyVerification_DEFAULT NULL +#define meshtastic_StoreForwardPlusPlus_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, sfpp_message_type, 1) \ +X(a, STATIC, SINGULAR, BYTES, message_hash, 2) \ +X(a, STATIC, SINGULAR, BYTES, commit_hash, 3) \ +X(a, STATIC, SINGULAR, BYTES, root_hash, 4) \ +X(a, STATIC, SINGULAR, BYTES, message, 5) \ +X(a, STATIC, SINGULAR, UINT32, encapsulated_id, 6) \ +X(a, STATIC, SINGULAR, UINT32, encapsulated_to, 7) \ +X(a, STATIC, SINGULAR, UINT32, encapsulated_from, 8) \ +X(a, STATIC, SINGULAR, UINT32, encapsulated_rxtime, 9) +#define meshtastic_StoreForwardPlusPlus_CALLBACK NULL +#define meshtastic_StoreForwardPlusPlus_DEFAULT NULL + #define meshtastic_Waypoint_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, id, 1) \ X(a, STATIC, OPTIONAL, SFIXED32, latitude_i, 2) \ @@ -1980,6 +2052,7 @@ extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg; extern const pb_msgdesc_t meshtastic_Routing_msg; extern const pb_msgdesc_t meshtastic_Data_msg; extern const pb_msgdesc_t meshtastic_KeyVerification_msg; +extern const pb_msgdesc_t meshtastic_StoreForwardPlusPlus_msg; extern const pb_msgdesc_t meshtastic_Waypoint_msg; extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg; extern const pb_msgdesc_t meshtastic_MeshPacket_msg; @@ -2013,6 +2086,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_Routing_fields &meshtastic_Routing_msg #define meshtastic_Data_fields &meshtastic_Data_msg #define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg +#define meshtastic_StoreForwardPlusPlus_fields &meshtastic_StoreForwardPlusPlus_msg #define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg #define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg #define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg @@ -2069,6 +2143,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_QueueStatus_size 23 #define meshtastic_RouteDiscovery_size 256 #define meshtastic_Routing_size 259 +#define meshtastic_StoreForwardPlusPlus_size 371 #define meshtastic_ToRadio_size 504 #define meshtastic_User_size 115 #define meshtastic_Waypoint_size 165 diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index 67adc60cc55..6b89c6a37a6 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -86,6 +86,11 @@ typedef enum _meshtastic_PortNum { /* Paxcounter lib included in the firmware ENCODING: protobuf */ meshtastic_PortNum_PAXCOUNTER_APP = 34, + /* Store and Forward++ module included in the firmware + ENCODING: protobuf + This module is specifically for Native Linux nodes, and provides a Git-style + chain of messages. */ + meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP = 35, /* Provides a hardware serial interface to send and receive from the Meshtastic network. Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network. From d8bfab5b2c87afccde755f2d5edde190d04f602b Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 20 Dec 2025 03:07:50 +0000 Subject: [PATCH 04/39] guards against using presets outside of region --- src/mesh/RadioInterface.cpp | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 6d154e7689e..a4616c1eb07 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -558,6 +558,26 @@ void RadioInterface::applyModemConfig() cr = 5; sf = 9; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: + bw = 125; + cr = 5; + sf = 10; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: + bw = 62.5; + cr = 6; + sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: + bw = 62.5; + cr = 6; + sf = 8; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: + bw = 250; + cr = 5; + sf = 7; + break; } } else { sf = loraConfig.spread_factor; @@ -604,6 +624,38 @@ void RadioInterface::applyModemConfig() // Set to default modem preset loraConfig.use_preset = true; loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + } else if (isOneOf(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && + !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, + meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { + static const char *err_string = "Narrow preset requires narrow region or ham setting. Fall back to LongFast preset."; + LOG_ERROR(err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + sprintf(cn->message, err_string); + service->sendClientNotification(cn); + + // Set to default modem preset + loraConfig.use_preset = true; + if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866) { + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; + } else + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { + static const char *err_string = "Narrow_868 requires 62.5kHz bandwidth. Fall back to NarrowFast preset"; + LOG_ERROR(err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + sprintf(cn->message, err_string); + service->sendClientNotification(cn); + + // Set to NarrowFast preset which is compliant + loraConfig.use_preset = true; + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST; } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; LOG_ERROR(err_string); From dcf476c2de777d3623f4fb4657946e7bb28a82a1 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Tue, 23 Dec 2025 03:19:00 +0000 Subject: [PATCH 05/39] update EU 866MHz band description --- src/mesh/RadioInterface.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index a4616c1eb07..596a9eff16f 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -188,9 +188,9 @@ const RegionInfo regions[] = { RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false), /* - EU 866MHz RFID band (ETSI EN 302 208): 4 channels at 865.7/866.3/866.9/867.5 MHz - 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) - https://www.etsi.org/deliver/etsi_en/302200_302299/302208/03.04.01_60/en_302208v030401p.pdf + EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) + Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% + (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false), From 8fa1c4adf87a4f32d5a5634852ee5e0797ae7fb4 Mon Sep 17 00:00:00 2001 From: Chloe Bethel Date: Wed, 24 Dec 2025 00:10:11 +0000 Subject: [PATCH 06/39] Refactor preset validation to happen before applying radio config (and don't turn off Bluetooth if it's invalid) --- src/mesh/RadioInterface.cpp | 326 ++++++++++++++++++++---------------- src/mesh/RadioInterface.h | 3 + src/modules/AdminModule.cpp | 4 + 3 files changed, 186 insertions(+), 147 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 596a9eff16f..ff56b15be56 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -495,6 +495,180 @@ uint32_t RadioInterface::getChannelNum() return savedChannelNum; } +struct ModemConfig { + float bw; + uint8_t sf; + uint8_t cr; +}; + +ModemConfig settingsForPreset(meshtastic_Config_LoRaConfig_ModemPreset preset) { + ModemConfig cfg = {0}; + switch (preset) { + case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: + cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; + cfg.cr = 5; + cfg.sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 8; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 9; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 10; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: + cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; + cfg.cr = 8; + cfg.sf = 11; + break; + default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 11; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: + cfg.bw = (myRegion->wideLora) ? 406.25 : 125; + cfg.cr = 8; + cfg.sf = 11; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW: + cfg.bw = (myRegion->wideLora) ? 406.25 : 125; + cfg.cr = 8; + cfg.sf = 12; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: + cfg.bw = 125; + cfg.cr = 5; + cfg.sf = 9; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: + cfg.bw = 125; + cfg.cr = 5; + cfg.sf = 10; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: + cfg.bw = 62.5; + cfg.cr = 6; + cfg.sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: + cfg.bw = 62.5; + cfg.cr = 6; + cfg.sf = 8; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: + cfg.bw = 250; + cfg.cr = 5; + cfg.sf = 7; + break; + } + + return cfg; +} + +bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfig) { + bool validConfig = false; + + auto cfg = settingsForPreset(loraConfig.modem_preset); + + float bw; + if(loraConfig.use_preset) { + bw = cfg.bw; + } else { + bw = loraConfig.bandwidth; + } + + if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { + const float regionSpanKHz = (myRegion->freqEnd - myRegion->freqStart) * 1000.0f; + const float requestedBwKHz = bw; + const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset + const char *presetName = + DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); + + char err_string[160]; + if (isWideRequest) { + snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.", + myRegion->name, presetName); + } else { + snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.", + myRegion->name, regionSpanKHz, requestedBwKHz); + } + LOG_ERROR("%s", err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + snprintf(cn->message, sizeof(cn->message), "%s", err_string); + service->sendClientNotification(cn); + + // Set to default modem preset + loraConfig.use_preset = true; + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + } else if (isOneOf(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && + !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, + meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { + static const char *err_string = "Narrow preset requires narrow region or ham setting. Fall back to LongFast preset."; + LOG_ERROR(err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + sprintf(cn->message, err_string); + service->sendClientNotification(cn); + + // Set to default modem preset + loraConfig.use_preset = true; + if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866) { + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; + } else + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { + static const char *err_string = "Narrow_868 requires 62.5kHz bandwidth. Fall back to NarrowFast preset"; + LOG_ERROR(err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + sprintf(cn->message, err_string); + service->sendClientNotification(cn); + + // Set to NarrowFast preset which is compliant + loraConfig.use_preset = true; + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST; + } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { + static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; + LOG_ERROR(err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + sprintf(cn->message, err_string); + service->sendClientNotification(cn); + + // Set to LiteFast preset which is compliant + loraConfig.use_preset = true; + loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; + } else { + validConfig = true; + } + + return validConfig; +} + /** * Pull our channel settings etc... from protobufs to the dumb interface settings */ @@ -506,79 +680,10 @@ void RadioInterface::applyModemConfig() bool validConfig = false; // We need to check for a valid configuration while (!validConfig) { if (loraConfig.use_preset) { - - switch (loraConfig.modem_preset) { - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: - bw = (myRegion->wideLora) ? 1625.0 : 500; - cr = 5; - sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST: - bw = (myRegion->wideLora) ? 812.5 : 250; - cr = 5; - sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW: - bw = (myRegion->wideLora) ? 812.5 : 250; - cr = 5; - sf = 8; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST: - bw = (myRegion->wideLora) ? 812.5 : 250; - cr = 5; - sf = 9; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: - bw = (myRegion->wideLora) ? 812.5 : 250; - cr = 5; - sf = 10; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: - bw = (myRegion->wideLora) ? 1625.0 : 500; - cr = 8; - sf = 11; - break; - default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. - bw = (myRegion->wideLora) ? 812.5 : 250; - cr = 5; - sf = 11; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: - bw = (myRegion->wideLora) ? 406.25 : 125; - cr = 8; - sf = 11; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW: - bw = (myRegion->wideLora) ? 406.25 : 125; - cr = 8; - sf = 12; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: - bw = 125; - cr = 5; - sf = 9; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: - bw = 125; - cr = 5; - sf = 10; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: - bw = 62.5; - cr = 6; - sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: - bw = 62.5; - cr = 6; - sf = 8; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: - bw = 250; - cr = 5; - sf = 7; - break; - } + auto settings = settingsForPreset(loraConfig.modem_preset); + sf = settings.sf; + cr = settings.cr; + bw = settings.bw; } else { sf = loraConfig.spread_factor; cr = loraConfig.coding_rate; @@ -598,80 +703,7 @@ void RadioInterface::applyModemConfig() bw = 1625.0; } - if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { - const float regionSpanKHz = (myRegion->freqEnd - myRegion->freqStart) * 1000.0f; - const float requestedBwKHz = bw; - const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset - const char *presetName = - DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); - - char err_string[160]; - if (isWideRequest) { - snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.", - myRegion->name, presetName); - } else { - snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.", - myRegion->name, regionSpanKHz, requestedBwKHz); - } - LOG_ERROR("%s", err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - snprintf(cn->message, sizeof(cn->message), "%s", err_string); - service->sendClientNotification(cn); - - // Set to default modem preset - loraConfig.use_preset = true; - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; - } else if (isOneOf(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && - !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, - meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { - static const char *err_string = "Narrow preset requires narrow region or ham setting. Fall back to LongFast preset."; - LOG_ERROR(err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); - service->sendClientNotification(cn); - - // Set to default modem preset - loraConfig.use_preset = true; - if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866) { - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; - } else - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; - } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { - static const char *err_string = "Narrow_868 requires 62.5kHz bandwidth. Fall back to NarrowFast preset"; - LOG_ERROR(err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); - service->sendClientNotification(cn); - - // Set to NarrowFast preset which is compliant - loraConfig.use_preset = true; - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST; - } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { - static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; - LOG_ERROR(err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); - service->sendClientNotification(cn); - - // Set to LiteFast preset which is compliant - loraConfig.use_preset = true; - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; - } else { - validConfig = true; - } + validConfig = validateModemConfig(loraConfig); } power = loraConfig.tx_power; diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 6049a11cc27..f6087accadc 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -220,6 +220,9 @@ class RadioInterface // Whether we use the default frequency slot given our LoRa config (region and modem preset) static bool uses_default_frequency_slot; + // Check if a candidate radio configuration is valid. + static bool validateModemConfig(meshtastic_Config_LoRaConfig &loraConfig); + protected: int8_t power = 17; // Set by applyModemConfig() diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index a3a3278c725..bc51d182e6d 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -746,6 +746,10 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) LOG_WARN("Invalid bandwidth %d, setting to default", originalBandwidth); } + if(!RadioInterface::validateModemConfig(validatedLora)) { + return; + } + // If no lora radio parameters change, don't need to reboot if (oldLoraConfig.use_preset == validatedLora.use_preset && oldLoraConfig.region == validatedLora.region && oldLoraConfig.modem_preset == validatedLora.modem_preset && oldLoraConfig.bandwidth == validatedLora.bandwidth && From 94aa0fb67f65e880867ab6df59473229a682840a Mon Sep 17 00:00:00 2001 From: nomdetom Date: Wed, 24 Dec 2025 00:44:14 +0000 Subject: [PATCH 07/39] add default preset to regions --- src/mesh/MeshRadio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 1eed7559b8b..1f8a98a8327 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -16,6 +16,7 @@ struct RegionInfo { bool audioPermitted; bool freqSwitching; bool wideLora; + meshtastic_Config_LoRaConfig_ModemPreset defaultPreset; const char *name; // EU433 etc }; From 3921945256a2f18e8a30f4abfbc1107652b6acd5 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Wed, 24 Dec 2025 03:07:58 +0000 Subject: [PATCH 08/39] update RDEF macro to include default presets and preset bits --- src/mesh/MeshRadio.h | 20 ++++ src/mesh/RadioInterface.cpp | 226 ++++++++++++++++++------------------ 2 files changed, 135 insertions(+), 111 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 1f8a98a8327..31e5be83729 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -5,6 +5,25 @@ #include "PointerQueue.h" #include "configuration.h" +struct RegionPresetBits { + uint16_t allowPreset_LONG_FAST : 1; + uint16_t allowPreset_LONG_SLOW : 1; + uint16_t allowPreset_VERY_LONG_SLOW : 1; // Deprecated + uint16_t allowPreset_MEDIUM_SLOW : 1; + uint16_t allowPreset_MEDIUM_FAST : 1; + uint16_t allowPreset_SHORT_SLOW : 1; + uint16_t allowPreset_SHORT_FAST : 1; + uint16_t allowPreset_LONG_MODERATE : 1; + uint16_t allowPreset_SHORT_TURBO : 1; // 500kHz BW + uint16_t allowPreset_LONG_TURBO : 1; // 500kHz BW + uint16_t allowPreset_LITE_FAST : 1; // For EU_866 + uint16_t allowPreset_LITE_SLOW : 1; // For EU_866 + uint16_t allowPreset_NARROW_FAST : 1; // Narrow BW + uint16_t allowPreset_NARROW_SLOW : 1; // Narrow BW + uint16_t allowPreset_HAM_FAST : 1; // 500kHz BW + uint16_t reserved : 1; +}; + // Map from old region names to new region enums struct RegionInfo { meshtastic_Config_LoRaConfig_RegionCode code; @@ -17,6 +36,7 @@ struct RegionInfo { bool freqSwitching; bool wideLora; meshtastic_Config_LoRaConfig_ModemPreset defaultPreset; + RegionPresetBits presetBits; const char *name; // EU433 etc }; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index ff56b15be56..2d5f196a911 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -18,10 +18,11 @@ uint32_t pow_of_2(uint32_t n) return 1 << n; } -#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora) \ +#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora, \ + default_preset, preset_bits) \ { \ meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \ - frequency_switching, wide_lora, #name \ + frequency_switching, wide_lora, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, preset_bits, #name \ } const RegionInfo regions[] = { @@ -29,7 +30,7 @@ const RegionInfo regions[] = { https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ */ - RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false), + RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), /* EN300220 ETSI V3.2.1 [Table B.1, Item H, p. 21] @@ -37,7 +38,7 @@ const RegionInfo regions[] = { https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.02.01_60/en_30022002v030201p.pdf FIXME: https://github.com/meshtastic/firmware/issues/3371 */ - RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false), + RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, LONG_FAST, 0b1111111100000000), /* https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ @@ -53,33 +54,33 @@ const RegionInfo regions[] = { AFA) to avoid a duty cycle. (Please refer to line P page 22 of this document.) https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.01.01_60/en_30022002v030101p.pdf */ - RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false), + RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, LONG_FAST, 0b1111111100000000), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false), + RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, LONG_FAST, 0b1111111111000000), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://www.arib.or.jp/english/html/overview/doc/5-STD-T108v1_5-E1.pdf https://qiita.com/ammo0613/items/d952154f1195b64dc29f */ - RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false), + RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, LONG_FAST, 0b1111111111000000), /* https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf Also used in Brazil. */ - RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false), + RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), /* 433.05 - 434.79 MHz, 25mW EIRP max, No duty cycle restrictions AU Low Interference Potential https://www.acma.gov.au/licences/low-interference-potential-devices-lipd-class-licence NZ General User Radio Licence for Short Range Devices https://gazette.govt.nz/notice/id/2022-go3100 */ - RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false), + RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, LONG_FAST, 0b1111111111000000), /* https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf @@ -87,13 +88,13 @@ const RegionInfo regions[] = { Note: - We do LBT, so 100% is allowed. */ - RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false), + RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, LONG_FAST, 0b1111111111000000), /* https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0 https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters */ - RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false), + RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, LONG_FAST, 0b1111111111000000), /* Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor. @@ -101,42 +102,42 @@ const RegionInfo regions[] = { https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 */ - RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false), + RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, LONG_FAST, 0b1111111111000000), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false), + RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), /* https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf */ - RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false), + RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, LONG_FAST, 0b1111111111000000), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false), + RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, LONG_FAST, 0b1111111111000000), /* 433,05-434,7 Mhz 10 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false), + RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, LONG_FAST, 0b1111111111000000), /* 868,0-868,6 Mhz 25 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false), + RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, LONG_FAST, 0b1111111111000000), /* Malaysia 433 - 435 MHz at 100mW, no restrictions. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false), + RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, LONG_FAST, 0b1111111111000000), /* Malaysia @@ -145,14 +146,14 @@ const RegionInfo regions[] = { Frequency hopping is used for 919 - 923 MHz. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false), + RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, LONG_FAST, 0b1111111111000000), /* Singapore SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions. https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf */ - RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false), + RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, LONG_FAST, 0b1111111111000000), /* Philippines @@ -162,8 +163,9 @@ const RegionInfo regions[] = { https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135 */ - RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false), RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false), - RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false), + RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, LONG_FAST, 0b1111111111000000), /* Kazakhstan @@ -171,49 +173,50 @@ const RegionInfo regions[] = { 863 - 868 MHz <25 mW EIRP, 500kHz channels allowed, must not be used at airfields https://github.com/meshtastic/firmware/issues/7204 */ - RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false), RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true), + RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, LONG_FAST, 0b1111111111000000), /* Nepal 865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf */ - RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false), + RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), /* Brazil 902 - 907.5 MHz , 1W power limit, no duty cycle restrictions https://github.com/meshtastic/firmware/issues/3741 */ - RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false), + RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false), + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, LITE_FAST, 0b0000000000110000), /* EU 868MHz band: 3 channels at 868.415/868.4925/868.570 MHz 15 kHz gap between channels, 27 dBm, duty cycle 10% */ - RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false), + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, NARROW_FAST, 0b0000000000001100), /* HAM 433MHz band */ - RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false), + RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false, NARROW_FAST, 0b0000000000001110), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ - RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true), + RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, LONG_FAST, 0b1111111111000000), /* This needs to be last. Same as US. */ - RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false) + RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1000000000000000) }; @@ -501,91 +504,93 @@ struct ModemConfig { uint8_t cr; }; -ModemConfig settingsForPreset(meshtastic_Config_LoRaConfig_ModemPreset preset) { +ModemConfig settingsForPreset(meshtastic_Config_LoRaConfig_ModemPreset preset) +{ ModemConfig cfg = {0}; switch (preset) { - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: - cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; - cfg.cr = 5; - cfg.sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 8; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 9; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 10; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: - cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; - cfg.cr = 8; - cfg.sf = 11; - break; - default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 11; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: - cfg.bw = (myRegion->wideLora) ? 406.25 : 125; - cfg.cr = 8; - cfg.sf = 11; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW: - cfg.bw = (myRegion->wideLora) ? 406.25 : 125; - cfg.cr = 8; - cfg.sf = 12; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: - cfg.bw = 125; - cfg.cr = 5; - cfg.sf = 9; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: - cfg.bw = 125; - cfg.cr = 5; - cfg.sf = 10; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: - cfg.bw = 62.5; - cfg.cr = 6; - cfg.sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: - cfg.bw = 62.5; - cfg.cr = 6; - cfg.sf = 8; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: - cfg.bw = 250; - cfg.cr = 5; - cfg.sf = 7; - break; - } + case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: + cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; + cfg.cr = 5; + cfg.sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 8; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 9; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 10; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: + cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; + cfg.cr = 8; + cfg.sf = 11; + break; + default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. + cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.cr = 5; + cfg.sf = 11; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: + cfg.bw = (myRegion->wideLora) ? 406.25 : 125; + cfg.cr = 8; + cfg.sf = 11; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW: + cfg.bw = (myRegion->wideLora) ? 406.25 : 125; + cfg.cr = 8; + cfg.sf = 12; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: + cfg.bw = 125; + cfg.cr = 5; + cfg.sf = 9; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: + cfg.bw = 125; + cfg.cr = 5; + cfg.sf = 10; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: + cfg.bw = 62.5; + cfg.cr = 6; + cfg.sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: + cfg.bw = 62.5; + cfg.cr = 6; + cfg.sf = 8; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: + cfg.bw = 500; + cfg.cr = 5; + cfg.sf = 7; + break; + } return cfg; } -bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfig) { +bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfig) +{ bool validConfig = false; auto cfg = settingsForPreset(loraConfig.modem_preset); - + float bw; - if(loraConfig.use_preset) { + if (loraConfig.use_preset) { bw = cfg.bw; } else { bw = loraConfig.bandwidth; @@ -601,10 +606,10 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi char err_string[160]; if (isWideRequest) { snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.", - myRegion->name, presetName); + myRegion->name, presetName); } else { snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.", - myRegion->name, regionSpanKHz, requestedBwKHz); + myRegion->name, regionSpanKHz, requestedBwKHz); } LOG_ERROR("%s", err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -616,11 +621,10 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to default modem preset loraConfig.use_preset = true; - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + loraConfig.modem_preset = myRegion->defaultPreset; } else if (isOneOf(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && - !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, - meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && + !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { static const char *err_string = "Narrow preset requires narrow region or ham setting. Fall back to LongFast preset."; LOG_ERROR(err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); From 44a2fda220ec9a38da07dbaaf997cf812c2712bc Mon Sep 17 00:00:00 2001 From: nomdetom Date: Wed, 24 Dec 2025 16:22:52 +0000 Subject: [PATCH 09/39] Refactor RDEF macro for improved readability and consistency; adjust spacing in modem configuration functions. From 8b2277491b4f9d85a0fb5540614224dabebecffd Mon Sep 17 00:00:00 2001 From: nomdetom Date: Thu, 25 Dec 2025 01:40:33 +0000 Subject: [PATCH 10/39] Improved the allowed presets checking by adding a bitfield to each region. Corrected some text. Inserted todo items. --- src/graphics/draw/MenuHandler.cpp | 6 ++- src/mesh/MeshRadio.h | 39 ++++++++++------- src/mesh/RadioInterface.cpp | 73 +++++++++++++++---------------- 3 files changed, 62 insertions(+), 56 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index e7e3f1921f0..74f3e2ee664 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -227,6 +227,8 @@ void menuHandler::DeviceRolePicker() screen->showOverlayBanner(bannerOptions); } +// TODO: make RadioPresetOption array dynamic based on available presets for region + void menuHandler::RadioPresetPicker() { static const RadioPresetOption presetOptions[] = { @@ -239,8 +241,8 @@ void menuHandler::RadioPresetPicker() {"ShortSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW}, {"ShortFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST}, {"ShortTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO}, - {"NarrowFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST}, - {"NarrowSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW}, + {"LiteFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST}, + {"LiteSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW}, {"NarrowFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST}, {"NarrowSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}, {"HamFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST}, diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 31e5be83729..f42518bd0be 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -5,25 +5,32 @@ #include "PointerQueue.h" #include "configuration.h" +// TODO: make this reduce to a uint16_t bitfield? + struct RegionPresetBits { - uint16_t allowPreset_LONG_FAST : 1; - uint16_t allowPreset_LONG_SLOW : 1; - uint16_t allowPreset_VERY_LONG_SLOW : 1; // Deprecated - uint16_t allowPreset_MEDIUM_SLOW : 1; - uint16_t allowPreset_MEDIUM_FAST : 1; - uint16_t allowPreset_SHORT_SLOW : 1; - uint16_t allowPreset_SHORT_FAST : 1; - uint16_t allowPreset_LONG_MODERATE : 1; - uint16_t allowPreset_SHORT_TURBO : 1; // 500kHz BW - uint16_t allowPreset_LONG_TURBO : 1; // 500kHz BW - uint16_t allowPreset_LITE_FAST : 1; // For EU_866 - uint16_t allowPreset_LITE_SLOW : 1; // For EU_866 - uint16_t allowPreset_NARROW_FAST : 1; // Narrow BW - uint16_t allowPreset_NARROW_SLOW : 1; // Narrow BW - uint16_t allowPreset_HAM_FAST : 1; // 500kHz BW - uint16_t reserved : 1; + bool allowPreset_LONG_FAST; + bool allowPreset_LONG_SLOW; + bool allowPreset_VERY_LONG_SLOW; // Deprecated + bool allowPreset_MEDIUM_SLOW; + bool allowPreset_MEDIUM_FAST; + bool allowPreset_SHORT_SLOW; + bool allowPreset_SHORT_FAST; + bool allowPreset_LONG_MODERATE; + bool allowPreset_SHORT_TURBO; // 500kHz BW + bool allowPreset_LONG_TURBO; // 500kHz BW + bool allowPreset_LITE_FAST; // For EU_866 + bool allowPreset_LITE_SLOW; // For EU_866 + bool allowPreset_NARROW_FAST; // Narrow BW + bool allowPreset_NARROW_SLOW; // Narrow BW + bool allowPreset_HAM_FAST; // 500kHz BW + bool reserved; }; +constexpr RegionPresetBits PRESETS_STD = {0b110111111100000}; +constexpr RegionPresetBits PRESETS_EU_868 = {0b110111110000000}; +constexpr RegionPresetBits PRESETS_LITE = {0b0000000000110000}; +constexpr RegionPresetBits PRESETS_NARROW = {0b0000000000001100}; + // Map from old region names to new region enums struct RegionInfo { meshtastic_Config_LoRaConfig_RegionCode code; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 2d5f196a911..fe0cf2a32ae 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -30,7 +30,7 @@ const RegionInfo regions[] = { https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ */ - RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), /* EN300220 ETSI V3.2.1 [Table B.1, Item H, p. 21] @@ -38,7 +38,7 @@ const RegionInfo regions[] = { https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.02.01_60/en_30022002v030201p.pdf FIXME: https://github.com/meshtastic/firmware/issues/3371 */ - RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, LONG_FAST, 0b1111111100000000), + RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), /* https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ @@ -54,33 +54,33 @@ const RegionInfo regions[] = { AFA) to avoid a duty cycle. (Please refer to line P page 22 of this document.) https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.01.01_60/en_30022002v030101p.pdf */ - RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, LONG_FAST, 0b1111111100000000), + RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, LONG_FAST, PRESETS_EU_868), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://www.arib.or.jp/english/html/overview/doc/5-STD-T108v1_5-E1.pdf https://qiita.com/ammo0613/items/d952154f1195b64dc29f */ - RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, LONG_FAST, PRESETS_STD), /* https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf Also used in Brazil. */ - RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), /* 433.05 - 434.79 MHz, 25mW EIRP max, No duty cycle restrictions AU Low Interference Potential https://www.acma.gov.au/licences/low-interference-potential-devices-lipd-class-licence NZ General User Radio Licence for Short Range Devices https://gazette.govt.nz/notice/id/2022-go3100 */ - RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, LONG_FAST, PRESETS_STD), /* https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf @@ -88,13 +88,13 @@ const RegionInfo regions[] = { Note: - We do LBT, so 100% is allowed. */ - RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, LONG_FAST, PRESETS_STD), /* https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0 https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters */ - RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, LONG_FAST, PRESETS_STD), /* Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor. @@ -102,42 +102,42 @@ const RegionInfo regions[] = { https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 */ - RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), /* https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf */ - RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, LONG_FAST, PRESETS_STD), /* 433,05-434,7 Mhz 10 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), /* 868,0-868,6 Mhz 25 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, LONG_FAST, PRESETS_STD), /* Malaysia 433 - 435 MHz at 100mW, no restrictions. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, LONG_FAST, PRESETS_STD), /* Malaysia @@ -146,14 +146,14 @@ const RegionInfo regions[] = { Frequency hopping is used for 919 - 923 MHz. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, LONG_FAST, 0b1111111111000000), + RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, LONG_FAST, PRESETS_STD), /* Singapore SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions. https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf */ - RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, LONG_FAST, PRESETS_STD), /* Philippines @@ -163,9 +163,9 @@ const RegionInfo regions[] = { https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135 */ - RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, LONG_FAST, 0b1111111111000000), - RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, LONG_FAST, 0b1111111111000000), - RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, LONG_FAST, PRESETS_STD), /* Kazakhstan @@ -173,35 +173,35 @@ const RegionInfo regions[] = { 863 - 868 MHz <25 mW EIRP, 500kHz channels allowed, must not be used at airfields https://github.com/meshtastic/firmware/issues/7204 */ - RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, LONG_FAST, 0b1111111111000000), - RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, LONG_FAST, 0b1111111111000000), + RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, LONG_FAST, PRESETS_STD), /* Nepal 865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf */ - RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), /* Brazil 902 - 907.5 MHz , 1W power limit, no duty cycle restrictions https://github.com/meshtastic/firmware/issues/3741 */ - RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, LONG_FAST, 0b1111111111000000), + RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, LITE_FAST, 0b0000000000110000), + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, LITE_FAST, PRESETS_LITE), /* EU 868MHz band: 3 channels at 868.415/868.4925/868.570 MHz 15 kHz gap between channels, 27 dBm, duty cycle 10% */ - RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, NARROW_FAST, 0b0000000000001100), + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, NARROW_FAST, PRESETS_NARROW), /* HAM 433MHz band @@ -211,7 +211,7 @@ const RegionInfo regions[] = { /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ - RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, LONG_FAST, 0b1111111111000000), + RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, LONG_FAST, PRESETS_STD), /* This needs to be last. Same as US. @@ -605,11 +605,11 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi char err_string[160]; if (isWideRequest) { - snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.", - myRegion->name, presetName); + snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to %.0f.", + myRegion->name, presetName, myRegion->defaultPreset); } else { - snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.", - myRegion->name, regionSpanKHz, requestedBwKHz); + snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to %.0f.", + myRegion->name, regionSpanKHz, requestedBwKHz, myRegion->defaultPreset); } LOG_ERROR("%s", err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -636,10 +636,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to default modem preset loraConfig.use_preset = true; - if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866) { - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; - } else - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; + loraConfig.modem_preset = myRegion->defaultPreset; } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { static const char *err_string = "Narrow_868 requires 62.5kHz bandwidth. Fall back to NarrowFast preset"; LOG_ERROR(err_string); @@ -652,7 +649,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to NarrowFast preset which is compliant loraConfig.use_preset = true; - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST; + loraConfig.modem_preset = myRegion->defaultPreset; } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; LOG_ERROR(err_string); @@ -665,7 +662,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to LiteFast preset which is compliant loraConfig.use_preset = true; - loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST; + loraConfig.modem_preset = myRegion->defaultPreset; } else { validConfig = true; } From ab601fa2974a6b9afe0340057b4c9335a83839d4 Mon Sep 17 00:00:00 2001 From: Chloe Bethel Date: Fri, 26 Dec 2025 13:25:55 +0000 Subject: [PATCH 11/39] Check settings against the new region, not the old one --- src/mesh/RadioInterface.cpp | 52 +++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index fe0cf2a32ae..e95d4229abe 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -240,6 +240,13 @@ void initRegion() myRegion = r; } +const RegionInfo *getRegion(meshtastic_Config_LoRaConfig_RegionCode code) { + const RegionInfo *r = regions; + for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != code; r++) + ; + return r; +} + /** * Get duty cycle for current region. EU_866: 10% for routers, 2.5% for mobile. */ @@ -504,52 +511,52 @@ struct ModemConfig { uint8_t cr; }; -ModemConfig settingsForPreset(meshtastic_Config_LoRaConfig_ModemPreset preset) +ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPreset preset) { ModemConfig cfg = {0}; switch (preset) { case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: - cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; + cfg.bw = wide ? 1625.0 : 500; cfg.cr = 5; cfg.sf = 7; break; case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.bw = wide ? 812.5 : 250; cfg.cr = 5; cfg.sf = 7; break; case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.bw = wide ? 812.5 : 250; cfg.cr = 5; cfg.sf = 8; break; case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.bw = wide ? 812.5 : 250; cfg.cr = 5; cfg.sf = 9; break; case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.bw = wide ? 812.5 : 250; cfg.cr = 5; cfg.sf = 10; break; case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: - cfg.bw = (myRegion->wideLora) ? 1625.0 : 500; + cfg.bw = wide ? 1625.0 : 500; cfg.cr = 8; cfg.sf = 11; break; default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. - cfg.bw = (myRegion->wideLora) ? 812.5 : 250; + cfg.bw = wide ? 812.5 : 250; cfg.cr = 5; cfg.sf = 11; break; case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: - cfg.bw = (myRegion->wideLora) ? 406.25 : 125; + cfg.bw = wide ? 406.25 : 125; cfg.cr = 8; cfg.sf = 11; break; case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW: - cfg.bw = (myRegion->wideLora) ? 406.25 : 125; + cfg.bw = wide ? 406.25 : 125; cfg.cr = 8; cfg.sf = 12; break; @@ -587,7 +594,8 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi { bool validConfig = false; - auto cfg = settingsForPreset(loraConfig.modem_preset); + const RegionInfo *newRegion = getRegion(loraConfig.region); + auto cfg = settingsForPreset(newRegion->wideLora, loraConfig.modem_preset); float bw; if (loraConfig.use_preset) { @@ -596,8 +604,8 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi bw = loraConfig.bandwidth; } - if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { - const float regionSpanKHz = (myRegion->freqEnd - myRegion->freqStart) * 1000.0f; + if ((newRegion->freqEnd - newRegion->freqStart) < bw / 1000) { + const float regionSpanKHz = (newRegion->freqEnd - newRegion->freqStart) * 1000.0f; const float requestedBwKHz = bw; const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset const char *presetName = @@ -606,10 +614,10 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi char err_string[160]; if (isWideRequest) { snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to %.0f.", - myRegion->name, presetName, myRegion->defaultPreset); + newRegion->name, presetName, newRegion->defaultPreset); } else { snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to %.0f.", - myRegion->name, regionSpanKHz, requestedBwKHz, myRegion->defaultPreset); + newRegion->name, regionSpanKHz, requestedBwKHz, newRegion->defaultPreset); } LOG_ERROR("%s", err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -621,7 +629,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to default modem preset loraConfig.use_preset = true; - loraConfig.modem_preset = myRegion->defaultPreset; + loraConfig.modem_preset = newRegion->defaultPreset; } else if (isOneOf(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { @@ -636,8 +644,8 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to default modem preset loraConfig.use_preset = true; - loraConfig.modem_preset = myRegion->defaultPreset; - } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { + loraConfig.modem_preset = newRegion->defaultPreset; + } else if (newRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { static const char *err_string = "Narrow_868 requires 62.5kHz bandwidth. Fall back to NarrowFast preset"; LOG_ERROR(err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -649,8 +657,8 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to NarrowFast preset which is compliant loraConfig.use_preset = true; - loraConfig.modem_preset = myRegion->defaultPreset; - } else if (myRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { + loraConfig.modem_preset = newRegion->defaultPreset; + } else if (newRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; LOG_ERROR(err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -662,7 +670,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to LiteFast preset which is compliant loraConfig.use_preset = true; - loraConfig.modem_preset = myRegion->defaultPreset; + loraConfig.modem_preset = newRegion->defaultPreset; } else { validConfig = true; } @@ -681,7 +689,7 @@ void RadioInterface::applyModemConfig() bool validConfig = false; // We need to check for a valid configuration while (!validConfig) { if (loraConfig.use_preset) { - auto settings = settingsForPreset(loraConfig.modem_preset); + auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); sf = settings.sf; cr = settings.cr; bw = settings.bw; From 9536221953f049a95032d942fb53cdae56389d13 Mon Sep 17 00:00:00 2001 From: phaseloop Date: Sun, 28 Dec 2025 19:52:22 +0100 Subject: [PATCH 12/39] use array of accepted modes per region --- src/mesh/MeshRadio.h | 62 ++++++++----- src/mesh/RadioInterface.cpp | 169 +++++++++++++++++++----------------- 2 files changed, 129 insertions(+), 102 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index f42518bd0be..5b062bed81b 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -5,31 +5,44 @@ #include "PointerQueue.h" #include "configuration.h" -// TODO: make this reduce to a uint16_t bitfield? - -struct RegionPresetBits { - bool allowPreset_LONG_FAST; - bool allowPreset_LONG_SLOW; - bool allowPreset_VERY_LONG_SLOW; // Deprecated - bool allowPreset_MEDIUM_SLOW; - bool allowPreset_MEDIUM_FAST; - bool allowPreset_SHORT_SLOW; - bool allowPreset_SHORT_FAST; - bool allowPreset_LONG_MODERATE; - bool allowPreset_SHORT_TURBO; // 500kHz BW - bool allowPreset_LONG_TURBO; // 500kHz BW - bool allowPreset_LITE_FAST; // For EU_866 - bool allowPreset_LITE_SLOW; // For EU_866 - bool allowPreset_NARROW_FAST; // Narrow BW - bool allowPreset_NARROW_SLOW; // Narrow BW - bool allowPreset_HAM_FAST; // 500kHz BW - bool reserved; + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO +}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE +}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW +}; + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = { + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW +}; + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = { + meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST, }; -constexpr RegionPresetBits PRESETS_STD = {0b110111111100000}; -constexpr RegionPresetBits PRESETS_EU_868 = {0b110111110000000}; -constexpr RegionPresetBits PRESETS_LITE = {0b0000000000110000}; -constexpr RegionPresetBits PRESETS_NARROW = {0b0000000000001100}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, +}; // Map from old region names to new region enums struct RegionInfo { @@ -43,7 +56,8 @@ struct RegionInfo { bool freqSwitching; bool wideLora; meshtastic_Config_LoRaConfig_ModemPreset defaultPreset; - RegionPresetBits presetBits; + // static list of available presets + const meshtastic_Config_LoRaConfig_ModemPreset *availablePresets; const char *name; // EU433 etc }; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index e95d4229abe..b80d9086166 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -19,10 +19,10 @@ uint32_t pow_of_2(uint32_t n) } #define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora, \ - default_preset, preset_bits) \ + default_preset, available_presets) \ { \ meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \ - frequency_switching, wide_lora, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, preset_bits, #name \ + frequency_switching, wide_lora, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ } const RegionInfo regions[] = { @@ -206,7 +206,7 @@ const RegionInfo regions[] = { /* HAM 433MHz band */ - RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false, NARROW_FAST, 0b0000000000001110), + RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false, NARROW_FAST, PRESETS_HAM), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. @@ -216,7 +216,7 @@ const RegionInfo regions[] = { /* This needs to be last. Same as US. */ - RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, 0b1000000000000000) + RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_UNDEF) }; @@ -592,11 +592,42 @@ ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPrese bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfig) { - bool validConfig = false; + bool validConfig = true; + char err_string[160]; const RegionInfo *newRegion = getRegion(loraConfig.region); + auto cfg = settingsForPreset(newRegion->wideLora, loraConfig.modem_preset); + // early check - if we use preset, make sure it's on available preset list + if(loraConfig.use_preset){ + bool preset_valid = false; + + for(int i=0;iavailablePresets);i++){ + if(loraConfig.modem_preset == newRegion->availablePresets[i]){ + preset_valid = true; + break; + } + } + + if(!preset_valid){ + const char *presetName = + DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); + + snprintf(err_string, sizeof(err_string), "Selected preset %s is not on a list of available presets for region %s", + presetName, newRegion->name); + + LOG_ERROR("%s", err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + snprintf(cn->message, sizeof(cn->message), "%s", err_string); + service->sendClientNotification(cn); + return false; + } + } // end if use_preset + float bw; if (loraConfig.use_preset) { bw = cfg.bw; @@ -604,20 +635,25 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi bw = loraConfig.bandwidth; } + // this is probably wrong (?) as you can still select last channel in a band, set + // wide bandwidth and transmit outside the band and the check will not catch it // phaseloop + // this only makes sens if you happen to be in the center of the region band if ((newRegion->freqEnd - newRegion->freqStart) < bw / 1000) { const float regionSpanKHz = (newRegion->freqEnd - newRegion->freqStart) * 1000.0f; const float requestedBwKHz = bw; const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset const char *presetName = DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); + const char *defaultPresetName = + DisplayFormatters::getModemPresetDisplayName(newRegion->defaultPreset, false, true); - char err_string[160]; + // actual falling back is done in applyModemSettings() if (isWideRequest) { - snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to %.0f.", - newRegion->name, presetName, newRegion->defaultPreset); + snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to %s.", + newRegion->name, presetName, defaultPresetName); } else { - snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to %.0f.", - newRegion->name, regionSpanKHz, requestedBwKHz, newRegion->defaultPreset); + snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to %s.", + newRegion->name, regionSpanKHz, requestedBwKHz, defaultPresetName); } LOG_ERROR("%s", err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -630,49 +666,6 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // Set to default modem preset loraConfig.use_preset = true; loraConfig.modem_preset = newRegion->defaultPreset; - } else if (isOneOf(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW) && - !isOneOf(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868, meshtastic_Config_LoRaConfig_RegionCode_HAM_US433)) { - static const char *err_string = "Narrow preset requires narrow region or ham setting. Fall back to LongFast preset."; - LOG_ERROR(err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); - service->sendClientNotification(cn); - - // Set to default modem preset - loraConfig.use_preset = true; - loraConfig.modem_preset = newRegion->defaultPreset; - } else if (newRegion->code == meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 && bw != 62.5) { - static const char *err_string = "Narrow_868 requires 62.5kHz bandwidth. Fall back to NarrowFast preset"; - LOG_ERROR(err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); - service->sendClientNotification(cn); - - // Set to NarrowFast preset which is compliant - loraConfig.use_preset = true; - loraConfig.modem_preset = newRegion->defaultPreset; - } else if (newRegion->code == meshtastic_Config_LoRaConfig_RegionCode_EU_866 && bw != 125) { - static const char *err_string = "EU_866 requires 125kHz bandwidth. Fall back to LiteFast preset"; - LOG_ERROR(err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); - service->sendClientNotification(cn); - - // Set to LiteFast preset which is compliant - loraConfig.use_preset = true; - loraConfig.modem_preset = newRegion->defaultPreset; - } else { - validConfig = true; } return validConfig; @@ -686,33 +679,53 @@ void RadioInterface::applyModemConfig() // Set up default configuration // No Sync Words in LORA mode meshtastic_Config_LoRaConfig &loraConfig = config.lora; - bool validConfig = false; // We need to check for a valid configuration - while (!validConfig) { - if (loraConfig.use_preset) { - auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); - sf = settings.sf; - cr = settings.cr; - bw = settings.bw; - } else { - sf = loraConfig.spread_factor; - cr = loraConfig.coding_rate; - bw = loraConfig.bandwidth; - - if (bw == 31) // This parameter is not an integer - bw = 31.25; - if (bw == 62) // Fix for 62.5Khz bandwidth - bw = 62.5; - if (bw == 200) - bw = 203.125; - if (bw == 400) - bw = 406.25; - if (bw == 800) - bw = 812.5; - if (bw == 1600) - bw = 1625.0; + const RegionInfo *newRegion = getRegion(loraConfig.region); + + if (loraConfig.use_preset) { + if(!validateModemConfig(loraConfig)){ + loraConfig.modem_preset = newRegion->defaultPreset; + } + + auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); + sf = settings.sf; + cr = settings.cr; + bw = settings.bw; + } + + else { + + // fix bandwidth settings and validate + sf = loraConfig.spread_factor; + cr = loraConfig.coding_rate; + bw = loraConfig.bandwidth; + + if (bw == 31) // This parameter is not an integer + bw = 31.25; + if (bw == 62) // Fix for 62.5Khz bandwidth + bw = 62.5; + if (bw == 200) + bw = 203.125; + if (bw == 400) + bw = 406.25; + if (bw == 800) + bw = 812.5; + if (bw == 1600) + bw = 1625.0; + + loraConfig.bandwidth = bw; // feed back for validation + + // if validation fails - revert to default region preset + + if(!validateModemConfig(loraConfig)){ + loraConfig.modem_preset = newRegion->defaultPreset; + loraConfig.use_preset = true; } - validConfig = validateModemConfig(loraConfig); + auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); + sf = settings.sf; + cr = settings.cr; + bw = settings.bw; + } power = loraConfig.tx_power; From e624b8f68f7929a8f371bdb9a52b2316f8468629 Mon Sep 17 00:00:00 2001 From: phaseloop Date: Sun, 28 Dec 2025 20:39:16 +0100 Subject: [PATCH 13/39] fix compliation error --- src/mesh/MeshRadio.h | 49 +++++++------------------------------ src/mesh/RadioInterface.cpp | 39 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 5b062bed81b..f9cfc96e16c 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -5,45 +5,6 @@ #include "PointerQueue.h" #include "configuration.h" - -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO -}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE -}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW -}; - -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = { - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW -}; - -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = { - meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST, -}; - -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, -}; - // Map from old region names to new region enums struct RegionInfo { meshtastic_Config_LoRaConfig_RegionCode code; @@ -71,4 +32,12 @@ extern void initRegion(); * For EU_866, returns 10% for fixed devices (ROUTER, ROUTER_LATE) and 2.5% for mobile devices. * For other regions, returns the standard duty cycle. */ -extern float getEffectiveDutyCycle(); \ No newline at end of file +extern float getEffectiveDutyCycle(); + + +extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[]; +extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[]; +extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[]; +extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[]; +extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[]; +extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[]; \ No newline at end of file diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index b80d9086166..c9816e2ead4 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -12,6 +12,45 @@ #include #include + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO +}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE +}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW +}; + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = { + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW +}; + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = { + meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST, +}; + +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = { + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, +}; + // Calculate 2^n without calling pow() uint32_t pow_of_2(uint32_t n) { From e1ea21f56ae4a500d83237c53afe42a5af8196da Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 29 Dec 2025 02:58:53 +0000 Subject: [PATCH 14/39] added ham check --- src/mesh/MeshRadio.h | 2 +- src/mesh/RadioInterface.cpp | 147 +++++++++++++++++------------------- 2 files changed, 70 insertions(+), 79 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index f9cfc96e16c..610b496ce74 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -16,6 +16,7 @@ struct RegionInfo { bool audioPermitted; bool freqSwitching; bool wideLora; + bool licensedOnly; // Only allow in HAM mode meshtastic_Config_LoRaConfig_ModemPreset defaultPreset; // static list of available presets const meshtastic_Config_LoRaConfig_ModemPreset *availablePresets; @@ -34,7 +35,6 @@ extern void initRegion(); */ extern float getEffectiveDutyCycle(); - extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[]; extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[]; extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[]; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index c9816e2ead4..d66b22c5b7f 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -12,44 +12,29 @@ #include #include - meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO -}; + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO}; meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, - meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE -}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, + meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE // no TURBO modes in EU868 }; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = {meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = { - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW -}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = {meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = { - meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST, -}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = {meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = { - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, -}; +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = {meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}; // Calculate 2^n without calling pow() uint32_t pow_of_2(uint32_t n) @@ -58,10 +43,11 @@ uint32_t pow_of_2(uint32_t n) } #define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora, \ - default_preset, available_presets) \ + licensed_only, default_preset, available_presets) \ { \ meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \ - frequency_switching, wide_lora, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ + frequency_switching, wide_lora, licensed_only, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, \ + available_presets, #name \ } const RegionInfo regions[] = { @@ -69,7 +55,7 @@ const RegionInfo regions[] = { https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ */ - RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), /* EN300220 ETSI V3.2.1 [Table B.1, Item H, p. 21] @@ -77,7 +63,7 @@ const RegionInfo regions[] = { https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.02.01_60/en_30022002v030201p.pdf FIXME: https://github.com/meshtastic/firmware/issues/3371 */ - RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ @@ -93,33 +79,33 @@ const RegionInfo regions[] = { AFA) to avoid a duty cycle. (Please refer to line P page 22 of this document.) https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.01.01_60/en_30022002v030101p.pdf */ - RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, LONG_FAST, PRESETS_EU_868), + RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, false, LONG_FAST, PRESETS_EU_868), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://www.arib.or.jp/english/html/overview/doc/5-STD-T108v1_5-E1.pdf https://qiita.com/ammo0613/items/d952154f1195b64dc29f */ - RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf Also used in Brazil. */ - RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), /* 433.05 - 434.79 MHz, 25mW EIRP max, No duty cycle restrictions AU Low Interference Potential https://www.acma.gov.au/licences/low-interference-potential-devices-lipd-class-licence NZ General User Radio Licence for Short Range Devices https://gazette.govt.nz/notice/id/2022-go3100 */ - RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf @@ -127,13 +113,13 @@ const RegionInfo regions[] = { Note: - We do LBT, so 100% is allowed. */ - RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0 https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters */ - RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, false, LONG_FAST, PRESETS_STD), /* Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor. @@ -141,42 +127,42 @@ const RegionInfo regions[] = { https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 */ - RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf */ - RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, false, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, false, LONG_FAST, PRESETS_STD), /* 433,05-434,7 Mhz 10 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), /* 868,0-868,6 Mhz 25 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, false, LONG_FAST, PRESETS_STD), /* Malaysia 433 - 435 MHz at 100mW, no restrictions. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, false, LONG_FAST, PRESETS_STD), /* Malaysia @@ -185,14 +171,14 @@ const RegionInfo regions[] = { Frequency hopping is used for 919 - 923 MHz. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, LONG_FAST, PRESETS_STD), + RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, false, LONG_FAST, PRESETS_STD), /* Singapore SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions. https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf */ - RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, false, LONG_FAST, PRESETS_STD), /* Philippines @@ -202,9 +188,9 @@ const RegionInfo regions[] = { https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135 */ - RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), - RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, LONG_FAST, PRESETS_STD), - RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, false, LONG_FAST, PRESETS_STD), /* Kazakhstan @@ -212,50 +198,50 @@ const RegionInfo regions[] = { 863 - 868 MHz <25 mW EIRP, 500kHz channels allowed, must not be used at airfields https://github.com/meshtastic/firmware/issues/7204 */ - RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, LONG_FAST, PRESETS_STD), - RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, LONG_FAST, PRESETS_STD), + RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, false, LONG_FAST, PRESETS_STD), /* Nepal 865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf */ - RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), /* Brazil 902 - 907.5 MHz , 1W power limit, no duty cycle restrictions https://github.com/meshtastic/firmware/issues/3741 */ - RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, LITE_FAST, PRESETS_LITE), + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, false, LITE_FAST, PRESETS_LITE), /* EU 868MHz band: 3 channels at 868.415/868.4925/868.570 MHz 15 kHz gap between channels, 27 dBm, duty cycle 10% */ - RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, NARROW_FAST, PRESETS_NARROW), + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, NARROW_FAST, PRESETS_NARROW), /* HAM 433MHz band */ - RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false, NARROW_FAST, PRESETS_HAM), + RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false, true, NARROW_FAST, PRESETS_HAM), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ - RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, LONG_FAST, PRESETS_STD), + RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, false, LONG_FAST, PRESETS_STD), /* This needs to be last. Same as US. */ - RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, LONG_FAST, PRESETS_UNDEF) + RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_UNDEF) }; @@ -264,6 +250,8 @@ bool RadioInterface::uses_default_frequency_slot = true; static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1]; +// + void initRegion() { const RegionInfo *r = regions; @@ -279,10 +267,15 @@ void initRegion() myRegion = r; } -const RegionInfo *getRegion(meshtastic_Config_LoRaConfig_RegionCode code) { +const RegionInfo *getRegion(meshtastic_Config_LoRaConfig_RegionCode code) +{ const RegionInfo *r = regions; for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != code; r++) ; + if (r->licensedOnly == true && !devicestate.owner.is_licensed) { + LOG_WARN("Region code %d not permitted without license, defaulting to unset", config.lora.region); + r = 0; // Default to unset + } return r; } @@ -639,22 +632,22 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi auto cfg = settingsForPreset(newRegion->wideLora, loraConfig.modem_preset); // early check - if we use preset, make sure it's on available preset list - if(loraConfig.use_preset){ + if (loraConfig.use_preset) { bool preset_valid = false; - for(int i=0;iavailablePresets);i++){ - if(loraConfig.modem_preset == newRegion->availablePresets[i]){ + for (int i = 0; i < sizeof(newRegion->availablePresets); i++) { + if (loraConfig.modem_preset == newRegion->availablePresets[i]) { preset_valid = true; break; } } - if(!preset_valid){ + if (!preset_valid) { const char *presetName = - DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); + DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); snprintf(err_string, sizeof(err_string), "Selected preset %s is not on a list of available presets for region %s", - presetName, newRegion->name); + presetName, newRegion->name); LOG_ERROR("%s", err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); @@ -676,15 +669,14 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi // this is probably wrong (?) as you can still select last channel in a band, set // wide bandwidth and transmit outside the band and the check will not catch it // phaseloop - // this only makes sens if you happen to be in the center of the region band + // this only makes sense if you happen to be in the center of the region band if ((newRegion->freqEnd - newRegion->freqStart) < bw / 1000) { const float regionSpanKHz = (newRegion->freqEnd - newRegion->freqStart) * 1000.0f; const float requestedBwKHz = bw; const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset const char *presetName = DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); - const char *defaultPresetName = - DisplayFormatters::getModemPresetDisplayName(newRegion->defaultPreset, false, true); + const char *defaultPresetName = DisplayFormatters::getModemPresetDisplayName(newRegion->defaultPreset, false, true); // actual falling back is done in applyModemSettings() if (isWideRequest) { @@ -721,7 +713,7 @@ void RadioInterface::applyModemConfig() const RegionInfo *newRegion = getRegion(loraConfig.region); if (loraConfig.use_preset) { - if(!validateModemConfig(loraConfig)){ + if (!validateModemConfig(loraConfig)) { loraConfig.modem_preset = newRegion->defaultPreset; } @@ -755,7 +747,7 @@ void RadioInterface::applyModemConfig() // if validation fails - revert to default region preset - if(!validateModemConfig(loraConfig)){ + if (!validateModemConfig(loraConfig)) { loraConfig.modem_preset = newRegion->defaultPreset; loraConfig.use_preset = true; } @@ -764,7 +756,6 @@ void RadioInterface::applyModemConfig() sf = settings.sf; cr = settings.cr; bw = settings.bw; - } power = loraConfig.tx_power; @@ -920,4 +911,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p) sendingPacket = p; return p->encrypted.size + sizeof(PacketHeader); -} +} \ No newline at end of file From 9162a6f8acb1fb4ca7861d06058e5944da977382 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 29 Dec 2025 18:09:35 +0000 Subject: [PATCH 15/39] interim for review --- src/mesh/RadioInterface.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index d66b22c5b7f..7b67fc6eaa6 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -272,10 +272,6 @@ const RegionInfo *getRegion(meshtastic_Config_LoRaConfig_RegionCode code) const RegionInfo *r = regions; for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != code; r++) ; - if (r->licensedOnly == true && !devicestate.owner.is_licensed) { - LOG_WARN("Region code %d not permitted without license, defaulting to unset", config.lora.region); - r = 0; // Default to unset - } return r; } @@ -628,6 +624,10 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi char err_string[160]; const RegionInfo *newRegion = getRegion(loraConfig.region); + if (newRegion->licensedOnly == true && !devicestate.owner.is_licensed) { + LOG_WARN("Region code %d not permitted without license, reverting", config.lora.region); + // Phaseloop: I don't know how to return that this is invalid. Help! + } auto cfg = settingsForPreset(newRegion->wideLora, loraConfig.modem_preset); From 72b350c287db16e5b19d699627c6bb304332f46f Mon Sep 17 00:00:00 2001 From: wehooper4 Date: Sat, 3 Jan 2026 00:37:20 -0500 Subject: [PATCH 16/39] Update HAM US433 frequency range and config settings Updated US ham mode to full legal frequency range Set hamfast to a legal setting --- src/mesh/RadioInterface.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 7b67fc6eaa6..2971b2bd098 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -231,7 +231,7 @@ const RegionInfo regions[] = { /* HAM 433MHz band */ - RDEF(HAM_US433, 432.40f, 433.0f, 100, 0, 99, true, false, false, true, NARROW_FAST, PRESETS_HAM), + RDEF(HAM_US433, 430.00f, 450.0f, 100, 0, 99, true, false, false, true, NARROW_FAST, PRESETS_HAM), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. @@ -609,9 +609,9 @@ ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPrese cfg.sf = 8; break; case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: - cfg.bw = 500; + cfg.bw = 62.5; cfg.cr = 5; - cfg.sf = 7; + cfg.sf = 8; break; } @@ -911,4 +911,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p) sendingPacket = p; return p->encrypted.size + sizeof(PacketHeader); -} \ No newline at end of file +} From 469329620aec5266fa9490151608817a613701a1 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 3 Jan 2026 21:33:36 +0000 Subject: [PATCH 17/39] remove hamfast --- protobufs | 2 +- src/mesh/RadioInterface.cpp | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/protobufs b/protobufs index e2d639a59b6..59e887e3e92 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit e2d639a59b61e9a4bed5bb3b76c4adc8f6add036 +Subproject commit 59e887e3e921573065b9251eb1f519821123162a diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 2971b2bd098..7c9eeb59632 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -30,8 +30,8 @@ meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = {meshtastic_Config_LoR meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = {meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = {meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, +// Same as Narrow presets, but separate so that extra ham settings can be added later. +meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = {meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = {meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}; @@ -231,7 +231,7 @@ const RegionInfo regions[] = { /* HAM 433MHz band */ - RDEF(HAM_US433, 430.00f, 450.0f, 100, 0, 99, true, false, false, true, NARROW_FAST, PRESETS_HAM), + RDEF(HAM_US433, 430.00f, 450.0f, 100, 0, 99, true, false, false, true, NARROW_SLOW, PRESETS_HAM), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. @@ -608,11 +608,6 @@ ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPrese cfg.cr = 6; cfg.sf = 8; break; - case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: - cfg.bw = 62.5; - cfg.cr = 5; - cfg.sf = 8; - break; } return cfg; From ef959cc180deb5c8fc8b2ed12a9c02b90b1c273d Mon Sep 17 00:00:00 2001 From: NomDeTom <116762865+NomDeTom@users.noreply.github.com> Date: Sat, 3 Jan 2026 21:34:58 +0000 Subject: [PATCH 18/39] Update protobufs --- src/mesh/generated/meshtastic/admin.pb.cpp | 5 +++ src/mesh/generated/meshtastic/admin.pb.h | 50 +++++++++++++++++++++- src/mesh/generated/meshtastic/config.pb.h | 14 +++--- src/mesh/generated/meshtastic/mesh.pb.h | 25 +++++++---- 4 files changed, 74 insertions(+), 20 deletions(-) diff --git a/src/mesh/generated/meshtastic/admin.pb.cpp b/src/mesh/generated/meshtastic/admin.pb.cpp index 4c4d0e3d1d4..e358bc96d35 100644 --- a/src/mesh/generated/meshtastic/admin.pb.cpp +++ b/src/mesh/generated/meshtastic/admin.pb.cpp @@ -12,6 +12,9 @@ PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2) PB_BIND(meshtastic_AdminMessage_InputEvent, meshtastic_AdminMessage_InputEvent, AUTO) +PB_BIND(meshtastic_AdminMessage_OTAEvent, meshtastic_AdminMessage_OTAEvent, AUTO) + + PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO) @@ -33,3 +36,5 @@ PB_BIND(meshtastic_KeyVerificationAdmin, meshtastic_KeyVerificationAdmin, AUTO) + + diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index a542cf29c89..ec6e13e9e73 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -16,6 +16,16 @@ #endif /* Enum definitions */ +/* Firmware update mode for OTA updates */ +typedef enum _meshtastic_OTAMode { + /* Do not reboot into OTA mode */ + meshtastic_OTAMode_NO_REBOOT_OTA = 0, + /* Reboot into OTA mode for BLE firmware update */ + meshtastic_OTAMode_OTA_BLE = 1, + /* Reboot into OTA mode for WiFi firmware update */ + meshtastic_OTAMode_OTA_WIFI = 2 +} meshtastic_OTAMode; + /* TODO: REPLACE */ typedef enum _meshtastic_AdminMessage_ConfigType { /* TODO: REPLACE */ @@ -103,6 +113,17 @@ typedef struct _meshtastic_AdminMessage_InputEvent { uint16_t touch_y; } meshtastic_AdminMessage_InputEvent; +typedef PB_BYTES_ARRAY_T(32) meshtastic_AdminMessage_OTAEvent_ota_hash_t; +/* User is requesting an over the air update. + Node will reboot into the OTA loader */ +typedef struct _meshtastic_AdminMessage_OTAEvent { + /* Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only for now) */ + meshtastic_OTAMode reboot_ota_mode; + /* A 32 byte hash of the OTA firmware. + Used to verify the integrity of the firmware before applying an update. */ + meshtastic_AdminMessage_OTAEvent_ota_hash_t ota_hash; +} meshtastic_AdminMessage_OTAEvent; + /* Parameters for setting up Meshtastic for ameteur radio usage */ typedef struct _meshtastic_HamParameters { /* Amateur radio call sign, eg. KD2ABC */ @@ -261,7 +282,8 @@ typedef struct _meshtastic_AdminMessage { /* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */ int32_t factory_reset_device; /* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) - Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. */ + Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. + Deprecated in favor of reboot_ota_mode in 2.7.17 */ int32_t reboot_ota_seconds; /* This message is only supported for the simulator Portduino build. If received the simulator will exit successfully. */ @@ -275,6 +297,8 @@ typedef struct _meshtastic_AdminMessage { /* Tell the node to reset the nodedb. When true, favorites are preserved through reset. */ bool nodedb_reset; + /* Tell the node to reset into the OTA Loader */ + meshtastic_AdminMessage_OTAEvent ota_request; }; /* The node generates this key and sends it with any get_x_response packets. The client MUST include the same key with any set_x commands. Key expires after 300 seconds. @@ -288,6 +312,10 @@ extern "C" { #endif /* Helper constants for enums */ +#define _meshtastic_OTAMode_MIN meshtastic_OTAMode_NO_REBOOT_OTA +#define _meshtastic_OTAMode_MAX meshtastic_OTAMode_OTA_WIFI +#define _meshtastic_OTAMode_ARRAYSIZE ((meshtastic_OTAMode)(meshtastic_OTAMode_OTA_WIFI+1)) + #define _meshtastic_AdminMessage_ConfigType_MIN meshtastic_AdminMessage_ConfigType_DEVICE_CONFIG #define _meshtastic_AdminMessage_ConfigType_MAX meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG #define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG+1)) @@ -311,6 +339,8 @@ extern "C" { #define meshtastic_AdminMessage_payload_variant_remove_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation +#define meshtastic_AdminMessage_OTAEvent_reboot_ota_mode_ENUMTYPE meshtastic_OTAMode + @@ -320,12 +350,14 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_AdminMessage_init_default {0, {0}, {0, {0}}} #define meshtastic_AdminMessage_InputEvent_init_default {0, 0, 0, 0} +#define meshtastic_AdminMessage_OTAEvent_init_default {_meshtastic_OTAMode_MIN, {0, {0}}} #define meshtastic_HamParameters_init_default {"", 0, 0, ""} #define meshtastic_NodeRemoteHardwarePinsResponse_init_default {0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}} #define meshtastic_SharedContact_init_default {0, false, meshtastic_User_init_default, 0, 0} #define meshtastic_KeyVerificationAdmin_init_default {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0} #define meshtastic_AdminMessage_init_zero {0, {0}, {0, {0}}} #define meshtastic_AdminMessage_InputEvent_init_zero {0, 0, 0, 0} +#define meshtastic_AdminMessage_OTAEvent_init_zero {_meshtastic_OTAMode_MIN, {0, {0}}} #define meshtastic_HamParameters_init_zero {"", 0, 0, ""} #define meshtastic_NodeRemoteHardwarePinsResponse_init_zero {0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}} #define meshtastic_SharedContact_init_zero {0, false, meshtastic_User_init_zero, 0, 0} @@ -336,6 +368,8 @@ extern "C" { #define meshtastic_AdminMessage_InputEvent_kb_char_tag 2 #define meshtastic_AdminMessage_InputEvent_touch_x_tag 3 #define meshtastic_AdminMessage_InputEvent_touch_y_tag 4 +#define meshtastic_AdminMessage_OTAEvent_reboot_ota_mode_tag 1 +#define meshtastic_AdminMessage_OTAEvent_ota_hash_tag 2 #define meshtastic_HamParameters_call_sign_tag 1 #define meshtastic_HamParameters_tx_power_tag 2 #define meshtastic_HamParameters_frequency_tag 3 @@ -403,6 +437,7 @@ extern "C" { #define meshtastic_AdminMessage_shutdown_seconds_tag 98 #define meshtastic_AdminMessage_factory_reset_config_tag 99 #define meshtastic_AdminMessage_nodedb_reset_tag 100 +#define meshtastic_AdminMessage_ota_request_tag 102 #define meshtastic_AdminMessage_session_passkey_tag 101 /* Struct field encoding specification for nanopb */ @@ -461,7 +496,8 @@ X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_seconds,reboot_second X(a, STATIC, ONEOF, INT32, (payload_variant,shutdown_seconds,shutdown_seconds), 98) \ X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_config,factory_reset_config), 99) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,nodedb_reset,nodedb_reset), 100) \ -X(a, STATIC, SINGULAR, BYTES, session_passkey, 101) +X(a, STATIC, SINGULAR, BYTES, session_passkey, 101) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,ota_request,ota_request), 102) #define meshtastic_AdminMessage_CALLBACK NULL #define meshtastic_AdminMessage_DEFAULT NULL #define meshtastic_AdminMessage_payload_variant_get_channel_response_MSGTYPE meshtastic_Channel @@ -482,6 +518,7 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101) #define meshtastic_AdminMessage_payload_variant_store_ui_config_MSGTYPE meshtastic_DeviceUIConfig #define meshtastic_AdminMessage_payload_variant_add_contact_MSGTYPE meshtastic_SharedContact #define meshtastic_AdminMessage_payload_variant_key_verification_MSGTYPE meshtastic_KeyVerificationAdmin +#define meshtastic_AdminMessage_payload_variant_ota_request_MSGTYPE meshtastic_AdminMessage_OTAEvent #define meshtastic_AdminMessage_InputEvent_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, event_code, 1) \ @@ -491,6 +528,12 @@ X(a, STATIC, SINGULAR, UINT32, touch_y, 4) #define meshtastic_AdminMessage_InputEvent_CALLBACK NULL #define meshtastic_AdminMessage_InputEvent_DEFAULT NULL +#define meshtastic_AdminMessage_OTAEvent_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, reboot_ota_mode, 1) \ +X(a, STATIC, SINGULAR, BYTES, ota_hash, 2) +#define meshtastic_AdminMessage_OTAEvent_CALLBACK NULL +#define meshtastic_AdminMessage_OTAEvent_DEFAULT NULL + #define meshtastic_HamParameters_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, call_sign, 1) \ X(a, STATIC, SINGULAR, INT32, tx_power, 2) \ @@ -524,6 +567,7 @@ X(a, STATIC, OPTIONAL, UINT32, security_number, 4) extern const pb_msgdesc_t meshtastic_AdminMessage_msg; extern const pb_msgdesc_t meshtastic_AdminMessage_InputEvent_msg; +extern const pb_msgdesc_t meshtastic_AdminMessage_OTAEvent_msg; extern const pb_msgdesc_t meshtastic_HamParameters_msg; extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg; extern const pb_msgdesc_t meshtastic_SharedContact_msg; @@ -532,6 +576,7 @@ extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg #define meshtastic_AdminMessage_InputEvent_fields &meshtastic_AdminMessage_InputEvent_msg +#define meshtastic_AdminMessage_OTAEvent_fields &meshtastic_AdminMessage_OTAEvent_msg #define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg #define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg #define meshtastic_SharedContact_fields &meshtastic_SharedContact_msg @@ -540,6 +585,7 @@ extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_ADMIN_PB_H_MAX_SIZE meshtastic_AdminMessage_size #define meshtastic_AdminMessage_InputEvent_size 14 +#define meshtastic_AdminMessage_OTAEvent_size 36 #define meshtastic_AdminMessage_size 511 #define meshtastic_HamParameters_size 31 #define meshtastic_KeyVerificationAdmin_size 25 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 848a53a99c3..e9417682db8 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -288,9 +288,9 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode { meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26, /* EU 866MHz RFID band (ETSI EN 302 208) */ meshtastic_Config_LoRaConfig_RegionCode_EU_866 = 27, - /* EU 866MHz RFID band (ETSI EN 302 208) */ + /* EU 868MHz band, with narrow presets */ meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 = 28, - /* EU 866MHz RFID band (ETSI EN 302 208) */ + /* US 433MHz Amateur Use band */ meshtastic_Config_LoRaConfig_RegionCode_HAM_US433 = 29 } meshtastic_Config_LoRaConfig_RegionCode; @@ -338,11 +338,7 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset { /* Narrow Slow Moderate range preset optimized for EU 868MHz band with 62.5kHz bandwidth. Comparable link budget and data rate to LONG_FAST. */ - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW = 13, - /* Ham Fast - Short range preset optimized for 433MHz band with wide bandwidth. - Intended for use in amateur radio bands. */ - meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST = 14 + meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW = 13 } meshtastic_Config_LoRaConfig_ModemPreset; typedef enum _meshtastic_Config_BluetoothConfig_PairingMode { @@ -720,8 +716,8 @@ extern "C" { #define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_HAM_US433+1)) #define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST -#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST -#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST+1)) +#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW +#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW+1)) #define _meshtastic_Config_BluetoothConfig_PairingMode_MIN meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN #define _meshtastic_Config_BluetoothConfig_PairingMode_MAX meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 6f2c755bed2..344c0e68a10 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -92,8 +92,8 @@ typedef enum _meshtastic_HardwareModel { Less common/prototype boards listed here (needs one more byte over the air) --------------------------------------------------------------------------- */ meshtastic_HardwareModel_LORA_RELAY_V1 = 32, - /* TODO: REPLACE */ - meshtastic_HardwareModel_NRF52840DK = 33, + /* T-Echo Plus device from LilyGo */ + meshtastic_HardwareModel_T_ECHO_PLUS = 33, /* TODO: REPLACE */ meshtastic_HardwareModel_PPR = 34, /* TODO: REPLACE */ @@ -475,7 +475,10 @@ typedef enum _meshtastic_Routing_Error { meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED = 37, /* Airtime fairness rate limit exceeded for a packet This typically enforced per portnum and is used to prevent a single node from monopolizing airtime */ - meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38 + meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38, + /* PKI encryption failed, due to no public key for the remote node + This is different from PKI_UNKNOWN_PUBKEY which indicates a failure upon receiving a packet */ + meshtastic_Routing_Error_PKI_SEND_FAIL_PUBLIC_KEY = 39 } meshtastic_Routing_Error; /* Enum of message types */ @@ -822,6 +825,8 @@ typedef struct _meshtastic_StoreForwardPlusPlus { uint32_t encapsulated_from; /* The receive time of the message in question */ uint32_t encapsulated_rxtime; + /* Used in a LINK_REQUEST to specify the message X spots back from head */ + uint32_t chain_count; } meshtastic_StoreForwardPlusPlus; /* Waypoint message, used to share arbitrary locations across the mesh */ @@ -1349,8 +1354,8 @@ extern "C" { #define _meshtastic_Position_AltSource_ARRAYSIZE ((meshtastic_Position_AltSource)(meshtastic_Position_AltSource_ALT_BAROMETRIC+1)) #define _meshtastic_Routing_Error_MIN meshtastic_Routing_Error_NONE -#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED -#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED+1)) +#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_PKI_SEND_FAIL_PUBLIC_KEY +#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_PKI_SEND_FAIL_PUBLIC_KEY+1)) #define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE #define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF @@ -1428,7 +1433,7 @@ extern "C" { #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} -#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0} +#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} @@ -1460,7 +1465,7 @@ extern "C" { #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} #define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} -#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0} +#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} @@ -1548,6 +1553,7 @@ extern "C" { #define meshtastic_StoreForwardPlusPlus_encapsulated_to_tag 7 #define meshtastic_StoreForwardPlusPlus_encapsulated_from_tag 8 #define meshtastic_StoreForwardPlusPlus_encapsulated_rxtime_tag 9 +#define meshtastic_StoreForwardPlusPlus_chain_count_tag 10 #define meshtastic_Waypoint_id_tag 1 #define meshtastic_Waypoint_latitude_i_tag 2 #define meshtastic_Waypoint_longitude_i_tag 3 @@ -1773,7 +1779,8 @@ X(a, STATIC, SINGULAR, BYTES, message, 5) \ X(a, STATIC, SINGULAR, UINT32, encapsulated_id, 6) \ X(a, STATIC, SINGULAR, UINT32, encapsulated_to, 7) \ X(a, STATIC, SINGULAR, UINT32, encapsulated_from, 8) \ -X(a, STATIC, SINGULAR, UINT32, encapsulated_rxtime, 9) +X(a, STATIC, SINGULAR, UINT32, encapsulated_rxtime, 9) \ +X(a, STATIC, SINGULAR, UINT32, chain_count, 10) #define meshtastic_StoreForwardPlusPlus_CALLBACK NULL #define meshtastic_StoreForwardPlusPlus_DEFAULT NULL @@ -2143,7 +2150,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_QueueStatus_size 23 #define meshtastic_RouteDiscovery_size 256 #define meshtastic_Routing_size 259 -#define meshtastic_StoreForwardPlusPlus_size 371 +#define meshtastic_StoreForwardPlusPlus_size 377 #define meshtastic_ToRadio_size 504 #define meshtastic_User_size 115 #define meshtastic_Waypoint_size 165 From 2a25a15e03538452871c5f1bea36c2e4191424d3 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 3 Jan 2026 21:42:19 +0000 Subject: [PATCH 19/39] tidy up removing hamfast --- src/DisplayFormatters.cpp | 3 --- src/graphics/draw/MenuHandler.cpp | 8 +++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/DisplayFormatters.cpp b/src/DisplayFormatters.cpp index 1d53d4da479..fe8f914cdb7 100644 --- a/src/DisplayFormatters.cpp +++ b/src/DisplayFormatters.cpp @@ -49,9 +49,6 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: return useShortName ? "NarS" : "NarrowSlow"; break; - case meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST: - return useShortName ? "HamF" : "HamFast"; - break; default: return useShortName ? "Custom" : "Invalid"; break; diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 74f3e2ee664..f372631c82f 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -108,6 +108,8 @@ void menuHandler::LoraRegionPicker(uint32_t duration) "US", "EU_433", "EU_868", + "EU_866", + "NARROW_868", "CN", "JP", "ANZ", @@ -133,8 +135,6 @@ void menuHandler::LoraRegionPicker(uint32_t duration) "KZ_863", "NP_865", "BR_902", - "EU_866", - "NARROW_868", "HAM_US433"}; BannerOverlayOptions bannerOptions; #if defined(M5STACK_UNITC6L) @@ -244,9 +244,7 @@ void menuHandler::RadioPresetPicker() {"LiteFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST}, {"LiteSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW}, {"NarrowFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST}, - {"NarrowSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}, - {"HamFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_HAM_FAST}, - }; + {"NarrowSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}}; constexpr size_t presetCount = sizeof(presetOptions) / sizeof(presetOptions[0]); static std::array presetLabels{}; From 4a70f79cf7eab0cea03b806e846425b169e89887 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sun, 4 Jan 2026 01:12:58 +0000 Subject: [PATCH 20/39] fixed license check --- src/mesh/RadioInterface.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 7c9eeb59632..86f241966ea 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -619,9 +619,14 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi char err_string[160]; const RegionInfo *newRegion = getRegion(loraConfig.region); - if (newRegion->licensedOnly == true && !devicestate.owner.is_licensed) { - LOG_WARN("Region code %d not permitted without license, reverting", config.lora.region); - // Phaseloop: I don't know how to return that this is invalid. Help! + if (!newRegion) { // copilot said I had to check for null pointer + LOG_ERROR("Invalid region code %d", loraConfig.region); + return false; + } + + if (newRegion->licensedOnly && !devicestate.owner.is_licensed) { + LOG_WARN("Region code %s not permitted without license, reverting", newRegion->name); + return false; } auto cfg = settingsForPreset(newRegion->wideLora, loraConfig.modem_preset); @@ -630,7 +635,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi if (loraConfig.use_preset) { bool preset_valid = false; - for (int i = 0; i < sizeof(newRegion->availablePresets); i++) { + for (int i = 0; i < sizeof(newRegion->availablePresets); i++) { // copilot says int should be size_t or auto : preset ??? if (loraConfig.modem_preset == newRegion->availablePresets[i]) { preset_valid = true; break; From b87e88fd5d0680ae5917b3a675936586ebcefd37 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 5 Jan 2026 02:54:02 +0000 Subject: [PATCH 21/39] Add overrideSlot to RegionInfo and update RDEF macro usage, added error messages to client notification --- src/mesh/MeshRadio.h | 3 +- src/mesh/RadioInterface.cpp | 101 ++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 610b496ce74..0dcc420587b 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -16,7 +16,8 @@ struct RegionInfo { bool audioPermitted; bool freqSwitching; bool wideLora; - bool licensedOnly; // Only allow in HAM mode + bool licensedOnly; // Only allow in HAM mode + uint8_t overrideSlot; // default frequency slot if not using channel hashing meshtastic_Config_LoRaConfig_ModemPreset defaultPreset; // static list of available presets const meshtastic_Config_LoRaConfig_ModemPreset *availablePresets; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 86f241966ea..c1ab1708600 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -43,11 +43,11 @@ uint32_t pow_of_2(uint32_t n) } #define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora, \ - licensed_only, default_preset, available_presets) \ + licensed_only, override_slot, default_preset, available_presets) \ { \ meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \ - frequency_switching, wide_lora, licensed_only, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, \ - available_presets, #name \ + frequency_switching, wide_lora, licensed_only, override_slot, \ + meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ } const RegionInfo regions[] = { @@ -55,7 +55,7 @@ const RegionInfo regions[] = { https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ */ - RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* EN300220 ETSI V3.2.1 [Table B.1, Item H, p. 21] @@ -63,7 +63,7 @@ const RegionInfo regions[] = { https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.02.01_60/en_30022002v030201p.pdf FIXME: https://github.com/meshtastic/firmware/issues/3371 */ - RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ @@ -79,33 +79,33 @@ const RegionInfo regions[] = { AFA) to avoid a duty cycle. (Please refer to line P page 22 of this document.) https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.01.01_60/en_30022002v030101p.pdf */ - RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, false, LONG_FAST, PRESETS_EU_868), + RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, false, 0, LONG_FAST, PRESETS_EU_868), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://www.arib.or.jp/english/html/overview/doc/5-STD-T108v1_5-E1.pdf https://qiita.com/ammo0613/items/d952154f1195b64dc29f */ - RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf Also used in Brazil. */ - RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* 433.05 - 434.79 MHz, 25mW EIRP max, No duty cycle restrictions AU Low Interference Potential https://www.acma.gov.au/licences/low-interference-potential-devices-lipd-class-licence NZ General User Radio Licence for Short Range Devices https://gazette.govt.nz/notice/id/2022-go3100 */ - RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf @@ -113,13 +113,13 @@ const RegionInfo regions[] = { Note: - We do LBT, so 100% is allowed. */ - RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0 https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters */ - RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor. @@ -127,42 +127,41 @@ const RegionInfo regions[] = { https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 */ - RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), - + RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf */ - RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* 433,05-434,7 Mhz 10 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* 868,0-868,6 Mhz 25 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* Malaysia 433 - 435 MHz at 100mW, no restrictions. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* Malaysia @@ -171,14 +170,14 @@ const RegionInfo regions[] = { Frequency hopping is used for 919 - 923 MHz. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, false, LONG_FAST, PRESETS_STD), + RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, false, 0, LONG_FAST, PRESETS_STD), /* Singapore SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions. https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf */ - RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* Philippines @@ -188,9 +187,9 @@ const RegionInfo regions[] = { https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135 */ - RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), - RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, false, LONG_FAST, PRESETS_STD), - RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* Kazakhstan @@ -198,55 +197,56 @@ const RegionInfo regions[] = { 863 - 868 MHz <25 mW EIRP, 500kHz channels allowed, must not be used at airfields https://github.com/meshtastic/firmware/issues/7204 */ - RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, false, LONG_FAST, PRESETS_STD), - RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, false, LONG_FAST, PRESETS_STD), + RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true, false, 0, LONG_FAST, PRESETS_STD), /* Nepal 865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf */ - RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* Brazil 902 - 907.5 MHz , 1W power limit, no duty cycle restrictions https://github.com/meshtastic/firmware/issues/3741 */ - RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_STD), + RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, false, LITE_FAST, PRESETS_LITE), + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, false, 0, LITE_FAST, PRESETS_LITE), /* EU 868MHz band: 3 channels at 868.415/868.4925/868.570 MHz + Channel centres at 868.431/868.509/868.586 MHz, 15 kHz gap between channels, 27 dBm, duty cycle 10% */ - RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, NARROW_FAST, PRESETS_NARROW), + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, 1, NARROW_FAST, PRESETS_NARROW), /* HAM 433MHz band */ - RDEF(HAM_US433, 430.00f, 450.0f, 100, 0, 99, true, false, false, true, NARROW_SLOW, PRESETS_HAM), + RDEF(HAM_US433, 430.00f, 450.0f, 100, 0, 99, true, false, false, true, 0, NARROW_SLOW, PRESETS_HAM), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ - RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, false, LONG_FAST, PRESETS_STD), + RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, false, 0, LONG_FAST, PRESETS_STD), /* This needs to be last. Same as US. */ - RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, LONG_FAST, PRESETS_UNDEF) + RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_UNDEF) }; const RegionInfo *myRegion; -bool RadioInterface::uses_default_frequency_slot = true; +bool RadioInterface::uses_default_frequency_slot = true; // this is modified in init region static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1]; @@ -625,6 +625,17 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi } if (newRegion->licensedOnly && !devicestate.owner.is_licensed) { + snprintf(err_string, sizeof(err_string), "Selected region %s is not permitted without licensed mode activated", + newRegion->name); + + LOG_ERROR("%s", err_string); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_ERROR; + snprintf(cn->message, sizeof(cn->message), "%s", err_string); + service->sendClientNotification(cn); + return false; LOG_WARN("Region code %s not permitted without license, reverting", newRegion->name); return false; } @@ -635,7 +646,8 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi if (loraConfig.use_preset) { bool preset_valid = false; - for (int i = 0; i < sizeof(newRegion->availablePresets); i++) { // copilot says int should be size_t or auto : preset ??? + for (size_t i = 0; i < sizeof(newRegion->availablePresets); + i++) { // copilot says int should be size_t or auto : preset ??? if (loraConfig.modem_preset == newRegion->availablePresets[i]) { preset_valid = true; break; @@ -781,9 +793,18 @@ void RadioInterface::applyModemConfig() uint32_t channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels; // Check if we use the default frequency slot - RadioInterface::uses_default_frequency_slot = - channel_num == - hash(DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false, config.lora.use_preset)) % numChannels; + if (myRegion->overrideSlot == 0) { + RadioInterface::uses_default_frequency_slot = true; + channel_num = + hash(DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false, config.lora.use_preset)) % + numChannels; + } + // If we have an override slot, use it + // Note: overrideSlot is the same, regardless of which preset we use, so it should only be used where presets are limited. + else { + RadioInterface::uses_default_frequency_slot = false; + channel_num = myRegion->overrideSlot - 1; + } // Calculate frequency: freqStart is band edge, add half bandwidth to get first channel center float freq = myRegion->freqStart + (bw / 2000) + (channel_num * channelSpacing); @@ -911,4 +932,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p) sendingPacket = p; return p->encrypted.size + sizeof(PacketHeader); -} +} \ No newline at end of file From 7255a02766005a288be8124fdcc536ac9c6f5c70 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 5 Jan 2026 03:02:08 +0000 Subject: [PATCH 22/39] added logging if slot override is being used --- src/mesh/RadioInterface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index c1ab1708600..06c132e5f98 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -827,6 +827,9 @@ void RadioInterface::applyModemConfig() LOG_INFO("myRegion->freqStart -> myRegion->freqEnd: %f -> %f (%f MHz)", myRegion->freqStart, myRegion->freqEnd, myRegion->freqEnd - myRegion->freqStart); LOG_INFO("numChannels: %d x %.3fkHz", numChannels, bw); + if (myRegion->overrideSlot != 0) { + LOG_INFO("Using region override slot: %d", myRegion->overrideSlot); + } LOG_INFO("channel_num: %d", channel_num + 1); LOG_INFO("frequency: %f", getFreq()); LOG_INFO("Slot time: %u msec, preamble time: %u msec", slotTimeMsec, preambleTimeMsec); From 879daabe22d1d763d3f589ed0a411e3cb4e8a86a Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 5 Jan 2026 10:30:18 +0000 Subject: [PATCH 23/39] trunk FML --- src/modules/AdminModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index bc51d182e6d..fcb8e32004c 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -746,7 +746,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) LOG_WARN("Invalid bandwidth %d, setting to default", originalBandwidth); } - if(!RadioInterface::validateModemConfig(validatedLora)) { + if (!RadioInterface::validateModemConfig(validatedLora)) { return; } From f64e69c37223976153a6d150f050edf1547525b3 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 5 Jan 2026 11:50:00 +0000 Subject: [PATCH 24/39] fixed error in CR check, added logic for if a lower CR than default is used. --- src/mesh/RadioInterface.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 47fb051fa31..19bb20be827 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -609,11 +609,6 @@ ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPrese cfg.sf = 8; break; } - // If custom CR is being used already, continue to use it - if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate != cfg.cr) { - cfg.cr = loraConfig.coding_rate; - LOG_INFO("Using custom Coding Rate %u", cfg.cr); - } return cfg; } @@ -735,11 +730,20 @@ void RadioInterface::applyModemConfig() auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); sf = settings.sf; - cr = settings.cr; bw = settings.bw; - } - - else { + // If custom CR is being used already, check if the new preset is higher + if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate < settings.cr) { + cr = settings.cr; + LOG_INFO("Default Coding Rate is higher than custom setting, using %u", cr); + } + // If the custom CR is higher than the preset, use it + else if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate > settings.cr) { + cr = loraConfig.coding_rate; + LOG_INFO("Using custom Coding Rate %u", cr); + } else { + cr = settings.cr; + } + } else { // fix bandwidth settings and validate sf = loraConfig.spread_factor; From b09dbf886d6f6496995da66e51e765d1b023814a Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 17 Jan 2026 17:05:21 +0000 Subject: [PATCH 25/39] Remove ham settings for now. --- protobufs | 2 +- src/graphics/draw/MenuHandler.cpp | 4 +--- src/mesh/MeshRadio.h | 2 +- src/mesh/RadioInterface.cpp | 21 +++++++++------------ 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/protobufs b/protobufs index 59e887e3e92..116124b50c1 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 59e887e3e921573065b9251eb1f519821123162a +Subproject commit 116124b50c13385ada67b7ef1289bf88b390bbf6 diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 696bb09acab..7920bf711f1 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -136,9 +136,7 @@ void menuHandler::LoraRegionPicker(uint32_t duration) {"KZ_433", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_KZ_433}, {"KZ_863", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_KZ_863}, {"NP_865", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_NP_865}, - {"BR_902", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_BR_902}, - {"HAM_US433", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_HAM_US433}, - }; + {"BR_902", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_BR_902}}; constexpr size_t regionCount = sizeof(regionOptions) / sizeof(regionOptions[0]); static std::array regionLabels{}; diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 0dcc420587b..4737fa3a0d1 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -40,5 +40,5 @@ extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[]; extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[]; extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[]; extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[]; -extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[]; +// extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[]; extern meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[]; \ No newline at end of file diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 50fb42ce784..459550e2d3f 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -18,21 +18,22 @@ meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = { meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO}; + meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = { meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE // no TURBO modes in EU868 -}; + meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE}; // no TURBO modes in EU868 + meshtastic_Config_LoRaConfig_ModemPreset PRESETS_LITE[] = {meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW}; meshtastic_Config_LoRaConfig_ModemPreset PRESETS_NARROW[] = {meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; -// Same as Narrow presets, but separate so that extra ham settings can be added later. -meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = {meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; +// // Same as Narrow presets, but separate so that extra ham settings can be added later. +// meshtastic_Config_LoRaConfig_ModemPreset PRESETS_HAM[] = {meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST, +// meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW}; meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = {meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}; @@ -228,11 +229,6 @@ const RegionInfo regions[] = { */ RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, 1, NARROW_FAST, PRESETS_NARROW), - /* - HAM 433MHz band - */ - RDEF(HAM_US433, 430.00f, 450.0f, 100, 0, 99, true, false, false, true, 0, NARROW_SLOW, PRESETS_HAM), - /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ @@ -318,8 +314,9 @@ uint32_t RadioInterface::getPacketTime(const meshtastic_MeshPacket *p, bool rece /** The delay to use for retransmitting dropped packets */ uint32_t RadioInterface::getRetransmissionMsec(const meshtastic_MeshPacket *p) { - size_t numbytes =p->which_payload_variant == meshtastic_MeshPacket_decoded_tag ? - pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded) : p->encrypted.size+MESHTASTIC_HEADER_LENGTH; + size_t numbytes = p->which_payload_variant == meshtastic_MeshPacket_decoded_tag + ? pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded) + : p->encrypted.size + MESHTASTIC_HEADER_LENGTH; uint32_t packetAirtime = getPacketTime(numbytes + sizeof(PacketHeader)); // Make sure enough time has elapsed for this packet to be sent and an ACK is received. // LOG_DEBUG("Waiting for flooding message with airtime %d and slotTime is %d", packetAirtime, slotTimeMsec); From 8910650ebdc6069f49d650eb6d587065bdbf10bb Mon Sep 17 00:00:00 2001 From: NomDeTom <116762865+NomDeTom@users.noreply.github.com> Date: Sat, 17 Jan 2026 17:26:12 +0000 Subject: [PATCH 26/39] Update protobufs --- src/mesh/generated/meshtastic/admin.pb.h | 9 ++++---- src/mesh/generated/meshtastic/config.pb.h | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 5 ++-- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 23 ++++++++++++------- .../generated/meshtastic/module_config.pb.h | 23 ++++++++++++------- 6 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index 785558f1bb8..26b4343e9a4 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -270,6 +270,8 @@ typedef struct _meshtastic_AdminMessage { uint32_t set_ignored_node; /* Set specified node-num to be un-ignored on the NodeDB on the device */ uint32_t remove_ignored_node; + /* Set specified node-num to be muted */ + uint32_t toggle_muted_node; /* Begins an edit transaction for config, module config, owner, and channel settings changes This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) */ bool begin_edit_settings; @@ -279,8 +281,6 @@ typedef struct _meshtastic_AdminMessage { meshtastic_SharedContact add_contact; /* Initiate or respond to a key verification request */ meshtastic_KeyVerificationAdmin key_verification; - /* Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only for now) */ - meshtastic_OTAMode reboot_ota_mode; /* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */ int32_t factory_reset_device; /* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) @@ -339,7 +339,6 @@ extern "C" { #define meshtastic_AdminMessage_payload_variant_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation #define meshtastic_AdminMessage_payload_variant_restore_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation #define meshtastic_AdminMessage_payload_variant_remove_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation -#define meshtastic_AdminMessage_payload_variant_reboot_ota_mode_ENUMTYPE meshtastic_OTAMode #define meshtastic_AdminMessage_OTAEvent_reboot_ota_mode_ENUMTYPE meshtastic_OTAMode @@ -429,11 +428,11 @@ extern "C" { #define meshtastic_AdminMessage_store_ui_config_tag 46 #define meshtastic_AdminMessage_set_ignored_node_tag 47 #define meshtastic_AdminMessage_remove_ignored_node_tag 48 +#define meshtastic_AdminMessage_toggle_muted_node_tag 49 #define meshtastic_AdminMessage_begin_edit_settings_tag 64 #define meshtastic_AdminMessage_commit_edit_settings_tag 65 #define meshtastic_AdminMessage_add_contact_tag 66 #define meshtastic_AdminMessage_key_verification_tag 67 -#define meshtastic_AdminMessage_reboot_ota_mode_tag 68 #define meshtastic_AdminMessage_factory_reset_device_tag 94 #define meshtastic_AdminMessage_reboot_ota_seconds_tag 95 #define meshtastic_AdminMessage_exit_simulator_tag 96 @@ -489,11 +488,11 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_ui_config_response,get_u X(a, STATIC, ONEOF, MESSAGE, (payload_variant,store_ui_config,store_ui_config), 46) \ X(a, STATIC, ONEOF, UINT32, (payload_variant,set_ignored_node,set_ignored_node), 47) \ X(a, STATIC, ONEOF, UINT32, (payload_variant,remove_ignored_node,remove_ignored_node), 48) \ +X(a, STATIC, ONEOF, UINT32, (payload_variant,toggle_muted_node,toggle_muted_node), 49) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification,key_verification), 67) \ -X(a, STATIC, ONEOF, UENUM, (payload_variant,reboot_ota_mode,reboot_ota_mode), 68) \ X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \ X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \ diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index e9417682db8..63c42c2c36e 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -66,7 +66,7 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { but should not be given priority over other routers in order to avoid unnecessaraily consuming hops. */ meshtastic_Config_DeviceConfig_Role_ROUTER_LATE = 11, - /* Description: Treats packets from or to favorited nodes as ROUTER, and all other packets as CLIENT. + /* Description: Treats packets from or to favorited nodes as ROUTER_LATE, and all other packets as CLIENT. Technical Details: Used for stronger attic/roof nodes to distribute messages more widely from weaker, indoor, or less-well-positioned nodes. Recommended for users with multiple nodes where one CLIENT_BASE acts as a more powerful base station, such as an attic/roof node. */ diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 7fab82ff752..409805d243b 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -97,7 +97,8 @@ typedef struct _meshtastic_NodeInfoLite { /* Last byte of the node number of the node that should be used as the next hop to reach this node. */ uint8_t next_hop; /* Bitfield for storing booleans. - LSB 0 is_key_manually_verified */ + LSB 0 is_key_manually_verified + LSB 1 is_muted */ uint32_t bitfield; } meshtastic_NodeInfoLite; @@ -360,7 +361,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2277 +#define meshtastic_BackupPreferences_size 2279 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 3ab6f02c17b..2b44d0c9a1f 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size #define meshtastic_LocalConfig_size 749 -#define meshtastic_LocalModuleConfig_size 673 +#define meshtastic_LocalModuleConfig_size 675 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 2ba592a129a..68552ede5e3 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -294,6 +294,12 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_THINKNODE_M4 = 119, /* Elecrow ThinkNode M6 */ meshtastic_HardwareModel_THINKNODE_M6 = 120, + /* Elecrow Meshstick 1262 */ + meshtastic_HardwareModel_MESHSTICK_1262 = 121, + /* LilyGo T-Beam 1W */ + meshtastic_HardwareModel_TBEAM_1_WATT = 122, + /* LilyGo T5 S3 ePaper Pro (V1 and V2) */ + meshtastic_HardwareModel_T5_S3_EPAPER_PRO = 123, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -1013,6 +1019,9 @@ typedef struct _meshtastic_NodeInfo { Persists between NodeDB internal clean ups LSB 0 of the bitfield */ bool is_key_manually_verified; + /* True if node has been muted + Persistes between NodeDB internal clean ups */ + bool is_muted; } meshtastic_NodeInfo; typedef PB_BYTES_ARRAY_T(16) meshtastic_MyNodeInfo_device_id_t; @@ -1361,10 +1370,6 @@ extern "C" { #define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF #define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1)) -#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE -#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF -#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1)) - #define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET #define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX #define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1)) @@ -1441,7 +1446,7 @@ extern "C" { #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} -#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0} +#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0, 0} #define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} @@ -1473,7 +1478,7 @@ extern "C" { #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} -#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0} +#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0, 0} #define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} @@ -1603,6 +1608,7 @@ extern "C" { #define meshtastic_NodeInfo_is_favorite_tag 10 #define meshtastic_NodeInfo_is_ignored_tag 11 #define meshtastic_NodeInfo_is_key_manually_verified_tag 12 +#define meshtastic_NodeInfo_is_muted_tag 13 #define meshtastic_MyNodeInfo_my_node_num_tag 1 #define meshtastic_MyNodeInfo_reboot_count_tag 8 #define meshtastic_MyNodeInfo_min_app_version_tag 11 @@ -1846,7 +1852,8 @@ X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \ X(a, STATIC, OPTIONAL, UINT32, hops_away, 9) \ X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) \ X(a, STATIC, SINGULAR, BOOL, is_ignored, 11) \ -X(a, STATIC, SINGULAR, BOOL, is_key_manually_verified, 12) +X(a, STATIC, SINGULAR, BOOL, is_key_manually_verified, 12) \ +X(a, STATIC, SINGULAR, BOOL, is_muted, 13) #define meshtastic_NodeInfo_CALLBACK NULL #define meshtastic_NodeInfo_DEFAULT NULL #define meshtastic_NodeInfo_user_MSGTYPE meshtastic_User @@ -2148,7 +2155,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_MyNodeInfo_size 83 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 -#define meshtastic_NodeInfo_size 323 +#define meshtastic_NodeInfo_size 325 #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index 47d3b5baab6..dd0151e3f01 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -84,8 +84,11 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode { https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable */ meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT = 7, /* Used to configure and view some parameters of MeshSolar. -https://heltec.org/project/meshsolar/ */ - meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG = 8 + https://heltec.org/project/meshsolar/ */ + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG = 8, + /* Logs mesh traffic to the serial pins, ideal for logging via openLog or similar. */ + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_LOG = 9, /* includes other packets */ + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_LOGTEXT = 10 /* only text (channel & DM) */ } meshtastic_ModuleConfig_SerialConfig_Serial_Mode; /* TODO: REPLACE */ @@ -359,6 +362,8 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig { /* Enable/Disable the device telemetry module to send metrics to the mesh Note: We will still send telemtry to the connected phone / client every minute over the API */ bool device_telemetry_enabled; + /* Enable/Disable the air quality telemetry measurement module on-device display */ + bool air_quality_screen_enabled; } meshtastic_ModuleConfig_TelemetryConfig; /* Canned Messages Module Config */ @@ -481,8 +486,8 @@ extern "C" { #define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1)) #define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG+1)) +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_LOGTEXT +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_LOGTEXT+1)) #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK @@ -526,7 +531,7 @@ extern "C" { #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0} -#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0} #define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} @@ -542,7 +547,7 @@ extern "C" { #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0} -#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0} #define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN} @@ -631,6 +636,7 @@ extern "C" { #define meshtastic_ModuleConfig_TelemetryConfig_health_update_interval_tag 12 #define meshtastic_ModuleConfig_TelemetryConfig_health_screen_enabled_tag 13 #define meshtastic_ModuleConfig_TelemetryConfig_device_telemetry_enabled_tag 14 +#define meshtastic_ModuleConfig_TelemetryConfig_air_quality_screen_enabled_tag 15 #define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1 #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2 #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3 @@ -830,7 +836,8 @@ X(a, STATIC, SINGULAR, BOOL, power_screen_enabled, 10) \ X(a, STATIC, SINGULAR, BOOL, health_measurement_enabled, 11) \ X(a, STATIC, SINGULAR, UINT32, health_update_interval, 12) \ X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13) \ -X(a, STATIC, SINGULAR, BOOL, device_telemetry_enabled, 14) +X(a, STATIC, SINGULAR, BOOL, device_telemetry_enabled, 14) \ +X(a, STATIC, SINGULAR, BOOL, air_quality_screen_enabled, 15) #define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL #define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL @@ -915,7 +922,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 -#define meshtastic_ModuleConfig_TelemetryConfig_size 48 +#define meshtastic_ModuleConfig_TelemetryConfig_size 50 #define meshtastic_ModuleConfig_size 227 #define meshtastic_RemoteHardwarePin_size 21 From d0a611b795e3e4be720a5c9fd16e342a12de40eb Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 17 Jan 2026 17:29:51 +0000 Subject: [PATCH 27/39] Update protobuf submodule to latest commit --- protobufs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobufs b/protobufs index 116124b50c1..f53c63049ac 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 116124b50c13385ada67b7ef1289bf88b390bbf6 +Subproject commit f53c63049ac964eb2762fc1edaacd3b0863f5a1e From 7a3ed227f3408d7f350bf11f83b07c335fcc400a Mon Sep 17 00:00:00 2001 From: NomDeTom <116762865+NomDeTom@users.noreply.github.com> Date: Sat, 17 Jan 2026 17:46:21 +0000 Subject: [PATCH 28/39] Update protobufs --- src/mesh/generated/meshtastic/config.pb.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 63c42c2c36e..845c30a8d20 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -286,12 +286,10 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode { meshtastic_Config_LoRaConfig_RegionCode_NP_865 = 25, /* Brazil 902MHz */ meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26, - /* EU 866MHz RFID band (ETSI EN 302 208) */ + /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) */ meshtastic_Config_LoRaConfig_RegionCode_EU_866 = 27, /* EU 868MHz band, with narrow presets */ - meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 = 28, - /* US 433MHz Amateur Use band */ - meshtastic_Config_LoRaConfig_RegionCode_HAM_US433 = 29 + meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 = 28 } meshtastic_Config_LoRaConfig_RegionCode; /* Standard predefined channel settings @@ -712,8 +710,8 @@ extern "C" { #define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1)) #define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET -#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_HAM_US433 -#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_HAM_US433+1)) +#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 +#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868+1)) #define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST #define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW From 0d2f3a5efac43dc500cfbc7aa7d0b284e3fa4597 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Wed, 21 Jan 2026 23:32:50 +0000 Subject: [PATCH 29/39] Update protobuf submodule to latest commit --- protobufs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobufs b/protobufs index f53c63049ac..a7c51f5743b 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit f53c63049ac964eb2762fc1edaacd3b0863f5a1e +Subproject commit a7c51f5743bff9d5e6ef7ae3ddcac37201edc5ec From d8f5d6fed2fd16869f19d1fd7f1c3354cff07438 Mon Sep 17 00:00:00 2001 From: NomDeTom <116762865+NomDeTom@users.noreply.github.com> Date: Wed, 21 Jan 2026 23:33:31 +0000 Subject: [PATCH 30/39] Update protobufs --- src/mesh/generated/meshtastic/admin.pb.h | 8 +++--- src/mesh/generated/meshtastic/config.pb.h | 10 ++++---- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 16 ++++++++---- src/mesh/generated/meshtastic/mesh.pb.cpp | 3 +++ src/mesh/generated/meshtastic/mesh.pb.h | 17 +++++++++++++ .../generated/meshtastic/module_config.pb.cpp | 3 +++ .../generated/meshtastic/module_config.pb.h | 25 ++++++++++++++++++- src/mesh/generated/meshtastic/portnums.pb.h | 5 ++++ src/mesh/generated/meshtastic/telemetry.pb.h | 12 ++++++--- 10 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index 26b4343e9a4..efdead91b42 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -77,7 +77,9 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType { /* TODO: REPLACE */ meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG = 11, /* TODO: REPLACE */ - meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG = 12 + meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG = 12, + /* TODO: REPLACE */ + meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG = 13 } meshtastic_AdminMessage_ModuleConfigType; typedef enum _meshtastic_AdminMessage_BackupLocation { @@ -323,8 +325,8 @@ extern "C" { #define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG+1)) #define _meshtastic_AdminMessage_ModuleConfigType_MIN meshtastic_AdminMessage_ModuleConfigType_MQTT_CONFIG -#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG -#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG+1)) +#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG +#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG+1)) #define _meshtastic_AdminMessage_BackupLocation_MIN meshtastic_AdminMessage_BackupLocation_FLASH #define _meshtastic_AdminMessage_BackupLocation_MAX meshtastic_AdminMessage_BackupLocation_SD diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 845c30a8d20..b6713dc3abb 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -286,7 +286,7 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode { meshtastic_Config_LoRaConfig_RegionCode_NP_865 = 25, /* Brazil 902MHz */ meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26, - /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) */ + /* EU 866MHz band (Band no. 47b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) */ meshtastic_Config_LoRaConfig_RegionCode_EU_866 = 27, /* EU 868MHz band, with narrow presets */ meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 = 28 @@ -321,12 +321,12 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset { This preset performs similarly to LongFast, but with 500Khz bandwidth. */ meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO = 9, /* Lite Fast - Medium range preset optimized for EU 866MHz RFID band with 125kHz bandwidth. - Comparable link budget to MEDIUM_FAST but compliant with ETSI EN 302 208. */ + Medium range preset optimized for EU 866MHz SRD band with 125kHz bandwidth. + Comparable link budget to MEDIUM_FAST but compliant with Band no. 47b of 2006/771/EC. */ meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST = 10, /* Lite Slow - Medium-to-moderate range preset optimized for EU 866MHz RFID band with 125kHz bandwidth. - Comparable link budget to LONG_FAST but compliant with ETSI EN 302 208. */ + Medium-to-moderate range preset optimized for EU 866MHz SRD band with 125kHz bandwidth. + Comparable link budget to LONG_FAST but compliant with Band no. 47b of 2006/771/EC. */ meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW = 11, /* Narrow Fast Medium-to-moderate range preset optimized for EU 868MHz band with 62.5kHz bandwidth. diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 409805d243b..57e7df8fc0d 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -361,7 +361,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2279 +#define meshtastic_BackupPreferences_size 2362 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 2b44d0c9a1f..f11b1341946 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -87,6 +87,9 @@ typedef struct _meshtastic_LocalModuleConfig { /* Paxcounter Config */ bool has_paxcounter; meshtastic_ModuleConfig_PaxcounterConfig paxcounter; + /* StatusMessage Config */ + bool has_statusmessage; + meshtastic_ModuleConfig_StatusMessageConfig statusmessage; } meshtastic_LocalModuleConfig; @@ -96,9 +99,9 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_LocalConfig_init_default {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0, false, meshtastic_Config_SecurityConfig_init_default} -#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default, false, meshtastic_ModuleConfig_PaxcounterConfig_init_default} +#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default, false, meshtastic_ModuleConfig_PaxcounterConfig_init_default, false, meshtastic_ModuleConfig_StatusMessageConfig_init_default} #define meshtastic_LocalConfig_init_zero {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0, false, meshtastic_Config_SecurityConfig_init_zero} -#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero, false, meshtastic_ModuleConfig_PaxcounterConfig_init_zero} +#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero, false, meshtastic_ModuleConfig_PaxcounterConfig_init_zero, false, meshtastic_ModuleConfig_StatusMessageConfig_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_LocalConfig_device_tag 1 @@ -124,6 +127,7 @@ extern "C" { #define meshtastic_LocalModuleConfig_ambient_lighting_tag 12 #define meshtastic_LocalModuleConfig_detection_sensor_tag 13 #define meshtastic_LocalModuleConfig_paxcounter_tag 14 +#define meshtastic_LocalModuleConfig_statusmessage_tag 15 /* Struct field encoding specification for nanopb */ #define meshtastic_LocalConfig_FIELDLIST(X, a) \ @@ -161,7 +165,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \ X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11) \ X(a, STATIC, OPTIONAL, MESSAGE, ambient_lighting, 12) \ X(a, STATIC, OPTIONAL, MESSAGE, detection_sensor, 13) \ -X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14) +X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14) \ +X(a, STATIC, OPTIONAL, MESSAGE, statusmessage, 15) #define meshtastic_LocalModuleConfig_CALLBACK NULL #define meshtastic_LocalModuleConfig_DEFAULT NULL #define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig @@ -177,6 +182,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14) #define meshtastic_LocalModuleConfig_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig #define meshtastic_LocalModuleConfig_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig #define meshtastic_LocalModuleConfig_paxcounter_MSGTYPE meshtastic_ModuleConfig_PaxcounterConfig +#define meshtastic_LocalModuleConfig_statusmessage_MSGTYPE meshtastic_ModuleConfig_StatusMessageConfig extern const pb_msgdesc_t meshtastic_LocalConfig_msg; extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; @@ -186,9 +192,9 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size +#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size #define meshtastic_LocalConfig_size 749 -#define meshtastic_LocalModuleConfig_size 675 +#define meshtastic_LocalModuleConfig_size 758 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp index d8eee120336..7f1a738c652 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.cpp +++ b/src/mesh/generated/meshtastic/mesh.pb.cpp @@ -30,6 +30,9 @@ PB_BIND(meshtastic_StoreForwardPlusPlus, meshtastic_StoreForwardPlusPlus, 2) PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO) +PB_BIND(meshtastic_StatusMessage, meshtastic_StatusMessage, AUTO) + + PB_BIND(meshtastic_MqttClientProxyMessage, meshtastic_MqttClientProxyMessage, 2) diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 68552ede5e3..aeae4bd8456 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -858,6 +858,11 @@ typedef struct _meshtastic_Waypoint { uint32_t icon; } meshtastic_Waypoint; +/* Message for node status */ +typedef struct _meshtastic_StatusMessage { + char status[80]; +} meshtastic_StatusMessage; + typedef PB_BYTES_ARRAY_T(435) meshtastic_MqttClientProxyMessage_data_t; /* This message will be proxied over the PhoneAPI for the client to deliver to the MQTT server */ typedef struct _meshtastic_MqttClientProxyMessage { @@ -1402,6 +1407,7 @@ extern "C" { + #define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority #define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed #define meshtastic_MeshPacket_transport_mechanism_ENUMTYPE meshtastic_MeshPacket_TransportMechanism @@ -1444,6 +1450,7 @@ extern "C" { #define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} #define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} +#define meshtastic_StatusMessage_init_default {""} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} #define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0, 0} @@ -1476,6 +1483,7 @@ extern "C" { #define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} #define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} +#define meshtastic_StatusMessage_init_zero {""} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} #define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0, 0} @@ -1571,6 +1579,7 @@ extern "C" { #define meshtastic_Waypoint_name_tag 6 #define meshtastic_Waypoint_description_tag 7 #define meshtastic_Waypoint_icon_tag 8 +#define meshtastic_StatusMessage_status_tag 1 #define meshtastic_MqttClientProxyMessage_topic_tag 1 #define meshtastic_MqttClientProxyMessage_data_tag 2 #define meshtastic_MqttClientProxyMessage_text_tag 3 @@ -1806,6 +1815,11 @@ X(a, STATIC, SINGULAR, FIXED32, icon, 8) #define meshtastic_Waypoint_CALLBACK NULL #define meshtastic_Waypoint_DEFAULT NULL +#define meshtastic_StatusMessage_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, status, 1) +#define meshtastic_StatusMessage_CALLBACK NULL +#define meshtastic_StatusMessage_DEFAULT NULL + #define meshtastic_MqttClientProxyMessage_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, topic, 1) \ X(a, STATIC, ONEOF, BYTES, (payload_variant,data,payload_variant.data), 2) \ @@ -2072,6 +2086,7 @@ extern const pb_msgdesc_t meshtastic_Data_msg; extern const pb_msgdesc_t meshtastic_KeyVerification_msg; extern const pb_msgdesc_t meshtastic_StoreForwardPlusPlus_msg; extern const pb_msgdesc_t meshtastic_Waypoint_msg; +extern const pb_msgdesc_t meshtastic_StatusMessage_msg; extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg; extern const pb_msgdesc_t meshtastic_MeshPacket_msg; extern const pb_msgdesc_t meshtastic_NodeInfo_msg; @@ -2106,6 +2121,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg #define meshtastic_StoreForwardPlusPlus_fields &meshtastic_StoreForwardPlusPlus_msg #define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg +#define meshtastic_StatusMessage_fields &meshtastic_StatusMessage_msg #define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg #define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg #define meshtastic_NodeInfo_fields &meshtastic_NodeInfo_msg @@ -2161,6 +2177,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_QueueStatus_size 23 #define meshtastic_RouteDiscovery_size 256 #define meshtastic_Routing_size 259 +#define meshtastic_StatusMessage_size 81 #define meshtastic_StoreForwardPlusPlus_size 377 #define meshtastic_ToRadio_size 504 #define meshtastic_User_size 115 diff --git a/src/mesh/generated/meshtastic/module_config.pb.cpp b/src/mesh/generated/meshtastic/module_config.pb.cpp index f262df6a3da..bb57c3f2db0 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.cpp +++ b/src/mesh/generated/meshtastic/module_config.pb.cpp @@ -51,6 +51,9 @@ PB_BIND(meshtastic_ModuleConfig_CannedMessageConfig, meshtastic_ModuleConfig_Can PB_BIND(meshtastic_ModuleConfig_AmbientLightingConfig, meshtastic_ModuleConfig_AmbientLightingConfig, AUTO) +PB_BIND(meshtastic_ModuleConfig_StatusMessageConfig, meshtastic_ModuleConfig_StatusMessageConfig, AUTO) + + PB_BIND(meshtastic_RemoteHardwarePin, meshtastic_RemoteHardwarePin, AUTO) diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index dd0151e3f01..46a7164d246 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -409,6 +409,12 @@ typedef struct _meshtastic_ModuleConfig_AmbientLightingConfig { uint8_t blue; } meshtastic_ModuleConfig_AmbientLightingConfig; +/* StatusMessage config - Allows setting a status message for a node to periodically rebroadcast */ +typedef struct _meshtastic_ModuleConfig_StatusMessageConfig { + /* The actual status string */ + char node_status[80]; +} meshtastic_ModuleConfig_StatusMessageConfig; + /* A GPIO pin definition for remote hardware module */ typedef struct _meshtastic_RemoteHardwarePin { /* GPIO Pin number (must match Arduino) */ @@ -460,6 +466,8 @@ typedef struct _meshtastic_ModuleConfig { meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor; /* TODO: REPLACE */ meshtastic_ModuleConfig_PaxcounterConfig paxcounter; + /* TODO: REPLACE */ + meshtastic_ModuleConfig_StatusMessageConfig statusmessage; } payload_variant; } meshtastic_ModuleConfig; @@ -515,6 +523,7 @@ extern "C" { #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_event_press_ENUMTYPE meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar + #define meshtastic_RemoteHardwarePin_type_ENUMTYPE meshtastic_RemoteHardwarePinType @@ -534,6 +543,7 @@ extern "C" { #define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_StatusMessageConfig_init_default {""} #define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} #define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}} #define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_zero} @@ -550,6 +560,7 @@ extern "C" { #define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_StatusMessageConfig_init_zero {""} #define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN} /* Field tags (for use in manual encoding/decoding) */ @@ -653,6 +664,7 @@ extern "C" { #define meshtastic_ModuleConfig_AmbientLightingConfig_red_tag 3 #define meshtastic_ModuleConfig_AmbientLightingConfig_green_tag 4 #define meshtastic_ModuleConfig_AmbientLightingConfig_blue_tag 5 +#define meshtastic_ModuleConfig_StatusMessageConfig_node_status_tag 1 #define meshtastic_RemoteHardwarePin_gpio_pin_tag 1 #define meshtastic_RemoteHardwarePin_name_tag 2 #define meshtastic_RemoteHardwarePin_type_tag 3 @@ -672,6 +684,7 @@ extern "C" { #define meshtastic_ModuleConfig_ambient_lighting_tag 11 #define meshtastic_ModuleConfig_detection_sensor_tag 12 #define meshtastic_ModuleConfig_paxcounter_tag 13 +#define meshtastic_ModuleConfig_statusmessage_tag 14 /* Struct field encoding specification for nanopb */ #define meshtastic_ModuleConfig_FIELDLIST(X, a) \ @@ -687,7 +700,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_vari X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,ambient_lighting,payload_variant.ambient_lighting), 11) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,detection_sensor,payload_variant.detection_sensor), 12) \ -X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.paxcounter), 13) +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.paxcounter), 13) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,statusmessage,payload_variant.statusmessage), 14) #define meshtastic_ModuleConfig_CALLBACK NULL #define meshtastic_ModuleConfig_DEFAULT NULL #define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig @@ -703,6 +717,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.p #define meshtastic_ModuleConfig_payload_variant_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig #define meshtastic_ModuleConfig_payload_variant_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig #define meshtastic_ModuleConfig_payload_variant_paxcounter_MSGTYPE meshtastic_ModuleConfig_PaxcounterConfig +#define meshtastic_ModuleConfig_payload_variant_statusmessage_MSGTYPE meshtastic_ModuleConfig_StatusMessageConfig #define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ @@ -865,6 +880,11 @@ X(a, STATIC, SINGULAR, UINT32, blue, 5) #define meshtastic_ModuleConfig_AmbientLightingConfig_CALLBACK NULL #define meshtastic_ModuleConfig_AmbientLightingConfig_DEFAULT NULL +#define meshtastic_ModuleConfig_StatusMessageConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, node_status, 1) +#define meshtastic_ModuleConfig_StatusMessageConfig_CALLBACK NULL +#define meshtastic_ModuleConfig_StatusMessageConfig_DEFAULT NULL + #define meshtastic_RemoteHardwarePin_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, gpio_pin, 1) \ X(a, STATIC, SINGULAR, STRING, name, 2) \ @@ -887,6 +907,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_RangeTestConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_TelemetryConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg; extern const pb_msgdesc_t meshtastic_ModuleConfig_AmbientLightingConfig_msg; +extern const pb_msgdesc_t meshtastic_ModuleConfig_StatusMessageConfig_msg; extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ @@ -905,6 +926,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_TelemetryConfig_fields &meshtastic_ModuleConfig_TelemetryConfig_msg #define meshtastic_ModuleConfig_CannedMessageConfig_fields &meshtastic_ModuleConfig_CannedMessageConfig_msg #define meshtastic_ModuleConfig_AmbientLightingConfig_fields &meshtastic_ModuleConfig_AmbientLightingConfig_msg +#define meshtastic_ModuleConfig_StatusMessageConfig_fields &meshtastic_ModuleConfig_StatusMessageConfig_msg #define meshtastic_RemoteHardwarePin_fields &meshtastic_RemoteHardwarePin_msg /* Maximum encoded size of messages (where known) */ @@ -921,6 +943,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_RangeTestConfig_size 12 #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 #define meshtastic_ModuleConfig_SerialConfig_size 28 +#define meshtastic_ModuleConfig_StatusMessageConfig_size 81 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 #define meshtastic_ModuleConfig_TelemetryConfig_size 50 #define meshtastic_ModuleConfig_size 227 diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index 6b89c6a37a6..d31daa4b25c 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -91,6 +91,11 @@ typedef enum _meshtastic_PortNum { This module is specifically for Native Linux nodes, and provides a Git-style chain of messages. */ meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP = 35, + /* Node Status module + ENCODING: protobuf + This module allows setting an extra string of status for a node. + Broadcasts on change and on a timer, possibly once a day. */ + meshtastic_PortNum_NODE_STATUS_APP = 36, /* Provides a hardware serial interface to send and receive from the Meshtastic network. Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network. diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index dec89ba15d0..131dd9949cb 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -361,6 +361,8 @@ typedef struct _meshtastic_LocalStats { uint32_t heap_free_bytes; /* Number of packets that were dropped because the transmit queue was full. */ uint16_t num_tx_dropped; + /* Noise floor value measured in dBm */ + int32_t noise_floor; } meshtastic_LocalStats; /* Health telemetry metrics */ @@ -458,7 +460,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} #define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} @@ -467,7 +469,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} -#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} #define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} @@ -556,6 +558,7 @@ extern "C" { #define meshtastic_LocalStats_heap_total_bytes_tag 12 #define meshtastic_LocalStats_heap_free_bytes_tag 13 #define meshtastic_LocalStats_num_tx_dropped_tag 14 +#define meshtastic_LocalStats_noise_floor_tag 15 #define meshtastic_HealthMetrics_heart_bpm_tag 1 #define meshtastic_HealthMetrics_spO2_tag 2 #define meshtastic_HealthMetrics_temperature_tag 3 @@ -678,7 +681,8 @@ X(a, STATIC, SINGULAR, UINT32, num_tx_relay, 10) \ X(a, STATIC, SINGULAR, UINT32, num_tx_relay_canceled, 11) \ X(a, STATIC, SINGULAR, UINT32, heap_total_bytes, 12) \ X(a, STATIC, SINGULAR, UINT32, heap_free_bytes, 13) \ -X(a, STATIC, SINGULAR, UINT32, num_tx_dropped, 14) +X(a, STATIC, SINGULAR, UINT32, num_tx_dropped, 14) \ +X(a, STATIC, SINGULAR, INT32, noise_floor, 15) #define meshtastic_LocalStats_CALLBACK NULL #define meshtastic_LocalStats_DEFAULT NULL @@ -755,7 +759,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 #define meshtastic_HostMetrics_size 264 -#define meshtastic_LocalStats_size 76 +#define meshtastic_LocalStats_size 87 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 81 #define meshtastic_Telemetry_size 272 From 42548b77b23f990996a377bfe401d000c818645a Mon Sep 17 00:00:00 2001 From: nomdetom Date: Thu, 22 Jan 2026 00:17:09 +0000 Subject: [PATCH 31/39] Fix preset configuration for EU_866 region and update channel details for NARROW_868 --- src/mesh/RadioInterface.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 459550e2d3f..ea713c45f79 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -220,11 +220,11 @@ const RegionInfo regions[] = { Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, true, false, false, false, 0, LITE_FAST, PRESETS_LITE), + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, false, false, false, false, 0, LITE_FAST, PRESETS_LITE), /* - EU 868MHz band: 3 channels at 868.415/868.4925/868.570 MHz - Channel centres at 868.431/868.509/868.586 MHz, + EU 868MHz band: 3 channels at 869.415/869.4925/869.570 MHz + Channel centres at 869.446/869.524/869.601 MHz, 15 kHz gap between channels, 27 dBm, duty cycle 10% */ RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, 1, NARROW_FAST, PRESETS_NARROW), From fe01a401e96210ef60a0f4ed9956b646fcd94109 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Tue, 27 Jan 2026 14:27:27 +0000 Subject: [PATCH 32/39] Enhance region definitions by adding text, position, and telemetry throttle parameters --- src/mesh/MeshRadio.h | 7 ++-- src/mesh/RadioInterface.cpp | 68 ++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 4737fa3a0d1..67e88cff64d 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -16,8 +16,11 @@ struct RegionInfo { bool audioPermitted; bool freqSwitching; bool wideLora; - bool licensedOnly; // Only allow in HAM mode - uint8_t overrideSlot; // default frequency slot if not using channel hashing + bool licensedOnly; // Only allow in HAM mode + int8_t textThrottle; // text broadcast throttle - signed to allow future changes + int8_t positionThrottle; // position broadcast throttle - signed to allow future changes + int8_t telemetryThrottle; // telemetry broadcast throttle - signed to allow future changes + uint8_t overrideSlot; // default frequency slot if not using channel hashing meshtastic_Config_LoRaConfig_ModemPreset defaultPreset; // static list of available presets const meshtastic_Config_LoRaConfig_ModemPreset *availablePresets; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index ea713c45f79..18ecaa05aab 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -43,12 +43,12 @@ uint32_t pow_of_2(uint32_t n) return 1 << n; } -#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora, \ - licensed_only, override_slot, default_preset, available_presets) \ +#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, text_throttle, position_throttle, telemetry_throttle, \ + audio_permitted, frequency_switching, wide_lora, licensed_only, override_slot, default_preset, available_presets) \ { \ - meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \ - frequency_switching, wide_lora, licensed_only, override_slot, \ - meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ + meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, text_throttle, \ + position_throttle, telemetry_throttle, audio_permitted, frequency_switching, wide_lora, licensed_only, \ + override_slot, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ } const RegionInfo regions[] = { @@ -56,7 +56,7 @@ const RegionInfo regions[] = { https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ */ - RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* EN300220 ETSI V3.2.1 [Table B.1, Item H, p. 21] @@ -64,7 +64,7 @@ const RegionInfo regions[] = { https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.02.01_60/en_30022002v030201p.pdf FIXME: https://github.com/meshtastic/firmware/issues/3371 */ - RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ @@ -80,33 +80,33 @@ const RegionInfo regions[] = { AFA) to avoid a duty cycle. (Please refer to line P page 22 of this document.) https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.01.01_60/en_30022002v030101p.pdf */ - RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, false, 0, LONG_FAST, PRESETS_EU_868), + RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_EU_868), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://www.arib.or.jp/english/html/overview/doc/5-STD-T108v1_5-E1.pdf https://qiita.com/ammo0613/items/d952154f1195b64dc29f */ - RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf Also used in Brazil. */ - RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* 433.05 - 434.79 MHz, 25mW EIRP max, No duty cycle restrictions AU Low Interference Potential https://www.acma.gov.au/licences/low-interference-potential-devices-lipd-class-licence NZ General User Radio Licence for Short Range Devices https://gazette.govt.nz/notice/id/2022-go3100 */ - RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf @@ -114,13 +114,13 @@ const RegionInfo regions[] = { Note: - We do LBT, so 100% is allowed. */ - RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0 https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters */ - RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor. @@ -128,12 +128,12 @@ const RegionInfo regions[] = { https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 */ - RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf @@ -143,26 +143,26 @@ const RegionInfo regions[] = { /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* 433,05-434,7 Mhz 10 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* 868,0-868,6 Mhz 25 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Malaysia 433 - 435 MHz at 100mW, no restrictions. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Malaysia @@ -171,14 +171,14 @@ const RegionInfo regions[] = { Frequency hopping is used for 919 - 923 MHz. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Singapore SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions. https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf */ - RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Philippines @@ -188,9 +188,9 @@ const RegionInfo regions[] = { https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135 */ - RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), - RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, false, 0, LONG_FAST, PRESETS_STD), - RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Kazakhstan @@ -198,46 +198,46 @@ const RegionInfo regions[] = { 863 - 868 MHz <25 mW EIRP, 500kHz channels allowed, must not be used at airfields https://github.com/meshtastic/firmware/issues/7204 */ - RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, false, 0, LONG_FAST, PRESETS_STD), - RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Nepal 865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf */ - RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Brazil 902 - 907.5 MHz , 1W power limit, no duty cycle restrictions https://github.com/meshtastic/firmware/issues/3741 */ - RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, false, false, false, false, 0, LITE_FAST, PRESETS_LITE), + RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, false, false, false, false, 0, 99, 99, 0, LITE_FAST, PRESETS_LITE), /* EU 868MHz band: 3 channels at 869.415/869.4925/869.570 MHz Channel centres at 869.446/869.524/869.601 MHz, 15 kHz gap between channels, 27 dBm, duty cycle 10% */ - RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, 1, NARROW_FAST, PRESETS_NARROW), + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, 0, 0, 0, 1, NARROW_FAST, PRESETS_NARROW), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ - RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, false, 0, LONG_FAST, PRESETS_STD), + RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* This needs to be last. Same as US. */ - RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, LONG_FAST, PRESETS_UNDEF) + RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_UNDEF) }; @@ -538,7 +538,7 @@ struct ModemConfig { }; ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPreset preset) -{ +{ // Add throttle/dethrottles to each of these? ModemConfig cfg = {0}; switch (preset) { case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: From 8bc35ac6846f4b3f1e965b08dce2f2b9302b2718 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Tue, 27 Jan 2026 14:29:20 +0000 Subject: [PATCH 33/39] tunk --- src/mesh/RadioInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 18ecaa05aab..71f6e9721b4 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -138,7 +138,7 @@ const RegionInfo regions[] = { https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf */ - RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, false, 0, LONG_FAST, PRESETS_STD), + RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf From 694f4c967eac87bdd19cc88497622736ee3ba979 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Fri, 30 Jan 2026 02:47:32 +0000 Subject: [PATCH 34/39] Revert protobuf change --- src/mesh/generated/meshtastic/config.pb.h | 35 +++++------------------ 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index b6713dc3abb..8598f5626f5 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -285,11 +285,7 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode { /* Nepal 865MHz */ meshtastic_Config_LoRaConfig_RegionCode_NP_865 = 25, /* Brazil 902MHz */ - meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26, - /* EU 866MHz band (Band no. 47b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) */ - meshtastic_Config_LoRaConfig_RegionCode_EU_866 = 27, - /* EU 868MHz band, with narrow presets */ - meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 = 28 + meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26 } meshtastic_Config_LoRaConfig_RegionCode; /* Standard predefined channel settings @@ -319,24 +315,7 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset { meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO = 8, /* Long Range - Turbo This preset performs similarly to LongFast, but with 500Khz bandwidth. */ - meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO = 9, - /* Lite Fast - Medium range preset optimized for EU 866MHz SRD band with 125kHz bandwidth. - Comparable link budget to MEDIUM_FAST but compliant with Band no. 47b of 2006/771/EC. */ - meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST = 10, - /* Lite Slow - Medium-to-moderate range preset optimized for EU 866MHz SRD band with 125kHz bandwidth. - Comparable link budget to LONG_FAST but compliant with Band no. 47b of 2006/771/EC. */ - meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW = 11, - /* Narrow Fast - Medium-to-moderate range preset optimized for EU 868MHz band with 62.5kHz bandwidth. - Comparable link budget to SHORT_SLOW, but with half the data rate. - Intended to avoid interference with other devices. */ - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST = 12, - /* Narrow Slow - Moderate range preset optimized for EU 868MHz band with 62.5kHz bandwidth. - Comparable link budget and data rate to LONG_FAST. */ - meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW = 13 + meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO = 9 } meshtastic_Config_LoRaConfig_ModemPreset; typedef enum _meshtastic_Config_BluetoothConfig_PairingMode { @@ -710,12 +689,12 @@ extern "C" { #define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1)) #define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET -#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_NARROW_868 -#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_NARROW_868+1)) +#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_BR_902 +#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_BR_902+1)) #define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST -#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW -#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW+1)) +#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO +#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO+1)) #define _meshtastic_Config_BluetoothConfig_PairingMode_MIN meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN #define _meshtastic_Config_BluetoothConfig_PairingMode_MAX meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN @@ -1070,4 +1049,4 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg; } /* extern "C" */ #endif -#endif +#endif \ No newline at end of file From 34e39ae4744bb5f0b15a1cbb5cc796b7f0a3e416 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 2 Feb 2026 12:36:36 +0000 Subject: [PATCH 35/39] padding added to supplement spacing of channels --- src/mesh/MeshRadio.h | 5 ++- src/mesh/RadioInterface.cpp | 80 +++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index a9f8ee6df36..cfef5eee6fe 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -10,8 +10,9 @@ struct RegionInfo { meshtastic_Config_LoRaConfig_RegionCode code; float freqStart; float freqEnd; - float dutyCycle; - float spacing; + float dutyCycle; // modified by getEffectiveDutyCycle + float spacing; // gaps between radio channels + float padding; // padding at each side of the "operating channel" uint8_t powerLimit; // Or zero for not set bool audioPermitted; bool freqSwitching; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index ce55acb3d86..bac105860ed 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -62,12 +62,13 @@ uint32_t pow_of_2(uint32_t n) return 1 << n; } -#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, text_throttle, position_throttle, telemetry_throttle, \ - audio_permitted, frequency_switching, wide_lora, licensed_only, override_slot, default_preset, available_presets) \ +#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, padding, power_limit, text_throttle, position_throttle, \ + telemetry_throttle, audio_permitted, frequency_switching, wide_lora, licensed_only, override_slot, default_preset, \ + available_presets) \ { \ - meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, text_throttle, \ - position_throttle, telemetry_throttle, audio_permitted, frequency_switching, wide_lora, licensed_only, \ - override_slot, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ + meshtastic_Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, padding, power_limit, \ + text_throttle, position_throttle, telemetry_throttle, audio_permitted, frequency_switching, wide_lora, \ + licensed_only, override_slot, meshtastic_Config_LoRaConfig_ModemPreset_##default_preset, available_presets, #name \ } const RegionInfo regions[] = { @@ -75,7 +76,7 @@ const RegionInfo regions[] = { https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/ */ - RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(US, 902.0f, 928.0f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* EN300220 ETSI V3.2.1 [Table B.1, Item H, p. 21] @@ -83,7 +84,7 @@ const RegionInfo regions[] = { https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.02.01_60/en_30022002v030201p.pdf FIXME: https://github.com/meshtastic/firmware/issues/3371 */ - RDEF(EU_433, 433.0f, 434.0f, 10, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(EU_433, 433.0f, 434.0f, 10, 0, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ @@ -99,33 +100,33 @@ const RegionInfo regions[] = { AFA) to avoid a duty cycle. (Please refer to line P page 22 of this document.) https://www.etsi.org/deliver/etsi_en/300200_300299/30022002/03.01.01_60/en_30022002v030101p.pdf */ - RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_EU_868), + RDEF(EU_868, 869.4f, 869.65f, 10, 0, 0, 27, false, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_EU_868), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(CN, 470.0f, 510.0f, 100, 0, 0, 19, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf https://www.arib.or.jp/english/html/overview/doc/5-STD-T108v1_5-E1.pdf https://qiita.com/ammo0613/items/d952154f1195b64dc29f */ - RDEF(JP, 920.5f, 923.5f, 100, 0, 13, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(JP, 920.5f, 923.5f, 100, 0, 0, 13, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf Also used in Brazil. */ - RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(ANZ, 915.0f, 928.0f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* 433.05 - 434.79 MHz, 25mW EIRP max, No duty cycle restrictions AU Low Interference Potential https://www.acma.gov.au/licences/low-interference-potential-devices-lipd-class-licence NZ General User Radio Licence for Short Range Devices https://gazette.govt.nz/notice/id/2022-go3100 */ - RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(ANZ_433, 433.05f, 434.79f, 100, 0, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf @@ -133,13 +134,13 @@ const RegionInfo regions[] = { Note: - We do LBT, so 100% is allowed. */ - RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(RU, 868.7f, 869.2f, 100, 0, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://www.law.go.kr/LSW/admRulLsInfoP.do?admRulId=53943&efYd=0 https://resources.lora-alliance.org/technical-specifications/rp002-1-0-4-regional-parameters */ - RDEF(KR, 920.0f, 923.0f, 100, 0, 23, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(KR, 920.0f, 923.0f, 100, 0, 0, 23, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Taiwan, 920-925Mhz, limited to 0.5W indoor or coastal, 1.0W outdoor. @@ -147,7 +148,7 @@ const RegionInfo regions[] = { https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 */ - RDEF(TW, 920.0f, 925.0f, 100, 0, 27, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(TW, 920.0f, 925.0f, 100, 0, 0, 27, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf @@ -162,26 +163,26 @@ const RegionInfo regions[] = { /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(TH, 920.0f, 925.0f, 100, 0, 0, 16, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* 433,05-434,7 Mhz 10 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_433, 433.0f, 434.7f, 10, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(UA_433, 433.0f, 434.7f, 10, 0, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* 868,0-868,6 Mhz 25 mW https://nkrzi.gov.ua/images/upload/256/5810/PDF_UUZ_19_01_2016.pdf */ - RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(UA_868, 868.0f, 868.6f, 1, 0, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Malaysia 433 - 435 MHz at 100mW, no restrictions. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(MY_433, 433.0f, 435.0f, 100, 0, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Malaysia @@ -190,14 +191,14 @@ const RegionInfo regions[] = { Frequency hopping is used for 919 - 923 MHz. https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf */ - RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(MY_919, 919.0f, 924.0f, 100, 0, 0, 27, true, true, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Singapore SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions. https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf */ - RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(SG_923, 917.0f, 925.0f, 100, 0, 0, 20, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Philippines @@ -207,9 +208,9 @@ const RegionInfo regions[] = { https://github.com/meshtastic/firmware/issues/4948#issuecomment-2394926135 */ - RDEF(PH_433, 433.0f, 434.7f, 100, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), - RDEF(PH_868, 868.0f, 869.4f, 100, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), - RDEF(PH_915, 915.0f, 918.0f, 100, 0, 24, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_433, 433.0f, 434.7f, 100, 0, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_868, 868.0f, 869.4f, 100, 0, 0, 14, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(PH_915, 915.0f, 918.0f, 100, 0, 0, 24, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Kazakhstan @@ -217,46 +218,46 @@ const RegionInfo regions[] = { 863 - 868 MHz <25 mW EIRP, 500kHz channels allowed, must not be used at airfields https://github.com/meshtastic/firmware/issues/7204 */ - RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), - RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 0, 10, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Nepal 865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode. https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf */ - RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(NP_865, 865.0f, 868.0f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* Brazil 902 - 907.5 MHz , 1W power limit, no duty cycle restrictions https://github.com/meshtastic/firmware/issues/3741 */ - RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(BR_902, 902.0f, 907.5f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ - RDEF(EU_866, 865.6375f, 867.5625f, 2.5, 0.475, 27, false, false, false, false, 0, 99, 99, 0, LITE_FAST, PRESETS_LITE), + RDEF(EU_866, 865.6f, 867.6f, 2.5, 0.4, 0.0375f, 27, false, false, false, false, 0, 99, 99, 0, LITE_FAST, PRESETS_LITE), /* EU 868MHz band: 3 channels at 869.415/869.4925/869.570 MHz - Channel centres at 869.446/869.524/869.601 MHz, - 15 kHz gap between channels, 27 dBm, duty cycle 10% + Channel centres at 869.442/869.524/869.606 MHz, + 10 kHz padding on channels, 27 dBm, duty cycle 10% */ - RDEF(NARROW_868, 869.4f, 869.65f, 10, 0.015, 27, false, false, false, false, 0, 0, 0, 1, NARROW_FAST, PRESETS_NARROW), + RDEF(NARROW_868, 869.4f, 869.65f, 10, 0, 0.0104f, 27, false, false, false, false, 0, 0, 0, 1, NARROW_FAST, PRESETS_NARROW), /* 2.4 GHZ WLAN Band equivalent. Only for SX128x chips. */ - RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 0, 10, true, false, true, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* This needs to be last. Same as US. */ - RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_UNDEF) + RDEF(UNSET, 902.0f, 928.0f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_UNDEF) }; @@ -1095,8 +1096,10 @@ void RadioInterface::applyModemConfig() // Set final tx_power back onto config loraConfig.tx_power = (int8_t)power; // cppcheck-suppress assignmentAddressToInteger - // Calculate number of channels: spacing = gap between channels (0 for continuous spectrum) - float channelSpacing = myRegion->spacing + (bw / 1000); + // Calculate number of channels: + // spacing = gap between channels (0 for continuous spectrum) and at the beginning of the band + // padding = gap at the beginning and end of the channel (0 for no padding) + float channelSpacing = myRegion->spacing + (myRegion->padding * 2) + (bw / 1000); // in MHz uint32_t numChannels = round((myRegion->freqEnd - myRegion->freqStart + myRegion->spacing) / channelSpacing); // If user has manually specified a channel num, then use that, otherwise generate one by hashing the name @@ -1118,8 +1121,9 @@ void RadioInterface::applyModemConfig() channel_num = myRegion->overrideSlot - 1; } - // Calculate frequency: freqStart is band edge, add half bandwidth to get first channel center - float freq = myRegion->freqStart + (bw / 2000) + (channel_num * channelSpacing); + // Calculate frequency: freqStart is band edge, add half bandwidth (plus optional padding) to get middle of first channel + // subsequent channels are spaced by channelSpacing + float freq = myRegion->freqStart + (bw / 2000) + myRegion->padding + (channel_num * channelSpacing); // in MHz // override if we have a verbatim frequency if (loraConfig.override_frequency) { From 93ebbfc85e7bbd7335699fbd24475b27e33f9b83 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 2 Feb 2026 12:44:30 +0000 Subject: [PATCH 36/39] added more commentary --- src/mesh/RadioInterface.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index bac105860ed..b9e9694be17 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -237,15 +237,15 @@ const RegionInfo regions[] = { /* EU 866MHz band (Band no. 46b of 2006/771/EC and subsequent amendments) for Non-specific short-range devices (SRD) - Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 475 kHz gap between channels, 27 dBm, duty cycle 2.5% (mobile) or 10% - (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 + Gives 4 channels at 865.7/866.3/866.9/867.5 MHz, 400 kHz gap plus 37.5 kHz padding between channels, 27 dBm, + duty cycle 2.5% (mobile) or 10% (fixed) https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006D0771(01)-20250123 */ RDEF(EU_866, 865.6f, 867.6f, 2.5, 0.4, 0.0375f, 27, false, false, false, false, 0, 99, 99, 0, LITE_FAST, PRESETS_LITE), /* - EU 868MHz band: 3 channels at 869.415/869.4925/869.570 MHz - Channel centres at 869.442/869.524/869.606 MHz, - 10 kHz padding on channels, 27 dBm, duty cycle 10% + EU 868MHz band: 3 channels at 869.410/869.4625/869.577 MHz + Channel centres at 869.442/869.525/869.608 MHz, + 10.4 kHz padding on channels, 27 dBm, duty cycle 10% */ RDEF(NARROW_868, 869.4f, 869.65f, 10, 0, 0.0104f, 27, false, false, false, false, 0, 0, 0, 1, NARROW_FAST, PRESETS_NARROW), From 3b824c66d4eb8a5ac6d3e01ea28f0803a2136213 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Mon, 2 Feb 2026 15:31:04 +0000 Subject: [PATCH 37/39] merge conflicts fixed - TY Stary --- src/mesh/MeshRadio.h | 20 +++++ src/mesh/NodeDB.cpp | 2 +- src/mesh/RadioInterface.cpp | 154 ++++-------------------------------- 3 files changed, 37 insertions(+), 139 deletions(-) diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index cfef5eee6fe..29b8e4b4fa1 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -125,6 +125,26 @@ static inline void modemPresetToParams(meshtastic_Config_LoRaConfig_ModemPreset cr = 8; sf = 12; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: + bwKHz = 125; + cr = 5; + sf = 9; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: + bwKHz = 125; + cr = 5; + sf = 10; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: + bwKHz = 62.5f; + cr = 6; + sf = 7; + break; + case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: + bwKHz = 62.5f; + cr = 6; + sf = 8; + break; default: // LONG_FAST (or illegal) bwKHz = wideLora ? 812.5f : 250.0f; cr = 5; diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 0da4261b9a6..85313ded123 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1288,7 +1288,7 @@ void NodeDB::loadFromDisk() // Coerce LoRa config fields derived from presets while bootstrapping. // Some clients/UI components display bandwidth/spread_factor directly from config even in preset mode. if (config.has_lora && config.lora.use_preset) { - RadioInterface::bootstrapLoRaConfigFromPreset(config.lora); + RadioInterface::validateModemConfig(config.lora); } if (backupSecurity.private_key.size > 0) { diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index b9e9694be17..a1e886999a3 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -153,12 +153,12 @@ const RegionInfo regions[] = { /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf */ - RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(IN, 865.0f, 867.0f, 100, 0, 0, 30, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752 https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf */ - RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), + RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 0, 36, true, false, false, false, 0, 0, 0, 0, LONG_FAST, PRESETS_STD), /* https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf @@ -830,83 +830,13 @@ struct ModemConfig { uint8_t cr; }; -ModemConfig settingsForPreset(bool wide, meshtastic_Config_LoRaConfig_ModemPreset preset) -{ // Add throttle/dethrottles to each of these? - ModemConfig cfg = {0}; - switch (preset) { - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO: - cfg.bw = wide ? 1625.0 : 500; - cfg.cr = 5; - cfg.sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST: - cfg.bw = wide ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW: - cfg.bw = wide ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 8; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST: - cfg.bw = wide ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 9; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: - cfg.bw = wide ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 10; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: - cfg.bw = wide ? 1625.0 : 500; - cfg.cr = 8; - cfg.sf = 11; - break; - default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. - cfg.bw = wide ? 812.5 : 250; - cfg.cr = 5; - cfg.sf = 11; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: - cfg.bw = wide ? 406.25 : 125; - cfg.cr = 8; - cfg.sf = 11; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW: - cfg.bw = wide ? 406.25 : 125; - cfg.cr = 8; - cfg.sf = 12; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LITE_FAST: - cfg.bw = 125; - cfg.cr = 5; - cfg.sf = 9; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_LITE_SLOW: - cfg.bw = 125; - cfg.cr = 5; - cfg.sf = 10; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_FAST: - cfg.bw = 62.5; - cfg.cr = 6; - cfg.sf = 7; - break; - case meshtastic_Config_LoRaConfig_ModemPreset_NARROW_SLOW: - cfg.bw = 62.5; - cfg.cr = 6; - cfg.sf = 8; - break; - } - return cfg; -} - bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfig) { bool validConfig = true; char err_string[160]; + float bw; + uint8_t sf; + uint8_t cr; const RegionInfo *newRegion = getRegion(loraConfig.region); if (!newRegion) { // copilot said I had to check for null pointer @@ -930,7 +860,7 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi return false; } - auto cfg = settingsForPreset(newRegion->wideLora, loraConfig.modem_preset); + modemPresetToParams(loraConfig.modem_preset, newRegion->wideLora, bw, sf, cr); // early check - if we use preset, make sure it's on available preset list if (loraConfig.use_preset) { @@ -959,16 +889,11 @@ bool RadioInterface::validateModemConfig(meshtastic_Config_LoRaConfig &loraConfi snprintf(cn->message, sizeof(cn->message), "%s", err_string); service->sendClientNotification(cn); return false; + } else { + bw = loraConfig.bandwidth; } } // end if use_preset - float bw; - if (loraConfig.use_preset) { - bw = cfg.bw; - } else { - bw = loraConfig.bandwidth; - } - // this is probably wrong (?) as you can still select last channel in a band, set // wide bandwidth and transmit outside the band and the check will not catch it // phaseloop // this only makes sense if you happen to be in the center of the region band @@ -1018,69 +943,22 @@ void RadioInterface::applyModemConfig() if (!validateModemConfig(loraConfig)) { loraConfig.modem_preset = newRegion->defaultPreset; } - - auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); - sf = settings.sf; - bw = settings.bw; + uint8_t newcr; + modemPresetToParams(loraConfig.modem_preset, newRegion->wideLora, bw, sf, newcr); // If custom CR is being used already, check if the new preset is higher - if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate < settings.cr) { - cr = settings.cr; + if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate < newcr) { + LOG_INFO("Default Coding Rate is higher than custom setting, using %u", cr); } // If the custom CR is higher than the preset, use it - else if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate > settings.cr) { + else if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate > newcr) { cr = loraConfig.coding_rate; LOG_INFO("Using custom Coding Rate %u", cr); } else { sf = loraConfig.spread_factor; cr = loraConfig.coding_rate; - bw = loraConfig.bandwidth; - - if (bw == 31) // This parameter is not an integer - bw = 31.25; - if (bw == 62) // Fix for 62.5Khz bandwidth - bw = 62.5; - if (bw == 200) - bw = 203.125; - if (bw == 400) - bw = 406.25; - if (bw == 800) - bw = 812.5; - if (bw == 1600) - bw = 1625.0; + bw = bwCodeToKHz(loraConfig.bandwidth); } - - if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { - const float regionSpanKHz = (myRegion->freqEnd - myRegion->freqStart) * 1000.0f; - const float requestedBwKHz = bw; - const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset - const char *presetName = - DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); - - char err_string[160]; - if (isWideRequest) { - snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.", - myRegion->name, presetName); - } else { - snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.", - myRegion->name, regionSpanKHz, requestedBwKHz); - } - LOG_ERROR("%s", err_string); - RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); - - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_ERROR; - snprintf(cn->message, sizeof(cn->message), "%s", err_string); - service->sendClientNotification(cn); - - // Set to default modem preset - loraConfig.use_preset = true; - } - - auto settings = settingsForPreset(myRegion->wideLora, loraConfig.modem_preset); - sf = settings.sf; - cr = settings.cr; - bw = settings.bw; } power = loraConfig.tx_power; @@ -1149,7 +1027,7 @@ void RadioInterface::applyModemConfig() LOG_INFO("channel_num: %d", channel_num + 1); LOG_INFO("frequency: %f", getFreq()); LOG_INFO("Slot time: %u msec, preamble time: %u msec", slotTimeMsec, preambleTimeMsec); -} +} // end of applyModemConfig /** Slottime is the time to detect a transmission has started, consisting of: - CAD duration; @@ -1190,7 +1068,7 @@ void RadioInterface::limitPower(int8_t loraMaxPower) size_t num_pa_points = portduino_config.num_pa_points; const uint16_t *tx_gain = portduino_config.tx_gain_lora; #else - size_t num_pa_points = NUM_PA_POINTS; + int num_pa_points = NUM_PA_POINTS; const uint16_t tx_gain[NUM_PA_POINTS] = {TX_GAIN_LORA}; #endif From 47f8f40872d973927f1433922b51ac753bc497c2 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 14 Feb 2026 00:28:09 +0000 Subject: [PATCH 38/39] committing changes to protobufs --- protobufs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobufs b/protobufs index 36d895e1e42..44298d374fd 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 36d895e1e42db77f6308c9c029affc74648e0abe +Subproject commit 44298d374fd83cfbc36fdb76c6f966e980cadd93 From d619cf312c03d35c0b28ce601eb9c5417e550181 Mon Sep 17 00:00:00 2001 From: nomdetom Date: Sat, 14 Feb 2026 00:29:26 +0000 Subject: [PATCH 39/39] Update protobuf submodule to latest commit --- protobufs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobufs b/protobufs index 44298d374fd..f57b423a395 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 44298d374fd83cfbc36fdb76c6f966e980cadd93 +Subproject commit f57b423a395c7a54d3acaa83ac9036e4d9281d9e