Arduino RELAY switches over WiFi, controlled via HASS / MQTT, comes with OTA Support

Hi Ladies and Gents,

Sharing my simple project back to the Community.

I added simple Relay Switches to my HASS setup, using an Arduino Clone with builtin ESP8266 connected to a 4 Relay Switch Module.

My intention is to use these switches controlling my Sprinklers, and any free relay will be used for controlling the garden lights.

My Baseline:

To install:

pi@hassbian:~ $ cd /home/pi/hassbian-scripts/
pi@hassbian:~/hassbian-scripts $ sudo ./install_mosquitto.sh

Jot down the username and password you have entered when doing the MQTT installation, you will need that for the Sketch and YAML portion. You will need to replace the mqtt_username and mqtt_password respectively.

My Arduino Sketch as follows:

//EJ: 4 Relay Switch over WIFI using MQTT and Home Assistant with OTA Support
//EJ: The only way I know how to contribute to the HASS Community... you guys ROCK!!!!!
//EJ: Erick Joaquin :-) Australia

// Original sketch courtesy of ItKindaWorks
//ItKindaWorks - Creative Commons 2016
//github.com/ItKindaWorks
//
//Requires PubSubClient found here: https://github.com/knolleary/pubsubclient
//
//ESP8266 Simple MQTT switch controller


#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>

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

//EDIT THESE LINES TO MATCH YOUR SETUP
#define MQTT_SERVER "xxx.xxx.xxx.xxx"  //you MQTT IP Address
const char* ssid = "YOUESSID";
const char* password = "WIFI_PASSWORD";

//EJ: Data PIN Assignment on WEMOS D1 R2 https://www.wemos.cc/product/d1.html
// if you are using Arduino UNO, you will need to change the "D1 ~ D4" with the corresponding UNO DATA pin number 

const int switchPin1 = D1;
const int switchPin2 = D2;
const int switchPin3 = D3;
const int switchPin4 = D5;

//EJ: These are the MQTT Topic that will be used to manage the state of Relays 1 ~ 4
//EJ: Refer to my YAML component entry
//EJ: feel free to replicate the line if you have more relay switch to control, but dont forget to increment the number suffix so as increase switch logics in loop()

char const* switchTopic1 = "/house/switch1/";
char const* switchTopic2 = "/house/switch2/";
char const* switchTopic3 = "/house/switch3/";
char const* switchTopic4 = "/house/switch4/";


WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);

void setup() {
  //initialize the switch as an output and set to LOW (off)
  pinMode(switchPin1, OUTPUT); // Relay Switch 1
  digitalWrite(switchPin1, LOW);

  pinMode(switchPin2, OUTPUT); // Relay Switch 2
  digitalWrite(switchPin2, LOW);

  pinMode(switchPin3, OUTPUT); // Relay Switch 3
  digitalWrite(switchPin3, LOW);

  pinMode(switchPin4, OUTPUT); // Relay Switch 4
  digitalWrite(switchPin4, LOW);

  ArduinoOTA.setHostname("My Arduino WEMO"); // A name given to your ESP8266 module when discovering it as a port in ARDUINO IDE
  ArduinoOTA.begin(); // OTA initialization

  //start the serial line for debugging
  Serial.begin(115200);
  delay(100);

  //start wifi subsystem
  WiFi.begin(ssid, password);
  //attempt to connect to the WIFI network and then connect to the MQTT server
  reconnect();

  //wait a bit before starting the main loop
      delay(2000);
}


