Files
firmware/src/modules/Telemetry/BaseTelemetryModule.h
T
Thomas Göttgens 38074f584f Fix SENSOR power saving deep sleep truncating TX and skipping sleep on failed reads (#10939)
* Fix SENSOR power saving deep sleep behavior

Deep sleep could be entered while a telemetry packet was still queued
or on air, truncating the transmission. canSleep() gained a deepSleep
parameter and now vetoes in that case; light sleep is unchanged.
Telemetry modules defer a pending deep sleep (bounded to 30s) until the
radio is idle and no longer let the sensor polling interval override
the 5s pre-sleep grace period. A failed sensor read still arms deep
sleep instead of leaving the node awake for a full telemetry interval.

Fixes #10890
Fixes #10932

* Deduplicate telemetry deep sleep deferral logic

Move the radio-busy deferral and its counter into BaseTelemetryModule
and add an isPowerSavingSensor() helper. Removes the telemetry-specific
counter from OSThread. The sleep arming block stays per module because
it needs protected OSThread members not visible to the base class.
2026-07-08 07:30:46 -05:00

46 lines
1.7 KiB
C++

#pragma once
#include "DebugConfiguration.h"
#include "NodeDB.h"
#include "configuration.h"
#include "sleep.h"
class BaseTelemetryModule
{
protected:
bool isSensorOrRouterRole() const
{
return config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE;
}
/// True for a SENSOR role node with power saving enabled, the only combination that deep
/// sleeps between telemetry broadcasts
bool isPowerSavingSensor() const
{
return config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving;
}
/**
* Call while a deep sleep is pending (sleepOnNextExecution): the telemetry packet queued by
* sendTelemetry() goes out asynchronously, and sleeping while it is still queued or on air
* truncates the transmission. Returns true if the caller should reschedule in
* PREFLIGHT_SLEEP_RETRY_MS and check again. Bounded by MAX_PREFLIGHT_SLEEP_DEFERRALS so a
* busy mesh can't keep the node awake forever. Reset preflightSleepDeferrals to 0 whenever
* sleepOnNextExecution is armed.
*/
bool shouldDeferDeepSleep()
{
if (doPreflightSleep(true) || preflightSleepDeferrals >= MAX_PREFLIGHT_SLEEP_DEFERRALS)
return false;
preflightSleepDeferrals++;
LOG_DEBUG("Radio busy, defer deep sleep");
return true;
}
// While sleepOnNextExecution is pending, counts how often the deep sleep was postponed
// because doPreflightSleep() vetoed it (e.g. radio still transmitting)
uint32_t preflightSleepDeferrals = 0;
};