From 4906b12489dec802f77d6de27a37a823ff8c209d Mon Sep 17 00:00:00 2001 From: geeksville Date: Sun, 23 Feb 2020 08:53:52 -0800 Subject: [PATCH] prevent ble powerdown while phone is connected --- TODO.md | 4 +++- docs/sw-design.md | 1 + src/MeshBluetoothService.cpp | 35 ++++++++++++++++++++++++++++++----- src/PowerFSM.cpp | 12 ++---------- src/PowerFSM.h | 1 + src/configuration.h | 4 ++-- 6 files changed, 39 insertions(+), 18 deletions(-) diff --git a/TODO.md b/TODO.md index 65c12c410..e64665f01 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,8 @@ Items to complete before the first alpha release. -* don't enter NB state if we've recently talked to the phone (to prevent breaking syncing or bluetooth sw update) +* fix BLE wake so that we still are announcing +* have sw update prevent BLE sleep * 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 meshS) * implement CustomRF95::canSleep @@ -163,3 +164,4 @@ Items after the first final candidate release. * scrolling between screens based on press is busted * Use Neo-M8M API to put it in sleep mode (on hold until my new boards arrive) * update the prebuilt bins for different regulatory regions +* don't enter NB state if we've recently talked to the phone (to prevent breaking syncing or bluetooth sw update) diff --git a/docs/sw-design.md b/docs/sw-design.md index 56be154fe..7d6232c13 100644 --- a/docs/sw-design.md +++ b/docs/sw-design.md @@ -45,6 +45,7 @@ off during light sleep, but there is a TODO item to fix this. * While in NB: If we do have packets the phone (EVENT_PACKETS_FOR_PHONE) would want we transition to DARK mode for wait_bluetooth secs. * While in DARK/ON: If we receive EVENT_BLUETOOTH_PAIR we transition to ON and start our screen_on_secs timeout * While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown) +* While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts) ### events that decrease cpu activity diff --git a/src/MeshBluetoothService.cpp b/src/MeshBluetoothService.cpp index d6722e12f..a97692f1a 100644 --- a/src/MeshBluetoothService.cpp +++ b/src/MeshBluetoothService.cpp @@ -10,11 +10,29 @@ #include "mesh-pb-constants.h" #include "NodeDB.h" #include "configuration.h" +#include "PowerFSM.h" // This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in proccess at once static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)]; -class ProtobufCharacteristic : public BLECharacteristic, public BLECharacteristicCallbacks +/** + * This mixin just lets the power management state machine know the phone is still talking to us + */ +class BLEKeepAliveCallbacks : public BLECharacteristicCallbacks +{ +public: + void onRead(BLECharacteristic *c) + { + powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); + } + + void onWrite(BLECharacteristic *c) + { + powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); + } +}; + +class ProtobufCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks { const pb_msgdesc_t *fields; void *my_struct; @@ -30,6 +48,7 @@ public: void onRead(BLECharacteristic *c) { + BLEKeepAliveCallbacks::onRead(c); DEBUG_MSG("Got proto read\n"); size_t numbytes = pb_encode_to_bytes(trBytes, sizeof(trBytes), fields, my_struct); c->setValue(trBytes, numbytes); @@ -37,6 +56,7 @@ public: void onWrite(BLECharacteristic *c) { + BLEKeepAliveCallbacks::onWrite(c); writeToDest(c, my_struct); } @@ -53,7 +73,7 @@ protected: } }; -class NodeInfoCharacteristic : public BLECharacteristic, public BLECharacteristicCallbacks +class NodeInfoCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks { public: NodeInfoCharacteristic() @@ -64,6 +84,8 @@ public: void onRead(BLECharacteristic *c) { + BLEKeepAliveCallbacks::onRead(c); + const NodeInfo *info = nodeDB.readNextInfo(); if (info) @@ -81,7 +103,7 @@ public: void onWrite(BLECharacteristic *c) { - // dumpCharacteristic(pCharacteristic); + BLEKeepAliveCallbacks::onWrite(c); DEBUG_MSG("Got on nodeinfo write\n"); nodeDB.resetReadPointer(); } @@ -114,6 +136,8 @@ public: void onWrite(BLECharacteristic *c) { + BLEKeepAliveCallbacks::onWrite(c); // NOTE: We do not call the standard ProtobufCharacteristic superclass, because we want custom write behavior + static User o; // if the phone doesn't set ID we are careful to keep ours, we also always keep our macaddr if (writeToDest(c, &o)) { @@ -163,10 +187,11 @@ void bluetoothNotifyFromNum(uint32_t newValue) meshFromNumCharacteristic.notify(); } -class BluetoothMeshCallbacks : public BLECharacteristicCallbacks +class BluetoothMeshCallbacks : public BLEKeepAliveCallbacks { void onRead(BLECharacteristic *c) { + BLEKeepAliveCallbacks::onRead(c); DEBUG_MSG("Got on read\n"); if (c == &meshFromRadioCharacteristic) @@ -205,7 +230,7 @@ class BluetoothMeshCallbacks : public BLECharacteristicCallbacks void onWrite(BLECharacteristic *c) { - // dumpCharacteristic(pCharacteristic); + BLEKeepAliveCallbacks::onWrite(c); DEBUG_MSG("Got on write\n"); if (c == &meshToRadioCharacteristic) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 686da8766..52bf99935 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -24,16 +24,6 @@ static void sdsEnter() static void lsEnter() { - /* - // while we have bluetooth on, we can't do light sleep, but once off stay in light_sleep all the time - // we will wake from light sleep on button press or interrupt from the RF95 radio - if (!bluetoothOn && !is_screen_on() && service.radio.rf95.canSleep() && gps.canSleep()) - doLightSleep(radioConfig.preferences.ls_secs); - else - { - delay(msecstosleep); - } */ - while (!service.radio.rf95.canSleep()) delay(10); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives) @@ -141,6 +131,8 @@ void PowerFSM_setup() powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); + powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone"); + powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone"); powerFSM.add_timed_transition(&stateON, &stateDARK, radioConfig.preferences.screen_on_secs * 1000, NULL, "Screen-on timeout"); diff --git a/src/PowerFSM.h b/src/PowerFSM.h index 5627ff920..ea1e589dd 100644 --- a/src/PowerFSM.h +++ b/src/PowerFSM.h @@ -12,6 +12,7 @@ #define EVENT_BOOT 6 #define EVENT_BLUETOOTH_PAIR 7 #define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen +#define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth extern Fsm powerFSM; diff --git a/src/configuration.h b/src/configuration.h index 99cef5244..9c967f353 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -43,8 +43,8 @@ along with this program. If not, see . // Select which board is being used. If the outside build environment has sent a choice, just use that #if !defined(T_BEAM_V10) && !defined(HELTEC_LORA32) -#define T_BEAM_V10 // AKA Rev1 (second board released) -// #define HELTEC_LORA32 +//#define T_BEAM_V10 // AKA Rev1 (second board released) +#define HELTEC_LORA32 #define HW_VERSION_US // We encode the hardware freq range in the hw version string, so sw update can eventually install the correct build #endif