Lighting management with feedback using ESP8266 and electromechanical lighting relays

In this subforum you can show projects you have made, or you are busy with. Please create your own topic.

Moderator: leecollings

Post Reply
User avatar
Antori91
Posts: 136
Joined: Sunday 12 February 2017 17:12
Target OS: NAS (Synology & others)
Domoticz version: 4.10717
Location: France
Contact:

Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by Antori91 »

Hello,

I already use Domoticz for weather/temp data logging, alarm and heating management (see http://www.domoticz.com/forum/viewtopic ... 38&t=17032 ). I've deployed a new feature about lighting management. Among the lighting, there is two areas at my house with multiples lamps and multiple pushbuttons switches connected to two electromechanical lighting relays (GM43 series, a rather old LATCHING relay model) located at main panelboard.

For those two areas, I wanted to add Domoticz as "an additional pushbutton" able to know if lights are on (or off) and to switch on/off these two lighting areas. But I didn't want to change the pushbuttons or worst (meaning changing the wiring from the main panelboard !!) the way they are connected (pushbuttons to Neutral and Live only at the GM43 contacts).

The way I've done it :
- no change to the coil command with the pushbuttons,
- disconnect the lamps and the Live from the two GM43 relays contacts and use the contacts as a sensor/switch GPIO signal,
- use a WiFi Relay ESP8266 board with two relays to switch on/off the lamps of these two lighting areas.

Here is the Arduino sketch for the ESP8266. It uses MQTT to communicate with Domoticz.

Code: Select all

// @Antori91  http://www.domoticz.com/forum/memberlist.php?mode=viewprofile&u=13749
// ***** Lighting management 
//    Interfaces two GM43 devices with ElectroDragon IoT WiFi SPST/SPDT Relay board 
//    Lighting connected to relay *NO* output on SPDT (don't switch ON/OFF lamps during boot time)
// V0.3 First release - January 2018 
//       - CHANGE : Improve stability with use of an noise filter to read GPIO (digitalReadF instead of digitalRead)
//       - CHANGE : Switch OFF relays at boot time to avoid desynchronization between internal state and lighting in case of unattended ESP8266 reset
// V0.1  - January 2018
//    Initial Beta release 
 
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
 
// WiFi parameters
byte      WiFi_AP         = 1; // The WiFi Access Point we are connected to : 1 = main one or 2 = alternate one 
const     char *ssid      = "YOUR MAIN WIFI SSID";   //$$ 
const     char *password  = "YOUR MAIN WIFI PASSWORD";  //$$ 
const     char *ssid2     = "YOUR ALTERNATE WIFI SSID";   //$$ 
const     char *password2 =  "YOUR ALTERNATE WIFI PASSWORD"; //$$ 

// MQTT parameters
byte          willQoS            = 0;
char          willMessage[MQTT_MAX_PACKET_SIZE+1];
boolean       willRetain         = false;
const char*   mqtt_server        = "192.168.1.45"; //$$ CERTIFICATION=192.168.1.103 $$ PROD=192.168.1.45
const char*   topic_Domoticz_IN  = "domoticz/in";   //$$ 
const char*   topic_Domoticz_OUT = "domoticz/out";  //$$         
char          msgToPublish[MQTT_MAX_PACKET_SIZE+1]; 
WiFiClient    espClient;
PubSubClient  client(espClient);

// EDragon/ESP8266 board parameters
#define FILTER 3                       // N same readings every 100 ms must be read to validate GPIO reading ! 
#define Relay1                      12 // Digital Pin 12
#define Relay2                      13 // Digital Pin 13
#define GPIO4                        4 // GPIO-5 on SPDT connector
#define GPIO5                        5 // GPIO-4 on SPDT connector

// Lighting parameters
String      LIGHTING[2]         = { "ENTREE", "MEZZANINE" }; //$$ 
String      LIGHT_SWITCH_IDX[2] = { "50", "51" };            //$$ Corresponding DomoticZ switchs
String      LIGHT_ACTIVE[2]     = { "Off", "Off" };          // Lighting state (On or Off)    
boolean     LIGHT_CHANGED[2]    = { true, true };            // Flag to know if we must update DomoticZ because people have changed Lighting state using home pushbuttons. Initialize to *true* to reset DomoticZ switchs at boot.
int         cstate_GM43[2];                                  // GM43 current device status      
int         pstate_GM43[2];                                  // GM43 previous device status           
const char* LIGHT_MQTT_ID       = "LIGHTING";
                 

void setup() {   // ****************
      
   Serial.begin(115200);
   Serial.println("iot_EDRAGON_GM43_Lighting Booting - Firmware Version : 0.30");
   
   pinMode(Relay1,OUTPUT);   
   pinMode(Relay2,OUTPUT);  
   digitalWrite(Relay1, LOW);      // Lighting switch OFF 
   digitalWrite(Relay2, LOW);
   pinMode(GPIO4,INPUT);   
   pinMode(GPIO5,INPUT); 
   pstate_GM43[0] = digitalReadF(GPIO4); cstate_GM43[0] = pstate_GM43[0];
   pstate_GM43[1] = digitalReadF(GPIO5); cstate_GM43[1] = pstate_GM43[1];

   // connect to WiFi Access Point
   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);
   while (WiFi.waitForConnectResult() != WL_CONNECTED) {
      Serial.println("Connection to the main WiFi Failed!");
      PushbuttonsPressed();
      delay(2000);
      if( WiFi_AP == 1 ) {
         WiFi_AP=2;
         Serial.println("Trying to connect to the alternate WiFi...");
         WiFi.begin(ssid2, password2);
      } else {
         WiFi_AP=1;
         Serial.println("Trying to connect to the main WiFi...");
         WiFi.begin(ssid, password);    
      }
   } // while (WiFi.waitForConnectResult() != WL_CONNECTED) {

   // if ( MDNS.begin ( "esp8266" ) ) Serial.println ( "MDNS responder started" );
   
   // Port defaults to 8266
   // ArduinoOTA.setPort(8266);
   // Set OTA Hostname
   ArduinoOTA.setHostname(LIGHT_MQTT_ID);  
   // Set OTA authentication password
   ArduinoOTA.setPassword((const char *)"YOUR FOTA PASSWORD");
   ArduinoOTA.onStart([]() {
    Serial.println("Start");
   });
   ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
   });
   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
   });
   ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR)         Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR)   Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR)     Serial.println("End Failed");
   });
   ArduinoOTA.begin();

   // MQTT 
   client.setServer(mqtt_server, 1883);
   client.setCallback(callback);

   // say we are now ready and give configuration items
   Serial.println( "Ready" );
   Serial.print  ( "Connected to " ); if( WiFi_AP == 1 ) Serial.println( ssid ); else Serial.println( ssid2 );
   Serial.print  ( "IP address: " );  Serial.println( WiFi.localIP() );  
   Serial.print  ( "Lighting " ); Serial.print(LIGHTING[0]); Serial.print(" set to : "); Serial.print(LIGHT_ACTIVE[0]); Serial.print(" - its GM43-GPIO4 is : "); Serial.println(cstate_GM43[0]);
   Serial.print  ( "Lighting " ); Serial.print(LIGHTING[1]); Serial.print(" set to : "); Serial.print(LIGHT_ACTIVE[1]); Serial.print(" - its GM43-GPIO5 is : "); Serial.println(cstate_GM43[1]); 

} // void setup(  ****************


