diff --git a/MyConfig.h b/MyConfig.h index 366a676..2bc8e84 100644 --- a/MyConfig.h +++ b/MyConfig.h @@ -153,14 +153,22 @@ // #define MY_REPEATER_FEATURE /** - * @def MY_SMART_SLEEP_WAIT_DURATION - * @brief The wait period before going to sleep when using smartSleep-functions. +* @def MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS +* @brief Timeout (in ms) to re-establish link if node is send to sleep and transport is not ready. +*/ +#ifndef MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS +#define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS (10*1000ul) +#endif + +/** + * @def MY_SMART_SLEEP_WAIT_DURATION_MS + * @brief The wait period (in ms) before going to sleep when using smartSleep-functions. * * This period has to be long enough for controller to be able to send out * potential buffered messages. */ -#ifndef MY_SMART_SLEEP_WAIT_DURATION -#define MY_SMART_SLEEP_WAIT_DURATION 500 +#ifndef MY_SMART_SLEEP_WAIT_DURATION_MS +#define MY_SMART_SLEEP_WAIT_DURATION_MS (500ul) #endif /********************************** diff --git a/core/MyHwATMega328.cpp b/core/MyHwATMega328.cpp index 100d7ed..59b9526 100644 --- a/core/MyHwATMega328.cpp +++ b/core/MyHwATMega328.cpp @@ -21,7 +21,7 @@ #include "MyHwATMega328.h" -#define INVALID_INTERRUPT_NUM (0xFFu) +#define INVALID_INTERRUPT_NUM (0xFFu) volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu. volatile uint8_t _wakeUp1Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback. @@ -105,7 +105,7 @@ void hwInternalSleep(unsigned long ms) { int8_t hwSleep(unsigned long ms) { hwInternalSleep(ms); - return -1; + return MY_WAKE_UP_BY_TIMER; } int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { @@ -131,7 +131,7 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo } // Return what woke the mcu. - int ret = -1; // default: no interrupt triggered, timer wake up + int8_t ret = MY_WAKE_UP_BY_TIMER; // default: no interrupt triggered, timer wake up if (interruptWakeUp()) ret = static_cast(_wokeUpByInterrupt); // Clear woke-up-by-interrupt flag, so next sleeps won't return immediately. diff --git a/core/MyHwESP8266.cpp b/core/MyHwESP8266.cpp index 3c10105..1760b68 100644 --- a/core/MyHwESP8266.cpp +++ b/core/MyHwESP8266.cpp @@ -93,7 +93,7 @@ void hwWriteConfig(int adr, uint8_t value) int8_t hwSleep(unsigned long ms) { // TODO: Not supported! (void)ms; - return -2; + return MY_SLEEP_NOT_POSSIBLE; } int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { @@ -101,7 +101,7 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { (void)interrupt; (void)mode; (void)ms; - return -2; + return MY_SLEEP_NOT_POSSIBLE; } int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { @@ -111,7 +111,7 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo (void)interrupt2; (void)mode2; (void)ms; - return -2; + return MY_SLEEP_NOT_POSSIBLE; } ADC_MODE(ADC_VCC); diff --git a/core/MyHwSAMD.cpp b/core/MyHwSAMD.cpp index 2d85501..976d4cd 100644 --- a/core/MyHwSAMD.cpp +++ b/core/MyHwSAMD.cpp @@ -117,7 +117,7 @@ void hwReboot() { int8_t hwSleep(unsigned long ms) { // TODO: Not supported! (void)ms; - return -2; + return MY_SLEEP_NOT_POSSIBLE; } int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { @@ -125,7 +125,7 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { (void)interrupt; (void)mode; (void)ms; - return -2; + return MY_SLEEP_NOT_POSSIBLE; } int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { @@ -135,7 +135,7 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo (void)interrupt2; (void)mode2; (void)ms; - return -2; + return MY_SLEEP_NOT_POSSIBLE; } uint16_t hwCPUVoltage() { diff --git a/core/MySensorsCore.cpp b/core/MySensorsCore.cpp index e66f2d4..88f3b0e 100644 --- a/core/MySensorsCore.cpp +++ b/core/MySensorsCore.cpp @@ -280,12 +280,10 @@ void sendBatteryLevel(uint8_t value, bool enableAck) { } void sendHeartbeat(void) { - #if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) || defined(MY_RS485) + #if defined(MY_RADIO_FEATURE) uint32_t heartbeat = transportGetHeartbeat(); - #else - uint32_t heartbeat = hwMillis(); + _sendRoute(build(_msgTmp, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, false).set(heartbeat)); #endif - _sendRoute(build(_msgTmp, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, false).set(heartbeat)); } void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool enableAck) { @@ -444,104 +442,118 @@ bool wait(unsigned long ms, uint8_t cmd, uint8_t msgtype) { return expectedResponse; } - -int8_t sleep(unsigned long ms) { +int8_t _sleep(const uint32_t ms, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) { + debug(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), ms, smartSleep, interrupt1, mode1, interrupt2, mode2); + // OTA FW feature: do not sleep if FW update ongoing #if defined(MY_OTA_FIRMWARE_FEATURE) - if (_fwUpdateOngoing) { - // Do not sleep node while fw update is ongoing - wait(ms); - return -1; - } + if (_fwUpdateOngoing) { + debug(PSTR("!MCO:SLP:FWUPD\n")); // sleeping not possible, FW update ongoing + wait(ms); + return MY_SLEEP_NOT_POSSIBLE; + } #endif - // if repeater, do not sleep + // repeater feature: sleeping not possible #if defined(MY_REPEATER_FEATURE) - wait(ms); - return -1; - #else - #if defined(MY_RADIO_FEATURE) - transportPowerDown(); - #endif - setIndication(INDICATION_SLEEP); - const int8_t res = hwSleep(ms); - setIndication(INDICATION_WAKEUP); - return res; - #endif -} - -int8_t smartSleep(unsigned long ms) { - // notify controller about going to sleep - sendHeartbeat(); - // listen for incoming messages - wait(MY_SMART_SLEEP_WAIT_DURATION); - return sleep(ms); -} - -int8_t sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { - #if defined(MY_OTA_FIRMWARE_FEATURE) - if (_fwUpdateOngoing) { - // not supported - return -2; - } - #endif - #if defined(MY_REPEATER_FEATURE) - // not supported - (void)interrupt; - (void)mode; - (void)ms; - return -2; - #else - #if defined(MY_RADIO_FEATURE) - transportPowerDown(); - #endif - setIndication(INDICATION_SLEEP); - const int8_t res = hwSleep(interrupt, mode, ms); - setIndication(INDICATION_WAKEUP); - return res; - #endif -} - -int8_t smartSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { - // notify controller about going to sleep - sendHeartbeat(); - // listen for incoming messages - wait(MY_SMART_SLEEP_WAIT_DURATION); - return sleep(interrupt, mode, ms); -} - -int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { - #if defined(MY_OTA_FIRMWARE_FEATURE) - if (_fwUpdateOngoing) { - // not supported - return -2; - } - #endif - #if defined(MY_REPEATER_FEATURE) - // not supported + (void)smartSleep; (void)interrupt1; (void)mode1; (void)interrupt2; (void)mode2; - (void)ms; - return -2; + + debug(PSTR("!MCO:SLP:REP\n")); // sleeping not possible, repeater feature enabled + wait(ms); + return MY_SLEEP_NOT_POSSIBLE; #else + uint32_t sleepingTime = ms; #if defined(MY_RADIO_FEATURE) + // Do not sleep if transport not ready + if (!isTransportReady()) { + debug(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready + uint32_t sleepEnter = hwMillis(); + uint32_t sleepDelta = 0; + while (!isTransportReady() && (sleepDelta < sleepingTime) && (sleepDelta < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) { + _process(); + #if defined(ARDUINO_ARCH_ESP8266) + yield(); + #endif + sleepDelta = hwMillis() - sleepEnter; + } + // sleep remainder + if (sleepDelta < sleepingTime) { + sleepingTime -= sleepDelta; // calculate remaining sleeping time + debug(PSTR("MCO:SLP:MS=%lu\n"), sleepingTime); + } + else { + // no sleeping time left + return MY_SLEEP_NOT_POSSIBLE; + } + } + #endif + + if (smartSleep) { + // notify controller about going to sleep + sendHeartbeat(); + wait(MY_SMART_SLEEP_WAIT_DURATION_MS); // listen for incoming messages + } + + #if defined(MY_RADIO_FEATURE) + debug(PSTR("MCO:SLP:TPD\n")); // sleep, power down transport transportPowerDown(); #endif + setIndication(INDICATION_SLEEP); - const int8_t res = hwSleep(interrupt1, mode1, interrupt2, mode2, ms); + + int8_t res = MY_SLEEP_NOT_POSSIBLE; // default + + if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) { + // both IRQs + res = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTime); + } + else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { + // one IRQ + res = hwSleep(interrupt1, mode1, sleepingTime); + } + else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) { + // no IRQ + res = hwSleep(sleepingTime); + } + setIndication(INDICATION_WAKEUP); + debug(PSTR("MCO:SLP:WUP=%d\n"), res); // sleep wake-up return res; #endif } -int8_t smartSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { - // notify controller about going to sleep - sendHeartbeat(); - // listen for incoming messages - wait(MY_SMART_SLEEP_WAIT_DURATION); - return sleep(interrupt1, mode1, interrupt2, mode2, ms); +// sleep functions +int8_t sleep(const uint32_t ms, const bool smartSleep) { + return _sleep(ms, smartSleep); } +int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t ms, const bool smartSleep) { + return _sleep(ms, smartSleep, interrupt, mode); +} + +int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t ms, const bool smartSleep) { + return _sleep(ms, smartSleep, interrupt1, mode1, interrupt2, mode2); +} + +// deprecated smartSleep() functions +int8_t smartSleep(const uint32_t ms) { + // compatibility + return _sleep(ms, true); +} + +int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t ms) { + // compatibility + return _sleep(ms, true, interrupt, mode); +} + +int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t ms) { + // compatibility + return _sleep(ms, true, interrupt1, mode1, interrupt2, mode2); +} + + #ifdef MY_NODE_LOCK_FEATURE void nodeLock(const char* str) { // Make sure EEPROM is updated to locked status @@ -555,6 +567,7 @@ void nodeLock(const char* str) { _sendRoute(build(_msgTmp, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID,C_INTERNAL, I_LOCKED, false).set(str)); #if defined(MY_RADIO_FEATURE) transportPowerDown(); + debug(PSTR("MCO:NLK:TPD\n")); // power down transport #endif setIndication(INDICATION_SLEEP); (void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message diff --git a/core/MySensorsCore.h b/core/MySensorsCore.h index d9dafa6..f88a028 100644 --- a/core/MySensorsCore.h +++ b/core/MySensorsCore.h @@ -37,20 +37,26 @@ * * MySensorsCore debug log messages: * - * |E| SYS | SUB | Message | Comment - * |-|------|-------|-------------------------------------------|---------------------------------------------------------------------------- - * | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER) - * | | MCO | BGN | BFR | Callback before() - * | | MCO | BGN | STP | Callback setup() - * | | MCO | BGN | INIT OK,ID=%%d,PAR=%%d,DIS=%%d,REG=%%d | Core initialized, parent ID (PAR), distance to GW (DIS), registration (REG) - * | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter) - * |!| MCO | BGN | TSP FAIL | Transport initialization failed - * | | MCO | REG | REQ | Registration request - * | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW) - * |!| MCO | SND | NODE NOT REG | Node is not registered, cannot send message - * | | MCO | PIM | NODE REG=%%d | Registration response received, registration status (REG) - * | | MCO | PIM | ROUTE N=%%d,R=%%d | Routing table, messages to node (N) are routed via node (R) - * | | MCO | NLK | NODE LOCKED. UNLOCK: GND PIN %%d AND RESET| Node locked during booting, see signing chapter for additional information + * |E| SYS | SUB | Message | Comment + * |-|------|-------|-----------------------------------------------|---------------------------------------------------------------------------- + * | | MCO | BGN | INIT %%s,CP=%%s,LIB=%%s | Core initialization, capabilities (CP), library version (VER) + * | | MCO | BGN | BFR | Callback before() + * | | MCO | BGN | STP | Callback setup() + * | | MCO | BGN | INIT OK,ID=%%d,PAR=%%d,DIS=%%d,REG=%%d | Core initialized, parent ID (PAR), distance to GW (DIS), registration (REG) + * | | MCO | BGN | NODE UNLOCKED | Node successfully unlocked (see signing chapter) + * |!| MCO | BGN | TSP FAIL | Transport initialization failed + * | | MCO | REG | REQ | Registration request + * | | MCO | REG | NOT NEEDED | No registration needed (i.e. GW) + * |!| MCO | SND | NODE NOT REG | Node is not registered, cannot send message + * | | MCO | PIM | NODE REG=%%d | Registration response received, registration status (REG) + * | | MCO | PIM | ROUTE N=%%d,R=%%d | Routing table, messages to node (N) are routed via node (R) + * | | MCO | SLP | MS=%%lu,SMS=%%d,I1=%%d,M1=%%d,I2=%%d,M2=%%d | Sleep node, time (MS), smartSleep (SMS), Int1/M1, Int2/M2 + * | | MCO | SLP | TPD | Sleep node, powerdown transport + * | | MCO | SLP | WUP=%%d | Node woke-up, reason/IRQ (WUP) + * |!| MCO | SLP | FWUPD | Sleeping not possible, FW update ongoing + * |!| MCO | SLP | REP | Sleeping not possible, repeater feature enabled + * | | MCO | NLK | NODE LOCKED. UNLOCK: GND PIN %%d AND RESET | Node locked during booting, see signing chapter for additional information + * | | MCO | NLK | TPD | Powerdown transport * * * @brief API declaration for MySensorsCore @@ -67,10 +73,16 @@ #include #include -#define GATEWAY_ADDRESS ((uint8_t)0) //!< Node ID for GW sketch -#define NODE_SENSOR_ID 0xFF //!< Node child is always created/presented when a node is started -#define MY_CORE_VERSION ((uint8_t)2) //!< core version -#define MY_CORE_MIN_VERSION ((uint8_t)2) //!< min core version required for compatibility +#define GATEWAY_ADDRESS ((uint8_t)0) //!< Node ID for GW sketch +#define NODE_SENSOR_ID ((uint8_t)255) //!< Node child is always created/presented when a node is started +#define MY_CORE_VERSION ((uint8_t)2) //!< core version +#define MY_CORE_MIN_VERSION ((uint8_t)2) //!< min core version required for compatibility + +#define MY_WAKE_UP_BY_TIMER ((int8_t)-1) //!< Sleeping wake up by timer +#define MY_SLEEP_NOT_POSSIBLE ((int8_t)-2) //!< Sleeping not possible +#define INTERRUPT_NOT_DEFINED ((uint8_t)255) //!< _sleep() param: no interrupt defined +#define MODE_NOT_DEFINED ((uint8_t)255) //!< _sleep() param: no mode defined + #ifdef MY_DEBUG #define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) //!< debug @@ -232,16 +244,10 @@ bool wait(unsigned long ms, uint8_t cmd, uint8_t msgtype); /** * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. * @param ms Number of milliseconds to sleep. - * @return -1 if timer woke it up, -2 if not possible (e.g. ongoing FW update) + * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. + * @return @ref MY_WAKE_UP_BY_TIMER if timer woke it up, @ref MY_SLEEP_NOT_POSSIBLE if not possible (e.g. ongoing FW update) */ -int8_t sleep(unsigned long ms); -/** -* Same as sleep(), send heartbeat and process incoming messages before going to sleep. -* Specify the time to wait for incoming messages by defining MY_SMART_SLEEP_WAIT_DURATION to a time (ms). -* @param ms Number of milliseconds to sleep. -* @return -1 if timer woke it up, -2 if not possible (e.g. ongoing FW update) -*/ -int8_t smartSleep(unsigned long ms); +int8_t sleep(const uint32_t ms, const bool smartSleep = false); /** * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. @@ -250,18 +256,10 @@ int8_t smartSleep(unsigned long ms); * @param interrupt Interrupt that should trigger the wakeup * @param mode RISING, FALLING, CHANGE * @param ms Number of milliseconds to sleep or 0 to sleep forever - * @return Interrupt number if wake up was triggered by pin change, -1 if wake up was triggered by timer, -2 if sleep was not possible (e.g. ongoing FW update) + * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep + * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); -/** -* Same as sleep(), send heartbeat and process incoming messages before going to sleep. -* Specify the time to wait for incoming messages by defining MY_SMART_SLEEP_WAIT_DURATION to a time (ms). -* @param interrupt Interrupt that should trigger the wakeup -* @param mode RISING, FALLING, CHANGE -* @param ms Number of milliseconds to sleep or 0 to sleep forever -* @return Interrupt number if wake up was triggered by pin change, -1 if wake up was triggered by timer, -2 if sleep was not possible (e.g. ongoing FW update) -*/ -int8_t smartSleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); +int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t ms=0, const bool smartSleep = false); /** * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. @@ -272,10 +270,33 @@ int8_t smartSleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); * @param interrupt2 Second interrupt that should trigger the wakeup * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) * @param ms Number of milliseconds to sleep or 0 to sleep forever - * @return Interrupt number if wake up was triggered by pin change, -1 if wake up was triggered by timer, -2 if sleep was not possible (e.g. ongoing FW update) + * @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep. + * @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); +int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t ms=0, const bool smartSleep = false); + /** +* \deprecated Use sleep(ms, true) instead +* Same as sleep(), send heartbeat and process incoming messages before going to sleep. +* Specify the time to wait for incoming messages by defining MY_SMART_SLEEP_WAIT_DURATION to a time (ms). +* @param ms Number of milliseconds to sleep. +* @return @ref MY_WAKE_UP_BY_TIMER if timer woke it up, @ref MY_SLEEP_NOT_POSSIBLE if not possible (e.g. ongoing FW update) +*/ +int8_t smartSleep(const uint32_t ms); + +/** +* \deprecated Use sleep(interrupt, mode, ms, true) instead +* Same as sleep(), send heartbeat and process incoming messages before going to sleep. +* Specify the time to wait for incoming messages by defining MY_SMART_SLEEP_WAIT_DURATION to a time (ms). +* @param interrupt Interrupt that should trigger the wakeup +* @param mode RISING, FALLING, CHANGE +* @param ms Number of milliseconds to sleep or 0 to sleep forever +* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) +*/ +int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t ms = 0); + +/** +* \deprecated Use sleep(interrupt1, mode1, interrupt2, mode2, ms, true) instead * Same as sleep(), send heartbeat and process incoming messages before going to sleep. * Specify the time to wait for incoming messages by defining MY_SMART_SLEEP_WAIT_DURATION to a time (ms). * @param interrupt1 First interrupt that should trigger the wakeup @@ -283,9 +304,24 @@ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode * @param interrupt2 Second interrupt that should trigger the wakeup * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) * @param ms Number of milliseconds to sleep or 0 to sleep forever -* @return Interrupt number if wake up was triggered by pin change, -1 if wake up was triggered by timer, -2 if sleep was not possible (e.g. ongoing FW update) +* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) */ -int8_t smartSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); +int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t ms=0); + +/** +* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. +* See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin +* is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 +* @param ms Number of milliseconds to sleep or 0 to sleep forever +* @param interrupt1 (optional) First interrupt that should trigger the wakeup +* @param mode1 (optional) Mode for first interrupt (RISING, FALLING, CHANGE) +* @param interrupt2 (optional) Second interrupt that should trigger the wakeup +* @param mode2 (optional) Mode for second interrupt (RISING, FALLING, CHANGE) +* @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep. +* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update) +*/ +int8_t _sleep(const uint32_t ms, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED); + #ifdef MY_NODE_LOCK_FEATURE /**