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.
This commit is contained in:
11 files changed
+162
-48
No files matched your search
@@ -253,6 +253,8 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
|
||||
int32_t EnvironmentTelemetryModule::runOnce()
|
||||
{
|
||||
if (sleepOnNextExecution == true) {
|
||||
if (shouldDeferDeepSleep())
|
||||
return PREFLIGHT_SLEEP_RETRY_MS;
|
||||
sleepOnNextExecution = false;
|
||||
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval,
|
||||
default_telemetry_broadcast_interval_secs);
|
||||
@@ -334,6 +336,12 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
lastSentToPhone = millis();
|
||||
}
|
||||
}
|
||||
if (sleepOnNextExecution) {
|
||||
// Honor the pre-sleep grace period armed in sendTelemetry(): OSThread reschedules with
|
||||
// this return value, which would otherwise override setIntervalFromNow() with the sensor
|
||||
// polling interval (35 ms for BSEC2) and trigger deep sleep while the TX is still on air
|
||||
return FIVE_SECONDS_MS;
|
||||
}
|
||||
return min(sendToPhoneIntervalMs, result);
|
||||
}
|
||||
|
||||
@@ -635,7 +643,8 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
m.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
m.time = getTime();
|
||||
|
||||
if (getEnvironmentTelemetry(&m)) {
|
||||
bool validTelemetry = getEnvironmentTelemetry(&m);
|
||||
if (validTelemetry) {
|
||||
LOG_INFO("Send: barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f",
|
||||
m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current,
|
||||
m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity,
|
||||
@@ -670,7 +679,7 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
LOG_INFO("Send packet to mesh");
|
||||
service->sendToMesh(p, RX_SRC_LOCAL, true);
|
||||
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) {
|
||||
if (isPowerSavingSensor()) {
|
||||
meshtastic_ClientNotification *notification = clientNotificationPool.allocZeroed();
|
||||
notification->level = meshtastic_LogRecord_Level_INFO;
|
||||
notification->time = getValidTime(RTCQualityFromNet);
|
||||
@@ -679,14 +688,22 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
default_telemetry_broadcast_interval_secs) /
|
||||
1000U);
|
||||
service->sendClientNotification(notification);
|
||||
sleepOnNextExecution = true;
|
||||
LOG_DEBUG("Start next execution in 5s, then sleep");
|
||||
setIntervalFromNow(FIVE_SECONDS_MS);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
// Arm the pre-sleep sequence even when no valid reading was available this cycle (e.g. a
|
||||
// BSEC2 call timing violation): a power-saving SENSOR node must still return to deep sleep,
|
||||
// otherwise it stays awake until the next telemetry interval and drains its battery
|
||||
if (!phoneOnly && isPowerSavingSensor()) {
|
||||
if (!validTelemetry)
|
||||
LOG_WARN("Environment telemetry unavailable this cycle, sleep without sending");
|
||||
sleepOnNextExecution = true;
|
||||
preflightSleepDeferrals = 0;
|
||||
LOG_DEBUG("Start next execution in 5s, then sleep");
|
||||
setIntervalFromNow(FIVE_SECONDS_MS);
|
||||
}
|
||||
return validTelemetry;
|
||||
}
|
||||
|
||||
AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
|
||||
|
||||
Reference in New Issue
Block a user