void callback(char* topic, byte* payload, unsigned int length) {   // ****************
   
   DynamicJsonBuffer jsonBuffer( MQTT_MAX_PACKET_SIZE );
   String messageReceived="";
   
   // Affiche le topic entrant - display incoming Topic
   Serial.print("Message arrived [");
   Serial.print(topic);
   Serial.print("] ");

   // decode payload message
   for (int i = 0; i < length; i++) {
   messageReceived+=((char)payload[i]); 
   }
   // display incoming message
   Serial.print(messageReceived);
     
   // if domoticz message
   if ( strcmp(topic, topic_Domoticz_OUT) == 0 ) {
        JsonObject& root = jsonBuffer.parseObject(messageReceived);
        if (!root.success()) {
           Serial.println("parsing Domoticz/out JSON Received Message failed");
           return;
        }

        const char* idxChar = root["idx"];
        String idx = String( idxChar);
        
        if ( idx == LIGHT_SWITCH_IDX[0] ) {      
           const char* cmde = root["nvalue"];
           if( strcmp(cmde, "0") == 0 ) {  // 0 means we have to switch OFF the lamps
                if( LIGHT_ACTIVE[0] == "On" ) { digitalWrite(Relay1, LOW); LIGHT_ACTIVE[0] = "Off"; } 
           } else if( LIGHT_ACTIVE[0] == "Off" ) { digitalWrite(Relay1, HIGH); LIGHT_ACTIVE[0] = "On"; }           
           Serial.print("Lighting "); Serial.print(LIGHTING[0]); Serial.print(" is now : "); Serial.println(LIGHT_ACTIVE[0]);
        }  // if ( idx == LIGHT_SWITCH_IDX[0] ) {

        if ( idx == LIGHT_SWITCH_IDX[1] ) {      
           const char* cmde = root["nvalue"];
           if( strcmp(cmde, "0") == 0 ) { 
                if( LIGHT_ACTIVE[1] == "On" ) { digitalWrite(Relay2, LOW); LIGHT_ACTIVE[1] = "Off"; } 
           } else if( LIGHT_ACTIVE[1] == "Off" ) { digitalWrite(Relay2, HIGH); LIGHT_ACTIVE[1] = "On"; }    
           Serial.print("Lighting "); Serial.print(LIGHTING[1]); Serial.print(" is now : "); Serial.println(LIGHT_ACTIVE[1]);
        }  // if ( idx == LIGHT_SWITCH_IDX[0] ) {
                   
   } // if domoticz message
  
   delay(15); 
} // void callback(char* to   **************** 


void reconnect() {   // ****************
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String string;
    
    // Attempt to connect
    string = "{\"command\" : \"addlogmessage\", \"message\" : \"Lighting went Offline - IP : " +  WiFi.localIP().toString() + "\"}";
    string.toCharArray( willMessage, MQTT_MAX_PACKET_SIZE);
    // if ( client.connect(buf) ) {
    if ( client.connect( LIGHT_MQTT_ID, topic_Domoticz_IN, willQoS, willRetain, willMessage ) ) {
        Serial.println("connected");
        
        // suscribe to MQTT topics
        Serial.print("Subscribe to domoticz/out topic. Status=");
        if ( client.subscribe(topic_Domoticz_OUT, 0) ) Serial.println("OK"); else Serial.println("KO"); 
   
        // Wait ten seconds to try to be sure DomoticZ available after a DomoticZ server reboot (i.e. means avoid MQTT available but not yet DomoticZ)
        delay(10000);
        // Say now "Me the lighting, I'm here" 
        string = "{\"command\" : \"addlogmessage\", \"message\" : \"iot_EDRAGON_GM43_Lighting Online - Firmware Version : 0.30 - IP : " + WiFi.localIP().toString() + "\"}";
        string.toCharArray( msgToPublish, MQTT_MAX_PACKET_SIZE);
        Serial.print(msgToPublish);
        Serial.print("Published to domoticz/in. Status=");
        if ( client.publish(topic_Domoticz_IN, msgToPublish) ) Serial.println("OK"); else Serial.println("KO");                           
    } else {
        Serial.print("MQTT connection failed, rc=");          
        Serial.print(client.state());
        Serial.println(" try again in 2 seconds");
        PushbuttonsPressed();
        // Wait 2 seconds before retrying
        delay(2000);
    }  // if (client.connect
    
  } // while (!client.connected()) {
} // void reconnect() { **************** 