void loop(){

  //reconnect if connection is lost
  if (!client.connected() && WiFi.status() == 3) {reconnect();}

  //maintain MQTT connection
  client.loop();

  //MUST delay to allow ESP8266 WIFI functions to run
  delay(10); 
  ArduinoOTA.handle();
}

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

  //convert topic to string to make it easier to work with
  String topicStr = topic; 
  //EJ: Note:  the "topic" value gets overwritten everytime it receives confirmation (callback) message from MQTT

  //Print out some debugging info
  Serial.println("Callback update.");
  Serial.print("Topic: ");
  Serial.println(topicStr);

   if (topicStr == "/house/switch1/") 
    {

     //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
     if(payload[0] == '1'){
       digitalWrite(switchPin1, HIGH);
       client.publish("/house/switchConfirm1/", "1");
       }

      //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
     else if (payload[0] == '0'){
       digitalWrite(switchPin1, LOW);
       client.publish("/house/switchConfirm1/", "0");
       }
     }

     // EJ: copy and paste this whole else-if block, should you need to control more switches
     else if (topicStr == "/house/switch2/") 
     {
     //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
     if(payload[0] == '1'){
       digitalWrite(switchPin2, HIGH);
       client.publish("/house/switchConfirm2/", "1");
       }

      //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
     else if (payload[0] == '0'){
       digitalWrite(switchPin2, LOW);
       client.publish("/house/switchConfirm2/", "0");
       }
     }
     else if (topicStr == "/house/switch3/") 
     {
     //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
     if(payload[0] == '1'){
       digitalWrite(switchPin3, HIGH);
       client.publish("/house/switchConfirm3/", "1");
       }

      //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
     else if (payload[0] == '0'){
       digitalWrite(switchPin3, LOW);
       client.publish("/house/switchConfirm3/", "0");
       }
     }
     else if (topicStr == "/house/switch4/") 
     {
     //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
     if(payload[0] == '1'){
       digitalWrite(switchPin4, HIGH);
       client.publish("/house/switchConfirm4/", "1");
       }

      //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
     else if (payload[0] == '0'){
       digitalWrite(switchPin4, LOW);
       client.publish("/house/switchConfirm4/", "0");
       }
     }
}


void reconnect() {

  //attempt to connect to the wifi if connection is lost
  if(WiFi.status() != WL_CONNECTED){
    //debug printing
    Serial.print("Connecting to ");
    Serial.println(ssid);

    //loop while we wait for connection
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }

    //print out some more debug once connected
    Serial.println("");
    Serial.println("WiFi connected");  
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  }

  //make sure we are connected to WIFI before attemping to reconnect to MQTT
  if(WiFi.status() == WL_CONNECTED){
  // Loop until we're reconnected to the MQTT server
    while (!client.connected()) {
      Serial.print("Attempting MQTT connection...");

      // Generate client name based on MAC address and last 8 bits of microsecond counter
      String clientName;
      clientName += "esp8266-";
      uint8_t mac[6];
      WiFi.macAddress(mac);
      clientName += macToStr(mac);

      //if connected, subscribe to the topic(s) we want to be notified about
      //EJ: Delete "mqtt_username", and "mqtt_password" here if you are not using any 
      if (client.connect((char*) clientName.c_str(),"mqtt_username", "mqtt_password")) {  //EJ: Update accordingly with your MQTT account 
        Serial.print("\tMQTT Connected");
        client.subscribe(switchTopic1);
        client.subscribe(switchTopic2);
        client.subscribe(switchTopic3);
        client.subscribe(switchTopic4);
        //EJ: Do not forget to replicate the above line if you will have more than the above number of relay switches
      }

      //otherwise print failed for debugging
      else{Serial.println("\tFailed."); abort();}
    }
  }
}

//generate unique name from MAC addr
String macToStr(const uint8_t* mac){

  String result;

  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);

    if (i < 5){
      result += ':';
    }
  }

  return result;
}

Supported by (working alongside) the following entry in YAML

mqtt:
  broker: YOUR_MQTT_IPADDRESS 
  port: 1883
  client_id: home-assistant-1
  keepalive: 60
  username: mqtt_username
  password: mqtt_password
  protocol: 3.1 


switch 1:
  - platform: mqtt
    name: "MQTT Switch 1"
    state_topic: "/house/switchConfirm1/"
    command_topic: "/house/switch1/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    
  
switch 2:
  - platform: mqtt
    name: "MQTT Switch 2"
    state_topic: "/house/switchConfirm2/"
    command_topic: "/house/switch2/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    

switch 3:
  - platform: mqtt
    name: "MQTT Switch 3"
    state_topic: "/house/switchConfirm3/"
    command_topic: "/house/switch3/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    
  
switch 4:
  - platform: mqtt
    name: "MQTT Switch 4"
    state_topic: "/house/switchConfirm4/"
    command_topic: "/house/switch4/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    

