Ok, this is my Light Actuator Node, I'm developing a all in one solution, so the code ended up bit complex and a complete mess, I still need to clean it up...
// Enable debug prints to serial monitor
//#define MY_DEBUG
//#define MY_DEBUG_X
// Enable and select radio type attached
#define MY_RADIO_NRF24
// Enabled repeater feature for this node
#define MY_REPEATER_FEATURE
//#define MY_NODE_ID 1
#include <SPI.h>
#include <MySensors.h>
#include <Bounce2.h>
#define RELAY_START_ID 1
#define SWITCH_START_ID 10
// EDIT THIS VALUES--------------------------------
#define REFRESH_INTERVAL 30000
#define RETRY_REPEATS 5
#define MESSAGE_REPEATS 5
#define MESSAGE_REPEATS_DELAY 10
int RELAYS[] = { 0, 6 }; //5,6
int SWITCH[] = { 7, 8 }; //7,8
// ------------------------------------------------
#define RELAY_ON 1
#define RELAY_OFF 0
const int numberOfActuators = sizeof(RELAYS) / sizeof(int);
Bounce *debouncers[numberOfActuators];
MyMessage *messagesRelay[numberOfActuators];
MyMessage *messagesSwitch[numberOfActuators];
bool oldvalues[numberOfActuators];
int errorSending[numberOfActuators];
unsigned long lastRefreshTime[numberOfActuators];
// MY DEBUG -------------------------------------
void SerialPrintln(String text) {
#ifndef MY_DEBUG_X
return;
#endif
Serial.println(text);
}
void SerialPrintln(int text) {
#ifndef MY_DEBUG_X
return;
#endif
Serial.println(text);
}
void SerialPrint(String text) {
#ifndef MY_DEBUG_X
return;
#endif
Serial.print(text);
}
void SerialPrint(int text) {
#ifndef MY_DEBUG_X
return;
#endif
Serial.print(text);
}
//-------------------------------------
int relay_child_id(int index) {
return (index + RELAY_START_ID);
}
int switch_child_id(int index) {
return (index + SWITCH_START_ID);
}
void setup()
{
SerialPrint("Loading ");
SerialPrint(numberOfActuators);
SerialPrintln(" actuators");
for (int i = 0; i < numberOfActuators; i++) {
SerialPrint("Starting Child ");
SerialPrintln(i);
//Start Messages
messagesRelay[i] = new MyMessage(relay_child_id(i), V_STATUS);
messagesSwitch[i] = new MyMessage(switch_child_id(i), V_STATUS);
// Setup the button
if (SWITCH[i] > 0) {
pinMode(SWITCH[i], INPUT);
digitalWrite(SWITCH[i], HIGH); // Activate internal pull-up
debouncers[i] = new Bounce();//Create Debouncer
debouncers[i]->attach(SWITCH[i]);
debouncers[i]->interval(5);
debouncers[i]->update();
oldvalues[i] = debouncers[i]->read();//Starts Default Switch State
}
// Make sure relays are off when starting up
if (RELAYS[i] > 0) {
digitalWrite(RELAYS[i], RELAY_OFF);
pinMode(RELAYS[i], OUTPUT);
}
}
}
void SerialPrintLn(String thisIsAString) {
SerialPrintln(thisIsAString);
}
void presentation() {
char buffer[50];
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Light Actuator", "2.0");
// Register all lights and switches to GW
for (int i = 0; i < numberOfActuators; i++) {
if (RELAYS[i] > 0) {
sprintf(buffer, "Light %d", relay_child_id(i));
SerialPrint("Presenting ");
SerialPrintln(buffer);
present(relay_child_id(i), S_BINARY, buffer);
}
if (SWITCH[i] > 0 && RELAYS[i] == 0) {
sprintf(buffer, "Switch %d", switch_child_id(i));
SerialPrint("Presenting ");
SerialPrintln(buffer);
present(switch_child_id(i), S_BINARY, buffer);
}
}
}
bool messageRepeat(MyMessage &message, bool ack = true) {
int repeat = 1;
int repeatdelay = 0;
int index;
index = relay_index_id(message.sensor);
if (index < 0) {
index = switch_index_id(message.sensor);
}
if (index < 0) {
SerialPrintln("ERROR IN INDEX");
return false;
}
SerialPrint("Sending message of child ");
SerialPrintln(message.sensor);
while (repeat <= MESSAGE_REPEATS) {
if (send(message, ack)) {
SerialPrintln("Send OK");
errorSending[index] = 0;
return true;
} else {
SerialPrint("Send ERROR ");
SerialPrintln(repeat);
}
repeat++;
repeatdelay = repeatdelay + MESSAGE_REPEATS_DELAY;
wait(repeatdelay);
}
if (ack == true)
errorSending[index]++;
return false;
}
void status_update(int index) {
int value;
bool resend;
if (errorSending[index] > RETRY_REPEATS) {
errorSending[index] = 0;
return;
} else if (errorSending[index] > 0) {
SerialPrint("Lets send again ");
SerialPrintln(index);
resend = true;
} else {
resend = false;
}
if ( ( lastRefreshTime[index] == 0 ) or (millis() - lastRefreshTime[index] >= REFRESH_INTERVAL) or ( resend == true ) )
{
if (lastRefreshTime[index] == 0) {
lastRefreshTime[index] = millis();
}
SerialPrint("Sending Update of index ");
SerialPrintln(index);
//Update Relay
if (RELAYS[index] > 0) {
value = digitalRead(RELAYS[index]);
messageRepeat(messagesRelay[index]->set(value == RELAY_ON ? true : false), resend);
}
//Update Button
if (SWITCH[index] > 0 && RELAYS[index] == 0) {
debouncers[index]->update();
value = debouncers[index]->read();
messageRepeat(messagesSwitch[index]->set(value), resend);
}
lastRefreshTime[index] = millis();
}
}
void processLight(int index) {
bool value;
//Update State Of Light In Controller
status_update(index);
if (SWITCH[index] <= 0)
return;
debouncers[index]->update();
value = debouncers[index]->read();
//Process Switch
if (value != oldvalues[index]) {
//Process Relays
if (RELAYS[index] > 0)
lightToggle(index);
//Process Switch
if (SWITCH[index] > 0 && RELAYS[index] == 0)
messageRepeat(messagesSwitch[index]->set(value), true);
}
oldvalues[index] = value;
//Checks If Debounce State Changed During Process
debouncers[index]->update();
value = debouncers[index]->read();
if (value != oldvalues[index]) {
SerialPrintln("Value Changed During Process");
processLight(index);
}
}
void lightToggle(int index) { //Toggles Light State
if (RELAYS[index] <= 0)
return;
int value = digitalRead(RELAYS[index]);
lightUpdate(index, (value == LOW ? HIGH : LOW));
}
void lightUpdate(int index, int value) { //Updates Light State
if (RELAYS[index] <= 0)
return;
//Changes Light State
digitalWrite(RELAYS[index], value);
SerialPrint("--> Relay Light ");
SerialPrint(RELAYS[index]);
SerialPrint(" is ");
SerialPrintln(value);
//Sends Message To Controller
messageRepeat(messagesRelay[index]->set(value == RELAY_ON ? true : false));
}
void loop()
{
for (int i = 0; i < numberOfActuators; i++) {
processLight(i);
}
}
int relay_index_id(int sensor) {
if (sensor < RELAY_START_ID)
return -1;
else if (sensor >= SWITCH_START_ID)
return -2;
else if (sensor > numberOfActuators)
return -3;
else
return sensor - RELAY_START_ID;
}
int switch_index_id(int sensor) {
if (sensor < SWITCH_START_ID)
return -1;
else if (sensor >= ( SWITCH_START_ID + numberOfActuators) )
return -2;
else
return sensor - SWITCH_START_ID;
}
void receive(const MyMessage &message) {
int index;
//Only Process V_STATUS Message
if (message.type != V_STATUS)
return;
//Only Process Relay Status
index = relay_index_id(message.sensor);
if (index < 0)
return;
if (message.isAck()) {
SerialPrintln("--------------------");
SerialPrintln("->>>> Ack To Relay Message <<<<<-");
SerialPrint("Sensor: ");
SerialPrint(message.sensor);
SerialPrint(" Index: ");
SerialPrint(relay_index_id(message.sensor));
SerialPrint(" Status: ");
SerialPrintln(message.getBool());
} else {
if (RELAYS[index] <= 0)
return;
digitalWrite(RELAYS[index], message.getBool());
SerialPrintln("--------------------");
SerialPrintln("New Status Message");
SerialPrint("Sensor: ");
SerialPrint(message.sensor);
SerialPrint(" Index: ");
SerialPrint(relay_index_id(message.sensor));
SerialPrint(" Status: ");
SerialPrintln(message.getBool());
//Updates Status On Other Controllers
messageRepeat(messagesRelay[index]->set(message.getBool()));
}
}