byte digitalReadF(int GPIO) {
  int i;
  byte Reading = digitalRead(GPIO);
  byte NextReading;
  for( i=1; i <= FILTER ; i++ ) {
    delay( 100 );
    NextReading = digitalRead(GPIO);
    if( NextReading != Reading ) { i = 1; Reading = NextReading; }
  }
  return( Reading );
} // byte digitalReadF(GPIO) {

void PushbuttonsPressed() {  // ****************   
 
  cstate_GM43[0] = digitalReadF(GPIO4);  
  if( cstate_GM43[0] != pstate_GM43[0] )  {
      pstate_GM43[0] = cstate_GM43[0];
      LIGHT_CHANGED[0]=true;
      if( LIGHT_ACTIVE[0] == "Off") { 
          digitalWrite(Relay1, HIGH); LIGHT_ACTIVE[0] = "On";
      } else { 
          digitalWrite(Relay1, LOW);  LIGHT_ACTIVE[0] = "Off";
      } // if( LIGHT_ACTIVE[0] == "Off") { 
  } // if( cstate_GM43[0] != pstate_GM43[0] )  {

  cstate_GM43[1] = digitalReadF(GPIO5);  
  if( cstate_GM43[1] != pstate_GM43[1] )  {
      pstate_GM43[1] = cstate_GM43[1];
      LIGHT_CHANGED[1]=true;
      if( LIGHT_ACTIVE[1] == "Off") { 
          digitalWrite(Relay2, HIGH); LIGHT_ACTIVE[1] = "On"; 
      } else { 
          digitalWrite(Relay2, LOW);  LIGHT_ACTIVE[1] = "Off";
      } // if( LIGHT_ACTIVE[0] == "Off") { 
  } // if( cstate_GM43[0] != pstate_GM43[0] )  {  

}   // void PushbuttonsPressed() **************** 

void loop() {   // ****************
  if (!client.connected()) { // MQTT connection
    reconnect();
  }
  ArduinoOTA.handle();
 
  String string;
  // Check if people have pressed a home pushbutton to change Lighting state 
  PushbuttonsPressed();
  // if indeed a pushbutton was pressed, then update the corresponding DomoticZ switch
  if(  LIGHT_CHANGED[0] )  {
      string = "{\"command\" : \"switchlight\", \"idx\" : " + LIGHT_SWITCH_IDX[0] + ", \"switchcmd\": \"" + LIGHT_ACTIVE[0] + "\"}";
      string.toCharArray( msgToPublish, MQTT_MAX_PACKET_SIZE);
      Serial.print(msgToPublish);
      Serial.print(" Published to domoticz/in. Status=");
      if ( client.publish(topic_Domoticz_IN, msgToPublish) ) { LIGHT_CHANGED[0] = false; Serial.println("OK"); } else Serial.println("KO");  
  }    
  if(  LIGHT_CHANGED[1] )  {
      string = "{\"command\" : \"switchlight\", \"idx\" : " + LIGHT_SWITCH_IDX[1] + ", \"switchcmd\": \"" + LIGHT_ACTIVE[1] + "\"}";
      string.toCharArray( msgToPublish, MQTT_MAX_PACKET_SIZE);
      Serial.print(msgToPublish);
      Serial.print(" Published to domoticz/in. Status=");
      if ( client.publish(topic_Domoticz_IN, msgToPublish) ) { LIGHT_CHANGED[1] = false; Serial.println("OK"); } else Serial.println("KO");  
  }  
  
  client.loop();
  delay(100);
  
} // void loop()  **************** 
/* THE END */
iotGM43_BancTests.JPG
iotGM43_BancTests.JPG (161.41 KiB) Viewed 6502 times
iotGM43_Installé.JPG
iotGM43_Installé.JPG (137.91 KiB) Viewed 6502 times
MySwitchesPanel.JPG
MySwitchesPanel.JPG (281.58 KiB) Viewed 6502 times
Last edited by Antori91 on Monday 18 June 2018 14:27, edited 2 times in total.
Domoticz High Availability Cluster: Synology Dz V4.10693 (Main) - Raspberry Dz V4.10717 (Backup) - Scripts Node.js
Alarm server: Raspberry - motionEye - iot_ALARM-SVR Node.js
Sensors/Actuators: ESP8266-Arduino
https://github.com/Antori91/Home_Automation
User avatar
Antori91
Posts: 136
Joined: Sunday 12 February 2017 17:12
Target OS: NAS (Synology & others)
Domoticz version: 4.10717
Location: France
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by Antori91 »

