From 63da190e59760df921bcefddce88a2a32657628c Mon Sep 17 00:00:00 2001
From: DV <you@example.com>
Date: Sun, 26 Feb 2017 23:04:10 +0100
Subject: [PATCH] Release v1.1

---
 NodeManagerTemplate/NodeManager.cpp         | 306 ++++++++++++--------
 NodeManagerTemplate/NodeManager.h           | 183 ++++++++----
 NodeManagerTemplate/NodeManagerTemplate.ino |  28 +-
 NodeManagerTemplate/config.h                |  19 +-
 4 files changed, 342 insertions(+), 194 deletions(-)

diff --git a/NodeManagerTemplate/NodeManager.cpp b/NodeManagerTemplate/NodeManager.cpp
index 72c7eeb..b7708f0 100644
--- a/NodeManagerTemplate/NodeManager.cpp
+++ b/NodeManagerTemplate/NodeManager.cpp
@@ -4,17 +4,26 @@
 
 #include "NodeManager.h"
 
+/*
+ * Constants
+ */
+
+const char* BATTERY = "BATTERY";
+const char* AWAKE = "AWAKE";
+const char* REBOOT = "REBOOT";
+const char* CLEAR = "CLEAR";
+const char* WAKEUP = "WAKEUP";
 
 /***************************************
    PowerManager
 */
 
 // set the vcc and ground pin the sensor is connected to
