diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 6ae6ac0a8..f9f9cb79d 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -1115,3 +1115,8 @@ void MyMesh::loop() { uptime_millis += now - last_millis; last_millis = now; } + +// To get the current pending outbound packets at Dispatcher +int MyMesh::hasPendingWork(uint32_t now) const { + return _mgr->getOutboundCount(0xFFFFFFFF); +} diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index ed9f0c5fc..3f3b783fa 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -225,4 +225,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { bridge.begin(); } #endif + + // To get the current pending outbound packets at Dispatcher + int hasPendingWork(uint32_t now) const; }; diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 7387e77e7..0765ec668 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -19,12 +19,21 @@ void halt() { static char command[160]; +#ifdef POWERSAVING_MODE + unsigned long lastActive = 0; // mark last active time + unsigned long nextSleepinSecs = 120; // next sleep in seconds. First time is 2m to send advert and do repeater setup. +#endif + void setup() { Serial.begin(115200); delay(1000); board.begin(); +#ifdef POWERSAVING_MODE + lastActive = millis(); // mark last active time at boot +#endif + #ifdef DISPLAY_CLASS if (display.begin()) { display.startFrame(); @@ -117,4 +126,16 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); + +#ifdef POWERSAVING_MODE + if (the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // Try to sleep every nextSleepinSecs seconds + if(the_mesh.hasPendingWork(0xFFFFFFFF) == 0) { // Has no pending work. Safe to sleep + board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet + lastActive = millis(); + nextSleepinSecs = 5; // Default: To work for 5s and sleep again + } else { + nextSleepinSecs += 5; // To give 5 more seconds to send + } + } +#endif } diff --git a/src/MeshCore.h b/src/MeshCore.h index eb7940589..38976c310 100644 --- a/src/MeshCore.h +++ b/src/MeshCore.h @@ -51,6 +51,7 @@ class MainBoard { virtual void onAfterTransmit() { } virtual void reboot() = 0; virtual void powerOff() { /* no op */ } + virtual void sleep(uint32_t secs) { /* no op */ } virtual uint32_t getGpio() { return 0; } virtual void setGpio(uint32_t values) {} virtual uint8_t getStartupReason() const = 0; @@ -90,4 +91,4 @@ class RTCClock { } }; -} \ No newline at end of file +} diff --git a/src/helpers/ESP32Board.h b/src/helpers/ESP32Board.h index 64c92c43d..d010f322c 100644 --- a/src/helpers/ESP32Board.h +++ b/src/helpers/ESP32Board.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include "driver/rtc_io.h" class ESP32Board : public mesh::MainBoard { protected: @@ -42,6 +44,25 @@ class ESP32Board : public mesh::MainBoard { #endif } + void enterLightSleep(uint32_t secs) { +#if defined(CONFIG_IDF_TARGET_ESP32S3) // Supported ESP32 variants + if (rtc_gpio_is_valid_gpio((gpio_num_t)P_LORA_DIO_1)) { // Only enter sleep mode if P_LORA_DIO_1 is RTC pin + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // To wake up when receiving a LoRa packet + + if (secs > 0) { + esp_sleep_enable_timer_wakeup(secs * 1000000); // To wake up every hour to do periodically jobs + } + + esp_light_sleep_start(); // CPU enters light sleep + } +#endif + } + + void sleep(uint32_t secs) override { + if (WiFi.getMode() == WIFI_MODE_NULL) { // WiFi is off ~ No active OTA, safe to go to sleep + enterLightSleep(secs); // To wake up after "secs" seconds or when receiving a LoRa packet + } // Temperature from ESP32 MCU float getMCUTemperature() override { return temperatureRead(); diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 36c6386f6..fea0acf74 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -48,6 +48,7 @@ build_flags = -D MAX_NEIGHBOURS=50 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 + -D POWERSAVING_MODE=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + +<../examples/simple_repeater> diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index c26a5bc69..f1d2ef9ae 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -59,6 +59,7 @@ build_flags = -D MAX_NEIGHBOURS=50 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 + -D POWERSAVING_MODE=1 build_src_filter = ${Heltec_lora32_v4.build_src_filter} + +<../examples/simple_repeater>