Hello,
The latest code version is here : https://github.com/Antori91/Home_Automa ... 6_GM43.ino
Domoticz High Availability Cluster: Synology Dz V4.10693 (Main) - Raspberry Dz V4.10717 (Backup) - Scripts Node.js
Alarm server: Raspberry - motionEye - iot_ALARM-SVR Node.js
Sensors/Actuators: ESP8266-Arduino
https://github.com/Antori91/Home_Automation
WaaaghNL
Posts: 3
Joined: Wednesday 23 January 2019 11:56
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10362
Location: Waalre, NL
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by WaaaghNL »

Hi, i'm sorry to push up an old topic but i'm trying to get my Domoticz talking with my wemos over MQTT. the code i written was basic bot had no results. after some searching online i found your code on GitHub and made an iteration of it with only one wifi connection and changed the switch id's. But still got no luck getting it to work. it looks like it don't reads the domoticz/out JSON what domoticz provides (code block 1) but when i send a one line JSON string manual via the terminal it switching.

It looks like the callback function won't see the Domoticz JSON.

Domoticz Provided JSON

Code: Select all

{
   "Battery" : 255,
   "RSSI" : 12,
   "description" : "",
   "dtype" : "Light/Switch",
   "id" : "0001407C",
   "idx" : 44,
   "name" : "Zon is:",
   "nvalue" : 1,
   "stype" : "Switch",
   "svalue1" : "100",
   "switchType" : "On/Off",
   "unit" : 1
}
Result:

Code: Select all

Just dead space
Terminal code

Code: Select all

{"idx" : 44,"nvalue" : 1, "stype" : "Switch", "svalue1" : "100", "switchType" : "On/Off"}
mosquitto_pub -h localhost -t "domoticz/out" -m "{\"idx\" : 44,\"nvalue\" : 1, \"stype\" : \"Switch\", \"svalue1\" : \"100\", \"switchType\" : \"On/Off\"}"
Result:

Code: Select all

Entering MQTT Callback. Message arrived regarding topic [domoticz/out]
MQTT Callback. Parsing Domoticz Message arrived...
MQTT Callback. This message is about Domoticz Device Idx=44
Leaving MQTT Callback
Arduino Code

Code: Select all

// @Antori91  http://www.domoticz.com/forum/memberlist.php?mode=viewprofile&u=13749
// ***** Lighting management
//    Interfaces two GM43 devices with ElectroDragon IoT WiFi SPST/SPDT Relay board
//    Lighting connected to relay *NO* output on SPDT (don't switch ON/OFF lamps during boot time)
// V0.54 May 2018

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

// EDragon/ESP8266 board parameters
boolean ColdBoot                  = true;
#define FILTER                       3 // N+1 same readings every DELAY_FILTER ms must be read to validate GPIO reading ! 
#define DELAY_FILTER                25 // Delay in ms between two readings
#define Relay1                      12 // Digital Pin 12
#define Relay2                      13 // Digital Pin 13
#define GPIO4                        4 // GPIO-5 on SPDT connector
#define GPIO5                        5 // GPIO-4 on SPDT connector

// WiFi parameters
boolean   WiFiWasRenew = false;
#define   WiFiRetryDelay 2000 // Delay in ms between each WiFi connection retry
const char* ssid = "SECRET";
const char* password = "SECRET";

// MQTT parameters
#define MQTT_MAX_PACKET_SIZE 2048
#define MQTT_SERVER_IP        "domoticz.SECRET.nl"
byte          willQoS            = 0;
char          willMessage[MQTT_MAX_PACKET_SIZE + 1];
boolean       willRetain         = false;
const char*   mqtt_server        = MQTT_SERVER_IP;
const char*   topic_Domoticz_IN  = "domoticz/in";
const char*   topic_Domoticz_OUT = "domoticz/out";
char          msgToPublish[MQTT_MAX_PACKET_SIZE + 1];
WiFiClient    espClient;
PubSubClient  client(espClient);
#define       MQTTRetryDelay       2000 // Delay in ms between each MQTT connection retry
#define       MQTTMaxRetriesDelay  10  // if we didn't success to reconnect in that delay in mn, then restart the ESP
const int     MQTTMaxRetries     = MQTTMaxRetriesDelay * ( 60000 / ( 4000 + MQTTRetryDelay + FILTER * 2 * DELAY_FILTER ) ); // 4s is around the connection try duration
int           MQTTRetriesCounter = MQTTMaxRetries;

// Lighting parameters
String      LIGHTING[2]         = { "RGB", "SUN" }; //$$
String      LIGHT_SWITCH_IDX[2] = { "121", "44" };            // Corresponding DomoticZ switchs
String      LIGHT_ACTIVE[2]     = { "Off", "Off" };          // Lighting state (On or Off)
boolean     LIGHT_CHANGED[2]    = { true, true };            // Flag to know if we must update DomoticZ because people have changed Lighting state using home pushbuttons. Initialize to *true* to reset DomoticZ switchs at boot.
int         cstate_GM43[2];                                  // GM43 current device status
int         pstate_GM43[2];                                  // GM43 previous device status
const char* LIGHT_MQTT_ID       = "TWILIGHT";

