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:
co-authored by
GitHub
parent
ba473bf529
commit
38074f584f
@@ -141,8 +141,12 @@ class RadioInterface
|
||||
* Return true if we think the board can go to sleep (i.e. our tx queue is empty, we are not sending or receiving)
|
||||
*
|
||||
* This method must be used before putting the CPU into deep or light sleep.
|
||||
*
|
||||
* @param deepSleep true when the radio itself is about to be powered down (deep sleep or
|
||||
* shutdown) - an in-flight transmission then vetoes sleep, since it would be truncated on
|
||||
* air. false for a light sleep where the radio stays powered and finishes the TX on its own.
|
||||
*/
|
||||
virtual bool canSleep() { return true; }
|
||||
virtual bool canSleep(bool deepSleep = false) { return true; }
|
||||
|
||||
virtual bool wideLora() { return false; }
|
||||
|
||||
@@ -314,8 +318,9 @@ class RadioInterface
|
||||
*/
|
||||
void applyModemConfig();
|
||||
|
||||
/// Return 0 if sleep is okay
|
||||
int preflightSleepCb(void *unused = NULL) { return canSleep() ? 0 : 1; }
|
||||
/// Return 0 if sleep is okay. A non-NULL argument means the radio is about to be powered
|
||||
/// down (deep sleep / shutdown), see doPreflightSleep()
|
||||
int preflightSleepCb(void *deepSleep = NULL) { return canSleep(deepSleep != NULL) ? 0 : 1; }
|
||||
|
||||
int notifyDeepSleepCb(void *unused = NULL);
|
||||
|
||||
|
||||
@@ -222,11 +222,15 @@ meshtastic_QueueStatus RadioLibInterface::getQueueStatus()
|
||||
return qs;
|
||||
}
|
||||
|
||||
bool RadioLibInterface::canSleep()
|
||||
bool RadioLibInterface::canSleep(bool deepSleep)
|
||||
{
|
||||
bool res = txQueue.empty();
|
||||
// A packet being actively transmitted has already left the TX queue (sendingPacket), so
|
||||
// check it separately. It only vetoes deep sleep: light sleep keeps the radio powered and
|
||||
// the TX finishes on its own, but deep sleep powers the radio down and would truncate the
|
||||
// packet on air.
|
||||
bool res = txQueue.empty() && !(deepSleep && isSending());
|
||||
if (!res) { // only print debug messages if we are vetoing sleep
|
||||
LOG_DEBUG("Radio wait to sleep, txEmpty=%d", res);
|
||||
LOG_DEBUG("Radio wait to sleep, txEmpty=%d, txInFlight=%d", txQueue.empty(), isSending());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -180,8 +180,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
* Return true if we think the board can go to sleep (i.e. our tx queue is empty, we are not sending or receiving)
|
||||
*
|
||||
* This method must be used before putting the CPU into deep or light sleep.
|
||||
* With deepSleep set, an in-flight transmission also vetoes sleep (see RadioInterface).
|
||||
*/
|
||||
virtual bool canSleep() override;
|
||||
virtual bool canSleep(bool deepSleep) override;
|
||||
|
||||
/**
|
||||
* Start waiting to receive a message
|
||||
|
||||
Reference in New Issue
Block a user