From 375804c9e4f309ec7ef11f49086f9f116a1c23d1 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Tue, 3 Mar 2020 13:31:44 -0800 Subject: [PATCH] (needs testing) fixed the following during a plane flight * Have state machine properly enter deep sleep based on loss of mesh and phone comms. * Default to enter deep sleep if no LORA received for two hours (indicates user has probably left the mesh). Signed-off-by: Kevin Hester --- TODO.md | 8 ++++---- docs/sw-design.md | 6 +++--- src/MeshService.cpp | 7 +++++-- src/NodeDB.cpp | 6 +++--- src/PowerFSM.cpp | 23 ++++++++++++++++++----- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/TODO.md b/TODO.md index 73bdd492..6a9c9f7d 100644 --- a/TODO.md +++ b/TODO.md @@ -2,13 +2,11 @@ Items to complete soon (next couple of alpha releases). -* text messages are not showing on local screen if screen was on +* (fixed I think) text messages are not showing on local screen if screen was on -* The following three items are all the same: +* (needs testing) fixed the following during a plane flight: Have state machine properly enter deep sleep based on loss of mesh and phone comms. Default to enter deep sleep if no LORA received for two hours (indicates user has probably left the mesh). - If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs -for it (because it will redownload the nodedb when it comes back) * lower wait_bluetooth_secs to 30 seconds once we have the GPS power on (but GPS in sleep mode) across light sleep. For the time being I have it set at 2 minutes to ensure enough time for a GPS lock from scratch. @@ -43,6 +41,8 @@ Items to complete before the first beta release. During the beta timeframe the following improvements 'would be nice' (and yeah - I guess some of these items count as features, but it is a hobby project ;-) ) +* If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs +for it (because it will redownload the nodedb when it comes back) * Figure out why the RF95 ISR is never seeing RH_RF95_VALID_HEADER, so it is not protecting our rx packets from getting stomped on by sends * fix the frequency error reading in the RF95 RX code (can't do floating point math in an ISR ;-) * See CustomRF95::send and fix the problem of dropping partially received packets if we want to start sending diff --git a/docs/sw-design.md b/docs/sw-design.md index 7d6232c1..dd400e8f 100644 --- a/docs/sw-design.md +++ b/docs/sw-design.md @@ -6,7 +6,7 @@ This is a mini design doc for various core behaviors... From lower to higher power consumption. -* Super-deep-sleep (SDS) - everything is off, CPU, radio, bluetooth, GPS. Only wakes due to timer or button press +* Super-deep-sleep (SDS) - everything is off, CPU, radio, bluetooth, GPS. Only wakes due to timer or button press. We enter this mode only after no radio comms for a few hours, used to put the device into what is effectively "off" mode. onEntry: setBluetoothOn(false), call doDeepSleep onExit: (standard bootup code, starts in DARK) @@ -53,8 +53,8 @@ off during light sleep, but there is a TODO item to fix this. * While in ON: If it has been more than screen_on_secs since a press, lower to DARK * While in DARK: If time since last contact by our phone exceeds phone_timeout_secs (15 minutes), we transition down into NB mode * While in DARK or NB: If nothing above is forcing us to stay in a higher mode (wait_bluetooth_secs, min_wake_secs) we will lower down to LS state -* While in into LS: If either phone_sds_timeout_secs (default 1 hr) or mesh_sds_timeout_secs (default 1 hr) are exceeded we will lower into SDS mode for sds_secs (default 1 hr) (or a button press). -* Any time we enter LS mode: We stay in that mode for ls_secs (default 1 hr) (or until an interrupt, button press) +* While in LS: If either phone_sds_timeout_secs (default 2 hr) or mesh_sds_timeout_secs (default 2 hr) are exceeded we will lower into SDS mode for sds_secs (default 1 yr) (or a button press). +* Any time we enter LS mode: We stay in that until an interrupt, button press or other state transition. Every ls_secs (default 1 hr) and let the arduino loop() run one iteration (FIXME, not sure if we need this at all), and then immediately reenter lightsleep mode on the CPU. TODO: Eventually these scheduled intervals should be synchronized to the GPS clock, so that we can consider leaving the lora receiver off to save even more power. TODO: In NB mode we should put cpu into light sleep any time we really aren't that busy (without declaring LS state) - i.e. we should leave GPS on etc... diff --git a/src/MeshService.cpp b/src/MeshService.cpp index 2b3f0bc4..ef39e8f0 100644 --- a/src/MeshService.cpp +++ b/src/MeshService.cpp @@ -9,6 +9,7 @@ #include "GPS.h" #include "screen.h" #include "Periodic.h" +#include "PowerFSM.h" /* receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone. @@ -144,11 +145,13 @@ void MeshService::handleIncomingPosition(MeshPacket *mp) void MeshService::handleFromRadio(MeshPacket *mp) { + powerFSM.trigger(EVENT_RECEIVED_PACKET); // Possibly keep the node from sleeping + mp->rx_time = gps.getValidTime(); // store the arrival timestamp for the phone // If it is a position packet, perhaps set our clock (if we don't have a GPS of our own, otherwise wait for that to work) - if(!myNodeInfo.has_gps) - handleIncomingPosition(mp); + if (!myNodeInfo.has_gps) + handleIncomingPosition(mp); if (mp->has_payload && mp->payload.which_variant == SubPacket_user_tag) { diff --git a/src/NodeDB.cpp b/src/NodeDB.cpp index 55996a1e..8cf66b0f 100644 --- a/src/NodeDB.cpp +++ b/src/NodeDB.cpp @@ -54,9 +54,9 @@ void NodeDB::init() radioConfig.preferences.position_broadcast_secs = 15 * 60; radioConfig.preferences.wait_bluetooth_secs = 120; radioConfig.preferences.screen_on_secs = 30; - radioConfig.preferences.mesh_sds_timeout_secs = 60 * 60; - radioConfig.preferences.phone_sds_timeout_sec = 60 * 60; - radioConfig.preferences.sds_secs = 60 * 60; + radioConfig.preferences.mesh_sds_timeout_secs = 2 * 60 * 60; + radioConfig.preferences.phone_sds_timeout_sec = 2 * 260 * 60; + radioConfig.preferences.sds_secs = 365 * 24 * 60 * 60; // one year radioConfig.preferences.ls_secs = 60 * 60; radioConfig.preferences.phone_timeout_secs = 15 * 60; diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index e1e1494d..ed7b0d61 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -30,16 +30,17 @@ static void lsEnter() gps.prepareSleep(); // abandon in-process parsing - if(!isUSBPowered) // FIXME - temp hack until we can put gps in sleep mode, if we have AC when we go to sleep then leave GPS on - setGPSPower(false); // kill GPS power + if (!isUSBPowered) // FIXME - temp hack until we can put gps in sleep mode, if we have AC when we go to sleep then leave GPS on + setGPSPower(false); // kill GPS power } static void lsIdle() { uint32_t secsSlept = 0; esp_sleep_source_t wakeCause = ESP_SLEEP_WAKEUP_UNDEFINED; + bool reached_ls_secs = false; - while (secsSlept < radioConfig.preferences.ls_secs) + while (!reached_ls_secs) { // Briefly come out of sleep long enough to blink the led once every few seconds uint32_t sleepTime = 5; @@ -55,11 +56,20 @@ static void lsIdle() break; secsSlept += sleepTime; + reached_ls_secs = secsSlept >= radioConfig.preferences.ls_secs; } setLed(false); - // Regardless of why we woke (for now) just transition to NB (and that state will handle stuff like IRQs etc) - powerFSM.trigger(EVENT_WAKE_TIMER); + if (reached_ls_secs) + { + // stay in LS mode but let loop check whatever it wants + DEBUG_MSG("reached ls_secs, servicing loop()\n"); + } + else + { + // Regardless of why we woke just transition to NB (and that state will handle stuff like IRQs etc) + powerFSM.trigger(EVENT_WAKE_TIMER); + } } static void lsExit() @@ -147,5 +157,8 @@ void PowerFSM_setup() powerFSM.add_timed_transition(&stateDARK, &stateLS, radioConfig.preferences.wait_bluetooth_secs * 1000, NULL, "Bluetooth timeout"); + powerFSM.add_timed_transition(&stateLS, &stateSDS, radioConfig.preferences.mesh_sds_timeout_secs * 1000, NULL, "mesh timeout"); + powerFSM.add_timed_transition(&stateLS, &stateSDS, radioConfig.preferences.phone_sds_timeout_sec * 1000, NULL, "phone timeout"); + powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state } \ No newline at end of file