void eventWiFi(WiFiEvent_t event) {
  Serial.println("== WiFi Event Received ==");
  switch (event) {
    case WIFI_EVENT_STAMODE_CONNECTED:
      Serial.print("[WiFi STA] "); /*Serial.print(event);*/ Serial.println(" Connected");
      break;
    case WIFI_EVENT_STAMODE_DISCONNECTED:
      Serial.print("[WiFi STA] "); /*Serial.print(event);*/ Serial.print(" Disconnected - Status :"); Serial.print(WiFi.status()); Serial.print(" "); Serial.println(connectionStatus( WiFi.status()));
      break;
    case WIFI_EVENT_STAMODE_AUTHMODE_CHANGE:
      Serial.print("[WiFi STA] "); /*Serial.print(event);*/ Serial.println(" AuthMode Change");
      break;
    case WIFI_EVENT_STAMODE_GOT_IP:
      Serial.print("[WiFi STA] "); /*Serial.print(event);*/ Serial.println(" Got IP");
      Serial.printf(" == SUCCESS - Connected to WiFi AP %s ==\n", WiFi.SSID().c_str());
      WiFiWasRenew = true;
      break;
    case WIFI_EVENT_STAMODE_DHCP_TIMEOUT:
      Serial.print("[WiFi STA] "); /*Serial.print(event);*/ Serial.println(" DHCP Timeout");
      break;
    case WIFI_EVENT_SOFTAPMODE_STACONNECTED:
      Serial.print("[WiFi AP] "); /*Serial.print(event);*/ Serial.println(" Client Connected");
      break;
    case WIFI_EVENT_SOFTAPMODE_STADISCONNECTED:
      Serial.print("[WiFi AP] "); /*Serial.print(event);*/ Serial.println(" Client Disconnected");
      break;
    case WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED:
      Serial.print("[WiFi AP] "); /*Serial.print(event);*/ Serial.println(" Probe Request Received");
      break;
  }  // switch(event) {
} // void eventWiFi(WiFiEvent_t event) {

String connectionStatus( int which ) {
  switch ( which ) {
    case WL_CONNECTED:
      return "Connected";
      break;
    case WL_NO_SSID_AVAIL:
      return "AP not available";
      break;
    case WL_CONNECT_FAILED:
      return "Connect Failed";
      break;
    case WL_IDLE_STATUS:
      return "Idle status";
      break;
    case WL_DISCONNECTED:
      return "Disconnected";
      break;
    default:
      return "Unknown";
      break;
  }
} // String connectionStatus( int which ) {

void setup() {   // ****************

  Serial.begin(115200);

  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  digitalWrite(Relay1, LOW);      // Lighting switch OFF
  digitalWrite(Relay2, LOW);
  pinMode(GPIO4, INPUT);
  pinMode(GPIO5, INPUT);
  pstate_GM43[0] = digitalReadF(GPIO4, false); cstate_GM43[0] = pstate_GM43[0];
  pstate_GM43[1] = digitalReadF(GPIO5, false); cstate_GM43[1] = pstate_GM43[1];

  // connect to WiFi Access Point
  WiFi.onEvent(eventWiFi);
  WiFi.mode(WIFI_STA);
  Serial.printf( "Trying to connect to preferred WiFi AP %s\n", ssid );
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    PushbuttonsPressed(false);

    delay(WiFiRetryDelay);
    Serial.printf( "Trying to connect to WiFi AP %s\n", ssid );
    WiFi.begin(ssid, password);
  } // while (WiFi.waitForConnectResult() != WL_CONNECTED) {

  // if ( MDNS.begin ( "esp8266" ) ) Serial.println ( "MDNS responder started" );

  // MQTT
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  // say we are now ready and give configuration items
  Serial.println( "Ready" );
  Serial.print  ( "Connected to " ); Serial.printf ( "%s\n", ssid );
  Serial.print  ( "IP address: " );  Serial.println( WiFi.localIP() );
  Serial.print  ( "Lighting " ); Serial.print(LIGHTING[0]); Serial.print(" set to : "); Serial.print(LIGHT_ACTIVE[0]); Serial.print(" - its GM43-GPIO4 is : "); Serial.println(cstate_GM43[0]);
  Serial.print  ( "Lighting " ); Serial.print(LIGHTING[1]); Serial.print(" set to : "); Serial.print(LIGHT_ACTIVE[1]); Serial.print(" - its GM43-GPIO5 is : "); Serial.println(cstate_GM43[1]);

} // void setup(  ****************