Once ALL loaded in, restarted my HASS Server, and…

This showed up:

( I also created a group so I could control all of them in one go)

Some Hardware Pictures, showing the wiring between the two boards

D1 wire to Relay Switch IN1 (see third Picture)
D2 wire to Relay Switch IN2
D3 wire to Relay Switch IN3
D5 wire to Relay Switch IN4 (I use D4 for on-board LED checking)

WEMOS D1 R2 with Built in ESP8266

5V connector to Relay Switch VCC Pin
GND to Relay Switch GND


4 Relay Switch Module (5V, be careful when buying this as it also comes in 12V VCC Supply version)

  • I had chosen this one as it can be triggered by 3.3V . (which is what WEMOS I/O supports)

I uploaded a Video demo as well to see it action:
https://youtu.be/ted-apmywZo

Working perfectly for me!

Cheers
Erick
ps. I’m not a coder, just following amazing guides from Ben (www.bruhautomation.com, https://www.youtube.com/watch?v=tCGlQSsQ-Mc ), Itkindaworks (https://www.youtube.com/watch?v=gCgr1vwsJFA), and from this great chap whose videos gave me a good insight on programming (https://www.youtube.com/watch?v=LW8Rfh6TzGg) now i know a bit how to read the codes.

22 Likes

Nice work … but already done. Do you know https://www.letscontrolit.com/wiki/index.php/ESPEasy ?

1 Like

yep… i saw that earlier…

but i decided to share my work so others with similar setup as mine can simply do basic cut and paste, do the analysis and pairing between HASS, MQTT and an Arduino clone (WEMOS - UNO CLone with ESP8266 WiFi Support) which are not captured in ESPEasy.

4 Likes

Nice work. Can you post some hardware pictures also how you connect if possible

Done… I edited my original post adding in pictures and uploading a video to demonstrate it.

cheers
Erick

1 Like

Thanks Erik. I could not get my sketch working until I read your post. I used the LinkNode R4 that combines the ESP8266 and four relays on one module for less than $10 US.
Not sure what ArduinoOTA does?

Hi Graham,

The ArduinoOTA library will enable you access to your Arduino module over wifi/IP.

In my case, as my Arduino module is located in a difficult to access area, I reach it and update my sketch on the fly without connecting to the board physically (traditionally via COM/USB).

Just a note: ensure those 4 ArduinoOTA lines (1x lib, 2x in main, 1x in loop) are present in the new sketch you are pushing in (in case you are changing it) as you will lose OTA access to your module as soon as the new sketch takes effect.

cheers
Erick

1 Like

Thanks for sharing this.
I am getting an MQTT failed message on my serial monitor and I suspect it is because I have not put in my MQTT username or password in the IDE sketch but I don’t know how to include them without getting declaration errors cause my coding knowledge is rubbish. Where or how do I get my user/pass details incuded in the sketch?

Serial monitor message below:

WiFi connected
IP address:
192.168.1.19
Attempting MQTT connection… Failed.
Abort called

Find the line above and replace your username & password.

Thanks gpbenton!
It’s been there starring at me this whole time…
Great share

Hi
Thanks, this got me started with my project.
I did some changes to it. Added support for 4 inputs. Changed the outputs from low to high to support my relay module, I also started the outputs on D0, so I can use the led on D4 for diagnostics on status change on the inputs.

I’ve tested it with these components
NodeMcu: https://goo.gl/W0u9Sp
Relay module : https://goo.gl/RQrd4D

//OGD: Added support for 4 inputs, and changed from LOW to HIGH on the outputs
//OGD: Tested with NodeMcu 
// NodeMcu: https://goo.gl/W0u9Sp
// 4 channel relay module: https://goo.gl/RQrd4D
//EJ: 4 Relay Switch over WIFI using MQTT and Home Assistant with OTA Support
//EJ: The only way I know how to contribute to the HASS Community... you guys ROCK!!!!!
//EJ: Erick Joaquin :-) Australia
// Original sketch courtesy of ItKindaWorks
//ItKindaWorks - Creative Commons 2016
//github.com/ItKindaWorks
//
//Requires PubSubClient found here: https://github.com/knolleary/pubsubclient
//
//ESP8266 Simple MQTT switch controller


#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>

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

//EDIT THESE LINES TO MATCH YOUR SETUP
#define MQTT_SERVER "192.168.1.1"  //you MQTT IP Address
#define mqtt_user "username" 
#define mqtt_password "password"
#define mqtt_port 1883
const char* ssid = "ssid";
const char* password = "password";
char const* switchTopic1 = "/test/switch1/";
char const* switchTopic2 = "/test/switch2/";
char const* switchTopic3 = "/test/switch3/";
char const* switchTopic4 = "/test/switch4/";
char const* switchconfirmTopic1 = "/test/switchConfirm1/";
char const* switchconfirmTopic2 = "/test/switchConfirm2/";
char const* switchconfirmTopic3 = "/test/switchConfirm3/";
char const* switchconfirmTopic4 = "/test/switchConfirm4/";
char const* buttonTopic1 = "/test/button1/";
char const* buttonTopic2 = "/test/button2/";
char const* buttonTopic3 = "/test/button3/";
char const* buttonTopic4 = "/test/button4/";


//EJ: Data PIN Assignment on WEMOS D1 R2 https://www.wemos.cc/product/d1.html
// if you are using Arduino UNO, you will need to change the "D1 ~ D4" with the corresponding UNO DATA pin number 

const int switchPin1 = D0;
const int switchPin2 = D1;
const int switchPin3 = D2;
const int switchPin4 = D3;
const int led = D4;
const int buttonPin1 = D5;
const int buttonPin2 = D6;
const int buttonPin3 = D7;
const int buttonPin4 = D8;

// setup for input 1
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;

int lastButtonState1 = 0;
int lastButtonState2 = 0;
int lastButtonState3 = 0;
int lastButtonState4 = 0;

char msg01[20];
char msg02[20];
char msg03[20];
char msg04[20];

//EJ: These are the MQTT Topic that will be used to manage the state of Relays 1 ~ 4
//EJ: Refer to my YAML component entry
//EJ: feel free to replicate the line if you have more relay switch to control, but dont forget to increment the number suffix so as increase switch logics in loop()


WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, mqtt_port, callback, wifiClient);