-void PowerManager::setPowerPins(int ground_pin, int vcc_pin, long wait = 0) {
+void PowerManager::setPowerPins(int ground_pin, int vcc_pin, long wait = 10) {
   #if DEBUG == 1
-    Serial.print("PowerPins vcc=");
+    Serial.print("POWER V=");
     Serial.print(vcc_pin);
-    Serial.print(", gnd=");
+    Serial.print(" G=");
     Serial.println(ground_pin);
   #endif
   // configure the vcc pin as output and initialize to low (power off)
@@ -38,7 +47,7 @@ bool PowerManager::_hasPowerManager() {
 void PowerManager::powerOn() {
   if (! _hasPowerManager()) return;
   #if DEBUG == 1
-    Serial.print("PowerOn pin=");
+    Serial.print("ON P=");
     Serial.println(_vcc_pin);
   #endif
   // power on the sensor by turning high the vcc pin
@@ -51,7 +60,7 @@ void PowerManager::powerOn() {
 void PowerManager::powerOff() {
   if (! _hasPowerManager()) return;
   #if DEBUG == 1
-    Serial.print("PowerOff pin=");
+    Serial.print("OFF P=");
     Serial.println(_vcc_pin);
   #endif
   // power off the sensor by turning low the vcc pin
@@ -123,6 +132,9 @@ void Sensor::setFloatPrecision(int value) {
     void Sensor::setPowerPins(int ground_pin, int vcc_pin, long wait = 0) {
       _powerManager.setPowerPins(ground_pin, vcc_pin, wait);
     }
+    void Sensor::setAutoPowerPins(bool value) {
+      _auto_power_pins = value;
+    }
     void Sensor::powerOn() {
       _powerManager.powerOn();
     }
@@ -130,13 +142,16 @@ void Sensor::setFloatPrecision(int value) {
       _powerManager.powerOff();
     }
 #endif
+void Sensor::setSleepBetweenSend(int value) {
+  _sleep_between_send = value;
+}
 
 // present the sensor to the gateway and controller
 void Sensor::presentation() {
   #if DEBUG == 1
-    Serial.print("Present id=");
+    Serial.print("PRES I=");
     Serial.print(_child_id);
-    Serial.print(", pres=");
+    Serial.print(" T=");
     Serial.println(_presentation);
   #endif
   present(_child_id, _presentation);
@@ -153,7 +168,7 @@ void Sensor::loop(const MyMessage & message) {
   if (_pin == -1) return;
   #if POWER_MANAGER == 1
     // turn the sensor on
-    powerOn();
+    if (_auto_power_pins) powerOn();
   #endif
   // for numeric sensor requiring multiple samples, keep track of the total
   float total = 0;
@@ -209,7 +224,7 @@ void Sensor::loop(const MyMessage & message) {
   }
   // turn the sensor off
   #if POWER_MANAGER == 1
-    powerOff();
+    if (_auto_power_pins) powerOff();
   #endif
 }
 
@@ -225,20 +240,22 @@ void Sensor::receive(const MyMessage &message) {
 void Sensor::_send(MyMessage & message) {
   // send the message, multiple times if requested
   for (int i = 0; i < _retries; i++) {
+    // if configured, sleep beetween each send
+    if (_sleep_between_send > 0) sleep(_sleep_between_send);
     #if DEBUG == 1
-      Serial.print("Send to=");
+      Serial.print("SEND D=");
       Serial.print(message.destination);
-      Serial.print(" id=");
+      Serial.print(" I=");
       Serial.print(message.sensor);
-      Serial.print(" cmd=");
+      Serial.print(" C=");
       Serial.print(message.getCommand());
-      Serial.print(" type=");
+      Serial.print(" T=");
       Serial.print(message.type);
-      Serial.print(" str=");
+      Serial.print(" S=");
       Serial.print(message.getString());
-      Serial.print(" int=");
+      Serial.print(" N=");
       Serial.print(message.getInt());
-      Serial.print(" float=");
+      Serial.print(" F=");
       Serial.println(message.getFloat());
     #endif
     send(message);
@@ -284,11 +301,11 @@ void SensorAnalogInput::onLoop() {
   int percentage = 0;
   if (_output_percentage) percentage = _getPercentage(adc);
   #if DEBUG == 1
-    Serial.print(" AnalogInput id=");
+    Serial.print("A-IN I=");
     Serial.print(_child_id);
-    Serial.print(", val=");
+    Serial.print(" V=");
     Serial.print(adc);
-    Serial.print(", %=");
+    Serial.print(" %=");
     Serial.println(percentage);
   #endif
   // store the result
@@ -316,8 +333,11 @@ int SensorAnalogInput::_getAnalogRead() {
 // return a percentage from an analog value
 int SensorAnalogInput::_getPercentage(int adc) {
   float value = (float)adc;
+  // restore the original value
+  if (_reverse) value = 1024 - value;
   // scale the percentage based on the range provided
   float percentage = ((value - _range_min) / (_range_max - _range_min)) * 100;
+  if (_reverse) percentage = 100 - percentage;
   if (percentage > 100) percentage = 100;
   if (percentage < 0) percentage = 0;
   return (int)percentage;
@@ -386,13 +406,13 @@ void SensorThermistor::onLoop() {
   temperature -= 273.15;                         // convert to C
   if (! getControllerConfig().isMetric) temperature = temperature * 1.8 + 32;
   #if DEBUG == 1
-    Serial.print(" Thermistor id=");
+    Serial.print("THER I=");
     Serial.print(_child_id);
-    Serial.print(", adc=");
+    Serial.print(" V=");
     Serial.print(adc);
-    Serial.print(", tmp=");
+    Serial.print(" T=");
     Serial.println(temperature);
-    Serial.print(", m=");
+    Serial.print(" M=");
     Serial.println(getControllerConfig().isMetric);
   #endif
   // store the value
@@ -423,11 +443,11 @@ void SensorDigitalInput::onLoop() {
   // read the value
   int value = digitalRead(_pin);
   #if DEBUG == 1
-    Serial.print("DigitalInput id=");
+    Serial.print("D-IN I=");
     Serial.print(_child_id);
-    Serial.print(", pin=");
+    Serial.print(" P=");
     Serial.print(_pin);
-    Serial.print(", val=");
+    Serial.print(" V=");
     Serial.println(value);
   #endif
   // store the value
@@ -475,15 +495,15 @@ void SensorDigitalOutput::onReceive(const MyMessage & message) {
   int value = message.getInt();
   if (value != 0 && value != 1) return;
   #if DEBUG == 1
-    Serial.print("DigitalOutput id=");
+    Serial.print("DOUT I=");
     Serial.print(_child_id);
-    Serial.print(", pin=");
+    Serial.print(" P=");
     Serial.print(_pin);
-    Serial.print(", init=");
+    Serial.print(" S=");
     Serial.print(_initial_value);
-    Serial.print(", val=");
+    Serial.print(" V=");
     Serial.print(value);
-    Serial.print(", pls=");
+    Serial.print(" P=");
     Serial.println(_pulse_width);
   #endif
   // set the value
@@ -508,6 +528,12 @@ SensorRelay::SensorRelay(int child_id, int pin): SensorDigitalOutput(child_id, p
   setType(V_STATUS);
 }
 
+// define what to do during loop
+void SensorRelay::onLoop() {
+    // set the value to -1 so to avoid reporting to the gateway during loop
+    _value_int = -1;
+}
+
 /*
    SensorLatchingRelay
 */
@@ -558,9 +584,9 @@ void SensorDHT::onLoop() {
     // convert it
     if (! getControllerConfig().isMetric) temperature = temperature * 1.8 + 32;
     #if DEBUG == 1
-      Serial.print(" DHT id=");
+      Serial.print("DHT I=");
       Serial.print(_child_id);
-      Serial.print(", tmp=");
+      Serial.print(" T=");
       Serial.println(temperature);
     #endif
     // store the value
@@ -572,9 +598,9 @@ void SensorDHT::onLoop() {
     float humidity = _dht->readHumidity();
     if (isnan(humidity)) return;
     #if DEBUG == 1
-      Serial.print(" DHT id=");
+      Serial.print("DHT I=");
       Serial.print(_child_id);
-      Serial.print(", %=");
+      Serial.print(" H=");
       Serial.println(humidity);
     #endif
     // store the value
@@ -625,9 +651,9 @@ void SensorSHT21::onLoop() {
     // convert it
     if (! getControllerConfig().isMetric) temperature = temperature * 1.8 + 32;
     #if DEBUG == 1
-      Serial.print(" SHT21 id=");
+      Serial.print("SHT I=");
       Serial.print(_child_id);
-      Serial.print(", tmp=");
+      Serial.print(" T=");
       Serial.println(temperature);
     #endif
     // store the value
@@ -639,9 +665,9 @@ void SensorSHT21::onLoop() {
     float humidity = SHT2x.GetHumidity();
     if (isnan(humidity)) return;
     #if DEBUG == 1
-      Serial.print(" SHT21 id=");
+      Serial.print("SHT I=");
       Serial.print(_child_id);
-      Serial.print(", %=");
+      Serial.print(" H=");
       Serial.println(humidity);
     #endif
     // store the value
@@ -694,11 +720,11 @@ void SensorSwitch::onLoop() {
   // process the value
   if ( (_mode == RISING && value == HIGH ) || (_mode == FALLING && value == LOW) || (_mode == CHANGE) )  {
     #if DEBUG == 1
-      Serial.print("Switch id=");
+      Serial.print("SWITCH I=");
       Serial.print(_child_id);
-      Serial.print(", pin=");
+      Serial.print(" P=");
       Serial.print(_pin);
-      Serial.print(", val=");
+      Serial.print(" V=");
       Serial.println(value);
     #endif
     _value_int = value;
@@ -756,9 +782,9 @@ void SensorDs18b20::onLoop() {
   // convert it
   if (! getControllerConfig().isMetric) temperature = temperature * 1.8 + 32;
   #if DEBUG == 1
-    Serial.print(" Ds18b20 id=");
+    Serial.print("DS18 I=");
     Serial.print(_child_id);
-    Serial.print(", tmp=");
+    Serial.print(" T=");
     Serial.println(temperature);
   #endif
   // store the value
@@ -787,6 +813,9 @@ NodeManager::NodeManager() {
 void NodeManager::setRebootPin(int value) {
     _reboot_pin = value;
 }
+void NodeManager::setRetries(int value) {
+  _retries = value;
+}
 #if BATTERY_MANAGER == 1
   void NodeManager::setBatteryMin(float value) {
     _battery_min = value;
@@ -810,7 +839,7 @@ void NodeManager::setRebootPin(int value) {
   }
   void NodeManager::setSleep(int value1, int value2, int value3) {
     _sleep_mode = value1;
-    _sleep_time = value1;
+    _sleep_time = value2;
     _sleep_unit = value3;
   }
   void NodeManager::setSleepInterruptPin(int value) {
@@ -831,6 +860,9 @@ void NodeManager::setInterrupt(int pin, int mode, int pull = -1) {
   void NodeManager::setPowerPins(int ground_pin, int vcc_pin, long wait = 10) {
     _powerManager.setPowerPins(ground_pin, vcc_pin, wait);
   }
+  void NodeManager::setAutoPowerPins(bool value) {
+    _auto_power_pins = value;
+  }
   void NodeManager::powerOn() {
     _powerManager.powerOn();
   }
@@ -838,6 +870,9 @@ void NodeManager::setInterrupt(int pin, int mode, int pull = -1) {
     _powerManager.powerOff();
   }
 #endif
+void NodeManager::setSleepBetweenSend(int value) {
+  _sleep_between_send = value;
+}
 
 // register a sensor to this manager
 int NodeManager::registerSensor(int sensor_type, int pin = -1, int child_id = -1) {
@@ -911,7 +946,7 @@ int NodeManager::registerSensor(int sensor_type, int pin = -1, int child_id = -1
   #endif
   else {
     #if DEBUG == 1
-      Serial.print("Invalid sensor type=");
+      Serial.print("INVALID ");
       Serial.println(sensor_type);
     #endif
     return -1;
@@ -921,13 +956,13 @@ int NodeManager::registerSensor(int sensor_type, int pin = -1, int child_id = -1
 // attach a built-in or custom sensor to this manager
 int NodeManager::registerSensor(Sensor* sensor) {
   #if DEBUG == 1
-    Serial.print("Register id=");
+    Serial.print("REG I=");
     Serial.print(sensor->getChildId());
-    Serial.print(", pin=");
+    Serial.print(" P=");
     Serial.print(sensor->getPin());
-    Serial.print(", pres=");
+    Serial.print(" P=");
     Serial.print(sensor->getPresentation());
-    Serial.print(", type=");
+    Serial.print(" T=");
     Serial.println(sensor->getType());
   #endif
   // add the sensor to the array of registered sensors
@@ -944,26 +979,22 @@ Sensor* NodeManager::get(int child_id) {
 
 // setup NodeManager
 void NodeManager::before() {
-  #if DEBUG == 1
-    Serial.print("node_id=");
-    Serial.print(getNodeId());
-    Serial.print(", metric=");
-    Serial.println(getControllerConfig().isMetric);
-  #endif
   if (_reboot_pin > -1) {
     #if DEBUG == 1
-      Serial.print("Reboot pin=");
+      Serial.print("REB P=");
       Serial.println(_reboot_pin);
     #endif
     // setup the reboot pin
     pinMode(_reboot_pin, OUTPUT);
     digitalWrite(_reboot_pin, HIGH);
   }
-  // setup the sleep interrupt pin
-  if (_sleep_interrupt_pin > -1) {
-    // set the interrupt when the pin is connected to ground
-    setInterrupt(_sleep_interrupt_pin,FALLING,HIGH);
-  }
+  #if SLEEP_MANAGER == 1
+    // setup the sleep interrupt pin
+    if (_sleep_interrupt_pin > -1) {
+      // set the interrupt when the pin is connected to ground
+      setInterrupt(_sleep_interrupt_pin,FALLING,HIGH);
+    }
+  #endif
   // setup the interrupt pins
   if (_interrupt_1_mode != MODE_NOT_DEFINED) {
     pinMode(INTERRUPT_PIN_1,INPUT);
@@ -974,9 +1005,9 @@ void NodeManager::before() {
     if (_interrupt_2_pull > -1) digitalWrite(INTERRUPT_PIN_2,_interrupt_2_pull);
   }
   #if DEBUG == 1
-    Serial.print("Interrupt1 mode=");
+    Serial.print("INT1 M=");
     Serial.println(_interrupt_1_mode);
-    Serial.print("Interrupt2 mode=");
+    Serial.print("INT2 M=");
     Serial.println(_interrupt_2_mode);
   #endif
   #if REMOTE_CONFIGURATION == 1 && SLEEP_MANAGER == 1 && PERSIST == 1
@@ -991,11 +1022,11 @@ void NodeManager::before() {
       else if (major == 3) _sleep_time =  _sleep_time + 250 * 3;
       _sleep_unit = loadState(EEPROM_SLEEP_UNIT);
       #if DEBUG == 1
-        Serial.print("Load sleep mode=");
+        Serial.print("LOADSLP M=");
         Serial.print(_sleep_mode);
-        Serial.print(" time=");
+        Serial.print(" T=");
         Serial.print(_sleep_time);
-        Serial.print(" unit=");
+        Serial.print(" U=");
         Serial.println(_sleep_unit);
       #endif
     }
@@ -1012,23 +1043,23 @@ void NodeManager::before() {
 void NodeManager::presentation() {
   // present the service as a custom sensor to the controller
   #if DEBUG == 1
-    Serial.print("Present id=");
+    Serial.print("PRES I=");
     Serial.print(CONFIGURATION_CHILD_ID);
-    Serial.print(", type=");
+    Serial.print(", T=");
     Serial.println(S_CUSTOM);
   #endif
   present(CONFIGURATION_CHILD_ID, S_CUSTOM);
   #if BATTERY_MANAGER == 1 && BATTERY_SENSOR == 1
     #if DEBUG == 1
-      Serial.print("Present id=");
+      Serial.print("PRES I=");
       Serial.print(BATTERY_CHILD_ID);
-      Serial.print(", type=");
+      Serial.print(", T=");
       Serial.println(S_MULTIMETER);
     #endif
     // present the battery service
     present(BATTERY_CHILD_ID, S_MULTIMETER);
     // report battery level
-    _process("BATTERY");
+    _process(BATTERY);
   #endif
   // present each sensor
   for (int i = 0; i < 255; i++) {
@@ -1037,11 +1068,22 @@ void NodeManager::presentation() {
     _sensors[i]->presentation();
   }
   #if DEBUG == 1
-    Serial.println("Ready");
+    Serial.println("READY");
     Serial.println("");
   #endif
 }
 
+
+// setup NodeManager
+void NodeManager::setup() {
+  #if DEBUG == 1
+    Serial.print("MY I=");
+    Serial.print(getNodeId());
+    Serial.print(" M=");
+    Serial.println(getControllerConfig().isMetric);
+  #endif
+}
+
 // run the main function for all the register sensors
 void NodeManager::loop() {
   #if SLEEP_MANAGER == 1
@@ -1049,7 +1091,7 @@ void NodeManager::loop() {
     if (_sleep_mode != IDLE &&  _sleep_time != 0) {
       #if POWER_MANAGER == 1
         // turn on the pin powering all the sensors
-        powerOn();
+        if (_auto_power_pins) powerOn();
       #endif
       // run loop for all the registered sensors
       for (int i = 0; i < 255; i++) {
@@ -1059,10 +1101,12 @@ void NodeManager::loop() {
       }
       #if POWER_MANAGER == 1
         // turn off the pin powering all the sensors
-        powerOff();
+        if (_auto_power_pins) powerOff();
+      #endif
+      #if SLEEP_MANAGER == 1
+        // continue/start sleeping as requested
+        _sleep();
       #endif
-      // continue/start sleeping as requested
-      _sleep();
     }
   #endif
 }
@@ -1070,15 +1114,15 @@ void NodeManager::loop() {
 // dispacth inbound messages
 void NodeManager::receive(const MyMessage &message) {
   #if DEBUG == 1
-    Serial.print("Recv from=");
+    Serial.print("RECV F=");
     Serial.print(message.sender);
-    Serial.print(" id=");
+    Serial.print(" I=");
     Serial.print(message.sensor);
-    Serial.print(" cmd=");
+    Serial.print(" C=");
     Serial.print(message.getCommand());
-    Serial.print(" type=");
+    Serial.print(" T=");
     Serial.print(message.type);
-    Serial.print(" data=");
+    Serial.print(" D=");
     Serial.println(message.getString());
   #endif
   // process incoming service messages
@@ -1100,15 +1144,41 @@ void NodeManager::receive(const MyMessage &message) {
   }
 }
 
+// send a message to the network
+void NodeManager::_send(MyMessage & message) {
+  // send the message, multiple times if requested
+  for (int i = 0; i < _retries; i++) {
+    // if configured, sleep beetween each send
+    if (_sleep_between_send > 0) sleep(_sleep_between_send);
+    #if DEBUG == 1
+      Serial.print("SEND D=");
+      Serial.print(message.destination);
+      Serial.print(" I=");
+      Serial.print(message.sensor);
+      Serial.print(" C=");
+      Serial.print(message.getCommand());
+      Serial.print(" T=");
+      Serial.print(message.type);
+      Serial.print(" S=");
+      Serial.print(message.getString());
+      Serial.print(" I=");
+      Serial.print(message.getInt());
+      Serial.print(" F=");
+      Serial.println(message.getFloat());
+    #endif
+    send(message);
+  }
+}
+
 // process a service message
 void NodeManager::_process(const char * message) {
   // HELLO: hello request
   if (strcmp(message, "HELLO") == 0) {
-    send(_msg.set(message));
+    _send(_msg.set(message));
   }
   #if BATTERY_MANAGER == 1
     // BATTERY: return the battery level
-    else if (strcmp(message, "BATTERY") == 0) {
+    else if (strcmp(message, BATTERY) == 0) {
       // measure the board vcc
       float volt = _getVcc();
       // calculate the percentage
@@ -1116,40 +1186,40 @@ void NodeManager::_process(const char * message) {
       if (percentage > 100) percentage = 100;
       if (percentage < 0) percentage = 0;
       #if DEBUG == 1
-        Serial.print("Battery v=");
+        Serial.print("BATT V=");
         Serial.print(volt);
-        Serial.print(", %=");
+        Serial.print(" P=");
         Serial.println(percentage);
       #endif
       #if BATTERY_MANAGER == 1 && BATTERY_SENSOR == 1
         // report battery voltage
         MyMessage battery_msg(BATTERY_CHILD_ID, V_VOLTAGE);
-        send(battery_msg.set(volt, 2));
+        _send(battery_msg.set(volt, 2));
       #endif
       // report battery level percentage
       sendBatteryLevel(percentage);
     }
   #endif
   // REBOOT: reboot the board
-  else if (strcmp(message, "REBOOT") == 0 && _reboot_pin > -1) {
+  else if (strcmp(message, REBOOT) == 0 && _reboot_pin > -1) {
     #if DEBUG == 1
-      Serial.println("Reboot");
+      Serial.println(REBOOT);
     #endif
     // set the reboot pin connected to RST to low so to reboot the board
-    send(_msg.set(message));
+    _send(_msg.set(message));
     digitalWrite(_reboot_pin, LOW);
   }
   // CLEAR: clear the user's eeprom
-  else if (strcmp(message, "CLEAR") == 0) {
+  else if (strcmp(message, CLEAR) == 0) {
     #if DEBUG == 1
-      Serial.println("Clear");
+      Serial.println(CLEAR);
     #endif
     for (int i = 0; i <= EEPROM_LAST_ID; i++) saveState(i, 0xFF);
-    send(_msg.set(message));
+    _send(_msg.set(message));
   }
   // VERSION: send back the extension's version
   else if (strcmp(message, "VERSION") == 0) {
-    send(_msg.set(VERSION, 1));
+    _send(_msg.set(VERSION, 1));
   }
   #if REMOTE_CONFIGURATION == 1
     // IDxxx: change the node id to the provided one. E.g. ID025: change the node id to 25. Requires a reboot/restart
@@ -1162,14 +1232,14 @@ void NodeManager::_process(const char * message) {
       s[3] = '\0';
       int node_id = atoi(s);
       #if DEBUG == 1
-        Serial.print("Set node_id=");
+        Serial.print("MY I=");
         Serial.println(node_id);
       #endif
       // Save static ID to eeprom
       hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (uint8_t)node_id);
       // reboot the board
       #if REBOOT_PIN == 1
-        _process("REBOOT");
+        _process(REBOOT);
       #endif
     }
     #if SLEEP_MANAGER == 1
@@ -1181,7 +1251,7 @@ void NodeManager::_process(const char * message) {
         s[1] = '\0';
         _sleep_mode = atoi(s);
         #if DEBUG == 1
-          Serial.print("Set sleep mode=");
+          Serial.print("SLEEP M=");
           Serial.println(_sleep_mode);
         #endif
         #if PERSIST == 1
@@ -1189,7 +1259,7 @@ void NodeManager::_process(const char * message) {
           saveState(EEPROM_SLEEP_SAVED, 1);
           saveState(EEPROM_SLEEP_MODE, _sleep_mode);
         #endif
-        send(_msg.set(message));
+        _send(_msg.set(message));
       }
       // INTVLnnnX: set and save the wait/sleep interval to nnn where X is S=Seconds, M=mins, H=Hours, D=Days. E.g. INTVL010M would be 10 minutes
       else if (strlen(message) == 9 && strncmp("INTVL", message, strlen("INTVL")) == 0) {
@@ -1212,9 +1282,9 @@ void NodeManager::_process(const char * message) {
         s[3] = '\0';
         _sleep_time = atoi(s);
         #if DEBUG == 1
-          Serial.print("Set sleep time=");
+          Serial.print("SLEEP T=");
           Serial.print(_sleep_time);
-          Serial.print(", unit=");
+          Serial.print(" U=");
           Serial.println(_sleep_unit);
         #endif
         #if PERSIST == 1
@@ -1231,23 +1301,24 @@ void NodeManager::_process(const char * message) {
           saveState(EEPROM_SLEEP_TIME_MAJOR, major);
         #endif
         // interval set, reply back with the same message to acknowledge.
-        send(_msg.set(message));
+        _send(_msg.set(message));
       }
     #endif
     // end remote configuration
   #endif
   // WAKEUP: when received after a sleeping cycle or during wait, abort the cycle and stay awake
   #if SLEEP_MANAGER == 1
-    else if (strcmp(message, "WAKEUP") == 0) {
+    else if (strcmp(message, WAKEUP) == 0) {
       #if DEBUG == 1
-        Serial.println("Requested wake-up");
+        Serial.println(WAKEUP);
       #endif
-      send(_msg.set(message));
+      _send(_msg.set(message));
       _sleep_mode = IDLE;
     }
   #endif
 }
 
+#if SLEEP_MANAGER == 1
 // wrapper of smart sleep
 void NodeManager::_sleep() {
   // calculate the seconds to sleep
@@ -1257,13 +1328,13 @@ void NodeManager::_sleep() {
   else if (_sleep_unit == DAYS) sleep_sec = sleep_sec * 43200;
   long sleep_ms = sleep_sec * 1000;
   #if DEBUG == 1
-    Serial.print("Sleeping for ");
+    Serial.print("SLEEP ");
     Serial.print(sleep_sec);
     Serial.println("s");
   #endif
   #if SERVICE_MESSAGES == 1
     // notify the controller I'm going to sleep
-    send(_msg.set("SLEEPING"));
+    _send(_msg.set("SLEEPING"));
   #endif
   #if DEBUG == 1
     // print a new line to separate the different cycles
@@ -1292,25 +1363,24 @@ void NodeManager::_sleep() {
         interrupt_mode = _interrupt_2_mode;
       }
       #if DEBUG == 1
-        Serial.print("Woke up pin=");
+        Serial.print("WAKE P=");
         Serial.print(pin_number);
-        Serial.print(", mode=");
+        Serial.print(", M=");
         Serial.println(interrupt_mode);
       #endif
-      // when waking up from an interrupt on the wakup pin, stop sleeping
-      if (_sleep_interrupt_pin == pin_number) _sleep_mode = IDLE;
-  //    if (_interrupt_abort_sleep) _sleep_mode = IDLE;
-      // restore the interrupt pin value to its original value
-      // if (pin_number > 0) digitalWrite(pin_number, interrupt_mode == FALLING ? HIGH : LOW);
+      #if SLEEP_MANAGER == 1
+        // when waking up from an interrupt on the wakup pin, stop sleeping
+        if (_sleep_interrupt_pin == pin_number) _sleep_mode = IDLE;
+      #endif
     }
   }
   // coming out of sleep
   #if DEBUG == 1
-    Serial.println("Awake");
+    Serial.println(AWAKE);
   #endif
   #if SERVICE_MESSAGES == 1
     // notify the controller I am awake
-    send(_msg.set("AWAKE"));
+    _send(_msg.set(AWAKE));
   #endif
   #if BATTERY_MANAGER == 1
     // keep track of the number of sleeping cycles
@@ -1318,11 +1388,12 @@ void NodeManager::_sleep() {
     // battery has to be reported after the configured number of sleep cycles
     if (_battery_report_cycles == _cycles) {
       // time to report the battery level again
-      _process("BATTERY");
+      _process(BATTERY);
       _cycles = 0;
     }
   #endif
 }
+#endif
 
 
 // return the next available child_id
@@ -1335,6 +1406,7 @@ int NodeManager::_getAvailableChildId() {
   }
 }
 
+#if BATTERY_MANAGER == 1
 // return vcc in V
 float NodeManager::_getVcc() {
   // Measure Vcc against 1.1V Vref
@@ -1355,7 +1427,7 @@ float NodeManager::_getVcc() {
   // return Vcc in mV
   return (float)((1125300UL) / ADC) / 1000;
 }
-
+#endif
 
 // guess the initial value of a digital output based on the configured interrupt mode
 int NodeManager::_getInterruptInitialValue(int mode) {
diff --git a/NodeManagerTemplate/NodeManager.h b/NodeManagerTemplate/NodeManager.h
index 8c731f4..7fc3eda 100644
--- a/NodeManagerTemplate/NodeManager.h
+++ b/NodeManagerTemplate/NodeManager.h
@@ -7,36 +7,6 @@
 
 #include <Arduino.h>
 
-/***********************************
-   Sensors types
-*/
-// Generic analog sensor, return a pin's analog value or its percentage
-#define SENSOR_ANALOG_INPUT 0
-// LDR sensor, return the light level of an attached light resistor in percentage
-#define SENSOR_LDR 1
-// Thermistor sensor, return the temperature based on the attached thermistor
-#define SENSOR_THERMISTOR 2
-// Generic digital sensor, return a pin's digital value
-#define SENSOR_DIGITAL_INPUT 3
-// Generic digital output sensor, allows setting the digital output of a pin to the requested value
-#define SENSOR_DIGITAL_OUTPUT 4
-// Relay sensor, allows activating the relay
-#define SENSOR_RELAY 5
-// Latching Relay sensor, allows activating the relay with a pulse
-#define SENSOR_LATCHING_RELAY 6
-// DHT11/DHT22 sensors, return temperature/humidity based on the attached DHT sensor
-#define SENSOR_DHT11 7
-#define SENSOR_DHT22 8
-// SHT21 sensor, return temperature/humidity based on the attached SHT21 sensor
-#define SENSOR_SHT21 9
-// Generic switch, wake up the board when a pin changes status
-#define SENSOR_SWITCH 10
-// Door sensor, wake up the board and report when an attached magnetic sensor has been opened/closed
-#define SENSOR_DOOR 11
-// Motion sensor, wake up the board and report when an attached PIR has triggered
-#define SENSOR_MOTION 12
-// DS18B20 sensor, return the temperature based on the attached sensor
-#define SENSOR_DS18B20 13
 
 /***********************************
    Constants
@@ -71,54 +41,136 @@
 #define EEPROM_SLEEP_UNIT 4
 
 // define NodeManager version
-#define VERSION 1.0
+#define VERSION 1.1
+
+/************************************
+ * Include user defined configuration settings
+ */
+ 
+#include "config.h"
 
 /***********************************
-   Configuration settings
+   Default configuration settings
 */
-// default configuration settings
 
 // if enabled, will load the sleep manager library. Sleep mode and sleep interval have to be configured to make the board sleeping/waiting
-#define SLEEP_MANAGER 1
+#ifndef SLEEP_MANAGER
+  #define SLEEP_MANAGER 1
+#endif
 // if enabled, enable the capability to power on sensors with the arduino's pins to save battery while sleeping
-#define POWER_MANAGER 1
+#ifndef POWER_MANAGER
+  #define POWER_MANAGER 1
+#endif
 // if enabled, will load the battery manager library to allow the battery level to be reported automatically or on demand
-#define BATTERY_MANAGER 1
+#ifndef BATTERY_MANAGER
+  #define BATTERY_MANAGER 1
+#endif
 // if enabled, allow modifying the configuration remotely by interacting with the configuration child id
-#define REMOTE_CONFIGURATION 1
+#ifndef REMOTE_CONFIGURATION
+  #define REMOTE_CONFIGURATION 1
+#endif
 // if enabled, persist the configuration settings on EEPROM
-#define PERSIST 0
+#ifndef PERSIST
+  #define PERSIST 0
+#endif
 
 // if enabled, enable debug messages on serial port
-#define DEBUG 1
+#ifndef DEBUG
+  #define DEBUG 1
+#endif
 
 // if enabled, send a SLEEPING and AWAKE service messages just before entering and just after leaving a sleep cycle
-#define SERVICE_MESSAGES 1
+#ifndef SERVICE_MESSAGES
+  #define SERVICE_MESSAGES 1
+#endif
 // if enabled, a battery sensor will be created at BATTERY_CHILD_ID and will report vcc voltage together with the battery level percentage
-#define BATTERY_SENSOR 1
+#ifndef BATTERY_SENSOR
+  #define BATTERY_SENSOR 1
+#endif
 
 // the child id used to allow remote configuration
-#define CONFIGURATION_CHILD_ID 200
+#ifndef CONFIGURATION_CHILD_ID
+  #define CONFIGURATION_CHILD_ID 200
+#endif
 // the child id used to report the battery voltage to the controller
-#define BATTERY_CHILD_ID 201
+#ifndef BATTERY_CHILD_ID
+  #define BATTERY_CHILD_ID 201
+#endif
 
 // Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR
-#define MODULE_ANALOG_INPUT 1
+#ifndef MODULE_ANALOG_INPUT
+  #define MODULE_ANALOG_INPUT 0
+#endif
 // Enable this module to use one of the following sensors: SENSOR_DIGITAL_INPUT
-#define MODULE_DIGITAL_INPUT 1
+#ifndef MODULE_DIGITAL_INPUT
+  #define MODULE_DIGITAL_INPUT 0
+#endif
 // Enable this module to use one of the following sensors: SENSOR_DIGITAL_OUTPUT, SENSOR_RELAY, SENSOR_LATCHING_RELAY
-#define MODULE_DIGITAL_OUTPUT 1
+#ifndef MODULE_DIGITAL_OUTPUT
+  #define MODULE_DIGITAL_OUTPUT 0
+#endif
 // Enable this module to use one of the following sensors: SENSOR_SHT21
-#define MODULE_SHT21 0
+#ifndef MODULE_SHT21
+  #define MODULE_SHT21 0
+#endif
 // Enable this module to use one of the following sensors: SENSOR_DHT11, SENSOR_DHT22
-#define MODULE_DHT 0
+#ifndef MODULE_DHT
+  #define MODULE_DHT 0
+#endif
 // Enable this module to use one of the following sensors: SENSOR_SWITCH, SENSOR_DOOR, SENSOR_MOTION
-#define MODULE_SWITCH 0
+#ifndef MODULE_SWITCH
+  #define MODULE_SWITCH 0
+#endif
 // Enable this module to use one of the following sensors: SENSOR_DS18B20
-#define MODULE_DS18B20 0
+#ifndef MODULE_DS18B20
+  #define MODULE_DS18B20 0
+#endif
 
-// include user defined configuration difrectives
-#include "config.h"
+
+/***********************************
+   Sensors types
+*/
+#if MODULE_ANALOG_INPUT == 1
+  // Generic analog sensor, return a pin's analog value or its percentage
+  #define SENSOR_ANALOG_INPUT 1
+  // LDR sensor, return the light level of an attached light resistor in percentage
+  #define SENSOR_LDR 2
+  // Thermistor sensor, return the temperature based on the attached thermistor
+  #define SENSOR_THERMISTOR 3
+#endif
+#if MODULE_DIGITAL_INPUT == 1
+  // Generic digital sensor, return a pin's digital value
+  #define SENSOR_DIGITAL_INPUT 4
+#endif
+#if MODULE_DIGITAL_OUTPUT == 1
+  // Generic digital output sensor, allows setting the digital output of a pin to the requested value
+  #define SENSOR_DIGITAL_OUTPUT 5
+  // Relay sensor, allows activating the relay
+  #define SENSOR_RELAY 6
+  // Latching Relay sensor, allows activating the relay with a pulse
+  #define SENSOR_LATCHING_RELAY 7
+#endif
+#if MODULE_DHT == 1
+  // DHT11/DHT22 sensors, return temperature/humidity based on the attached DHT sensor
+  #define SENSOR_DHT11 8
+  #define SENSOR_DHT22 9
+#endif
+#if MODULE_SHT21 == 1
+  // SHT21 sensor, return temperature/humidity based on the attached SHT21 sensor
+  #define SENSOR_SHT21 10
+#endif
+#if MODULE_SWITCH == 1
+  // Generic switch, wake up the board when a pin changes status
+  #define SENSOR_SWITCH 11
+  // Door sensor, wake up the board and report when an attached magnetic sensor has been opened/closed
+  #define SENSOR_DOOR 12
+  // Motion sensor, wake up the board and report when an attached PIR has triggered
+  #define SENSOR_MOTION 13
+#endif
+#if MODULE_DS18B20 == 1
+  // DS18B20 sensor, return the temperature based on the attached sensor
+  #define SENSOR_DS18B20 14
+#endif
 
 /***********************************
   Libraries
@@ -158,7 +210,7 @@ class PowerManager {
   public:
     PowerManager() {};
     // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand
-    void setPowerPins(int ground_pin, int vcc_pin, long wait = 0);
+    void setPowerPins(int ground_pin, int vcc_pin, long wait = 10);
     void powerOn();
     void powerOff();
   private:
@@ -201,10 +253,16 @@ class Sensor {
     void setValueType(int value);
     // for float values, set the float precision (default: 2)
     void setFloatPrecision(int value);
+    // optionally sleep interval in milliseconds before sending each message to the radio network (default: 0)
+    void setSleepBetweenSend(int value);
     #if POWER_MANAGER == 1
       // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand
       void setPowerPins(int ground_pin, int vcc_pin, long wait = 0);
+      // if enabled the pins will be automatically powered on while awake and off during sleeping (default: true)
+      void setAutoPowerPins(bool value);
+      // manually turn the power on
       void powerOn();
+      // manually turn the power off
       void powerOff();
     #endif
     // define what to do at each stage of the sketch
@@ -218,6 +276,7 @@ class Sensor {
     virtual void onReceive(const MyMessage & message) = 0;
   protected:
     MyMessage _msg;
+    int _sleep_between_send = 0;
     int _pin = -1;
     int _child_id;
     int _presentation = S_CUSTOM;
@@ -231,6 +290,7 @@ class Sensor {
     void _send(MyMessage & msg);
     #if POWER_MANAGER  == 1
       PowerManager _powerManager;
+      bool _auto_power_pins = true;
     #endif
     int _value_type = TYPE_INTEGER;
     int _float_precision = 2;
@@ -346,6 +406,8 @@ class SensorDigitalOutput: public Sensor {
 class SensorRelay: public SensorDigitalOutput {
   public:
     SensorRelay(int child_id, int pin);
+    // define what to do at each stage of the sketch
+    void onLoop();
 };
 
 /*
@@ -458,6 +520,8 @@ class NodeManager {
     NodeManager();
     // the pin to connect to the RST pin to reboot the board (default: 4)
     void setRebootPin(int value);
+    // send the same service message multiple times (default: 1)
+    void setRetries(int value);
     #if BATTERY_MANAGER == 1
       // the expected vcc when the batter is fully discharged, used to calculate the percentage (default: 2.7)
       void setBatteryMin(float value);
@@ -479,6 +543,8 @@ class NodeManager {
     #endif
     // configure the interrupt pin and mode. Mode can be CHANGE, RISING, FALLING (default: MODE_NOT_DEFINED)
     void setInterrupt(int pin, int mode, int pull = -1);
+    // optionally sleep interval in milliseconds before sending each message to the radio network (default: 0)
+    void setSleepBetweenSend(int value);
     // register a built-in sensor
     int registerSensor(int sensor_type, int pin = -1, int child_id = -1);
     // register a custom sensor
@@ -488,13 +554,17 @@ class NodeManager {
     #if POWER_MANAGER == 1
       // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand
       void setPowerPins(int ground_pin, int vcc_pin, long wait = 10);
+      // if enabled the pins will be automatically powered on while awake and off during sleeping (default: true)
+      void setAutoPowerPins(bool value);
+      // manually turn the power on
       void powerOn();
+      // manually turn the power off
       void powerOff();
     #endif
-
     // hook into the main sketch functions
     void before();
     void presentation();
+    void setup();
     void loop();
     void receive(const MyMessage & msg);
   private:
@@ -511,12 +581,15 @@ class NodeManager {
       int _cycles = 0;
       float _getVcc();
     #endif
-
     #if POWER_MANAGER == 1
       // to optionally controller power pins
       PowerManager _powerManager;
+      bool _auto_power_pins = true;
     #endif
     MyMessage _msg;
+    void _send(MyMessage & msg);
+    int _sleep_between_send = 0;
+    int _retries = 1;
     int _interrupt_1_mode = MODE_NOT_DEFINED;
     int _interrupt_2_mode = MODE_NOT_DEFINED;
     int _interrupt_1_pull = -1;
diff --git a/NodeManagerTemplate/NodeManagerTemplate.ino b/NodeManagerTemplate/NodeManagerTemplate.ino
index 62b3a0c..90ea075 100644
--- a/NodeManagerTemplate/NodeManagerTemplate.ino
+++ b/NodeManagerTemplate/NodeManagerTemplate.ino
@@ -26,29 +26,21 @@ NodeManager nodeManager;
 void before() {
   // setup the serial port baud rate
   Serial.begin(9600);  
-  // connect pin 4 to RST to enable rebooting the board with a message
-  nodeManager.setRebootPin(4);
-  // set battery minimum voltage. This will be used to calculate the level percentage
-  //nodeManager.setBatteryMin(1.8);
-  // instruct the board to sleep for 10 minutes for each cycle
-  //nodeManager.setSleep(SLEEP,10,MINUTES);
-  // When pin 3 is connected to ground, the board will stop sleeping
-  //nodeManager.setSleepInterruptPin(3)
-  // all the sensors' vcc and ground are connected to pin 6 (vcc) and 7 (ground). NodeManager will enable the vcc pin every time just before loop() and wait for 100ms for the sensors to settle
-  //nodeManager.setPowerPins(6,7,100);
-  // register a thermistor sensor attached to pin A2
-  //nodeManager.registerSensor(SENSOR_THERMISTOR,A2);
-  // register a LDR sensor attached to pin A1 and average 3 samples
-  //int sensor_ldr = nodeManager.registerSensor(SENSOR_LDR,A1);
-  //((SensorLDR*)nodeManager.get(sensor_ldr))->setSamples(3);
-  
+  /*
+   * Register below your sensors
+   */
+
+
+  /*
+   * Register above your sensors
+   */
   nodeManager.before();
 }
 
 // presentation
 void presentation() {
   // Send the sketch version information to the gateway and Controller
-	sendSketchInfo("NodeManager", "1.0");
+	sendSketchInfo(SKETCH_NAME,SKETCH_VERSION);
   // call NodeManager presentation routine
   nodeManager.presentation();
 
@@ -56,6 +48,8 @@ void presentation() {
 
 // setup
 void setup() {
+  // call NodeManager setup routine
+  nodeManager.setup();
 }
 
 // loop
diff --git a/NodeManagerTemplate/config.h b/NodeManagerTemplate/config.h
index f22a56c..594d112 100644
--- a/NodeManagerTemplate/config.h
+++ b/NodeManagerTemplate/config.h
@@ -1,12 +1,21 @@
 #ifndef config_h
 #define config_h
 
+/**********************************
+ * Sketch configuration
+ */
+
+#define SKETCH_NAME "NodeManagerTemplate"
+#define SKETCH_VERSION "1.1"
+
 /**********************************
  * MySensors configuration
  */
-//#define MY_DEBUG
 #define MY_RADIO_NRF24
-
+//#define MY_RF24_ENABLE_ENCRYPTION
+//#define MY_DEBUG
+//#define MY_RF24_CHANNEL 76
+//#define MY_NODE_ID 100
 
 /***********************************
  * NodeManager configuration
@@ -19,7 +28,7 @@
 #define BATTERY_MANAGER 1
 // if enabled, allow modifying the configuration remotely by interacting with the configuration child id
 #define REMOTE_CONFIGURATION 1
-// if enabled, persist the configuration settings on EEPROM
+// if enabled, persist the remote configuration settings on EEPROM
 #define PERSIST 0
 
 // if enabled, enable debug messages on serial port
@@ -36,10 +45,10 @@
 #define MODULE_DIGITAL_INPUT 1
 // Enable this module to use one of the following sensors: SENSOR_DIGITAL_OUTPUT, SENSOR_RELAY, SENSOR_LATCHING_RELAY
 #define MODULE_DIGITAL_OUTPUT 1
-// Enable this module to use one of the following sensors: SENSOR_SHT21
-#define MODULE_SHT21 0
 // Enable this module to use one of the following sensors: SENSOR_DHT11, SENSOR_DHT22
 #define MODULE_DHT 0
+// Enable this module to use one of the following sensors: SENSOR_SHT21
+#define MODULE_SHT21 0
 // Enable this module to use one of the following sensors: SENSOR_SWITCH, SENSOR_DOOR, SENSOR_MOTION
 #define MODULE_SWITCH 0
 // Enable this module to use one of the following sensors: SENSOR_DS18B20
-- 
GitLab