void callback(char* topic, byte* payload, unsigned int length) {   // ****************

  DynamicJsonBuffer jsonBuffer( MQTT_MAX_PACKET_SIZE );
  String messageReceived = "";

  // Affiche le topic entrant - display incoming Topic
  Serial.print("\nEntering MQTT Callback. Message arrived regarding topic [");
  Serial.print(topic);
  Serial.println("]");

  // decode payload message
  for (int i = 0; i < length; i++) {
    messageReceived += ((char)payload[i]);
  }
  // display incoming message
  // Serial.println(messageReceived);

  // if domoticz message
  if ( strcmp(topic, topic_Domoticz_OUT) == 0 ) {
    Serial.println("MQTT Callback. Parsing Domoticz Message arrived...");
    JsonObject& root = jsonBuffer.parseObject(messageReceived);
    if (!root.success()) {
      Serial.println("parsing Domoticz/out JSON Received Message failed");
      return;
    }

    const char* idxChar = root["idx"];
    String idx = String( idxChar);
    Serial.print("MQTT Callback. This message is about Domoticz Device Idx="); Serial.println(idx);

    if ( idx == LIGHT_SWITCH_IDX[0] ) {
      const char* cmde = root["nvalue"];
      Serial.print("MQTT Callback. Light Command received="); Serial.println(cmde);
      if ( strcmp(cmde, "0") == 0 ) { // 0 means we have to switch OFF the lights
        if ( LIGHT_ACTIVE[0] == "On" ) {
          Serial.print("MQTT Callback. Turning Off Lighting ");
          Serial.println(LIGHTING[0]);
          digitalWrite(Relay1, LOW);
          delay(2000);
          LIGHT_ACTIVE[0] = "Off";
        }
      } else if ( LIGHT_ACTIVE[0] == "Off" ) {
        Serial.print("MQTT Callback. Turning On Lighting ");
        Serial.println(LIGHTING[0]);
        digitalWrite(Relay1, HIGH);
        delay(2000);
        LIGHT_ACTIVE[0] = "On";
      }
      Serial.print  ( "Lighting " ); Serial.print(LIGHTING[0]); Serial.print(" set from Domoticz to : "); Serial.print(LIGHT_ACTIVE[0]); Serial.print(" - its GM43-GPIO4 is : "); Serial.println(cstate_GM43[0]);
    }  // if ( idx == LIGHT_SWITCH_IDX[0] ) {

    if ( idx == LIGHT_SWITCH_IDX[1] ) {
      const char* cmde = root["nvalue"];
      Serial.print("MQTT Callback. Light Command received="); Serial.println(cmde);
      if ( strcmp(cmde, "0") == 0 ) {
        if ( LIGHT_ACTIVE[1] == "On" ) {
          Serial.print("MQTT Callback. Turning Off Lighting ");
          Serial.println(LIGHTING[1]);
          digitalWrite(Relay2, LOW);
          delay(2000);
          LIGHT_ACTIVE[1] = "Off";
        }
      } else if ( LIGHT_ACTIVE[1] == "Off" ) {
        Serial.print("MQTT Callback. Turning On Lighting ");
        Serial.println(LIGHTING[1]);
        digitalWrite(Relay2, HIGH);
        delay(2000);
        LIGHT_ACTIVE[1] = "On";
      }
      Serial.print  ( "Lighting " ); Serial.print(LIGHTING[1]); Serial.print(" set from Domoticz to : "); Serial.print(LIGHT_ACTIVE[1]); Serial.print(" - its GM43-GPIO5 is : "); Serial.println(cstate_GM43[1]);
    }  // if ( idx == LIGHT_SWITCH_IDX[1] ) {

  } // if domoticz message

  delay(15);
  Serial.println("Leaving MQTT Callback");
} // void callback(char* to   ****************


void reconnect() {   // ****************
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String string;

    // Attempt to connect
    string = "{\"command\" : \"addlogmessage\", \"message\" : \"Lighting went Offline - IP : " +  WiFi.localIP().toString() + "\"}";
    string.toCharArray( willMessage, MQTT_MAX_PACKET_SIZE);
    // if ( client.connect(buf) ) {
    if ( client.connect( LIGHT_MQTT_ID, topic_Domoticz_IN, willQoS, willRetain, willMessage ) ) {
      Serial.println("connected");

      // suscribe to MQTT topics
      Serial.print("Subscribe to domoticz/out topic. Status=");
      if ( client.subscribe(topic_Domoticz_OUT, 0) ) Serial.println("OK"); else Serial.println("KO");

      // Wait ten seconds to try to be sure DomoticZ available after a DomoticZ server reboot (i.e. means avoid MQTT available but not yet DomoticZ)
      // delay(10000);

      // Say now "Me the lighting, I'm here"
      if ( ColdBoot )
        string = "{\"command\" : \"addlogmessage\", \"message\" : \"iot_EDRAGON_GM43_Lighting Online - COLD BOOT Reason : " + ESP.getResetReason() + " - Firmware Version : 0.54 - SSID/IP/MAC : " + WiFi.SSID() + "/" + WiFi.localIP().toString() + "/" + WiFi.macAddress().c_str() + "\"}";
      else if ( WiFiWasRenew )
        string = "{\"command\" : \"addlogmessage\", \"message\" : \"iot_EDRAGON_GM43_Lighting Online - WIFI CONNECTION RENEWED - SSID/IP/MAC : " + WiFi.SSID() + "/" + WiFi.localIP().toString() + "/" + WiFi.macAddress().c_str() + "\"}";
      else string = "{\"command\" : \"addlogmessage\", \"message\" : \"iot_EDRAGON_GM43_Lighting Online - MQTT CONNECTION RENEWED - SSID/IP/MAC : " + WiFi.SSID() + "/" + WiFi.localIP().toString() + "/" + WiFi.macAddress().c_str() + "\"}";
      string.toCharArray( msgToPublish, MQTT_MAX_PACKET_SIZE);
      Serial.print(msgToPublish);
      Serial.print("Published to domoticz/in. Status=");
      if ( client.publish(topic_Domoticz_IN, msgToPublish) ) Serial.println("OK"); else Serial.println("KO");
      ColdBoot = false; WiFiWasRenew = false;
    } else {
      Serial.print("MQTT connection failed, rc=");
      Serial.print(client.state());
      Serial.print(", MQTTRetriesCounter=");
      Serial.print( MQTTRetriesCounter );
      Serial.print(" - Try again in ");
      Serial.print( (int)(MQTTRetryDelay / 1000) );
      Serial.println(" seconds");
      PushbuttonsPressed(false);
      if ( MQTTRetriesCounter-- == 0 ) ESP.restart();
      // Wait n seconds before retrying
      delay(MQTTRetryDelay);
    }  // if (client.connect

  } // while (!client.connected()) {
} // void reconnect() { ****************