`void setup() {`
  //initialize the switch as an output and set to HIGH (relay off)
  pinMode(switchPin1, OUTPUT); // Relay Switch 1
  digitalWrite(switchPin1, HIGH);

  pinMode(switchPin2, OUTPUT); // Relay Switch 2
  digitalWrite(switchPin2, HIGH);

  pinMode(switchPin3, OUTPUT); // Relay Switch 3
  digitalWrite(switchPin3, HIGH);

  pinMode(switchPin4, OUTPUT); // Relay Switch 4
  digitalWrite(switchPin4, HIGH);
  
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH);

  ArduinoOTA.setHostname("My Arduino WEMO"); // A name given to your ESP8266 module when discovering it as a port in ARDUINO IDE
  ArduinoOTA.begin(); // OTA initialization

  //start the serial line for debugging
  Serial.begin(115200);
  delay(100);

  //start wifi subsystem
  WiFi.begin(ssid, password);
  //attempt to connect to the WIFI network and then connect to the MQTT server
  reconnect();

  //wait a bit before starting the main loop
      delay(2000);
}

void loop(){

  //reconnect if connection is lost
  if (!client.connected() && WiFi.status() == 3) {reconnect();}

  //maintain MQTT connection
  client.loop();

  //MUST delay to allow ESP8266 WIFI functions to run
  delay(10); 
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);  
    if (buttonState1 != lastButtonState1)
    {
      digitalWrite(led, LOW);
      Serial.println("buttonState1");
      Serial.println(buttonState1);
      snprintf(msg01, 75, "%ld", buttonState1);
      client.publish(buttonTopic1, msg01);
      lastButtonState1 = buttonState1;
      digitalWrite(led, HIGH);
    }
    if (buttonState2 != lastButtonState2)
    {
      digitalWrite(led, LOW);
      Serial.println("buttonState2");
      Serial.println(buttonState2);
      snprintf(msg02, 75, "%ld", buttonState2);
      client.publish(buttonTopic2, msg02);
      lastButtonState2 = buttonState2;
      digitalWrite(led, HIGH);
    }
    if (buttonState3 != lastButtonState3)
    {
      digitalWrite(led, LOW);
      Serial.println("buttonState3");
      Serial.println(buttonState3);
      snprintf(msg03, 75, "%ld", buttonState3);
      client.publish(buttonTopic3, msg03);
      lastButtonState3= buttonState3;
      digitalWrite(led, HIGH);
    }
    if (buttonState4 != lastButtonState4)
    {
      digitalWrite(led, LOW);
      Serial.println("buttonState4");
      Serial.println(buttonState4);
      snprintf(msg04, 75, "%ld", buttonState4);
      client.publish(buttonTopic4, msg04);
      lastButtonState4 = buttonState4;
      digitalWrite(led, HIGH);
    }
  ArduinoOTA.handle();
}

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

  //convert topic to string to make it easier to work with
  String topicStr = topic; 
  //EJ: Note:  the "topic" value gets overwritten everytime it receives confirmation (callback) message from MQTT

  //Print out some debugging info
  Serial.println("Callback update.");
  Serial.print("Topic: ");
  Serial.println(topicStr);
     
    if (topicStr == switchTopic1) 
    {

     //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
     if (payload[0] == '1'){
       digitalWrite(switchPin1, LOW);
       client.publish(switchconfirmTopic1, "1");
       }

  //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
 else if (payload[0] == '0'){
   digitalWrite(switchPin1, HIGH);
   client.publish(switchconfirmTopic1, "0");
   }
 }

 // EJ: copy and paste this whole else-if block, should you need to control more switches
 else if (topicStr ==switchTopic2) 
 {
 //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
 if(payload[0] == '1'){
   digitalWrite(switchPin2, LOW);
   client.publish(switchconfirmTopic2, "1");
   }

  //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
 else if (payload[0] == '0'){
   digitalWrite(switchPin2, HIGH);
   client.publish(switchconfirmTopic2, "0");
   }
 }
 else if (topicStr == switchTopic3) 
 {
 //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
 if(payload[0] == '1'){
   digitalWrite(switchPin3, LOW);
   client.publish(switchconfirmTopic3, "1");
   }

  //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
 else if (payload[0] == '0'){
   digitalWrite(switchPin3, HIGH);
   client.publish(switchconfirmTopic3, "0");
   }
 }
 else if (topicStr == switchTopic4) 
 {
 //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
 if(payload[0] == '1'){
   digitalWrite(switchPin4, LOW);
   client.publish(switchconfirmTopic4, "1");
   }

  //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
 else if (payload[0] == '0'){
   digitalWrite(switchPin4, HIGH);
   client.publish(switchconfirmTopic4, "0");
   }
 }
 }



