Compare commits

..

1 Commits

Author SHA1 Message Date
vidplace7
c6d77cf313 Upgrade trunk 2026-01-23 08:08:29 +00:00
11 changed files with 118 additions and 259 deletions

View File

@@ -9,14 +9,14 @@ plugins:
lint: lint:
enabled: enabled:
- checkov@3.2.497 - checkov@3.2.497
- renovate@42.84.2 - renovate@42.90.0
- prettier@3.8.0 - prettier@3.8.1
- trufflehog@3.92.5 - trufflehog@3.92.5
- yamllint@1.38.0 - yamllint@1.38.0
- bandit@1.9.3 - bandit@1.9.3
- trivy@0.68.2 - trivy@0.68.2
- taplo@0.10.0 - taplo@0.10.0
- ruff@0.14.13 - ruff@0.14.14
- isort@7.0.0 - isort@7.0.0
- markdownlint@0.47.0 - markdownlint@0.47.0
- oxipng@10.0.0 - oxipng@10.0.0

View File

@@ -397,7 +397,7 @@ uint32_t getValidTime(RTCQuality minQuality, bool local)
return (currentQuality >= minQuality) ? getTime(local) : 0; return (currentQuality >= minQuality) ? getTime(local) : 0;
} }
time_t gm_mktime(const struct tm *tm) time_t gm_mktime(struct tm *tm)
{ {
#if !MESHTASTIC_EXCLUDE_TZ #if !MESHTASTIC_EXCLUDE_TZ
time_t result = 0; time_t result = 0;
@@ -413,8 +413,8 @@ time_t gm_mktime(const struct tm *tm)
days_before_this_year -= 719162; // (1969 * 365 + 1969 / 4 - 1969 / 100 + 1969 / 400); days_before_this_year -= 719162; // (1969 * 365 + 1969 / 4 - 1969 / 100 + 1969 / 400);
// Now, within this tm->year, compute the days *before* this tm->month starts. // Now, within this tm->year, compute the days *before* this tm->month starts.
static const int days_before_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // non-leap year int days_before_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // non-leap year
int days_this_year_before_this_month = days_before_month[tm->tm_mon]; // tm->tm_mon is 0..11 int days_this_year_before_this_month = days_before_month[tm->tm_mon]; // tm->tm_mon is 0..11
// If this is a leap year, and we're past February, add a day: // If this is a leap year, and we're past February, add a day:
if (tm->tm_mon >= 2 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) { if (tm->tm_mon >= 2 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
@@ -435,7 +435,6 @@ time_t gm_mktime(const struct tm *tm)
return result; return result;
#else #else
struct tm tmCopy = *tm; return mktime(tm);
return mktime(&tmCopy);
#endif #endif
} }

View File

@@ -54,7 +54,7 @@ uint32_t getValidTime(RTCQuality minQuality, bool local = false);
RTCSetResult readFromRTC(); RTCSetResult readFromRTC();
time_t gm_mktime(const struct tm *tm); time_t gm_mktime(struct tm *tm);
#define SEC_PER_DAY 86400 #define SEC_PER_DAY 86400
#define SEC_PER_HOUR 3600 #define SEC_PER_HOUR 3600

View File

@@ -266,8 +266,52 @@ void menuHandler::FrequencySlotPicker()
// Calculate number of channels (copied from RadioInterface::applyModemConfig()) // Calculate number of channels (copied from RadioInterface::applyModemConfig())
meshtastic_Config_LoRaConfig &loraConfig = config.lora; meshtastic_Config_LoRaConfig &loraConfig = config.lora;
double bw = loraConfig.use_preset ? modemPresetToBwKHz(loraConfig.modem_preset, myRegion->wideLora) double bw = loraConfig.bandwidth;
: bwCodeToKHz(loraConfig.bandwidth); if (loraConfig.use_preset) {
switch (loraConfig.modem_preset) {
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO:
bw = (myRegion->wideLora) ? 1625.0 : 500;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
bw = (myRegion->wideLora) ? 812.5 : 250;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
bw = (myRegion->wideLora) ? 812.5 : 250;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
bw = (myRegion->wideLora) ? 812.5 : 250;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
bw = (myRegion->wideLora) ? 812.5 : 250;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO:
bw = (myRegion->wideLora) ? 1625.0 : 500;
break;
default:
bw = (myRegion->wideLora) ? 812.5 : 250;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
bw = (myRegion->wideLora) ? 406.25 : 125;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
bw = (myRegion->wideLora) ? 406.25 : 125;
break;
}
} else {
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;
}
uint32_t numChannels = 0; uint32_t numChannels = 0;
if (myRegion) { if (myRegion) {

View File

@@ -140,7 +140,7 @@ struct ScreenColor {
uint8_t b; uint8_t b;
bool useVariant; bool useVariant;
explicit ScreenColor(uint8_t rIn = 0, uint8_t gIn = 0, uint8_t bIn = 0, bool variantIn = false) ScreenColor(uint8_t rIn = 0, uint8_t gIn = 0, uint8_t bIn = 0, bool variantIn = false)
: r(rIn), g(gIn), b(bIn), useVariant(variantIn) : r(rIn), g(gIn), b(bIn), useVariant(variantIn)
{ {
} }

View File

@@ -22,99 +22,4 @@ struct RegionInfo {
extern const RegionInfo regions[]; extern const RegionInfo regions[];
extern const RegionInfo *myRegion; extern const RegionInfo *myRegion;
extern void initRegion(); extern void initRegion();
static inline float bwCodeToKHz(uint16_t bwCode)
{
if (bwCode == 31)
return 31.25f;
if (bwCode == 62)
return 62.5f;
if (bwCode == 200)
return 203.125f;
if (bwCode == 400)
return 406.25f;
if (bwCode == 800)
return 812.5f;
if (bwCode == 1600)
return 1625.0f;
return (float)bwCode;
}
static inline uint16_t bwKHzToCode(float bwKHz)
{
if (bwKHz > 31.24f && bwKHz < 31.26f)
return 31;
if (bwKHz > 62.49f && bwKHz < 62.51f)
return 62;
if (bwKHz > 203.12f && bwKHz < 203.13f)
return 200;
if (bwKHz > 406.24f && bwKHz < 406.26f)
return 400;
if (bwKHz > 812.49f && bwKHz < 812.51f)
return 800;
if (bwKHz > 1624.99f && bwKHz < 1625.01f)
return 1600;
return (uint16_t)(bwKHz + 0.5f);
}
static inline void modemPresetToParams(meshtastic_Config_LoRaConfig_ModemPreset preset, bool wideLora, float &bwKHz, uint8_t &sf,
uint8_t &cr)
{
switch (preset) {
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO:
bwKHz = wideLora ? 1625.0f : 500.0f;
cr = 5;
sf = 7;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
bwKHz = wideLora ? 812.5f : 250.0f;
cr = 5;
sf = 7;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
bwKHz = wideLora ? 812.5f : 250.0f;
cr = 5;
sf = 8;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
bwKHz = wideLora ? 812.5f : 250.0f;
cr = 5;
sf = 9;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
bwKHz = wideLora ? 812.5f : 250.0f;
cr = 5;
sf = 10;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO:
bwKHz = wideLora ? 1625.0f : 500.0f;
cr = 8;
sf = 11;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
bwKHz = wideLora ? 406.25f : 125.0f;
cr = 8;
sf = 11;
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
bwKHz = wideLora ? 406.25f : 125.0f;
cr = 8;
sf = 12;
break;
default: // LONG_FAST (or illegal)
bwKHz = wideLora ? 812.5f : 250.0f;
cr = 5;
sf = 11;
break;
}
}
static inline float modemPresetToBwKHz(meshtastic_Config_LoRaConfig_ModemPreset preset, bool wideLora)
{
float bwKHz = 0;
uint8_t sf = 0;
uint8_t cr = 0;
modemPresetToParams(preset, wideLora, bwKHz, sf, cr);
return bwKHz;
}

View File

@@ -13,7 +13,6 @@
#include "PacketHistory.h" #include "PacketHistory.h"
#include "PowerFSM.h" #include "PowerFSM.h"
#include "RTC.h" #include "RTC.h"
#include "RadioInterface.h"
#include "Router.h" #include "Router.h"
#include "SPILock.h" #include "SPILock.h"
#include "SafeFile.h" #include "SafeFile.h"
@@ -1298,13 +1297,6 @@ void NodeDB::loadFromDisk()
LOG_INFO("Loaded saved config version %d", config.version); LOG_INFO("Loaded saved config version %d", config.version);
} }
} }
// 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);
}
if (backupSecurity.private_key.size > 0) { if (backupSecurity.private_key.size > 0) {
LOG_DEBUG("Restoring backup of security config"); LOG_DEBUG("Restoring backup of security config");
config.security = backupSecurity; config.security = backupSecurity;

View File

@@ -220,34 +220,6 @@ void initRegion()
myRegion = r; myRegion = r;
} }
void RadioInterface::bootstrapLoRaConfigFromPreset(meshtastic_Config_LoRaConfig &loraConfig)
{
if (!loraConfig.use_preset) {
return;
}
// Find region info to determine whether "wide" LoRa is permitted (2.4 GHz uses wider bandwidth codes).
const RegionInfo *r = regions;
for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != loraConfig.region; r++)
;
const bool regionWideLora = r->wideLora;
float bwKHz = 0;
uint8_t sf = 0;
uint8_t cr = 0;
modemPresetToParams(loraConfig.modem_preset, regionWideLora, bwKHz, sf, cr);
// If selected preset requests a bandwidth larger than the region span, fall back to LONG_FAST.
if (r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && (r->freqEnd - r->freqStart) < (bwKHz / 1000.0f)) {
loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST;
modemPresetToParams(loraConfig.modem_preset, regionWideLora, bwKHz, sf, cr);
}
loraConfig.bandwidth = bwKHzToCode(bwKHz);
loraConfig.spread_factor = sf;
}
/** /**
* ## LoRaWAN for North America * ## LoRaWAN for North America
@@ -502,7 +474,54 @@ void RadioInterface::applyModemConfig()
bool validConfig = false; // We need to check for a valid configuration bool validConfig = false; // We need to check for a valid configuration
while (!validConfig) { while (!validConfig) {
if (loraConfig.use_preset) { if (loraConfig.use_preset) {
modemPresetToParams(loraConfig.modem_preset, myRegion->wideLora, bw, sf, cr);
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;
}
if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate != cr) { if (loraConfig.coding_rate >= 5 && loraConfig.coding_rate <= 8 && loraConfig.coding_rate != cr) {
cr = loraConfig.coding_rate; cr = loraConfig.coding_rate;
LOG_INFO("Using custom Coding Rate %u", cr); LOG_INFO("Using custom Coding Rate %u", cr);
@@ -510,7 +529,20 @@ void RadioInterface::applyModemConfig()
} else { } else {
sf = loraConfig.spread_factor; sf = loraConfig.spread_factor;
cr = loraConfig.coding_rate; cr = loraConfig.coding_rate;
bw = bwCodeToKHz(loraConfig.bandwidth); 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;
} }
if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) {

View File

@@ -7,9 +7,6 @@
#include "airtime.h" #include "airtime.h"
#include "error.h" #include "error.h"
// Forward decls to avoid pulling generated config headers into this widely-included file.
typedef struct _meshtastic_Config_LoRaConfig meshtastic_Config_LoRaConfig;
#define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission #define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission
#define MAX_LORA_PAYLOAD_LEN 255 // max length of 255 per Semtech's datasheets on SX12xx #define MAX_LORA_PAYLOAD_LEN 255 // max length of 255 per Semtech's datasheets on SX12xx
@@ -118,12 +115,6 @@ class RadioInterface
virtual ~RadioInterface() {} virtual ~RadioInterface() {}
/**
* Coerce LoRa config fields (bandwidth/spread_factor) derived from presets.
* This is used during early bootstrapping so UIs that display these fields directly remain consistent.
*/
static void bootstrapLoRaConfigFromPreset(meshtastic_Config_LoRaConfig &loraConfig);
/** /**
* Return true if we think the board can go to sleep (i.e. our tx queue is empty, we are not sending or receiving) * Return true if we think the board can go to sleep (i.e. our tx queue is empty, we are not sending or receiving)
* *

View File

@@ -1,100 +0,0 @@
#include "MeshRadio.h"
#include "RadioInterface.h"
#include "TestUtil.h"
#include <unity.h>
#include "meshtastic/config.pb.h"
static void test_bwCodeToKHz_specialMappings()
{
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 31.25f, bwCodeToKHz(31));
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 62.5f, bwCodeToKHz(62));
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 203.125f, bwCodeToKHz(200));
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 406.25f, bwCodeToKHz(400));
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 812.5f, bwCodeToKHz(800));
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 1625.0f, bwCodeToKHz(1600));
}
static void test_bwCodeToKHz_passthrough()
{
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 125.0f, bwCodeToKHz(125));
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 250.0f, bwCodeToKHz(250));
}
static void test_bootstrapLoRaConfigFromPreset_noopWhenUsePresetFalse()
{
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
cfg.use_preset = false;
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_US;
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST;
cfg.bandwidth = 123;
cfg.spread_factor = 8;
RadioInterface::bootstrapLoRaConfigFromPreset(cfg);
TEST_ASSERT_EQUAL_UINT16(123, cfg.bandwidth);
TEST_ASSERT_EQUAL_UINT32(8, cfg.spread_factor);
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST, cfg.modem_preset);
}
static void test_bootstrapLoRaConfigFromPreset_setsDerivedFields_nonWideRegion()
{
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
cfg.use_preset = true;
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_US;
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST;
RadioInterface::bootstrapLoRaConfigFromPreset(cfg);
TEST_ASSERT_EQUAL_UINT16(250, cfg.bandwidth);
TEST_ASSERT_EQUAL_UINT32(9, cfg.spread_factor);
}
static void test_bootstrapLoRaConfigFromPreset_setsDerivedFields_wideRegion()
{
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
cfg.use_preset = true;
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_LORA_24;
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST;
RadioInterface::bootstrapLoRaConfigFromPreset(cfg);
TEST_ASSERT_EQUAL_UINT16(800, cfg.bandwidth);
TEST_ASSERT_EQUAL_UINT32(9, cfg.spread_factor);
}
static void test_bootstrapLoRaConfigFromPreset_fallsBackIfBandwidthExceedsRegionSpan()
{
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
cfg.use_preset = true;
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_EU_868;
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO;
RadioInterface::bootstrapLoRaConfigFromPreset(cfg);
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, cfg.modem_preset);
TEST_ASSERT_EQUAL_UINT16(250, cfg.bandwidth);
TEST_ASSERT_EQUAL_UINT32(11, cfg.spread_factor);
}
void setUp(void) {}
void tearDown(void) {}
void setup()
{
delay(10);
delay(2000);
initializeTestEnvironment();
UNITY_BEGIN();
RUN_TEST(test_bwCodeToKHz_specialMappings);
RUN_TEST(test_bwCodeToKHz_passthrough);
RUN_TEST(test_bootstrapLoRaConfigFromPreset_noopWhenUsePresetFalse);
RUN_TEST(test_bootstrapLoRaConfigFromPreset_setsDerivedFields_nonWideRegion);
RUN_TEST(test_bootstrapLoRaConfigFromPreset_setsDerivedFields_wideRegion);
RUN_TEST(test_bootstrapLoRaConfigFromPreset_fallsBackIfBandwidthExceedsRegionSpan);
exit(UNITY_END());
}
void loop() {}

View File

@@ -67,8 +67,4 @@ void variant_shutdown()
nrf_gpio_cfg_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input nrf_gpio_cfg_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW; nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW;
nrf_gpio_cfg_sense_set(PIN_BUTTON1, sense1); nrf_gpio_cfg_sense_set(PIN_BUTTON1, sense1);
nrf_gpio_cfg_input(EXT_CHRG_DETECT, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
nrf_gpio_pin_sense_t sense2 = NRF_GPIO_PIN_SENSE_LOW;
nrf_gpio_cfg_sense_set(EXT_CHRG_DETECT, sense2);
} }