int digitalReadF(int GPIO, boolean DoMqttWork) {
  int i;
  int Reading = digitalRead(GPIO);
  if ( Reading != 0 && Reading != 1 ) {
    Serial.print("\n==== Error reading GPIO : ");
    Serial.println(GPIO);
  }
  int NextReading;
  for ( i = 1; i <= FILTER ; i++ ) {
    if ( DoMqttWork ) client.loop();
    delay( DELAY_FILTER );
    NextReading = digitalRead(GPIO);
    if ( NextReading != 0 && NextReading != 1 ) {
      Serial.print("\n==== Error reading GPIO : ");
      Serial.println(GPIO);
    }
    if ( NextReading != Reading ) {
      i = 1;
      Reading = NextReading;
      Serial.print("\n==== Restarting reading GPIO : "); Serial.println(GPIO);
    }
  }
  return ( Reading );
} // int digitalReadF(int GPIO, boolean DoMqttWork) {

void PushbuttonsPressed(boolean DoMqttWork) {  // ****************

  cstate_GM43[0] = digitalReadF(GPIO4, DoMqttWork);
  if ( cstate_GM43[0] != 0 && cstate_GM43[0] != 1 ) {
    Serial.print("\n==== Error cstate_GM43[0] : ");
    Serial.println(GPIO4);
  }
  if ( cstate_GM43[0] != pstate_GM43[0] )  {
    Serial.print( "\nLighting is going to changed. " ); Serial.print(LIGHTING[0]); Serial.print(" was : "); Serial.print(LIGHT_ACTIVE[0]); Serial.print(" - its GM43-GPIO4 is now : "); Serial.println(cstate_GM43[0]);
    pstate_GM43[0] = cstate_GM43[0];
    LIGHT_CHANGED[0] = true;
    if ( LIGHT_ACTIVE[0] == "Off") {
      digitalWrite(Relay1, HIGH); delay(2000); LIGHT_ACTIVE[0] = "On";
    } else {
      digitalWrite(Relay1, LOW);  delay(2000); LIGHT_ACTIVE[0] = "Off";
    } // if( LIGHT_ACTIVE[0] == "Off") {
    Serial.print( "Lighting has changed. " ); Serial.print(LIGHTING[0]); Serial.print(" set from Pushbuttons to : "); Serial.print(LIGHT_ACTIVE[0]); Serial.print(" - its GM43-GPIO4 is : "); Serial.println(cstate_GM43[0]);
  } // if( cstate_GM43[0] != pstate_GM43[0] )  {

  cstate_GM43[1] = digitalReadF(GPIO5, DoMqttWork);
  if ( cstate_GM43[1] != 0 && cstate_GM43[1] != 1 ) {
    Serial.print("\n==== Error cstate_GM43[1] : ");
    Serial.println(GPIO5);
  }
  if ( cstate_GM43[1] != pstate_GM43[1] )  {
    Serial.print( "\nLighting is going to changed. " ); Serial.print(LIGHTING[1]); Serial.print(" was : "); Serial.print(LIGHT_ACTIVE[1]); Serial.print(" - its GM43-GPIO5 is now: "); Serial.println(cstate_GM43[1]);
    pstate_GM43[1] = cstate_GM43[1];
    LIGHT_CHANGED[1] = true;
    if ( LIGHT_ACTIVE[1] == "Off") {
      digitalWrite(Relay2, HIGH); delay(2000); LIGHT_ACTIVE[1] = "On";
    } else {
      digitalWrite(Relay2, LOW);  delay(2000); LIGHT_ACTIVE[1] = "Off";
    } // if( LIGHT_ACTIVE[1] == "Off") {
    Serial.print( "Lighting has changed. " ); Serial.print(LIGHTING[1]); Serial.print(" set from Pushbuttons to : "); Serial.print(LIGHT_ACTIVE[1]); Serial.print(" - its GM43-GPIO5 is : "); Serial.println(cstate_GM43[1]);
  } // if( cstate_GM43[1] != pstate_GM43[1] )  {

}   // void PushbuttonsPressed(boolean DoMqttWork) ****************

void loop() {   // ****************
  if (!client.connected()) { // MQTT connection
    reconnect();
  }
  MQTTRetriesCounter = MQTTMaxRetries;

  String string;

  // Check if people have pressed a home pushbutton to change Lighting state
  PushbuttonsPressed(true);

  if (  LIGHT_CHANGED[0] )  {
    string = "{\"command\" : \"switchlight\", \"idx\" : " + LIGHT_SWITCH_IDX[0] + ", \"switchcmd\": \"" + LIGHT_ACTIVE[0] + "\"}";
    string.toCharArray( msgToPublish, MQTT_MAX_PACKET_SIZE);
    Serial.print(msgToPublish);
    Serial.print(" Published to domoticz/in. Status=");
    if ( client.publish(topic_Domoticz_IN, msgToPublish) ) {
      LIGHT_CHANGED[0] = false;
      Serial.println("OK");
    } else Serial.println("KO");
    Serial.print("GM43-GPIO4 is : "); Serial.println(cstate_GM43[0]);
  }
  if (  LIGHT_CHANGED[1] )  {
    string = "{\"command\" : \"switchlight\", \"idx\" : " + LIGHT_SWITCH_IDX[1] + ", \"switchcmd\": \"" + LIGHT_ACTIVE[1] + "\"}";
    string.toCharArray( msgToPublish, MQTT_MAX_PACKET_SIZE);
    Serial.print(msgToPublish);
    Serial.print(" Published to domoticz/in. Status=");
    if ( client.publish(topic_Domoticz_IN, msgToPublish) ) {
      LIGHT_CHANGED[1] = false;
      Serial.println("OK");
    } else Serial.println("KO");
    Serial.print("GM43-GPIO5 is : "); Serial.println(cstate_GM43[1]);
  }

  client.loop();
  delay(100);
} // void loop()  ****************
/* THE END */
User avatar
Antori91
Posts: 136
Joined: Sunday 12 February 2017 17:12
Target OS: NAS (Synology & others)
Domoticz version: 4.10717
Location: France
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by Antori91 »

