From b32e91317ffa8e27beac52a32aec1d812a1c63b5 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 11 Dec 2020 16:34:17 +0100 Subject: [PATCH] deep sleep further development --- include/globals.h | 3 +- include/rcommand.h | 4 ++- src/blecsan.cpp | 15 ++++++++-- src/display.cpp | 1 - src/main.cpp | 11 +++---- src/rcommand.cpp | 18 ++++++++---- src/reset.cpp | 71 +++++++++++++++++++++++++--------------------- src/wifiscan.cpp | 18 ++++++------ 8 files changed, 83 insertions(+), 58 deletions(-) diff --git a/include/globals.h b/include/globals.h index 947066c8..89b9ecca 100644 --- a/include/globals.h +++ b/include/globals.h @@ -64,7 +64,8 @@ enum runmode_t { RUNMODE_POWERCYCLE, RUNMODE_NORMAL, RUNMODE_WAKEUP, - RUNMODE_UPDATE + RUNMODE_UPDATE, + RUNMODE_SLEEP }; // Struct holding devices's runtime configuration diff --git a/include/rcommand.h b/include/rcommand.h index 488b7005..c26bce84 100644 --- a/include/rcommand.h +++ b/include/rcommand.h @@ -18,11 +18,13 @@ // table of remote commands and assigned functions typedef struct { const uint8_t opcode; - void (*func)(uint8_t []); + void (*func)(uint8_t[]); const uint8_t params; const bool store; } cmd_t; +extern bool rcmd_busy; + void rcommand(const uint8_t cmd[], const uint8_t cmdlength); void do_reset(bool warmstart); diff --git a/src/blecsan.cpp b/src/blecsan.cpp index b06e78a0..f39a2e58 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -254,8 +254,11 @@ void start_BLEscan(void) { // Initialize BT controller to allocate task and other resource. ESP_ERROR_CHECK(esp_coex_preference_set(ESP_COEX_PREFER_BT)); + if (!btStart()) { // enable bt_controller + ESP_LOGE(TAG, "Bluetooth controller start failed. Resetting device"); + do_reset(true); + } - btStart(); ESP_ERROR_CHECK(esp_bluedroid_init()); ESP_ERROR_CHECK(esp_bluedroid_enable()); @@ -269,10 +272,18 @@ void start_BLEscan(void) { void stop_BLEscan(void) { #if (BLECOUNTER) ESP_LOGI(TAG, "Shutting down bluetooth scanner ..."); + + ESP_LOGD(TAG, "unregister GAP callback..."); ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); + ESP_LOGD(TAG, "bluedroid disable..."); ESP_ERROR_CHECK(esp_bluedroid_disable()); + ESP_LOGD(TAG, "bluedroid deinit..."); ESP_ERROR_CHECK(esp_bluedroid_deinit()); - btStop(); // disable bt_controller + + if (!btStop()) { // disable bt_controller + ESP_LOGE(TAG, "Bluetooth controller stop failed. Resetting device"); + do_reset(true); + } ESP_ERROR_CHECK(esp_coex_preference_set(ESP_COEX_PREFER_WIFI)); ESP_LOGI(TAG, "Bluetooth scanner stopped"); #endif // BLECOUNTER diff --git a/src/display.cpp b/src/display.cpp index 43be8d80..4ccb1b7e 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -603,7 +603,6 @@ void dp_shutdown(void) { if (!I2C_MUTEX_LOCK()) ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds()); else { - cfg.screenon = 0; obdPower(&ssoled, false); delay(DISPLAYREFRESH_MS / 1000 * 1.1); I2C_MUTEX_UNLOCK(); // release i2c bus access diff --git a/src/main.cpp b/src/main.cpp index ffaa544c..6bba631a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -292,7 +292,7 @@ void setup() { macQueueInit(); // start BLE scan callback if BLE function is enabled in NVRAM configuration -// or switch off bluetooth, if not compiled +// or remove bluetooth stack from RAM, if option bluetooth is not compiled #if (BLECOUNTER) strcat_P(features, " BLE"); if (cfg.blescan) { @@ -412,16 +412,17 @@ void setup() { #if (WIFICOUNTER) strcat_P(features, " WIFI"); - // start wifi in monitor mode and start channel rotation timer - + // install wifi driver in RAM and start channel hopping wifi_sniffer_init(); - if (cfg.blescan) { + + // start wifi sniffing, if enabled + if (cfg.wifiscan) { ESP_LOGI(TAG, "Starting Wifi..."); switch_wifi_sniffer(1); } else switch_wifi_sniffer(0); #else - // switch off wifi + // remove wifi driver from RAM, if option wifi not compiled esp_wifi_deinit(); #endif diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 791346e2..c18db679 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -5,6 +5,9 @@ // Local logging tag static const char TAG[] = __FILE__; +// global variable indicating if rcommand() is executing +bool rcmd_busy = false; + // set of functions that can be triggered by remote commands void set_reset(uint8_t val[]) { switch (val[0]) { @@ -65,14 +68,15 @@ void set_wifichancycle(uint8_t val[]) { // update Wifi channel rotation timer period if (cfg.wifichancycle > 0) { if (xTimerIsTimerActive(WifiChanTimer) == pdFALSE) - xTimerStart(WifiChanTimer, (TickType_t) 0); + xTimerStart(WifiChanTimer, (TickType_t)0); xTimerChangePeriod(WifiChanTimer, pdMS_TO_TICKS(cfg.wifichancycle * 10), 100); - ESP_LOGI(TAG, - "Remote command: set Wifi channel hopping interval to %.1f seconds", - cfg.wifichancycle / float(100)); + ESP_LOGI( + TAG, + "Remote command: set Wifi channel hopping interval to %.1f seconds", + cfg.wifichancycle / float(100)); } else { - xTimerStop(WifiChanTimer, (TickType_t) 0); + xTimerStop(WifiChanTimer, (TickType_t)0); esp_wifi_set_channel(WIFI_CHANNEL_MIN, WIFI_SECOND_CHAN_NONE); channel = WIFI_CHANNEL_MIN; ESP_LOGI(TAG, "Remote command: set Wifi channel hopping to off"); @@ -397,6 +401,7 @@ void rcommand(const uint8_t cmd[], const uint8_t cmdlength) { uint8_t foundcmd[cmdlength], cursor = 0; bool storeflag = false; + rcmd_busy = true; while (cursor < cmdlength) { @@ -428,4 +433,7 @@ void rcommand(const uint8_t cmd[], const uint8_t cmdlength) { if (storeflag) saveConfig(); + + rcmd_busy = false; + } // rcommand() diff --git a/src/reset.cpp b/src/reset.cpp index bd0284d7..c3983459 100644 --- a/src/reset.cpp +++ b/src/reset.cpp @@ -13,12 +13,11 @@ RTC_DATA_ATTR runmode_t RTC_runmode = RUNMODE_POWERCYCLE; RTC_DATA_ATTR struct timeval RTC_sleep_start_time; timeval sleep_stop_time; -const char *runmode[4] = {"powercycle", "normal", "wakeup", "update"}; +const char *runmode[5] = {"powercycle", "normal", "wakeup", "update", "sleep"}; void do_reset(bool warmstart) { if (warmstart) { - ESP_LOGI(TAG, "restarting device (warmstart), keeping runmode %s", - runmode[RTC_runmode]); + ESP_LOGI(TAG, "restarting device (warmstart)"); } else { #if (HAS_LORA) if (RTC_runmode == RUNMODE_NORMAL) { @@ -26,8 +25,7 @@ void do_reset(bool warmstart) { } #endif RTC_runmode = RUNMODE_POWERCYCLE; - ESP_LOGI(TAG, "restarting device (coldstart), setting runmode %s", - runmode[RTC_runmode]); + ESP_LOGI(TAG, "restarting device (coldstart)"); } esp_restart(); } @@ -78,41 +76,16 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60, if (!GPIO_IS_VALID_GPIO(wakeup_gpio)) wakeup_gpio = GPIO_NUM_MAX; - // ensure we are in normal runmode, not udpate or wakeup - if ((RTC_runmode != RUNMODE_NORMAL) -#if (HAS_LORA) - || (LMIC.opmode & (OP_JOINING | OP_REJOIN)) -#endif - ) - return; - ESP_LOGI(TAG, "Preparing to sleep..."); + RTC_runmode = RUNMODE_SLEEP; + // stop further enqueuing of senddata sendTimer.detach(); - // shutdown MQTT safely -#ifdef HAS_MQTT -// to come -#endif - -// shutdown SPI safely -#ifdef HAS_SPI -// to come -#endif - // halt interrupts accessing i2c bus mask_user_IRQ(); - // switch off radio -#if (BLECOUNTER) - stop_BLEscan(); - btStop(); -#endif -#if (WIFICOUNTER) - switch_wifi_sniffer(0); -#endif - // wait a while (max 100 sec) to clear send queues ESP_LOGI(TAG, "Waiting until send queues are empty..."); for (i = 10; i > 0; i--) { @@ -136,11 +109,43 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60, } if (i == 0) goto Error; +#endif // (HAS_LORA) +// shutdown MQTT safely +#ifdef HAS_MQTT +// to come +#endif + +// shutdown SPI safely +#ifdef HAS_SPI +// to come +#endif + + // wait until rcommands are all done + for (i = 10; i > 0; i--) { + if (rcmd_busy) + vTaskDelay(pdMS_TO_TICKS(1000)); + else + break; + } + if (i == 0) + goto Error; + +// switch off radio +#if (WIFICOUNTER) + switch_wifi_sniffer(0); +#endif +#if (BLECOUNTER) + stop_BLEscan(); + btStop(); +#endif + + // save LMIC state to RTC RAM +#if (HAS_LORA) SaveLMICToRTC(wakeup_sec); #endif // (HAS_LORA) -// switch off display +// set display to power save mode #ifdef HAS_DISPLAY dp_shutdown(); #endif diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 3dc1bfeb..ccb6a87e 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -70,33 +70,31 @@ void wifi_sniffer_init(void) { ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode - // setup wifi channel rotation timer + // setup wifi channel hopping timer WifiChanTimer = xTimerCreate("WifiChannelTimer", (cfg.wifichancycle > 0) ? pdMS_TO_TICKS(cfg.wifichancycle) : pdMS_TO_TICKS(50), pdTRUE, (void *)0, switchWifiChannel); + // start timer if (cfg.wifichancycle > 0) - xTimerStart(WifiChanTimer, (TickType_t) 0); - else - esp_wifi_set_channel(WIFI_CHANNEL_MIN, WIFI_SECOND_CHAN_NONE); + xTimerStart(WifiChanTimer, (TickType_t)0); } void switch_wifi_sniffer(uint8_t state) { if (state) { // switch wifi sniffer on ESP_ERROR_CHECK(esp_wifi_start()); - if (cfg.wifichancycle > 0) - xTimerStart(WifiChanTimer, (TickType_t) 0); - else - esp_wifi_set_channel(WIFI_CHANNEL_MIN, WIFI_SECOND_CHAN_NONE); esp_wifi_set_promiscuous(true); + esp_wifi_set_channel(WIFI_CHANNEL_MIN, WIFI_SECOND_CHAN_NONE); + if (cfg.wifichancycle > 0) + xTimerStart(WifiChanTimer, (TickType_t)0); } else { // switch wifi sniffer off + macs_wifi = 0; // clear WIFI counter if (xTimerIsTimerActive(WifiChanTimer) != pdFALSE) - xTimerStop(WifiChanTimer, (TickType_t) 0); + xTimerStop(WifiChanTimer, (TickType_t)0); esp_wifi_set_promiscuous(false); ESP_ERROR_CHECK(esp_wifi_stop()); - macs_wifi = 0; // clear WIFI counter } } \ No newline at end of file