void reconnect() {

//attempt to connect to the wifi if connection is lost
  if(WiFi.status() != WL_CONNECTED){
//debug printing
Serial.print("Connecting to ");
Serial.println(ssid);

//loop while we wait for connection
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}

//print out some more debug once connected
Serial.println("");
Serial.println("WiFi connected");  
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
  }

  //make sure we are connected to WIFI before attemping to reconnect to MQTT
  if(WiFi.status() == WL_CONNECTED){
  // Loop until we're reconnected to the MQTT server
    while (!client.connected()) {
      Serial.print("Attempting MQTT connection...");

  // Generate client name based on MAC address and last 8 bits of microsecond counter
  String clientName;
  clientName += "esp8266-";
  uint8_t mac[6];
  WiFi.macAddress(mac);
  clientName += macToStr(mac);

  //if connected, subscribe to the topic(s) we want to be notified about
  //EJ: Delete "mqtt_username", and "mqtt_password" here if you are not using any 
  if (client.connect((char*) clientName.c_str(),mqtt_user, mqtt_password)) {  //EJ: Update accordingly with your MQTT account 
    Serial.print("\tMQTT Connected");
    client.subscribe(switchTopic1);
    client.subscribe(switchTopic2);
    client.subscribe(switchTopic3);
    client.subscribe(switchTopic4);
    //EJ: Do not forget to replicate the above line if you will have more than the above number of relay switches
  }

  //otherwise print failed for debugging
  else{Serial.println("\tFailed."); abort();}
    }
  }
}