Hello WaaaghNL,

First of all, there is one thing I don't like in the code you added, it's the #define MQTT_MAX_PACKET_SIZE 2048 you added. This define shouldn't be here I think. For my part, I've modified the PubSubClient.h itself (see screenshot below).

Then, I'm not sure to understand if it works or not when issuing a command line. I ask this question especially because I don't see the message corresponding to Serial.print("MQTT Callback. Light Command received="); Serial.println(cmde); This message should be between "MQTT Callback. This message is about Domoticz Device Idx=44" and "Leaving MQTT Callback".

If it works from command line, you have to check your Domoticz MQTT parameters. By the way, below are the MQTT messages (sent by Domoticz) I get when I switch on/off from Domoticz one of the two lighting involved.

{
"Battery" : 255,
"RSSI" : 12,
"dtype" : "Light/Switch",
"id" : "00014083",
"idx" : 51,
"name" : "MEZZANINE",
"nvalue" : 1,
"stype" : "Switch",
"svalue1" : "0",
"switchType" : "On/Off",
"unit" : 1
}

{
"Battery" : 255,
"RSSI" : 12,
"dtype" : "Light/Switch",
"id" : "00014083",
"idx" : 51,
"name" : "MEZZANINE",
"nvalue" : 0,
"stype" : "Switch",
"svalue1" : "0",
"switchType" : "On/Off",
"unit" : 1
}
Capture.GIF
Capture.GIF (16.27 KiB) Viewed 4509 times
Domoticz High Availability Cluster: Synology Dz V4.10693 (Main) - Raspberry Dz V4.10717 (Backup) - Scripts Node.js
Alarm server: Raspberry - motionEye - iot_ALARM-SVR Node.js
Sensors/Actuators: ESP8266-Arduino
https://github.com/Antori91/Home_Automation
WaaaghNL
Posts: 3
Joined: Wednesday 23 January 2019 11:56
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10362
Location: Waalre, NL
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by WaaaghNL »

hi, i don't know if i'm doing it right but i added an tab in the Arduino sketch with the name "PubSubClient.h", removed the line "#define MQTT_MAX_PACKET_SIZE 2048" from the sketch, and i'm still getting the same problem. When Domoticz sends MQTT message the callback won't run. But if i send is by hand it works like normal.

i made a little vid with the problem: https://www.youtube.com/watch?v=hDrjLHG ... e=youtu.be
User avatar
Antori91
Posts: 136
Joined: Sunday 12 February 2017 17:12
Target OS: NAS (Synology & others)
Domoticz version: 4.10717
Location: France
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by Antori91 »

Correct to remove the line "#define MQTT_MAX_PACKET_SIZE 2048" from the sketch
NOT correct to add a tab in the Arduino sketch with the name "PubSubClient.h". Instead, you have to modify the PubSubClient.h file within your Arduino libraries. Depending on your installation, it is located somewhere in ...\Arduino\libraries\PubSubClient\src
In my environment, this file is in C:\Users\USERNAME\Documents\Arduino\libraries\PubSubClient\src

PS: your video is not available
Domoticz High Availability Cluster: Synology Dz V4.10693 (Main) - Raspberry Dz V4.10717 (Backup) - Scripts Node.js
Alarm server: Raspberry - motionEye - iot_ALARM-SVR Node.js
Sensors/Actuators: ESP8266-Arduino
https://github.com/Antori91/Home_Automation
WaaaghNL
Posts: 3
Joined: Wednesday 23 January 2019 11:56
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10362
Location: Waalre, NL
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by WaaaghNL »

Oh wow thanks! it works now. Only one thing. Your version of "PubSubClient.h" is a little bit outdated and won't compile without errors referring to the 2.7.0 PubSubClient.cpp

I Compared your code to the original "PubSubClient.h" (2.7.0) and only copied 2 lines from your code into the original to get it working.

Image
User avatar
Antori91
Posts: 136
Joined: Sunday 12 February 2017 17:12
Target OS: NAS (Synology & others)
Domoticz version: 4.10717
Location: France
Contact:

Re: Lighting management with feedback using ESP8266 and electromechanical lighting relays

Post by Antori91 »

Fine! By modifying "PubSubClient.h", what I meant was actually just change the line MQTT_MAX_PACKET_SIZE line (and eventually the MQTT_KEEPALIVE line, this modification is not mandatory at all) in your library original file.
Domoticz High Availability Cluster: Synology Dz V4.10693 (Main) - Raspberry Dz V4.10717 (Backup) - Scripts Node.js
Alarm server: Raspberry - motionEye - iot_ALARM-SVR Node.js
Sensors/Actuators: ESP8266-Arduino
https://github.com/Antori91/Home_Automation
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest