Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/mesh/Default.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
#define default_broadcast_smart_minimum_interval_secs 5 * 60
// Floor for our own position broadcasts when stationary (unchanged beyond the broadcast
// precision) or fixed_position: identical positions get deduped by traffic management anyway.
#define default_position_stationary_broadcast_secs (12 * 60 * 60)
// Held one hour above default_traffic_mgmt_position_min_interval_secs so this refresh clears
// the receivers' dedup window instead of being dropped as a duplicate.
#define default_position_stationary_broadcast_secs (6 * 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)
Expand All @@ -39,9 +41,11 @@
enum class TrafficType { POSITION, TELEMETRY };

// Traffic management defaults
#define default_traffic_mgmt_position_precision_bits 19 // ~90m grid cells (±45m)
#define default_traffic_mgmt_position_min_interval_secs (11 * 60 * 60) // 11 hours between identical positions
// Role cap: tracker-role origins may refresh a duplicate position this often (vs the 11h default).
#define default_traffic_mgmt_position_precision_bits 19 // ~90m grid cells (±45m)
// Kept below default_position_stationary_broadcast_secs so a stationary node's periodic refresh
// is not deduped away by its neighbours.
#define default_traffic_mgmt_position_min_interval_secs (5 * 60 * 60) // 5 hours between identical positions
// Role cap: tracker-role origins may refresh a duplicate position this often (vs the 5h default).
#define default_traffic_mgmt_tracker_position_min_interval_secs (60 * 60) // 1 hour
// Role cap: lost-and-found origins may refresh a duplicate position this often, so a lost
// device updates frequently without flooding. (Quantised to the dedup tick: ~2 ticks.)
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/NodeDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,7 @@ static void installTrafficManagementDefaults(meshtastic_LocalModuleConfig &mc)
mc.has_traffic_management = true;
mc.traffic_management = meshtastic_ModuleConfig_TrafficManagementConfig_init_zero;
#if HAS_TRAFFIC_MANAGEMENT
// Position dedup ships enabled at the 11-hour default window on all supported targets.
// Position dedup ships enabled at the 5-hour default window on all supported targets.
// STM32WL is excluded at compile time (HAS_TRAFFIC_MANAGEMENT=0 in mesh-pb-constants.h).
// Set position_min_interval_secs=0 at runtime to disable dedup.
mc.traffic_management.position_min_interval_secs = default_traffic_mgmt_position_min_interval_secs;
Expand Down
2 changes: 1 addition & 1 deletion src/modules/PositionModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ int32_t PositionModule::runOnce()

bool waitingForFreshPosition = (lastGpsSend == 0) && !config.position.fixed_position && !nodeDB->hasLocalPositionSinceBoot();