//generate unique name from MAC addr
String macToStr(const uint8_t* mac){

  String result;

  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);

if (i < 5){
  result += ':';
}
  }

  return result;
}

sensor config in Home-Assistant for the inputs:

- platform: mqtt
  name: mqtt_test_1
  state_topic: "/test/button1/"
  payload_on: "1"
  payload_off: "0"
  
- platform: mqtt
  name: mqtt_test_2
  state_topic: "/test/button2/"
  payload_on: "1"
  payload_off: "0"

- platform: mqtt
  name: mqtt_test_3
  state_topic: "/test/button3/"
  payload_on: "1"
  payload_off: "0"
  
- platform: mqtt
  name: mqtt_test_4
  state_topic: "/test/button4/"
  payload_on: "1"
  payload_off: "0"

switch config in Home-Assistant:

switch 1:
  - platform: mqtt
    name: "MQTT Switch 1"
    state_topic: "/test/switchConfirm1/"
    command_topic: "/test/switch1/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    
  
switch 2:
  - platform: mqtt
    name: "MQTT Switch 2"
    state_topic: "/test/switchConfirm2/"
    command_topic: "/test/switch2/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    

switch 3:
  - platform: mqtt
    name: "MQTT Switch 3"
    state_topic: "/test/switchConfirm3/"
    command_topic: "/test/switch3/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true    
  
switch 4:
  - platform: mqtt
    name: "MQTT Switch 4"
    state_topic: "/test/switchConfirm4/"
    command_topic: "/test/switch4/"
    payload_on: "1"
    payload_off: "0"
    qos: 0
    retain: true
5 Likes

doing this with mysensors (mysensors.org) is so much easier.

just 1 time 9 lines in the yaml and a wifi gateway with 4 relays as sketch.
the advantage is also that you can add more switches afterwards without even editing a single entry in the yaml.

That’s true, but I do this for learning some programming.

1 Like

I made this last year with a wemos d1 mini and homey esp 8266 firmware.

I also added a slider input so I can set a timer for how long the sprinklers have to be on.

1 Like

@olegunnar!
Nice work!

please do share your Use Case so we can help associate the purpose of your code for any future use, in case any hobbyist out there may be planning something similar. we could reuse it (with pride).

Keep up the good work.

Btw, you can use MQTT “retain” option should you wish to ensure the last stored value is picked up by your Arduino. (i find it useful specially when restarting either my HA or my Arduino module)

@ReneTode, admittedly it is indeed a tedious approach, I will highly appreciate if you can share that section of code please for the YAML part and the 4 relay sketch (in case you still have them handy). I went to mysensor.org and was overwhelmed with so many areas to read.

@koen01 Can you share your automation / slide timer as well please, I am using the 4 relay switch for Garden Lights and Sprinkler control. It would be a big help to have a timer for my sprinkler…

HA and its community Rocks!

slider to adjust the duration the sprinklers run:

input_slider: 
  sprinklertimer: 
    name: Sprinkler timer 
    icon: mdi:clock 
    initial: 45 
    min: 0 
    max: 60 
    step: 5 

Switch to turn the sprinkler program on:

input_boolean:
  sprinkler:
    name: Sprinkler program
    initial: off
    icon: mdi:timer

automation:

3 Likes

in the yaml you need something like this (see the mysensors component for exact details)

mysensors:
  gateways:
    - device: 'your_ip'
      baud_rate: 9600
      persistence_file: '/home/pi/HAlogs/mysensors3.json'
      tcp_port: 5025
  optimistic: false
  debug: true
  persistence: true
  version: '2.0'

a sketch should look something like: (i just combined 2 of my sketches without testing, so might be faulty)

