Conversation
There was a problem hiding this comment.
Pull request overview
This pull request attempts to improve the congestion scaling algorithm in Meshtastic by replacing hardcoded throttling factors with a dynamic formula based on LoRa spread factor and bandwidth. The goal is to make the scaling more responsive to actual radio parameters rather than using preset-specific constants.
Changes:
- Modified
Default::congestionScalingCoefficient()to calculate throttling factors usingpow(2, spread_factor) / (bandwidth * 100000)instead of hardcoded values - Added unit tests in
test/test_default/test_main.cppto verify scaling behavior for different device roles and presets - Updated comments to document the new formula values compared to original hardcoded factors
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| src/mesh/Default.h | Replaced hardcoded throttling factors (0.075, 0.04, 0.02, 0.01) with formula-based calculation using spread factor and bandwidth |
| test/test_default/test_main.cpp | Added new test file with 4 test cases for router, client below threshold, client with default scaling, and client with MEDIUM_FAST preset |
test/test_default/test_main.cpp
Outdated
| void test_client_default_preset_scaling() | ||
| { | ||
| config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; | ||
| config.lora.use_preset = false; | ||
| // nodesOverForty = 10 -> coefficient = 1 + 10 * 0.075 = 1.75 => 60000 * 1.75 = 105000 | ||
| uint32_t res = Default::getConfiguredOrDefaultMsScaled(0, 60, 50); | ||
| TEST_ASSERT_EQUAL_UINT32(105000U, res); |
There was a problem hiding this comment.
This test doesn't set config.lora.bandwidth or config.lora.spread_factor when using use_preset = false. The new formula in Default.h directly accesses these fields, which will be 0 after initializeTestEnvironment() initializes config, leading to division by zero.
The test should explicitly set these fields, for example:
config.lora.bandwidth = 250; // 250 kHz
config.lora.spread_factor = 11; // LONG_FAST defaultHowever, note that the formula in Default.h has bugs that need to be fixed first (see comments on Default.h).
| // Unit tests for Default::getConfiguredOrDefaultMsScaled | ||
| #include "Default.h" | ||
| #include "TestUtil.h" | ||
| #include <unity.h> | ||
|
|
||
| void test_router_no_scaling() | ||
| { | ||
| config.device.role = meshtastic_Config_DeviceConfig_Role_ROUTER; | ||
| uint32_t res = Default::getConfiguredOrDefaultMsScaled(0, 60, 100); | ||
| TEST_ASSERT_EQUAL_UINT32(60000U, res); | ||
| } | ||
|
|
||
| void test_client_below_threshold() | ||
| { | ||
| config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; | ||
| config.lora.use_preset = false; | ||
| uint32_t res = Default::getConfiguredOrDefaultMsScaled(0, 60, 40); | ||
| TEST_ASSERT_EQUAL_UINT32(60000U, res); | ||
| } | ||
|
|
||
| void test_client_default_preset_scaling() | ||
| { | ||
| config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; | ||
| config.lora.use_preset = false; | ||
| // nodesOverForty = 10 -> coefficient = 1 + 10 * 0.075 = 1.75 => 60000 * 1.75 = 105000 | ||
| uint32_t res = Default::getConfiguredOrDefaultMsScaled(0, 60, 50); | ||
| TEST_ASSERT_EQUAL_UINT32(105000U, res); | ||
| } | ||
|
|
||
| void test_client_medium_fast_preset_scaling() | ||
| { | ||
| config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; | ||
| config.lora.use_preset = true; | ||
| config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST; | ||
| // nodesOverForty = 30 -> coefficient = 1 + 30 * 0.02 = 1.6 => 60000 * 1.6 = 96000 | ||
| uint32_t res = Default::getConfiguredOrDefaultMsScaled(0, 60, 70); | ||
| TEST_ASSERT_EQUAL_UINT32(96000U, res); | ||
| } | ||
|
|
||
| void setup() | ||
| { | ||
| // Small delay to match other test mains | ||
| delay(10); | ||
| initializeTestEnvironment(); | ||
| UNITY_BEGIN(); | ||
| RUN_TEST(test_router_no_scaling); | ||
| RUN_TEST(test_client_below_threshold); | ||
| RUN_TEST(test_client_default_preset_scaling); | ||
| RUN_TEST(test_client_medium_fast_preset_scaling); | ||
| exit(UNITY_END()); | ||
| } | ||
|
|
||
| void loop() {} |
There was a problem hiding this comment.
The test suite is missing several important test cases:
-
Test with explicitly set bandwidth and spread_factor: When
use_preset = false, both fields should be explicitly set to avoid division by zero and test the actual formula behavior. -
Test for LONG_FAST preset: Should test the default preset (SF11, BW=250kHz) with
use_preset = true. -
Test for edge cases:
- Very high node counts (e.g., 100+ nodes)
- Special bandwidth codes (31, 62, 200, 800, 1600) that map to non-integer kHz values
- Different spread factors (SF7, SF12)
-
Test for SENSOR and TRACKER roles: These roles also don't scale (like ROUTER), according to Default.cpp lines 45-46.
These additional tests would help ensure the formula works correctly across all supported configurations.
There was a problem hiding this comment.
Done it all again. Lets see what it looks like...
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…2 utility function
…getConfiguredOrDefaultMsScaled
|
Looks like the tests need some work: |
|
Better: Processing test_default in coverage environment
--------------------------------------------------------------------------------
Building...
Testing...
Portduino is starting, VFS root at /home/runner/.portduino/default
Running in simulated mode.
DEBUG | ??:??:?? 0 Upgrade time to quality NTP
WARN | 06:58:59 0 RTC not found (found address 0x00)
WARN | 06:58:59 0 RTC not found (found address 0x00)
test/test_default/test_main.cpp:102:test_router_no_scaling:PASS
test/test_default/test_main.cpp:103:test_client_below_threshold:PASS
test/test_default/test_main.cpp:104:test_client_default_preset_scaling:PASS
test/test_default/test_main.cpp:105:test_client_medium_fast_preset_scaling:PASS
-----------------------
4 Tests 0 Failures 0 Ignored
OK
-------------- coverage:test_default [PASSED] Took 14.49 seconds -------------- |
@Jorropo did the thing. Have a look.
🤝 Attestations