// Hold to the 12h floor when fixed_position (every role: pinning yourself forfeits the
// Hold to the 6h floor when fixed_position (every role: pinning yourself forfeits the
// exception) or when stationary. A real move still goes out early via smart-broadcast below.
// Not-fixed exceptions: lost-and-found broadcasts freely; trackers judge movement at their
// own (unclamped) precision rather than the on-wire one (useConfiguredPrecision).
Expand Down
2 changes: 1 addition & 1 deletion src/modules/TrafficManagementModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ bool TrafficManagementModule::shouldDropPosition(const meshtastic_MeshPacket *p,
const int32_t lat_truncated = truncateCoordinate(pos->latitude_i, precision);
const int32_t lon_truncated = truncateCoordinate(pos->longitude_i, precision);
const uint8_t fingerprint = computePositionFingerprint(lat_truncated, lon_truncated, precision);
// Drop gate uses the RAW configured interval: 0 means "dedup disabled". The 12 h default
// Drop gate uses the RAW configured interval: 0 means "dedup disabled". The 5 h default
// is only for TTL sizing - feeding it here would silently defeat that contract.
uint32_t minIntervalMs = secsToMs(moduleConfig.traffic_management.position_min_interval_secs);

Expand Down
18 changes: 9 additions & 9 deletions test/test_traffic_management/test_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2806,12 +2806,12 @@ static void test_tm_nextHop_keptAliveAcrossMaintenanceSweep(void)

/**
* Verify TRACKER role caps the dedup window at 1 hour.
* A duplicate position that would normally be blocked for 11 h (default) must
* A duplicate position that would normally be blocked for 5 h (default) must
* be forwarded once the 1-hour tracker cap expires.
*/
static void test_tm_trackerRole_capsDedupWindowAtOneHour(void)
{
// Operator interval is 11 h - longer than the tracker cap.
// Operator interval is 5 h - longer than the tracker cap.
moduleConfig.traffic_management.position_min_interval_secs = default_traffic_mgmt_position_min_interval_secs;
installWellKnownPrimaryChannelWithPrecision(16);

Expand Down Expand Up @@ -2872,11 +2872,11 @@ static void test_tm_takTrackerRole_capsDedupWindowAtOneHour(void)
* hot and warm NodeDB stores - the TMM unified cache is the third fallback. The
* role is cached on the entry while NodeDB still knows the node; once NodeDB
* forgets it (getNodeRole → CLIENT), the cached role must keep the 1-hour cap
* applied instead of reverting to the 11-hour default interval.
* applied instead of reverting to the 5-hour default interval.
*/
static void test_tm_trackerRole_survivesNodeDbEvictionViaCachedRole(void)
{
// Operator interval is 11 h - longer than the tracker cap.
// Operator interval is 5 h - longer than the tracker cap.
moduleConfig.traffic_management.position_min_interval_secs = default_traffic_mgmt_position_min_interval_secs;
installWellKnownPrimaryChannelWithPrecision(16);

Expand All @@ -2896,8 +2896,8 @@ static void test_tm_trackerRole_survivesNodeDbEvictionViaCachedRole(void)
mockNodeDB->clearCachedNode();

ProcessMessage r2 = module.handleReceived(dup); // within 1-hour cap - still drop
// Advance past the tracker cap (3600 s) but stay well under the 11-hour default.
// Without the cached-role fallback this would still be inside the 11-hour window
// Advance past the tracker cap (3600 s) but stay well under the 5-hour default.
// Without the cached-role fallback this would still be inside the 5-hour window
// (CLIENT → no exception) and wrongly drop; with it, the 1-hour cap lets it pass.
TrafficManagementModule::s_testNowMs += (default_traffic_mgmt_tracker_position_min_interval_secs * 1000UL) + 1;
ProcessMessage r3 = module.handleReceived(afterCap);
Expand Down Expand Up @@ -2935,7 +2935,7 @@ static void test_tm_roleChange_viaNodeInfo_dropsTrackerException(void)
meshtastic_MeshPacket info = makeNodeInfoPacketWithRole(kRemoteNode, meshtastic_Config_DeviceConfig_Role_CLIENT);
module.handleReceived(info);

// Past the 1-hour tracker cap but within the 11-hour CLIENT interval. With the stale
// Past the 1-hour tracker cap but within the 5-hour CLIENT interval. With the stale
// TRACKER role this would pass; after the demotion it must drop (full interval applies).
TrafficManagementModule::s_testNowMs += (default_traffic_mgmt_tracker_position_min_interval_secs * 1000UL) + 1;
meshtastic_MeshPacket afterCap = makePositionPacket(kRemoteNode, 374221234, -1220845678);
Expand Down Expand Up @@ -3042,12 +3042,12 @@ static void test_tm_trackerRole_doesNotLengthenShorterOperatorInterval(void)

/**
* Verify LOST_AND_FOUND role caps duplicate-position dedup at ~15 min (2 pos-ticks),
* not the old one-tick fast-announce. A configured 11-hour interval is shortened to the
* not the old one-tick fast-announce. A configured 5-hour interval is shortened to the
* 15-min cap; a duplicate one tick later still drops, but one past the 2-tick cap passes.
*/
static void test_tm_lostAndFoundRole_capsDedupAtFifteenMinutes(void)
{
// Long interval that would normally suppress duplicates for 11 h.
// Long interval that would normally suppress duplicates for 5 h.
moduleConfig.traffic_management.position_min_interval_secs = default_traffic_mgmt_position_min_interval_secs;
installWellKnownPrimaryChannelWithPrecision(16);

Expand Down
Loading