/**
 * The MySensors Arduino library handles the wireless radio link and protocol
 * between your home built sensors/actuators and HA controller of choice.
 * The sensors forms a self healing radio network with optional repeaters. Each
 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
 * network topology allowing messages to be routed to nodes.
 *
 * Created by Henrik Ekblad <[email protected]>
 * Copyright (C) 2013-2015 Sensnology AB
 * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
 *
 * Documentation: http://www.mysensors.org
 * Support Forum: http://forum.mysensors.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 *******************************
 *
 * REVISION HISTORY
 * Version 1.0 - Henrik EKblad
 * Contribution by a-lurker and Anticimex,
 * Contribution by Norbert Truchsess <[email protected]>
 * Contribution by Ivo Pullens (ESP8266 support)
 *
 * DESCRIPTION
 * The EthernetGateway sends data received from sensors to the WiFi link.
 * The gateway also accepts input on ethernet interface, which is then sent out to the radio network.
 *
 * VERA CONFIGURATION:
 * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin.
 * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003
 *
 * LED purposes:
 * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs in your sketch, only the LEDs that is defined is used.
 * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
 * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
 * - ERR (red) - fast blink on error during transmission error or recieve crc error
 *
 * See http://www.mysensors.org/build/esp8266_gateway for wiring instructions.
 * nRF24L01+  ESP8266
 * VCC        VCC
 * CE         GPIO4
 * CSN/CS     GPIO15
 * SCK        GPIO14
 * MISO       GPIO12
 * MOSI       GPIO13
 * GND        GND
 *
 * Not all ESP8266 modules have all pins available on their external interface.
 * This code has been tested on an ESP-12 module.
 * The ESP8266 requires a certain pin configuration to download code, and another one to run code:
 * - Connect REST (reset) via 10K pullup resistor to VCC, and via switch to GND ('reset switch')
 * - Connect GPIO15 via 10K pulldown resistor to GND
 * - Connect CH_PD via 10K resistor to VCC
 * - Connect GPIO2 via 10K resistor to VCC
 * - Connect GPIO0 via 10K resistor to VCC, and via switch to GND ('bootload switch')
 *
  * Inclusion mode button:
 * - Connect GPIO5 via switch to GND ('inclusion switch')
 *
 * Hardware SHA204 signing is currently not supported!
 *
 * Make sure to fill in your ssid and WiFi password below for ssid & pass.
 */


// Enable debug prints to serial monitor
#define MY_DEBUG

// Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h
#define MY_BAUD_RATE 9600

// Enables and select radio type (if attached)
#define MY_RADIO_NRF24
#define MY_RF24_CHANNEL 50
//#define MY_RADIO_RFM69

#define MY_GATEWAY_ESP8266

#define MY_ESP8266_SSID "your_ssid"
#define MY_ESP8266_PASSWORD "your_password"

// Enable UDP communication
//#define MY_USE_UDP

// Set the hostname for the WiFi Client. This is the hostname
// it will pass to the DHCP server if not static.
#define MY_ESP8266_HOSTNAME "keller-gateway"

// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP)
//#define MY_IP_ADDRESS 192,168,178,87

// If using static ip you need to define Gateway and Subnet address as well
//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1
//#define MY_IP_SUBNET_ADDRESS 255,255,255,0

// The port to keep open on node server mode
#define MY_PORT 5025

// How many clients should be able to connect to this gateway (default 1)
#define MY_GATEWAY_MAX_CLIENTS 5

// Controller ip address. Enables client mode (default is "server" mode).
// Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere.
//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68

// Enable inclusion mode
#define MY_INCLUSION_MODE_FEATURE

// Enable Inclusion mode button on gateway
#define MY_INCLUSION_BUTTON_FEATURE
// Set inclusion mode duration (in seconds)
#define MY_INCLUSION_MODE_DURATION 60
// Digital pin used for inclusion mode button
#define MY_INCLUSION_MODE_BUTTON_PIN  3


// Set blinking period
 #define MY_DEFAULT_LED_BLINK_PERIOD 300

// Flash leds on rx/tx/err
// Led pins used if blinking feature is enabled above
#define MY_DEFAULT_ERR_LED_PIN 16  // Error led pin
#define MY_DEFAULT_RX_LED_PIN  16  // Receive led pin
#define MY_DEFAULT_TX_LED_PIN  16  // the PCB, on board LED

#if defined(MY_USE_UDP)
  #include <WiFiUdp.h>
#endif

