Merge pull request #558 from tekka007/SleepRework

Redesign sleep() functions
This commit is contained in:
Henrik Ekblad
2016-09-19 21:35:54 +02:00
committed by GitHub
6 changed files with 195 additions and 138 deletions
+12 -4
View File
@@ -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
/**********************************
+3 -3
View File
@@ -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<int8_t>(_wokeUpByInterrupt);
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
+3 -3
View File
@@ -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);
+3 -3
View File
@@ -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() {
+96 -83
View File
@@ -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
+78 -42
View File
@@ -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 <stddef.h>
#include <stdarg.h>
#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
/**