Hi!
The design is highly special for my unique use case, and the code is long (2000 rows) - this is the reason why I have asked for a general idea in the first place if there is a known bug in the ethernet/mqtt library, or a known limitation of the hardware. But I try to attach the code now.
Please keep in mind that this code was intended to use only for myself, so there are places where it is not really nice, but is a working solution. I have started extending the code of Jeroen Schaeken's MqttRelayWithState in the first place (arduinoHouse/mqttRelayWithState.ino at master · jschaeke/arduinoHouse · GitHub) so you can recognize traits of that code in mine but it has been completely rewritten with a lot additional functionalities.
I do not have a diagram at this point but i will create it soon (I only have an excel table to have a list of pins which pin does what).
A question at first: I use pins 11, 12 too (but not 10 or 13). Somewhere I read that pins 10-11-12-13 are used by the ethernet shield but I am nut sure...
So anyway, here is my sketch (sensitive parts are exchanged with A,B,X,Y,Z letters):
#include <Ethernet.h>
#include <PubSubClient.h>
#include <Bounce2.h>
#include <AsyncDelay.h>
#include <DHT.h>
// temp & hum sensors
#define DHT1PIN 2
#define DHT2PIN 3
#define DHT3PIN 4
#define DHT4PIN 5
#define DHT5PIN 58
#define DHT6PIN 59
#define DHTTYPE DHT21
DHT dht1(DHT1PIN, DHTTYPE);
DHT dht2(DHT2PIN, DHTTYPE);
DHT dht3(DHT3PIN, DHTTYPE);
DHT dht4(DHT4PIN, DHTTYPE);
DHT dht5(DHT5PIN, DHTTYPE);
DHT dht6(DHT6PIN, DHTTYPE);
// shutters
#define SHUTTER1UPPIN 60
#define SHUTTER1DOWNPIN 61
#define SHUTTER2UPPIN 62
#define SHUTTER2DOWNPIN 63
#define SHUTTER1UPSWITCH 64
#define SHUTTER1DOWNSWITCH 65
#define SHUTTER2UPSWITCH 66
#define SHUTTER2DOWNSWITCH 67
// Update these with values suitable for your network.
byte mac[] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
byte server[] = { A, B, X, Y };
byte ip[] = { A, B, X, Y };
EthernetClient ethernetClient;
PubSubClient client(ethernetClient);
long lastMsg = 0;
char msg[50];
int value = 0;
AsyncDelay delay_rainsensor;
AsyncDelay delay_tempsensor;
AsyncDelay delay_closetLED1;
AsyncDelay delay_closetLED2;
AsyncDelay delay_closetLED3;
const char* outTopic = "stat/arduinomega/state";
const char* outSceneTopic = "stat/arduinomega/";
const char* outSensorTopic = "tele/arduinomega/SENSOR";
//const char* inTopic = "cmnd/arduinomega/POWER/#";
const char* inTopic2 = "cmnd/arduinomega/DEF";
const char* inTopic = "cmnd/arduinomega/#";
const char* outRelayTopic = "stat/arduinomega/POWER";
const char* outPinTopic = "stat/arduinomega/switch";
const char* outShutterCmdTopic = "stat/arduinomega/SHUTTER";
const char* outShutterPosTopic = "stat/arduinomega/SHUTTERPOS";
const char* inShutterCmndTopic = "cmnd/arduinomega/SHUTTER";
const char* inRestartCmndTopic = "cmnd/arduinomega/RESTART";
bool shutterButtonStates[] = {
HIGH, HIGH, HIGH, HIGH
}; // pin: 64, 65, 66, 67
bool relayStates[] = {
LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW
};
int relayPins[] = {
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34
}; // an array of pin numbers to which LEDs are attached
const int pinCount = 14;
//int pinCount = 10;
int reedSensorPins[] = {
8, 9, 11, 12, 14, 44, 55, 57
}; // an array of pin numbers to which REED sensors are attached
const int reedSensorPinCount = 8;
const int PIRCount = 4;
const int tempSensorCount = 5;
bool relaysTurnOn[pinCount] = {};
unsigned long int overridePIR[PIRCount] = {};
bool nightPeeRelays[pinCount] = {};
//--------------------CONFIGURABLE DEFAULTS-------------------------
int defTimeoutStateChangeCounterMs = 1000; // 1 second
int defNumStateChangeDisableEnablePIRs = 5;
int defNumStateChangeTurnOnAll = 4;
int defNumStateChangeTurnOffAll = 3;
int defNumStateChangeControlShutter = 3;
int defNumStateChangeStayTurnedONOrNightPee = 2; // if turnOnAllLights is active it forces the current light to exclude from OFF timer, OR
// if turnOnAllLight is not active it initiates Mark's night pee feature to turn on several lights
unsigned long int defTimerTurnOnAllLightsMs = 180000; // 3 minutes
unsigned long int defTimerTurnOnLightsForNightPeeMs = 180000; // 3 minutes
int defOverridePIRTimeoutMin = 60;
int defDisablePIR1 = 0;
int defDisablePIR2 = 0;
int defDisablePIR3 = 0;
int defDisablePIR4 = 0;
unsigned long int defTimerPIR1Ms = 30000;
unsigned long int defTimerPIR2Ms = 30000;
unsigned long int defTimerPIR3Ms = 30000;
unsigned long int defTimerPIR4Ms = 30000;
unsigned long int defDelayRainSensorMs = 10000;
unsigned long int defDelayTempSensorMs = 30000;
unsigned long int defDelayTimerClosetLEDMs = 300000;
unsigned long int defRainSensorTresholdValue = 900;
unsigned long int defShutter1OpenCloseDurationMs = 49000; //49 sec
unsigned long int defShutter2OpenCloseDurationMs = 49000; //49 sec
unsigned long int defShutter1MotorStartDurationMs = 1200; //1,2 sec
unsigned long int defShutter2MotorStartDurationMs = 1200; //1,2 sec
int defStairsTurnOnClosetShelfLights = 1;
int defWardrobeTurnOnClosetShelfLights = 1;
int defTimerTurnOffLightDuringDayMin = 10;
bool excludedRelays[pinCount] = {};
//-----------------------------------------------------
int defDisableEnablePIRs = 1;
String dayOrNight = "NIGHT"; // override this info from OPENHAB via MQTT message (topic: cmnd/arduinomega/DAYORNIGHT) when time of day changes...
int expCnt1 = 0;
int expCnt2 = 0;
int expCnt3 = 0;
int counter = 0;
int initCounter;
unsigned long int turnOnAllLightsTimestamp = 0;
unsigned long int turnOnLightsForNightPeeTimestamp = 0;
unsigned long int MQTTFailedConnectTime = 0;
unsigned long int timerPIR1 = 0;
unsigned long int timerPIR2 = 0;
unsigned long int timerPIR3 = 0;
unsigned long int timerPIR4 = 0;
// shutter variable initialization
int Shutter1Direction = 20; // values: 1-UP, 2-DOWN, 10-STOP (previous state was UP), 20-STOP (previous state was DOWN)
unsigned long int Shutter1OperationTimeMs = 0;
long int Shutter1PosTimeMs = 0;
int Shutter2Direction = 20; // values: 1-UP, 2-DOWN, 10-STOP (previous state was UP), 20-STOP (previous state was DOWN)
unsigned long int Shutter2OperationTimeMs = 0;
long int Shutter2PosTimeMs = 0;
unsigned long int millisTStampTimerDuringDay[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0
};
unsigned long int millisTStamp[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0
};
int lightCnt = 9;
int toggleCnt[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0
}; // 18 19 20 45 46 47 48 40 42
#define PIN_DETECT_6 6
#define PIN_DETECT_7 7
#define PIN_DETECT_8 8
#define PIN_DETECT_9 9
#define PIN_DETECT_44 44
#define PIN_DETECT_11 11
#define PIN_DETECT_12 12
#define PIN_DETECT_57 57 // 13 is LED and not recommended to be used...
#define PIN_DETECT_14 14
#define PIN_DETECT_15 15
#define PIN_DETECT_16 16
#define PIN_DETECT_17 17
#define PIN_DETECT_18 18
#define PIN_DETECT_19 19
#define PIN_DETECT_20 20
#define PIN_DETECT_45 45
#define PIN_DETECT_46 46
#define PIN_DETECT_47 47
#define PIN_DETECT_48 48
#define PIN_DETECT_40 40
#define PIN_DETECT_41 41
#define PIN_DETECT_42 42
#define PIN_DETECT_55 55
#define PIN_DETECT_56 56
#define PIN_DETECT_43 43
#define PIN_DETECT_54 54 // A0
#define PIN_DETECT_64 64
#define PIN_DETECT_65 65
#define PIN_DETECT_66 66
#define PIN_DETECT_67 67
#define PIN_DETECT_68 68
//---------END NEW PINS ------------------
Bounce debounce6 = Bounce();
Bounce debounce7 = Bounce();
Bounce debounce8 = Bounce();
Bounce debounce9 = Bounce();
Bounce debounce44 = Bounce();
Bounce debounce11 = Bounce();
Bounce debounce12 = Bounce();
Bounce debounce57 = Bounce();
Bounce debounce14 = Bounce();
Bounce debounce15 = Bounce();
Bounce debounce16 = Bounce();
Bounce debounce17 = Bounce();
Bounce debounce18 = Bounce();
Bounce debounce19 = Bounce();
Bounce debounce20 = Bounce();
Bounce debounce45 = Bounce();
Bounce debounce46 = Bounce();
Bounce debounce47 = Bounce();
Bounce debounce48 = Bounce();
Bounce debounce40 = Bounce();
Bounce debounce41 = Bounce();
Bounce debounce42 = Bounce();
Bounce debounce55 = Bounce();
Bounce debounce56 = Bounce();
Bounce debounce43 = Bounce();
Bounce debounce64 = Bounce();
Bounce debounce65 = Bounce();
Bounce debounce66 = Bounce();
Bounce debounce67 = Bounce();
Bounce debounce68 = Bounce();
// -------------------------------
boolean doSwitch = false;
void setup_ethernet() {
Serial.println("\nSetup ethernet");
delay(10);
// We start by connecting to a WiFi network
Ethernet.begin(mac, ip);
digitalWrite(13, LOW);
delay(500);
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
digitalWrite(13, HIGH);
}
void shutterControl(int pin, int OnOff) {
if (pin == SHUTTER1UPSWITCH) {
if(OnOff == 0) {
//alway safe to turn OFF relay but do not resend OFF command
if (digitalRead(SHUTTER1UPPIN) == HIGH) {
executeShutterCmd(1, 0, 1);
}
} else {
// check the belonging relay and manage turn off that...
if(digitalRead(SHUTTER1DOWNPIN) == LOW) {
Serial.print(digitalRead(SHUTTER1UPPIN), DEC);
// belonging relay is OFF -> safe to turn this ON
if(digitalRead(SHUTTER1UPPIN) == LOW) {
executeShutterCmd(1, 1, 0);
}
} else {
// belonging relay is ON -> STOP shutter
executeShutterCmd(1, 0, 2);
}
}
} else if (pin == SHUTTER1DOWNSWITCH) {
if(OnOff == 0) {
//alway safe to turn OFF relay but do not resend OFF command
if (digitalRead(SHUTTER1DOWNPIN) == HIGH) {
executeShutterCmd(1, 0, 2);
}
} else {
// check the belonging relay and manage turn off that...
if(digitalRead(SHUTTER1UPPIN) == LOW) {
// belonging relay is OFF -> safe to turn this ON
if(digitalRead(SHUTTER1DOWNPIN) == LOW) {
executeShutterCmd(1, 2, 0);
}
} else {
// belonging relay is ON -> STOP shutter
executeShutterCmd(1, 0, 1);
}
}
} else if (pin == SHUTTER2UPSWITCH) {
if(OnOff == 0) {
//alway safe to turn OFF relay but do not resend OFF command
if (digitalRead(SHUTTER2UPPIN) == HIGH) {
executeShutterCmd(2, 0, 1);
}
} else {
// check the belonging relay and manage turn off that...
if(digitalRead(SHUTTER2DOWNPIN) == LOW) {
// belonging relay is OFF -> safe to turn this ON
if(digitalRead(SHUTTER2UPPIN) == LOW) {
executeShutterCmd(2, 1, 0);
}
} else {
// belonging relay is ON -> STOP shutter
executeShutterCmd(2, 0, 2);
}
}
} else if (pin == SHUTTER2DOWNSWITCH) {
if(OnOff == 0) {
//alway safe to turn OFF relay but do not resend OFF command
if (digitalRead(SHUTTER2DOWNPIN) == HIGH) {
executeShutterCmd(2, 0, 2);
}
} else {
// check the belonging relay and manage turn off that...
if(digitalRead(SHUTTER2UPPIN) == LOW) {
// belonging relay is OFF -> safe to turn this ON
if(digitalRead(SHUTTER2DOWNPIN) == LOW) {
executeShutterCmd(2, 2, 0);
}
} else {
// belonging relay is ON -> STOP shutter
executeShutterCmd(2, 0, 1);
}
}
}
}
void executeShutterSequence(int shutterNum) { //sequence goes like: UP, STOP, DOWN, STOP, ...
int shutterDirection;
Serial.print("Executing next command for shutter");
Serial.println(shutterNum, DEC);
if(shutterNum == 1) {
shutterDirection = Shutter1Direction;
} else if (shutterNum == 2) {
shutterDirection = Shutter2Direction;
}
if(shutterDirection == 10) {
// Execute DOWN after STOP
executeShutterCmd(shutterNum, 2, 0);
} else if (shutterDirection == 20) {
// Execute UP after STOP
executeShutterCmd(shutterNum, 1, 0);
} else if (shutterDirection == 1) {
// Execute STOP after UP
executeShutterCmd(shutterNum, 0, 1);
} else if (shutterDirection == 2) {
// Execute STOP after DOWN
executeShutterCmd(shutterNum, 0, 2);
}
}
void executeShutterCmd(int shutterNum, int dir, int fromDir) { // dir: 0-STOP, 1-UP, 2-DOWN; fromDir says if we STOP the shutter from moving UP (value: 1) or DOWN (value: 2)
//position: 0-fully closed, 100-fully opened; Fully closed: 0ms, Fully Opened: defShutterXOpenCloseDuration
int shutterPos = 0;
if(shutterNum == 1) {
if(dir == 0) {
Shutter1OperationTimeMs = millis() - Shutter1OperationTimeMs;
// STOP the shutter, calculate and publish position, direction
if(fromDir == 1) { //STOP from UP
Shutter1Direction = 10;
digitalWrite(SHUTTER1UPPIN,LOW);
Shutter1PosTimeMs = Shutter1PosTimeMs + Shutter1OperationTimeMs;
} else if (fromDir == 2) { //STOP from DOWN
Shutter1Direction = 20;
digitalWrite(SHUTTER1DOWNPIN,LOW);
Shutter1PosTimeMs = Shutter1PosTimeMs - Shutter1OperationTimeMs;
}
//normalize pos time if we ran out of it
if(Shutter1PosTimeMs > defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs){
Shutter1PosTimeMs = defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs;
} else if (Shutter1PosTimeMs < 0) {
Shutter1PosTimeMs = 0;
}
shutterPos = Shutter1PosTimeMs * 100 / (defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs);
publishShutterDir(1, 0);
publishShutterPos(1, shutterPos);
} else if (dir == 1 && Shutter1PosTimeMs < defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs) {
// Shutter UP
digitalWrite(SHUTTER1UPPIN,HIGH);
Shutter1Direction = 1;
Shutter1OperationTimeMs = millis();
publishShutterDir(1, 1);
} else if (dir == 2) {
// Shutter DOWN
digitalWrite(SHUTTER1DOWNPIN,HIGH);
Shutter1Direction = 2;
Shutter1OperationTimeMs = millis();
publishShutterDir(1, 2);
}
} else if (shutterNum == 2) {
if(dir == 0) {
Shutter2OperationTimeMs = millis() - Shutter2OperationTimeMs;
// STOP the shutter, calculate and publish position, direction
if(fromDir == 1) { //STOP from UP
Shutter2Direction = 10;
digitalWrite(SHUTTER2UPPIN,LOW);
Shutter2PosTimeMs = Shutter2PosTimeMs + Shutter2OperationTimeMs;
} else if (fromDir == 2) { //STOP from DOWN
Shutter2Direction = 20;
digitalWrite(SHUTTER2DOWNPIN,LOW);
Shutter2PosTimeMs = Shutter2PosTimeMs - Shutter2OperationTimeMs;
}
//normalize pos time if we ran out of it
if(Shutter2PosTimeMs > defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs){
Shutter2PosTimeMs = defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs;
} else if (Shutter2PosTimeMs < 0) {
Shutter2PosTimeMs = 0;
}
shutterPos = Shutter2PosTimeMs * 100 / (defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs);
publishShutterDir(2, 0);
publishShutterPos(2, shutterPos);
} else if (dir == 1 && Shutter2PosTimeMs < (defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs)) {
// Shutter UP
digitalWrite(SHUTTER2UPPIN,HIGH);
Shutter2Direction = 1;
Shutter2OperationTimeMs = millis();
publishShutterDir(2, 1);
} else if (dir == 2) {
// Shutter DOWN
digitalWrite(SHUTTER2DOWNPIN,HIGH);
Shutter2Direction = 2;
Shutter2OperationTimeMs = millis();
publishShutterDir(2, 2);
}
}
}
bool get_token(String &from, String &to, uint8_t index, char separator, unsigned long int length)
{
uint16_t start = 0, idx = 0;
uint8_t cur = 0;
while (idx < length)
{
if (from.charAt(idx) == separator)
{
if (cur == index)
{
to = from.substring(start, idx);
return true;
}
cur++;
while ((idx < length - 1) && (from.charAt(idx + 1) == separator)) idx++;
start = idx + 1;
}
idx++;
}
if ((cur == index) && (start < length))
{
to = from.substring(start, length);
return true;
}
return false;
}
void setDefaultValues(byte* payload, unsigned long int length) {
int token_idx = 0;
int idx = 0;
String token, payloadStr;
String tokenValueArr;
Serial.println("\n Received new DEFAULT values via MQTT!");
while (get_token(payload, token, token_idx, ' ', length)) {
Serial.println("\nToken: " + token);
if (token.startsWith("timeoutStateChangeCounterMs")) {
defTimeoutStateChangeCounterMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ntimeoutStateChangeCounterMs changed to:"+(String)defTimeoutStateChangeCounterMs);
} else if (token.startsWith("numStateChangeTurnOnAll")) {
defNumStateChangeTurnOnAll = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefNumStateChangeTurnOnAll changed to:"+(String)defNumStateChangeTurnOnAll);
} else if (token.startsWith("numStateChangeDisableEnablePIRs")) {
defNumStateChangeDisableEnablePIRs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefNumStateChangeTurnOnAll changed to:"+(String)defNumStateChangeTurnOnAll);
} else if (token.startsWith("numStateChangeTurnOffAll")) {
defNumStateChangeTurnOffAll = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefNumStateChangeTurnOffAll changed to:"+(String)defNumStateChangeTurnOffAll);
} else if (token.startsWith("numStateChangeControlShutter")) {
defNumStateChangeControlShutter = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefNumStateChangeControlShutter changed to:"+(String)defNumStateChangeControlShutter);
} else if (token.startsWith("numStateChangeStayTurnedONOrNightPee")) { // override turn off timer for belonging relay
defNumStateChangeStayTurnedONOrNightPee = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefNumStateChangeStayTurnedONOrNightPee changed to:"+(String)defNumStateChangeStayTurnedONOrNightPee);
} else if (token.startsWith("timerTurnOnAllLightsMs")) { // timer to turn off all lights after turnOnAllLights feature executed
defTimerTurnOnAllLightsMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerTurnOnAllLightsMs changed to:"+(String)defTimerTurnOnAllLightsMs);
} else if (token.startsWith("timerTurnOnLightsForNightPeeMs")) {
defTimerTurnOnLightsForNightPeeMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerTurnOnLightsForNightPeeMs changed to:"+(String)defTimerTurnOnLightsForNightPeeMs);
} else if (token.startsWith("overridePIRTimeoutMin")) {
defOverridePIRTimeoutMin = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\defOverridePIRTimeoutMin changed to:"+(String)defOverridePIRTimeoutMin);
} else if (token.startsWith("disablePIR1")) {
defDisablePIR1 = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDisablePIR1 changed to:"+(String)defDisablePIR1);
} else if (token.startsWith("disablePIR2")) {
defDisablePIR2 = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDisablePIR2 changed to:"+(String)defDisablePIR2);
} else if (token.startsWith("disablePIR3")) {
defDisablePIR3 = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDisablePIR3 changed to:"+(String)defDisablePIR3);
} else if (token.startsWith("disablePIR4")) {
defDisablePIR4 = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDisablePIR4 changed to:"+(String)defDisablePIR4);
} else if (token.startsWith("disableAllPIRs")) {
if (token.substring(token.indexOf('=') + 1) == '1' ) {
defDisablePIR1 = 1;
defDisablePIR2 = 1;
defDisablePIR3 = 1;
defDisablePIR4 = 1;
} else if (token.substring(token.indexOf('=') + 1) == '0' ) {
defDisablePIR1 = 0;
defDisablePIR2 = 0;
defDisablePIR3 = 0;
defDisablePIR4 = 0;
}
Serial.println("\ndisableAllPIRs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timerPIR1Ms")) { // timer to turn off assigned relay after PIR detected motion and turned relay on
defTimerPIR1Ms = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerPIR1Ms changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timerPIR2Ms")) { // timer to turn off assigned relay after PIR detected motion and turned relay on
defTimerPIR2Ms = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerPIR2Ms changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timerPIR3Ms")) { // timer to turn off assigned relay after PIR detected motion and turned relay on
defTimerPIR3Ms = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerPIR3Ms changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timerPIR4Ms")) { // timer to turn off assigned relay after PIR detected motion and turned relay on
defTimerPIR4Ms = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerPIR4Ms changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("statCycleRainSensorMs")) {
defDelayRainSensorMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDelayRainSensorMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("statCycleTempSensorMs")) {
defDelayTempSensorMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDelayTempSensorMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timeoutClosetLEDMs")) {
defDelayTimerClosetLEDMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDelayTimerClosetLEDMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("shutter1OpenCloseDurationMs")) {
defShutter1OpenCloseDurationMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefShutter1OpenCloseDurationMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("shutter2OpenCloseDurationMs")) {
defShutter2OpenCloseDurationMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefShutter2OpenCloseDurationMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("shutter1MotorStartDurationMs")) {
defShutter1MotorStartDurationMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefShutter1MotorStartDurationMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("shutter2MotorStartDurationMs")) {
defShutter2MotorStartDurationMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefShutter2MotorStartDurationMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("rainSensorTresholdValue")) {
defRainSensorTresholdValue = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefRainSensorTresholdValue changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timerClosetLEDMs")) {
defDelayTimerClosetLEDMs = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefDelayTimerClosetLEDMs changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("stairsTurnOnClosetShelfLights")) {
defStairsTurnOnClosetShelfLights = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefStairsTurnOnClosetShelfLights changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if(token.startsWith("wardrobeTurnOnClosetShelfLights")) {
defWardrobeTurnOnClosetShelfLights = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\defWardrobeTurnOnClosetShelfLights changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("timerTurnOffLightDuringDayMin")) {
defTimerTurnOffLightDuringDayMin = token.substring(token.indexOf('=') + 1).toInt();
Serial.println("\ndefTimerTurnOffLightDuringDayMin changed to:"+(String)token.substring(token.indexOf('=') + 1));
} else if (token.startsWith("excludedRelaysTurnOnAllLights")) { // we have 14relays (from pin 21 to pin 34).
// Example for this parameter in the format: excludedRelaysTurnOnAllLights=false,false,true,true,false,false,false,false,false,false,false,false,false,false
// Pin numbers of relays: D21 D22 D23 D24 D25 D26 D27 D28 D29 D30 D31 D32 D33 D34
// those relays won't be turned on by the feature of TurnOnAllLights
tokenValueArr = token.substring(token.indexOf('=') + 1);
Serial.print("\nexcludedRelaysTurnOnAllLights changed to:");
while (get_token(tokenValueArr, token, idx, ',', tokenValueArr.length()))
{
if(token.startsWith("1") || token.startsWith("true")) {
excludedRelays[idx] = true;
Serial.print(" true");
} else {
excludedRelays[idx] = false;
Serial.print(" false");
}
idx++;
}
Serial.println();
}
token_idx++;
}
}
void delayTimers() {
delay_rainsensor.start(defDelayRainSensorMs, AsyncDelay::MILLIS);
delay_tempsensor.start(defDelayTempSensorMs, AsyncDelay::MILLIS);
}
void publishPinStates() {
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
char* state = relayStates[thisPin] == LOW ? "OFF" : "ON";
publishRelayState(thisPin + 1, state);
}
for (int thisPin = 0; thisPin < reedSensorPinCount; thisPin++) {
char* state = digitalRead(reedSensorPins[thisPin]) == LOW ? "OFF" : "ON";
publishPinState(reedSensorPins[thisPin], state);
}
}
void toggleRelay(int pos) {
Serial.println("\ntoggle relay: ");
Serial.println(pos);
Serial.println(relayPins[pos]);
if (digitalRead(relayPins[pos]) == HIGH) {
//Turning off is safe to be done immediately
digitalWrite(relayPins[pos], LOW);
relayStates[pos] = LOW;
publishRelayState(pos +1,"OFF") ;
Serial.println("\nRelay: OFF ");
//closet leds for stairs light turn OFF
if(pos == 10 && defStairsTurnOnClosetShelfLights == 1) {
digitalWrite(relayPins[0], LOW);
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
} else if(pos == 10 && defStairsTurnOnClosetShelfLights == 2) {
digitalWrite(relayPins[1], LOW);
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
switchRelay('0', 1); // pin22 - blue LED
} else if(pos == 10 && defStairsTurnOnClosetShelfLights == 3) {
digitalWrite(relayPins[0], LOW); // pin21 - white LED
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
}
//closet leds for Wardrobe light turn OFF
if(pos == 2 && defWardrobeTurnOnClosetShelfLights == 1) {
digitalWrite(relayPins[0], LOW);
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
} else if(pos == 2 && defWardrobeTurnOnClosetShelfLights == 2) {
digitalWrite(relayPins[1], LOW);
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
switchRelay('0', 1); // pin22 - blue LED
} else if(pos == 2 && defWardrobeTurnOnClosetShelfLights == 3) {
digitalWrite(relayPins[0], LOW); // pin21 - white LED
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
digitalWrite(relayPins[1], LOW); // pin22 - blue LED
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
}
// check timer during day and reset if necessary
if ((pos >= 2 && pos <= 10) && (millisTStampTimerDuringDay[pos-2] != 0)) {
millisTStampTimerDuringDay[pos-2] = 0;
}
} else if (digitalRead(relayPins[pos]) == LOW) {
//turning on is done in setStates
digitalWrite(relayPins[pos], HIGH);
publishRelayState(pos +1,"ON") ;
relayStates[pos] = HIGH;
Serial.println("\nRelay: ON ");
//there is a timer to turn off the light during the day...
if(dayOrNight.equals("DAY") && pos >= 2 && pos <= 10) {
millisTStampTimerDuringDay[pos-2] = millis();
}
}
}
void switchRelay(char* switchState, int pos) {
Serial.println("\nSwitch relay: ");
Serial.println(pos);
Serial.println(relayPins[pos]);
if (switchState == '0') {
//Turning off is safe to be done immediately
digitalWrite(relayPins[pos], LOW);
relayStates[pos] = LOW;
publishRelayState(pos +1,"OFF") ;
Serial.println("\nRelay: OFF ");
//closet leds for stairs light turn OFF
if(pos == 10 && defStairsTurnOnClosetShelfLights == 1) {
digitalWrite(relayPins[0], LOW);
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
} else if(pos == 10 && defStairsTurnOnClosetShelfLights == 2) {
digitalWrite(relayPins[1], LOW);
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
switchRelay('0', 1); // pin22 - blue LED
} else if(pos == 10 && defStairsTurnOnClosetShelfLights == 3) {
digitalWrite(relayPins[0], LOW); // pin21 - white LED
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
digitalWrite(relayPins[1], LOW); // pin22 - blue LED
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
}
//closet leds for Wardrobe light turn OFF
if(pos == 2 && defWardrobeTurnOnClosetShelfLights == 1) {
digitalWrite(relayPins[0], LOW);
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
} else if(pos == 2 && defWardrobeTurnOnClosetShelfLights == 2) {
digitalWrite(relayPins[1], LOW);
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
switchRelay('0', 1); // pin22 - blue LED
} else if(pos == 2 && defWardrobeTurnOnClosetShelfLights == 3) {
digitalWrite(relayPins[0], LOW); // pin21 - white LED
relayStates[0] = LOW;
publishRelayState(0 +1,"OFF") ;
Serial.println("\nRelay: 21 OFF ");
digitalWrite(relayPins[1], LOW); // pin22 - blue LED
relayStates[1] = LOW;
publishRelayState(1 +1,"OFF") ;
Serial.println("\nRelay: 22 OFF ");
}
// check timer during day and reset if necessary
if ((pos >= 2 && pos <= 10) && (millisTStampTimerDuringDay[pos-2] != 0)){
millisTStampTimerDuringDay[pos-2] = 0;
}
} else if (switchState == '1') {
//turning on is done in setStates
digitalWrite(relayPins[pos], HIGH);
publishRelayState(pos +1,"ON") ;
relayStates[pos] = HIGH;
Serial.println("\nRelay: ON ");
//there is a timer to turn off the light during the day...
if(dayOrNight.equals("DAY") && pos >= 2 && pos <= 10) {
millisTStampTimerDuringDay[pos-2] = millis();
}
}
}
void cmdAcknowledged(int OnOff, int togglePos, int cmdNum) {
int blinkTimeMs;
int relayPos = togglePos + 2;
if (OnOff == 1) {
// feature turning ON -> long blinks
blinkTimeMs = 1000;
} else {
// feature turning OFF -> short blinks
blinkTimeMs = 250;
}
for(int i=0; i<(cmdNum*2); i++){
delay(blinkTimeMs);
if (digitalRead(relayPins[relayPos]) == HIGH) {
switchRelay('0', relayPos);
} else {
switchRelay('1', relayPos);
}
}
}
void turnOnAllLightsWithTimer() {
// only use this feature if night pee feature is not active
if (turnOnLightsForNightPeeTimestamp == 0 ) {
// check if feature is already active?
if (turnOnAllLightsTimestamp == 0) {
turnOnAllLightsTimestamp = millis();
// feature not yet active
//reinitialize array
memcpy(relaysTurnOn, '\0', sizeof(relaysTurnOn));
for (int relayPos = 0; relayPos < pinCount; relayPos++) {
if (digitalRead(relayPins[relayPos]) == LOW) {
if (excludedRelays[relayPos] == false) {
if((relayPos == 3 || relayPos == 4) && (digitalRead(55) == HIGH)) { // do not turn on bedroom lights when bedroom door is closed
continue;
}
switchRelay('1', relayPos);
relaysTurnOn[relayPos] = true;
}
}
}
} else {
turnOnAllLightsTimestamp = millis(); // we need to update timestamp anyway - even if feature is already activated
}
} else {
Serial.println("\nPEE is active, not starting TurnOnAllLights!");
}
}
void turnOnLightsForNightPeeWithTimer() {
if (turnOnAllLightsTimestamp == 0) {
// we can only use this feature if turnOnAllLights is not active
if (turnOnLightsForNightPeeTimestamp != 0) {
// feature is active -> only extend timer
turnOnLightsForNightPeeTimestamp = millis();
} else {
// feature is not active -> activate
memcpy(relaysTurnOn, '\0', sizeof(relaysTurnOn));
turnOnLightsForNightPeeTimestamp = millis();
for (int relayPos = 0; relayPos < pinCount; relayPos++) {
if (nightPeeRelays[relayPos] == true) {
switchRelay('1', relayPos);
relaysTurnOn[relayPos] = true;
}
}
}
}
}
void turnOffLights() {
for (int relayPos = 0; relayPos < pinCount; relayPos++) {
if (relaysTurnOn[relayPos] == true ) {
switchRelay('0', relayPos);
}
}
turnOnAllLightsTimestamp = 0; // it means feature not active
turnOnLightsForNightPeeTimestamp = 0;
memcpy(relaysTurnOn, '\0', sizeof(relaysTurnOn));
}
void turnOffAllLights() {
Serial.println("\ninitialize all PINS to go LOW with turnOffAllLights");
for (int relayPos = 0; relayPos < pinCount; relayPos++) {
switchRelay('0', relayPos);
}
turnOnAllLightsTimestamp = 0; // it means feature not active
turnOnLightsForNightPeeTimestamp = 0;
memcpy(relaysTurnOn, '\0', sizeof(relaysTurnOn));
}
void checkTimeoutAndExecute() {
// check toggle timeout
for (int pos = 0; pos < lightCnt; pos++) {
if ((toggleCnt[pos] > 0) && (millisTStamp[pos] + defTimeoutStateChangeCounterMs < millis())) {
//timer expired -> execute command
executeCmnd(pos);
}
// turn off light after timer expired
if ((millisTStampTimerDuringDay[pos] != 0) && (millisTStampTimerDuringDay[pos] + defTimerTurnOffLightDuringDayMin * 60000 < millis())) {
//timer expired -> execute command
switchRelay('0', pos + 2);
millisTStampTimerDuringDay[pos] = 0;
}
}
}
void lightForceToStayOn(int togglePos) {
if (turnOnAllLightsTimestamp != 0) {
relaysTurnOn[togglePos + 2] = false; // relay position is toggleposition + 2
} else if (togglePos == 3 || togglePos == 4) { // you can initiate night pee only from kids room!
turnOnLightsForNightPeeWithTimer();
Serial.println("\nPee");
} else {
// we need to turn ON the light anyway if it is not turned on already...
//togglePos 0 1 2 3 4 5 6 7 8
// map between togglePos and Pins: 18 19 20 45 46 47 48 40 42
// map between togglePos and relayPin: 23 24 25 26 27 28 29 30 31
if(digitalRead(togglePos + 23) == LOW ) {
switchRelay('1', togglePos +2); //relayPos is togglePos + 2
}
overridePIRIfNecessary(togglePos);
}
}
void overridePIRIfNecessary(int togglePos){
if (togglePos == 8) {
//PIR sensor 1 - lepcso
overridePIR[0] = millis();
Serial.println("PIR1 overriden for stairs");
} else if (togglePos == 7 ) {
//PIR sensor 2 - eloszoba
overridePIR[1] = millis();
Serial.println("PIR2 overriden for upstairs corridor");
} else if (togglePos == 6) {
//PIR sensor 3 - bathroom
overridePIR[2] = millis();
Serial.println("PIR3 overriden for bathroom");
} else if(togglePos == 0) {
//PIR sensor 4 - Wardrobe
overridePIR[3] = millis();
Serial.println("PIR4 overriden for wardrobe");
}
}
void executeCmnd(int togglePos) {
Serial.println("\nExecute command:");
Serial.println(toggleCnt[togglePos], DEC);
if (toggleCnt[togglePos] == 1) { // this is only a normal switch
toggleRelay(togglePos + 2); //relayPos is togglePos+2
delay(50); // allow time for state change
//consider if closet leds should be turned on if stairs is turned on
if(togglePos == 8 && digitalRead(relayPins[togglePos+2]) == HIGH) {
if(defStairsTurnOnClosetShelfLights == 1) {
switchRelay('1', 0); // pin21 - white LED
} else if (defStairsTurnOnClosetShelfLights == 2) {
switchRelay('1', 1); // pin21 - blue LED
} else if (defStairsTurnOnClosetShelfLights == 3) {
switchRelay('1', 0); // pin21 - white LED
switchRelay('1', 1); // pin21 - blue LED
}
}
//consider if closet leds should be turned on if Wardrobe main light is turned on
if(togglePos == 0 && digitalRead(relayPins[togglePos+2]) == HIGH) {
if(defWardrobeTurnOnClosetShelfLights == 1) {
switchRelay('1', 0); // pin21 - white LED
} else if (defWardrobeTurnOnClosetShelfLights == 2) {
switchRelay('1', 1); // pin21 - blue LED
} else if (defWardrobeTurnOnClosetShelfLights == 3) {
switchRelay('1', 0); // pin21 - white LED
switchRelay('1', 1); // pin21 - blue LED
}
}
} else if ((toggleCnt[togglePos] == defNumStateChangeControlShutter) && (togglePos == 1 || togglePos == 2 || togglePos == 6)) { // pins: 19, 20 - (bedroom), 48 - bathroom
if(togglePos == 1 || togglePos == 2) {
executeShutterSequence(1); //control shutter of the same room with the light switch (shutter1-bedroom)
} else if(togglePos == 6) {
executeShutterSequence(2); //control shutter of the same room with the light switch (shutter2-bathroom)
}
}else if (toggleCnt[togglePos] == defNumStateChangeStayTurnedONOrNightPee) {
if (turnOnAllLightsTimestamp != 0) {
//light force to stay turned on
lightForceToStayOn(togglePos);
Serial.println("\nlightForceStayOn");
cmdAcknowledged(1, togglePos, defNumStateChangeStayTurnedONOrNightPee);
} else {
// initiate disable PIR feature or from kids room the nightPee feature
lightForceToStayOn(togglePos);
}
} else if (toggleCnt[togglePos] == defNumStateChangeTurnOffAll) {
// initiate turn off all lights
turnOffAllLights();
Serial.println("\nTurnOFFAllLights");
} else if (toggleCnt[togglePos] == defNumStateChangeTurnOnAll) {
// initiate turn on all lights
turnOnAllLightsWithTimer();
Serial.println("\nTurnONAllLights");
} else if (toggleCnt[togglePos] == defNumStateChangeDisableEnablePIRs) {
if(defDisablePIR1 == 0) {
// disable PIR sensors
defDisablePIR1 = 1;
defDisablePIR2 = 1;
defDisablePIR3 = 1;
defDisablePIR4 = 1;
defDisableEnablePIRs = 0; //PIRs OFF so disabled
cmdAcknowledged(0, togglePos, defNumStateChangeDisableEnablePIRs);
Serial.println("\nDisablePIRS");
} else {
//enable PIR sensors
defDisablePIR1 = 0;
defDisablePIR2 = 0;
defDisablePIR3 = 0;
defDisablePIR4 = 0;
defDisableEnablePIRs = 1; //PIRS ON so enabled
cmdAcknowledged(1, togglePos, defNumStateChangeDisableEnablePIRs);
Serial.println("\nEnablePIRS");
}
}
toggleCnt[togglePos] = 0;
millisTStamp[togglePos] = 0;
}
void handleToggle(int togglePos, int relayPos) {
if (toggleCnt[togglePos] == 0) {
// new toggle sequence
Serial.println("\nNew sequence!");
millisTStamp[togglePos] = millis();
toggleCnt[togglePos] = 1;
} else if (millisTStamp[togglePos] + defTimeoutStateChangeCounterMs < millis()) {
// timer expired -> execute without adding this extra toggle
Serial.println("\nTimer EXPIRED! Execute cmnd");
executeCmnd(togglePos);
} else {
// still within time -> increase toggleCnt and start new timer
toggleCnt[togglePos] = toggleCnt[togglePos] + 1;
Serial.println("\nIncrease toggleCnt to:"+toggleCnt[togglePos]);
millisTStamp[togglePos] = millis();
}
}
void setStates() {
if (doSwitch) {
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(relayPins[thisPin], relayStates[thisPin]);
}
doSwitch = false;
delay_tempsensor.start(defDelayTempSensorMs, AsyncDelay::MILLIS);
}
}
void publishShutterDir(int shutterNum, int dir) {
char outputTopicBuff[100];
//char shutterNumC = shutterNum;
char shutterNumC[3];
memset(outputTopicBuff, '\0', sizeof(outputTopicBuff));
memset(shutterNumC, '\0', sizeof(shutterNumC));
String shutterNumStr = String(shutterNum);
shutterNumStr.toCharArray(shutterNumC, shutterNumStr.length() + 1);
strcpy(outputTopicBuff, outShutterCmdTopic);
strcat(outputTopicBuff, shutterNumC);
Serial.print("\nShutter");
Serial.print(shutterNum, DEC);
Serial.print(": ");
if(dir == 0) {
client.publish(outputTopicBuff, "0");
Serial.println("STOP");
} else if (dir == 1) { //UP
client.publish(outputTopicBuff, "1");
Serial.println("UP");
} else if (dir == 2) { //DOWN
client.publish(outputTopicBuff, "2");
Serial.println("DOWN");
}
}
void publishShutterPos(int shutterNum, int pos) {
char outputTopicBuff[100];
//char shutterNumC = shutterNum;
char posC[4];
//sprintf(posC,"%d", pos);
char shutterNumC[3];
memset(outputTopicBuff, '\0', sizeof(outputTopicBuff));
memset(posC, '\0', sizeof(posC));
memset(shutterNumC, '\0', sizeof(shutterNumC));
String shutterNumStr = String(shutterNum);
shutterNumStr.toCharArray(shutterNumC, shutterNumStr.length() + 1);
String posStr = String(pos);
posStr.toCharArray(posC, posStr.length() + 1);
strcpy(outputTopicBuff, outShutterPosTopic);
strcat(outputTopicBuff, shutterNumC);
Serial.print("\nShutter");
Serial.print(shutterNum, DEC);
Serial.print("position: ");
Serial.println(pos, DEC);
client.publish(outputTopicBuff, posC);
}
void publishScene(char* scene, char* state) {
char outputTopicBuff[100];
memset(outputTopicBuff, '\0', sizeof(outputTopicBuff));
strcpy(outputTopicBuff, outSceneTopic);
char sceneName[30];
memset(sceneName, '\0', sizeof(sceneName));
sprintf(sceneName, "%s", scene);
strcat(outputTopicBuff, sceneName);
client.publish(outputTopicBuff, state);
Serial.println("\nscene state change:");
Serial.println(state);
}
void publishRelayState(int relayNbr, char* state) {
char outputTopicBuff[100];
memset(outputTopicBuff, '\0', sizeof(outputTopicBuff));
strcpy(outputTopicBuff, outRelayTopic);
char relaybuffer[5];
memset(relaybuffer, '\0', sizeof(relaybuffer));
sprintf(relaybuffer, "%d", relayNbr);
strcat(outputTopicBuff, relaybuffer);
client.publish(outputTopicBuff, state);
// reset PIR override - in case if it had been activated
if(state == "OFF" && relayPins[relayNbr - 1] == 23) { //wardrobe
overridePIR[3] = 0;
} else if(state == "OFF" && relayPins[relayNbr - 1] == 29) { //bathroom
overridePIR[2] = 0;
} else if(state == "OFF" && relayPins[relayNbr - 1] == 30) { //upstairs corridor
overridePIR[1] = 0;
} else if(state == "OFF" && relayPins[relayNbr - 1] == 31) { //stairs
overridePIR[0] = 0;
}
}
void publishPinState(int pinNbr, char* state) {
char outputTopicBuff[100];
memset(outputTopicBuff, '\0', sizeof(outputTopicBuff));
strcpy(outputTopicBuff, outPinTopic);
char relaybuffer[5];
memset(relaybuffer, '\0', sizeof(relaybuffer));
sprintf(relaybuffer, "%d", pinNbr);
strcat(outputTopicBuff, relaybuffer);
client.publish(outputTopicBuff, state);
Serial.println("\npinstate changed:");
Serial.println(pinNbr);
Serial.println(state);
}
void motionDetected(int pinNr, int OnOff) {
// PIR sensors are not active during turnOnAllLights and turnOnLightNightPee features
if (turnOnAllLightsTimestamp == 0 && turnOnLightsForNightPeeTimestamp == 0) {
switch(pinNr) {
case 15: //PIR sensor1
if(defDisablePIR1 == 0 && overridePIR[0] == 0) {
if(OnOff == 0) {
timerPIR1 = millis();
} else {
if(digitalRead(relayPins[10]) == LOW) { //Pin31 is the belonging relay, whose position in array is 10
switchRelay('1', 10);
timerPIR1 = 0;
}
}
}
break;
case 16: //PIR sensor2
if(defDisablePIR2 == 0 && overridePIR[1] == 0) {
if(OnOff == 0) {
timerPIR2 = millis();
} else {
if(digitalRead(relayPins[9]) == LOW) { //Pin30 is the belonging relay, whose position in array is 9
switchRelay('1', 9);
timerPIR2 = 0;
}
}
}
break;
case 17: //PIR sensor3
if(defDisablePIR3 == 0 && overridePIR[2] == 0) {
if(OnOff == 0) {
timerPIR3 = millis();
} else {
if(digitalRead(relayPins[8]) == LOW) { //Pin29 is the belonging relay, whose position in array is 8
switchRelay('1', 8);
timerPIR3 = 0;
}
}
}
break;
case 56: //PIR sensor4
if(defDisablePIR4 == 0 && overridePIR[3] == 0) {
if(OnOff == 0) {
timerPIR4 = millis();
} else {
if(digitalRead(relayPins[2]) == LOW) { //Pin23 is the belonging relay, whose position in array is 8
switchRelay('1', 2);
timerPIR4 = 0;
}
}
}
break;
}
}
}
void checkPIRTimersAndTurnOffRelayIfNecessary() {
if (((timerPIR1 != 0) && (timerPIR1 + defTimerPIR1Ms < millis()) && (overridePIR[0] == 0)) || // timer expired after motion sensor went to OFF
(overridePIR[0] !=0 && overridePIR[0] + defOverridePIRTimeoutMin * 60000 < millis())) { // override PIR sensor is activated, but timeout reached -> turning OFF light
//turn OFF relay
switchRelay('0', 10);
timerPIR1 = 0;
overridePIR[0] = 0;
} else if (((timerPIR2 != 0) && (timerPIR2 + defTimerPIR2Ms < millis()) && (overridePIR[1] == 0)) || // timer expired after motion sensor went to OFF
(overridePIR[1] !=0 && overridePIR[1] + defOverridePIRTimeoutMin * 60000 < millis())) { // override PIR sensor is activated, but timeout reached -> turning OFF light
//turn OFF relay
switchRelay('0', 9);
timerPIR2 = 0;
overridePIR[1] = 0;
} else if (((timerPIR3 != 0) && (timerPIR3 + defTimerPIR3Ms < millis()) && (overridePIR[2] == 0)) || // timer expired after motion sensor went to OFF
(overridePIR[2] !=0 && overridePIR[2] + defOverridePIRTimeoutMin * 60000 < millis())) { // override PIR sensor is activated, but timeout reached -> turning OFF light
//turn OFF relay
switchRelay('0', 8);
timerPIR3 = 0;
overridePIR[2] = 0;
} else if (((timerPIR4 != 0) && (timerPIR4 + defTimerPIR4Ms < millis()) && (overridePIR[3] == 0)) || // timer expired after motion sensor went to OFF
(overridePIR[3] !=0 && overridePIR[3] + defOverridePIRTimeoutMin * 60000 < millis())) { // override PIR sensor is activated, but timeout reached -> turning OFF light
//turn OFF relay
switchRelay('0', 2);
timerPIR4 = 0;
overridePIR[3] = 0;
}
}
void checkAndHandleShutterPosition() {
int shutter1Pos = 0;
int shutter2Pos = 0;
//CHECK SHUTTER1
if(Shutter1Direction == 1 && Shutter1OperationTimeMs + 1000 < millis()) { // send position update every second
Shutter1OperationTimeMs = millis() - Shutter1OperationTimeMs;
Shutter1PosTimeMs = Shutter1PosTimeMs + Shutter1OperationTimeMs;
if(Shutter1PosTimeMs >= (defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs)) {// check if max position reached
// max position reached - STOP shutter
digitalWrite(SHUTTER1UPPIN, LOW);
Shutter1PosTimeMs = defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs;
Shutter1Direction = 10;
//publish STOP
publishShutterDir(1, 0);
}
shutter1Pos = Shutter1PosTimeMs * 100 / (defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs);
publishShutterPos(1, shutter1Pos);
Shutter1OperationTimeMs = millis();
} else if (Shutter1Direction == 2 && Shutter1OperationTimeMs + 1000 < millis()) {
Shutter1OperationTimeMs = millis() - Shutter1OperationTimeMs;
Shutter1PosTimeMs = Shutter1PosTimeMs - Shutter1OperationTimeMs;
if(Shutter1PosTimeMs <= 0) {// check if min position reached
// min position reached - STOP shutter
digitalWrite(SHUTTER1DOWNPIN, LOW);
Shutter1PosTimeMs = 0;
Shutter1Direction = 20;
//publish STOP
publishShutterDir(1, 0);
}
shutter1Pos = Shutter1PosTimeMs * 100 / (defShutter1OpenCloseDurationMs + defShutter1MotorStartDurationMs);
publishShutterPos(1, shutter1Pos);
Shutter1OperationTimeMs = millis();
}
// CHECK SHUTTER2
if(Shutter2Direction == 1 && Shutter2OperationTimeMs + 1000 < millis()) {
Shutter2OperationTimeMs = millis() - Shutter2OperationTimeMs;
Shutter2PosTimeMs = Shutter2PosTimeMs + Shutter2OperationTimeMs;
if(Shutter2PosTimeMs >= (defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs)) {// check if max position reached
// max position reached - STOP shutter
digitalWrite(SHUTTER2UPPIN, LOW);
Shutter2PosTimeMs = defShutter2OpenCloseDurationMs;
Shutter2Direction = 10;
//publish STOP
publishShutterDir(2, 0);
}
shutter2Pos = Shutter2PosTimeMs * 100 / (defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs);
publishShutterPos(2, shutter2Pos);
Shutter2OperationTimeMs = millis();
} else if (Shutter2Direction == 2 && Shutter2OperationTimeMs + 1000 < millis()) {
Shutter2OperationTimeMs = millis() - Shutter2OperationTimeMs;
Shutter2PosTimeMs = Shutter2PosTimeMs - Shutter2OperationTimeMs;
if(Shutter2PosTimeMs <= 0) {// check if min position reached
// min position reached - STOP shutter
digitalWrite(SHUTTER2DOWNPIN, LOW);
Shutter2PosTimeMs = 0;
Shutter2Direction = 20;
//publish STOP
publishShutterDir(2, 0);
}
shutter2Pos = Shutter2PosTimeMs * 100 / (defShutter2OpenCloseDurationMs + defShutter2MotorStartDurationMs);
publishShutterPos(2, shutter2Pos);
Shutter2OperationTimeMs = millis();
}
}
void callback(char* topic, byte* payload, unsigned int length) {
int relayNumber;
int posInArray;
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("\nLength: " + (String)length);
String topicString = String(topic);
if (topicString.length() >= 20 && topicString.startsWith("cmnd/arduinomega/DEF")) {
// set default values!
setDefaultValues(payload, length);
} else if (topicString.length() >= 27 && topicString.startsWith("cmnd/arduinomega/DAYORNIGHT")) {
String payloadStr = String((char*)payload);
if(payloadStr.startsWith("DAY")) {
dayOrNight = "DAY";
} else {
dayOrNight = "NIGHT";
}
Serial.println("dayOrNight new value: " + dayOrNight);
} else if (topicString.length() >= 25 && topicString.startsWith("cmnd/arduinomega/SHUTTER")) {
if(topicString.charAt(24) == '1') { //SHUTTER1
//String payloadStr = String((char*)payload);
//if(payloadStr.startsWith("0")) {
if(payload[0] == '0') {
Serial.println("\nShutter1 command STOP executing...");
shutterControl(SHUTTER1UPSWITCH, 0);
shutterControl(SHUTTER1DOWNSWITCH, 0);
//} else if(payloadStr.startsWith("1")) {
} else if(payload[0] == '1') {
Serial.println("\nShutter1 command UP executing...");
shutterControl(SHUTTER1UPSWITCH, 1);
//} else if(payloadStr.startsWith("2")) {
} else if(payload[0] == '2') {
Serial.println("\nShutter1 command DOWN executing...");
shutterControl(SHUTTER1DOWNSWITCH, 1);
}
} else if (topicString.charAt(24) == '2') { //SHUTTER2
if(payload[0] == '0') {
Serial.println("\nShutter2 command STOP executing...");
shutterControl(SHUTTER2UPSWITCH, 0);
shutterControl(SHUTTER2DOWNSWITCH, 0);
//} else if(payloadStr.startsWith("1")) {
} else if(payload[0] == '1') {
Serial.println("\nShutter2 command UP executing...");
shutterControl(SHUTTER2UPSWITCH, 1);
//} else if(payloadStr.startsWith("2")) {
} else if(payload[0] == '2') {
Serial.println("\nShutter2 command DOWN executing...");
shutterControl(SHUTTER2DOWNSWITCH, 1);
}
}
} else if (topicString.length() >= 22 && topicString.startsWith("cmnd/arduinomega/POWER")) {
relayNumber = topicString.substring(22).toInt();
posInArray = relayNumber - 1;
Serial.println(posInArray, DEC);
char* switchState = (char)payload[0];
if (switchState == '2') {
if (relayStates[posInArray] == HIGH) {
switchState = '0';
} else {
switchState = '1';
}
}
switchRelay(switchState, posInArray);
if (switchState == '1') {
doSwitch = true;
}
} else if (topicString.length() >= 22 && topicString.startsWith("cmnd/arduinomega/RESTART")) {
char* switchState = (char)payload[0];
if (switchState == '1') {
// RESTART ARDUINO
asm volatile ( "jmp 0");
}
} else if (topicString.length() >= 26 && topicString.startsWith("cmnd/arduinomega/GETCONFIG")) {
char outstr[150];
sprintf(outstr, " defTimeoutStateChangeCounterMs: %d;"
" defNumStateChangeDisableEnablePIRs: %d;"
" defNumStateChangeTurnOnAll: %d;"
" defNumStateChangeTurnOffAll: %d;"
" defNumStateChangeControlShutter: %d;"
" defNumStateChangeStayTurnedONOrNightPee: %d;"
" defTimerTurnOnAllLightsMs: %d;"
" defTimerTurnOnLightsForNightPeeMs: %d;"
" defOverridePIRTimeoutMin: %d;"
" defDisablePIR1: %d;"
" defDisablePIR2: %d;"
" defDisablePIR3: %d;"
" defDisablePIR4: %d;"
" defTimerPIR1Ms: %d;"
" defTimerPIR2Ms: %d;"
" defTimerPIR3Ms: %d;"
" defTimerPIR4Ms: %d;"
" defDelayRainSensorMs: %d;"
" defDelayTempSensorMs: %d;"
" defDelayTimerClosetLEDMs: %d;"
" defRainSensorTresholdValue: %d;"
" defShutter1OpenCloseDurationMs: %d;"
" defShutter2OpenCloseDurationMs: %d;"
" defShutter1MotorStartDurationMs: %d"
" defShutter2MotorStartDurationMs: %d"
" defStairsTurnOnClosetShelfLights: %d;"
" defWardrobeTurnOnClosetShelfLights: %d;"
" defTimerTurnOffLightDuringDayMin: %d;"
" defDisableEnablePIRs: %d;"
" dayOrNight: %s;", defTimeoutStateChangeCounterMs, defNumStateChangeDisableEnablePIRs, defNumStateChangeTurnOnAll, defNumStateChangeTurnOffAll, defNumStateChangeControlShutter,
defNumStateChangeStayTurnedONOrNightPee, defOverridePIRTimeoutMin, defDisablePIR1, defDisablePIR2, defDisablePIR3, defDisablePIR4, defTimerPIR1Ms, defTimerPIR2Ms,
defTimerPIR3Ms, defTimerPIR4Ms, defDelayRainSensorMs, defDelayTempSensorMs, defDelayTimerClosetLEDMs, defRainSensorTresholdValue, defShutter1OpenCloseDurationMs,
defShutter2OpenCloseDurationMs, defShutter1MotorStartDurationMs, defShutter2MotorStartDurationMs, defStairsTurnOnClosetShelfLights, defWardrobeTurnOnClosetShelfLights, defTimerTurnOffLightDuringDayMin, defDisableEnablePIRs, dayOrNight);
for(int i = 0; i < pinCount; i++) {
if(excludedRelays[i] == false) {
sprintf(outstr, " excludedRelays[%d]: false;");
} else {
sprintf(outstr, " excludedRelays[%d]: true;");
}
}
sprintf(outstr, '\0');
client.publish("stat/arduinomega/CONFIG", outstr);
//bool excludedRelays[pinCount] = {};
}
}
void reconnect() {
Serial.println("\nTrying to connect to MQTT...");
if (client.connect("XXX", "YYY", "ZZZ")) {
Serial.println("connected");
client.subscribe(inTopic);
delay(100);
client.subscribe(inShutterCmndTopic);
delay(100);
client.publish(outTopic, "ON");
digitalWrite(13, HIGH);
publishPinStates();
//delay(100);
//client.subscribe(inTopic2);
MQTTFailedConnectTime = 0;
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
digitalWrite(13, LOW);
delay(500);
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
}
}
void printRelayStates() {
Serial.print("\nPin states:");
for (int i = 0; i < pinCount; i++) {
Serial.print(relayPins[i]);
Serial.print(": ");
Serial.print(relayStates[i], DEC);
Serial.print(",");
Serial.print(digitalRead(relayPins[i]));
Serial.print("; ");
}
Serial.print("\n");
}
void printTemperature(DHT sensor, char const * topic)
{
float temp = sensor.readTemperature();
float hum = sensor.readHumidity();
if(isnan(temp)) {
Serial.println("Failed to read temperature from DHT sensor!");
return;
}
if(isnan(hum)) {
Serial.println("Failed to read humidity from DHT sensor!");
return;
}
Serial.print(" temperature: ");
Serial.print(temp);
Serial.print(" Celsius,\t humidity: ");
Serial.print(hum);
Serial.println(" %");
char temp_char[5];
char hum_char[5];
dtostrf(temp, 2, 1, temp_char);
temp_char[4]='\0';
dtostrf(hum, 2, 1, hum_char);
hum_char[4]='\0';
char outstr[150];
sprintf(outstr, "{\"AM2301\":{\"Temperature\":%s,\"Humidity\":%s},\"TempUnit\":\"C\"}", temp_char, hum_char);
client.publish(topic, outstr);
}
void setup() {
client.setBufferSize(2048); //PubSubClient change max length of message
initCounter = 0;
expCnt1 = 0;
expCnt2 = 0;
expCnt3 = 0;
// add default values
excludedRelays[7] = true; //by default exclude: 8th element, which is D28 pin, which is guest room
excludedRelays[11] = true; // 12th element, which is D32 pin -> wardrobe LED1
excludedRelays[12] = true; // 13th element, D33 -> wardrobe LED2
excludedRelays[13] = true; // 14th element, D34 -> bedroom closet LED
nightPeeRelays[8] = true;
nightPeeRelays[9] = true;
nightPeeRelays[10] = true;
Serial.begin(115200);
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(relayPins[thisPin], LOW);
pinMode(relayPins[thisPin], OUTPUT);
}
//manually initialize shutter relays as well...
digitalWrite(SHUTTER1UPPIN, LOW);
pinMode(SHUTTER1UPPIN, OUTPUT);
digitalWrite(SHUTTER1DOWNPIN, LOW);
pinMode(SHUTTER1DOWNPIN, OUTPUT);
digitalWrite(SHUTTER2UPPIN, LOW);
pinMode(SHUTTER2UPPIN, OUTPUT);
digitalWrite(SHUTTER2DOWNPIN, LOW);
pinMode(SHUTTER2DOWNPIN, OUTPUT);
//init state relayboard
//turnAllOff();
delayTimers();
//input
pinMode(PIN_DETECT_6, INPUT_PULLUP);
pinMode(PIN_DETECT_7, INPUT_PULLUP);
pinMode(PIN_DETECT_8, INPUT_PULLUP);
pinMode(PIN_DETECT_9, INPUT_PULLUP);
pinMode(PIN_DETECT_44, INPUT_PULLUP);
pinMode(PIN_DETECT_11, INPUT_PULLUP);
pinMode(PIN_DETECT_12, INPUT_PULLUP);
pinMode(PIN_DETECT_57, INPUT_PULLUP);
pinMode(PIN_DETECT_14, INPUT_PULLUP);
pinMode(PIN_DETECT_15, INPUT_PULLUP);
pinMode(PIN_DETECT_16, INPUT_PULLUP);
pinMode(PIN_DETECT_17, INPUT_PULLUP);
pinMode(PIN_DETECT_18, INPUT_PULLUP);
pinMode(PIN_DETECT_19, INPUT_PULLUP);
pinMode(PIN_DETECT_20, INPUT_PULLUP);
pinMode(PIN_DETECT_45, INPUT_PULLUP);
pinMode(PIN_DETECT_46, INPUT_PULLUP);
pinMode(PIN_DETECT_47, INPUT_PULLUP);
pinMode(PIN_DETECT_48, INPUT_PULLUP);
pinMode(PIN_DETECT_40, INPUT_PULLUP);
pinMode(PIN_DETECT_41, INPUT_PULLUP);
pinMode(PIN_DETECT_42, INPUT_PULLUP);
pinMode(PIN_DETECT_55, INPUT_PULLUP);
pinMode(PIN_DETECT_56, INPUT_PULLUP);
pinMode(PIN_DETECT_43, INPUT_PULLUP);
pinMode(PIN_DETECT_54, INPUT_PULLUP);
pinMode(PIN_DETECT_64, INPUT_PULLUP);
pinMode(PIN_DETECT_65, INPUT_PULLUP);
pinMode(PIN_DETECT_66, INPUT_PULLUP);
pinMode(PIN_DETECT_67, INPUT_PULLUP);
pinMode(PIN_DETECT_68, INPUT_PULLUP);
// -------------------------------------
debounce6.attach(PIN_DETECT_6);
debounce7.attach(PIN_DETECT_7);
debounce8.attach(PIN_DETECT_8);
debounce9.attach(PIN_DETECT_9);
debounce44.attach(PIN_DETECT_44);
debounce11.attach(PIN_DETECT_11);
debounce12.attach(PIN_DETECT_12);
debounce57.attach(PIN_DETECT_57);
debounce14.attach(PIN_DETECT_14);
debounce15.attach(PIN_DETECT_15);
debounce16.attach(PIN_DETECT_16);
debounce17.attach(PIN_DETECT_17);
debounce18.attach(PIN_DETECT_18);
debounce19.attach(PIN_DETECT_19);
debounce20.attach(PIN_DETECT_20);
debounce45.attach(PIN_DETECT_45);
debounce46.attach(PIN_DETECT_46);
debounce47.attach(PIN_DETECT_47);
debounce48.attach(PIN_DETECT_48);
debounce40.attach(PIN_DETECT_40);
debounce41.attach(PIN_DETECT_41);
debounce42.attach(PIN_DETECT_42);
debounce55.attach(PIN_DETECT_55);
debounce56.attach(PIN_DETECT_56);
debounce43.attach(PIN_DETECT_43);
debounce64.attach(PIN_DETECT_64);
debounce65.attach(PIN_DETECT_65);
debounce66.attach(PIN_DETECT_66);
debounce67.attach(PIN_DETECT_67);
debounce68.attach(PIN_DETECT_68);
// -----------------------------------
debounce6.interval(50);
debounce7.interval(50);
debounce8.interval(50);
debounce9.interval(50);
debounce44.interval(50);
debounce11.interval(50);
debounce12.interval(50);
debounce57.interval(50);
debounce14.interval(50);
debounce15.interval(50);
debounce16.interval(50);
debounce17.interval(50);
debounce18.interval(50);
debounce19.interval(50);
debounce20.interval(50);
debounce45.interval(50);
debounce46.interval(50);
debounce47.interval(50);
debounce48.interval(50);
debounce40.interval(50);
debounce41.interval(50);
debounce42.interval(50);
debounce55.interval(50);
debounce56.interval(50);
debounce43.interval(50);
debounce64.interval(50);
debounce65.interval(50);
debounce66.interval(50);
debounce67.interval(50);
debounce68.interval(50);
// ------------------------------------
setup_ethernet();
client.setServer(server, 1883);
client.setCallback(callback);
dht1.begin();
dht2.begin();
dht3.begin();
dht4.begin();
dht5.begin();
dht6.begin();
memset(overridePIR, 0, PIRCount*sizeof(int));
}
void loop() {
//if(initCounter == 0) {
//during first run init the relay states
// turnOffAllLights();
// initCounter++;
//}
// try to reconnect 3times 2seconds apart, and retry this sequence after 30seconds
if ((!client.connected()) && ((MQTTFailedConnectTime + 30000 < millis()) || (millis()< 30000 && counter != -1) || counter > 0)) {
if(counter < 4){
reconnect();
counter = counter +1;
} else {
if(millis() < 30000){
counter = -1;
} else{
counter = 0;
}
MQTTFailedConnectTime = millis();
}
}
checkTimeoutAndExecute();
checkAndHandleShutterPosition();
if ((turnOnAllLightsTimestamp != 0) && (turnOnAllLightsTimestamp + defTimerTurnOnAllLightsMs < millis())) {
// timer expired -> turn off lights that had been turned on with turnOnAllLights
turnOffLights();
} else if ((turnOnLightsForNightPeeTimestamp != 0) && (turnOnLightsForNightPeeTimestamp + defTimerTurnOnLightsForNightPeeMs < millis())) {
turnOffLights();
}
checkPIRTimersAndTurnOffRelayIfNecessary();
if (delay_tempsensor.isExpired()) {
printRelayStates();
for(int i = 1; i <= tempSensorCount; i++) {
char outBuff[30];
sprintf(outBuff, "%s%d", outSensorTopic, i);
switch(i) {
case 1:
printTemperature(dht1, outBuff);
break;
case 2:
printTemperature(dht2, outBuff);
break;
case 3:
printTemperature(dht3, outBuff);
break;
case 4:
printTemperature(dht4, outBuff);
break;
case 5:
printTemperature(dht5, outBuff);
break;
case 6:
printTemperature(dht6, outBuff);
break;
}
}
delay_tempsensor.repeat();
}
debounce6.update(); //wardrobe LED white switch
if ( debounce6.fell()){
publishPinState(6, "OFF");
toggleRelay(0);
} else if (debounce6.rose()) {
publishPinState(6, "ON");
toggleRelay(0);
}
debounce7.update(); // wardrobe LED blue switch
if ( debounce7.fell()){
publishPinState(7, "OFF");
toggleRelay(1);
} else if (debounce7.rose()) {
publishPinState(7, "ON");
toggleRelay(1);
}
debounce8.update();
if ( delay_closetLED1.isExpired() && expCnt1 == 0) {
switchRelay('0', 11);
expCnt1 = 1;
} else if ( debounce8.rose()){
publishPinState(8, "ON");
switchRelay('1', 11);
//delay_closetLED1.start(defDelayTimerClosetLEDMs, AsyncDelay::MILLIS);
Serial.println(defDelayTimerClosetLEDMs, DEC);
delay_closetLED1.start(defDelayTimerClosetLEDMs, AsyncDelay::MILLIS);
expCnt1 = 0;
} else if (debounce8.fell()) {
publishPinState(8, "OFF");
switchRelay('0', 11);
}
debounce9.update();
if ( delay_closetLED2.isExpired() && expCnt2 == 0) {
switchRelay('0', 12);
expCnt2 = 1;
} else if ( debounce9.rose()){
publishPinState(9, "ON");
switchRelay('1', 12);
delay_closetLED2.start(defDelayTimerClosetLEDMs, AsyncDelay::MILLIS);
expCnt2 = 0;
} else if (debounce9.fell()) {
publishPinState(9, "OFF");
switchRelay('0', 12);
}
debounce44.update();
if ( delay_closetLED3.isExpired() && expCnt3 == 0) {
switchRelay('0', 13);
expCnt3 = 1;
} else if ( debounce44.rose()){
publishPinState(44, "ON");
switchRelay('1', 13);
delay_closetLED3.start(defDelayTimerClosetLEDMs, AsyncDelay::MILLIS);
expCnt3 = 0;
} else if (debounce44.fell()) {
publishPinState(44, "OFF");
switchRelay('0', 13);
}
debounce11.update();
if ( debounce11.fell()){
publishPinState(11, "OFF");
} else if (debounce11.rose()) {
publishPinState(11, "ON");
}
debounce12.update();
if ( debounce12.fell()){
publishPinState(12, "OFF");
} else if (debounce12.rose()) {
publishPinState(12, "ON");
}
debounce57.update();
if ( debounce57.fell()){
publishPinState(57, "OFF");
} else if (debounce57.rose()) {
publishPinState(57, "ON");
}
debounce14.update();
if ( debounce14.fell()){
publishPinState(14, "OFF");
} else if (debounce14.rose()) {
publishPinState(14, "ON");
}
debounce15.update();
if ( debounce15.fell()){
publishPinState(15, "OFF");
motionDetected(15, 0);
} else if (debounce15.rose()) {
publishPinState(15, "ON");
motionDetected(15, 1);
}
debounce16.update();
if ( debounce16.fell()){
publishPinState(16, "OFF");
motionDetected(16, 0);
} else if (debounce16.rose()) {
publishPinState(16, "ON");
motionDetected(16, 1);
}
debounce17.update();
if ( debounce17.fell()){
publishPinState(17, "OFF");
motionDetected(17, 0);
} else if (debounce17.rose()) {
publishPinState(17, "ON");
motionDetected(17, 1);
}
debounce18.update();
if ( debounce18.fell()){
publishPinState(18, "OFF");
handleToggle(0, 2);
} else if (debounce18.rose()) {
publishPinState(18, "ON");
handleToggle(0, 2);
}
debounce19.update();
if ( debounce19.fell()){
publishPinState(19, "OFF");
handleToggle(1, 3);
} else if (debounce19.rose()) {
publishPinState(19, "ON");
handleToggle(1, 3);
}
debounce20.update();
if ( debounce20.fell()){
publishPinState(20, "OFF");
handleToggle(2, 4);
} else if (debounce20.rose()) {
publishPinState(20, "ON");
handleToggle(2, 4);
}
debounce45.update();
if ( debounce45.fell()){
publishPinState(45, "OFF");
handleToggle(3, 5);
} else if (debounce45.rose()) {
publishPinState(45, "ON");
handleToggle(3, 5);
}
debounce46.update();
if ( debounce46.fell()){
publishPinState(46, "OFF");
handleToggle(4, 6);
} else if (debounce46.rose()) {
publishPinState(46, "ON");
handleToggle(4, 6);
}
debounce47.update();
if ( debounce47.fell()){
publishPinState(47, "OFF");
handleToggle(5, 7);
} else if (debounce47.rose()) {
publishPinState(47, "ON");
handleToggle(5, 7);
}
debounce48.update();
if ( debounce48.fell()){
publishPinState(48, "OFF");
handleToggle(6, 8);
} else if (debounce48.rose()) {
publishPinState(48, "ON");
handleToggle(6, 8);
}
debounce40.update();
if ( debounce40.fell()){
publishPinState(40, "OFF");
handleToggle(7, 9);
} else if (debounce40.rose()) {
publishPinState(40, "ON");
handleToggle(7, 9);
}
debounce41.update();
if ( debounce41.fell()){
publishPinState(41, "OFF");
handleToggle(7, 9);
} else if (debounce41.rose()) {
publishPinState(41, "ON");
handleToggle(7, 9);
}
debounce42.update();
if ( debounce42.fell()){
publishPinState(42, "OFF");
handleToggle(8, 10);
} else if (debounce42.rose()) {
publishPinState(42, "ON");
handleToggle(8, 10);
}
debounce55.update(); //bedroom door sensor
if ( debounce55.fell()){
publishPinState(55, "OFF");
} else if (debounce55.rose()) {
publishPinState(55, "ON");
}
debounce56.update(); //wardrobe PIR
if ( debounce56.fell()){
publishPinState(56, "OFF");
motionDetected(56, 0);
} else if (debounce56.rose()) {
publishPinState(56, "ON");
motionDetected(56, 1);
}
debounce43.update();
if ( debounce43.fell()){
publishPinState(43, "OFF");
handleToggle(8, 10);
} else if (debounce43.rose()) {
publishPinState(43, "ON");
handleToggle(8, 10);
}
//Shutter1Up
debounce64.update();
if ( debounce64.fell()){
publishPinState(64, "OFF");
} else if (debounce64.rose()) {
publishPinState(64, "ON");
shutterControl(SHUTTER1UPSWITCH, 1);
}
//Shutter1Down
debounce65.update();
if ( debounce65.fell()){
publishPinState(65, "OFF");
} else if (debounce65.rose()) {
publishPinState(65, "ON");
shutterControl(SHUTTER1DOWNSWITCH, 1);
}
//Shutter2Up
debounce66.update();
if ( debounce66.fell()){
publishPinState(66, "OFF");
} else if (debounce66.rose()) {
publishPinState(66, "ON");
shutterControl(SHUTTER2UPSWITCH, 1);
}
//Shutter2Down
debounce67.update();
if ( debounce67.fell()){
publishPinState(67, "OFF");
} else if (debounce67.rose()) {
publishPinState(67, "ON");
shutterControl(SHUTTER2DOWNSWITCH, 1);
}
// Custom switch, bound to nothing by default...
debounce68.update();
if ( debounce68.fell()){
publishPinState(68, "OFF");
} else if (debounce68.rose()) {
publishPinState(68, "ON");
}
// ---------------------------------
if (delay_rainsensor.isExpired()) {
int val = analogRead(54);
char cstr[10];
sprintf(cstr, "%d", val);
char topic[30];
char outstr[150];
sprintf(topic, "%s%d", outSensorTopic, 6);
Serial.print("\nRain sensor value:");
Serial.print(val, DEC);
if (val < defRainSensorTresholdValue ) {
sprintf(outstr, "{\"RAIN_SENSOR\":{\"Value\":%d,\"Raining:\":ON}}", val);
Serial.println(", Raining: ON");
} else {
sprintf(outstr, "{\"RAIN_SENSOR\":{\"Value\":%d,\"Raining:\":OFF}}", val);
Serial.println(", Raining: OFF");
}
client.publish(topic, outstr);
delay_rainsensor.repeat();
}
client.loop();
}