#include <ESP8266WiFi.h>

#include <MySensors.h>

//##########################################
// voor relayswitches
//##########################################
#define RELAY_1  5  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define RELAY_ON 1  // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
#define CHILD_ID_RELAY1 1
MyMessage msg1(CHILD_ID_RELAY1, V_STATUS);

//##########################################
// algemeen
//##########################################
#define CONTROLESWITCH 200
MyMessage msgcontroleswitch(CONTROLESWITCH, V_STATUS);
bool gemeld=false;
long time=0;
long time2=0;

void before() { 
//##########################################
// voor relayswitches
//##########################################
    pinMode(RELAY_1, OUTPUT);   
    digitalWrite(RELAY_1, loadState(CHILD_ID_RELAY1)?RELAY_ON:RELAY_OFF);
}

void setup() {
}

void presentation() {
  sendSketchInfo("backup gateway", "1.0");  
  present(CONTROLESWITCH,S_BINARY);
  present(CHILD_ID_RELAY1, S_BINARY);
}

void loop() {
//##########################################
// algemeen
//##########################################  
  if ( not gemeld){
    melden();
    gemeld=true;    
  }
  if (millis()-time>1800000){
    weermelden();
  }
}

void receive(const MyMessage &message) {
  if (message.type==V_STATUS) {    
     if (message.sensor==CONTROLESWITCH){
        weermelden();
     }
     if (message.sensor==CHILD_ID_RELAY1){   
        digitalWrite(RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
        saveState(CHILD_ID_RELAY1, message.getBool());
        send(msg1.set(message.getBool()));       
     } 
  }
}
void melden(){
  send(msgcontroleswitch.set(0));  
  send(msg1.setSensor(CHILD_ID_RELAY1).set(loadState(CHILD_ID_RELAY1)));
}
void weermelden(){
  send(msgcontroleswitch.set(0));  
  send(msg1.setSensor(CHILD_ID_RELAY1).set(loadState(CHILD_ID_RELAY1)));
  time=millis();
}

this is a default esp gateway combined with a sketch that i use to control a single switch.

1 Like

I was worried about the abort() statement in the reconnect function and replaced it with
delay(2000); break;
My concern was that my irrigation system would not recover after the MQTT server was shutdown and restarted.
Apparently, abort() = while (true)' which seems like a potential place for the code to hang up.

Thank you! This is perfect for what I want (well almost).
I am trying to make a ceiling fan switch to use with HASS. I have wired the first 3 channels as the 3 fan speeds and the 4th simply as a light switch. With the 4 ch relay I have wired the capacitor from the selector switch and with the inputs as you have done I am able to wire the speed selector switch on the wall into the inputs so I can change either with the switch or with HASS. The only thing I need to do somehow is to interlock the 3 speed relays. What do I need to add to the code so that if relay 1 is turned on relays 2 or 3 are turned off before this happens. Sorry if this is confusing I am very new to programming these boards and have attempted to add the code myself but have not quite got it yet. I would appreciate any help.

Thanks

I something simular with an electric car charger, where different relay combinations changes the charging current. There I use one scene for every mode, and I turn on the scenes from an automation.
If the fan can be destroyd if the releay combination is wrong, I would do it in the arduino, since you can turn on that relay from frontend. If you need to do it from arduino let me know

Here is how I’ve set up my scenes

- name: ev1_off
  entities:
    switch.ev1_r1:
      state: on
    switch.ev1_r2:
      state: on
    switch.ev1_r3:
      state: on
    switch.ev1_r4:
      state: on
- name: ev1_10
  entities:
    switch.ev1_r1:
      state: on
    switch.ev1_r2:
      state: on
    switch.ev1_r3:
      state: off
    switch.ev1_r4:
      state: on
- name: ev1_16
  entities:
    switch.ev1_r1:
      state: off
    switch.ev1_r2:
      state: on
    switch.ev1_r3:
      state: off
    switch.ev1_r4:
      state: on
- name: ev1_20
  entities:
    switch.ev1_r1:
      state: on
    switch.ev1_r2:
      state: off
    switch.ev1_r3:
      state: off
    switch.ev1_r4:
      state: on
1 Like