diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 241f2cd10..daa18e6af 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -52,7 +52,7 @@ jobs: node-version: 24 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v5 with: version: latest diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 91cf49b2b..479a0ae04 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,8 +8,8 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - checkov@3.2.508 - - renovate@43.76.3 + - checkov@3.2.510 + - renovate@43.78.0 - prettier@3.8.1 - trufflehog@3.93.8 - yamllint@1.38.0 diff --git a/platformio.ini b/platformio.ini index db3782390..f9add198b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -126,7 +126,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/622b034d8791153de9d16a473723cb8625d35839.zip + https://github.com/meshtastic/device-ui/archive/f36d2a953524e372b78c5b4147ec55f38716964e.zip ; Common libs for environmental measurements in telemetry module [environmental_base] diff --git a/src/mesh/Default.h b/src/mesh/Default.h index f4633790e..069ffc0eb 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -13,12 +13,12 @@ #define TEN_SECONDS_MS 10 * 1000 #define MAX_INTERVAL INT32_MAX // FIXME: INT32_MAX to avoid overflow issues with Apple clients but should be UINT32_MAX -#define min_default_telemetry_interval_secs 30 * 60 +#define min_default_telemetry_interval_secs IF_ROUTER(ONE_DAY / 2, 30 * 60) #define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60) #define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60) #define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60) #define default_broadcast_smart_minimum_interval_secs 5 * 60 -#define min_default_broadcast_interval_secs 60 * 60 +#define min_default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60) #define min_default_broadcast_smart_minimum_interval_secs 5 * 60 #define default_wait_bluetooth_secs IF_ROUTER(1, 60) #define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 428a64fcf..38998af83 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -322,9 +322,9 @@ NodeDB::NodeDB() // config.network.enabled_protocols = meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST; // If we are setup to broadcast on any default channel slot (with default frequency slot semantics), - // ensure that the telemetry intervals are coerced to the minimum value of 30 minutes or more. + // ensure that the telemetry intervals are coerced to the role-aware minimum value. if (channels.hasDefaultChannel()) { - LOG_DEBUG("Coerce telemetry to min of 30 minutes on defaults"); + LOG_DEBUG("Coerce telemetry to role-aware minimum on defaults"); moduleConfig.telemetry.device_update_interval = Default::getConfiguredOrMinimumValue( moduleConfig.telemetry.device_update_interval, min_default_telemetry_interval_secs); moduleConfig.telemetry.environment_update_interval = Default::getConfiguredOrMinimumValue( @@ -347,7 +347,7 @@ NodeDB::NodeDB() } } if (positionUsesDefaultChannel) { - LOG_DEBUG("Coerce position broadcasts to min of 1 hour and smart broadcast min of 5 minutes on defaults"); + LOG_DEBUG("Coerce position broadcasts to role-aware minimum and smart broadcast min of 5 minutes on defaults"); config.position.position_broadcast_secs = Default::getConfiguredOrMinimumValue(config.position.position_broadcast_secs, min_default_broadcast_interval_secs); config.position.broadcast_smart_minimum_interval_secs = Default::getConfiguredOrMinimumValue( diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index 79bda557c..f41fafdee 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -30,7 +30,8 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes auto p = *pptr; - if (mp.decoded.want_response) { + // Suppress replies to senders we've replied to recently (12H window) + if (mp.decoded.want_response && !isFromUs(&mp)) { const NodeNum sender = getFrom(&mp); const uint32_t now = mp.rx_time ? mp.rx_time : getTime(); auto it = lastNodeInfoSeen.find(sender); @@ -119,7 +120,13 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha meshtastic_MeshPacket *NodeInfoModule::allocReply() { - if (suppressReplyForCurrentRequest) { + // Only apply suppression when actually replying to someone else's request, not for periodic broadcasts. + const bool isReplyingToExternalRequest = currentRequest && + currentRequest->which_payload_variant == meshtastic_MeshPacket_decoded_tag && + currentRequest->decoded.portnum == meshtastic_PortNum_NODEINFO_APP && + currentRequest->decoded.want_response && !isFromUs(currentRequest); + + if (suppressReplyForCurrentRequest && isReplyingToExternalRequest) { LOG_DEBUG("Skip send NodeInfo since we heard the requester <12h ago"); ignoreRequest = true; suppressReplyForCurrentRequest = false; diff --git a/test/test_default/test_main.cpp b/test/test_default/test_main.cpp index d832fc809..9da367897 100644 --- a/test/test_default/test_main.cpp +++ b/test/test_default/test_main.cpp @@ -10,8 +10,9 @@ static uint32_t computeExpectedMs(uint32_t defaultSeconds, uint32_t numOnlineNod { uint32_t baseMs = Default::getConfiguredOrDefaultMs(0, defaultSeconds); - // Routers don't scale - if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) { + // Routers (including ROUTER_LATE) don't scale + if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER || + config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) { return baseMs; } @@ -93,6 +94,39 @@ void test_client_medium_fast_preset_scaling() TEST_ASSERT_INT_WITHIN(1, expected, res); } +void test_router_uses_router_minimums() +{ + config.device.role = meshtastic_Config_DeviceConfig_Role_ROUTER; + + uint32_t telemetry = Default::getConfiguredOrMinimumValue(60, min_default_telemetry_interval_secs); + uint32_t position = Default::getConfiguredOrMinimumValue(60, min_default_broadcast_interval_secs); + + TEST_ASSERT_EQUAL_UINT32(ONE_DAY / 2, telemetry); + TEST_ASSERT_EQUAL_UINT32(ONE_DAY / 2, position); +} + +void test_router_late_uses_router_minimums() +{ + config.device.role = meshtastic_Config_DeviceConfig_Role_ROUTER_LATE; + + uint32_t telemetry = Default::getConfiguredOrMinimumValue(60, min_default_telemetry_interval_secs); + uint32_t position = Default::getConfiguredOrMinimumValue(60, min_default_broadcast_interval_secs); + + TEST_ASSERT_EQUAL_UINT32(ONE_DAY / 2, telemetry); + TEST_ASSERT_EQUAL_UINT32(ONE_DAY / 2, position); +} + +void test_client_uses_public_channel_minimums() +{ + config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; + + uint32_t telemetry = Default::getConfiguredOrMinimumValue(60, min_default_telemetry_interval_secs); + uint32_t position = Default::getConfiguredOrMinimumValue(60, min_default_broadcast_interval_secs); + + TEST_ASSERT_EQUAL_UINT32(30 * 60, telemetry); + TEST_ASSERT_EQUAL_UINT32(60 * 60, position); +} + void setup() { // Small delay to match other test mains @@ -103,6 +137,9 @@ void setup() RUN_TEST(test_client_below_threshold); RUN_TEST(test_client_default_preset_scaling); RUN_TEST(test_client_medium_fast_preset_scaling); + RUN_TEST(test_router_uses_router_minimums); + RUN_TEST(test_router_late_uses_router_minimums); + RUN_TEST(test_client_uses_public_channel_minimums); exit(UNITY_END()); } diff --git a/variants/esp32s3/heltec_v4/platformio.ini b/variants/esp32s3/heltec_v4/platformio.ini index 8d9921d6a..9acf30c21 100644 --- a/variants/esp32s3/heltec_v4/platformio.ini +++ b/variants/esp32s3/heltec_v4/platformio.ini @@ -68,7 +68,7 @@ build_flags = -D INPUTDRIVER_BUTTON_TYPE=0 -D HAS_SCREEN=1 -D HAS_TFT=1 - -D RAM_SIZE=1560 + -D RAM_SIZE=1860 -D LV_LVGL_H_INCLUDE_SIMPLE -D LV_CONF_INCLUDE_SIMPLE -D LV_COMP_CONF_INCLUDE_SIMPLE @@ -83,9 +83,9 @@ build_flags = -D USE_PACKET_API -D LGFX_DRIVER=LGFX_HELTEC_V4_TFT -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_HELTEC_V4_TFT.h\" - -D VIEW_320x240 - -D MAP_FULL_REDRAW - -D DISPLAY_SIZE=320x240 ; landscape mode + -D VIEW_240x320 + -D DISPLAY_SET_RESOLUTION + -D DISPLAY_SIZE=240x320 ; portrait mode -D LGFX_PIN_SCK=17 -D LGFX_PIN_MOSI=33 -D LGFX_PIN_DC=16