Bit of help with ESP8266, MQTT and HASSIO

Hello guys,

I try to make this simple project because I have another project ( an irrigation programmer with 4 x relays, 1 x dth 22 , 1 x drop sensor and 1 x moister sensor) connected with node red and I want to migrate to home assistant. This project works very good.

I try from a week to figure out why my new project is not work. I use a ESP8266 NodeMCU the home assistant is installed on a laptop with Ubuntu and I use a docker. The ESP is connected on WiFi, the mqtt broker show me the connection but when I press button on the home automation interface nothing happens. On ESP I connect on the pin D2 a led.

This is the cod from arduino:

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

// Update these with values suitable for your network.
const char* ssid = "Archer";
const char* password = "@test@";
const char* mqtt_server = "192.168.100.149";

WiFiClient espClient;
PubSubClient client(espClient);
int SwitchedPin = D2;
String switch1;
String strTopic;
String strPayload;

void setup_wifi() {
 Serial.begin(115200);
  delay(100);
 
  // We start by connecting to a WiFi network
 
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';
  strTopic = String((char*)topic);
  if(strTopic == "ha/switch1")
    {
    switch1 = String((char*)payload);
    if(switch1 == "ON")
      {
        Serial.println("ON");
        Serial.println(strTopic);
        Serial.println(strPayload);
        digitalWrite(SwitchedPin, HIGH);
        client.publish("ha/switch1", "ON");
      }
    else
      {
        Serial.println("OFF");
        digitalWrite(SwitchedPin, LOW);
      }
    }
}
 
 
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.subscribe("ha/#");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
 
void setup()
{
  setup_wifi(); 
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  pinMode(SwitchedPin, OUTPUT);
  digitalWrite(SwitchedPin, LOW);
}
 
void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

This is the output from serial:

Connecting to Archer
..........
WiFi connected
IP address: 
192.168.100.151
Attempting MQTT connection...connected

This is the configuration yaml:

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Light
switch:
    - platform: mqtt
      name: "Switch1"
      state_topic: "ha/switch1"
      command_topic: "ha/switch1"
      qos: 0
      payload_on: "ON"
      payload_off: "OFF"
# Uncomment this if you are using SSL/TLS, running in Docker container, etc.
# http:
#   base_url: example.duckdns.org:8123
# MQTT broker
mqtt:
    broker: 192.168.100.149
    port: 1883
# Text to speech
tts:
  - platform: google_translate

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

This is the configure UI:

entity: switch.switch1
hold_action:
  action: more-info
icon_height: 30px
show_icon: true
show_name: true
tap_action:
  action: toggle
type: button

This is the conf of mqtt:

logins: []
anonymous: true
customize:
  active: false
  folder: mosquitto
certfile: fullchain.pem
keyfile: privkey.pem
require_certificate: false

And this is the mqtt broker logs:

[10:54:23] INFO: Setup mosquitto configuration
[10:54:23] WARNING: SSL not enabled - No valid certs found!
[10:54:23] INFO: No local user available
[10:54:23] INFO: Initialize Hass.io Add-on services
[10:54:23] INFO: Initialize Home Assistant discovery
[10:54:23] INFO: Start Mosquitto daemon
1588924463: mosquitto version 1.6.3 starting
1588924463: Config loaded from /etc/mosquitto.conf.
1588924463: Loading plugin: /usr/share/mosquitto/auth-plug.so
1588924463: |-- *** auth-plug: startup
1588924463:  ├── Username/password checking enabled.
1588924463:  ├── TLS-PSK checking enabled.
1588924463:  └── Extended authentication not enabled.
1588924463: Opening ipv4 listen socket on port 1883.
1588924463: Opening ipv6 listen socket on port 1883.
1588924463: Opening websockets listen socket on port 1884.
1588924463: Warning: Mosquitto should not be run as root/administrator.
1588924465: New connection from 172.30.32.1 on port 1883.
[INFO] found homeassistant on local database
1588924465: New client connected from 172.30.32.1 as auto-7549CD0D-61C7-A608-7AD8-41810E6EF5D4 (p2, c1, k60, u'homeassistant').
1588924467: New connection from 192.168.100.151 on port 1883.
1588924467: New client connected from 192.168.100.151 as arduinoClient (p2, c1, k15).

Thanks for help. :slight_smile:

Hello @ady_soft,

first of all make sure the switch actuation is published to MQTT correctly.
This can be done easily via Home Assistants Developer Tools:

If the MQTT part of HA works, the issue is related to your ESP implementation.

According to the arduino code, you do not see if an MQTT message was received. You could also add additional debug output in the callback to see how far you get.
I’m a bit puzzled about that line: payload[length] = '\0';
This looks like an out of bounds array access to me.
Try that instead:

void callback(char* topic, byte* payload, unsigned int length) {
  char dataBuf[length+1];               // define a char buffer to add 0 termination
  memcpy(dataBuf, payload, length);     // copy byte buffer to char buffer
  dataBuf[sizeof(dataBuf)-1] = 0;       // add 0 termination
  String str_payload= String(dataBuf);  // copy to string variable
  Serial.println(topic);
  if(strTopic == "ha/switch1/cmd") {
    Serial.println(str_payload);
    if (str_payload == "ON") {
        Serial.println("ON");
        digitalWrite(SwitchedPin, HIGH);
        client.publish("ha/switch1/state", "ON");
    } else {
        Serial.println("OFF");
        digitalWrite(SwitchedPin, LOW);
        client.publish("ha/switch1/state", "OFF");
    }
  }
}

General hint:
I recommend to use different topics for the MQTT switch sommand and state information., e.g.:

      state_topic: "ha/switch1/state"
      command_topic: "ha/switch1/cmd"

If a device does not follow your command, the state won’t change and you’ll see that in the UI.
If the same topic is used, you do not know whether the device really switched or not.

1 Like

Thanks @eXtatic for reply. I tried but same result. I found another example but same problem nothings happen when I use buttons from UI . This time I connected 4 relays

//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.100.149"  //you MQTT IP Address
const char* ssid = "Archer";
const char* password = "@test@";

//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())) {  //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;
}

Serial:

.........
WiFi connected
IP address: 
192.168.100.151
Attempting MQTT connection...	MQTT Connected

Yaml:


# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Light
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    
# Uncomment this if you are using SSL/TLS, running in Docker container, etc.
# http:
#   base_url: example.duckdns.org:8123
# MQTT broker
mqtt:
    broker: 192.168.100.149
    port: 1883
# Text to speech
tts:
  - platform: google_translate

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

MQTT logs:

[19:13:05] INFO: Setup mosquitto configuration
[19:13:05] WARNING: SSL not enabled - No valid certs found!
[19:13:05] INFO: No local user available
[19:13:05] INFO: Initialize Hass.io Add-on services
[19:13:05] INFO: Initialize Home Assistant discovery
[19:13:05] INFO: Start Mosquitto daemon
1589127185: mosquitto version 1.6.3 starting
1589127185: Config loaded from /etc/mosquitto.conf.
1589127185: Loading plugin: /usr/share/mosquitto/auth-plug.so
1589127185: |-- *** auth-plug: startup
1589127185:  ├── Username/password checking enabled.
1589127185:  ├── TLS-PSK checking enabled.
1589127185:  └── Extended authentication not enabled.
1589127185: Opening ipv4 listen socket on port 1883.
1589127185: Opening ipv6 listen socket on port 1883.
1589127185: Opening websockets listen socket on port 1884.
1589127185: Warning: Mosquitto should not be run as root/administrator.
1589127186: New connection from 172.30.32.1 on port 1883.
[INFO] found homeassistant on local database
1589127186: New client connected from 172.30.32.1 as auto-95EBA2B5-3293-6F69-A7B4-40F47EF2EA58 (p2, c1, k60, u'homeassistant').
1589127192: New connection from 192.168.100.151 on port 1883.
1589127192: New client connected from 192.168.100.151 as esp8266-2c:f4:32:3c:63:b2 (p2, c1, k15).

I have also this message:

ps: when I press restart button from mqtt add on the relays make a noise like a click.

I can’t figure out where I’m wrong. :frowning:
Can anyone share a sketch that works with esp8266 NODEMCU.
Thanks very much.

Did you check the MQTT traffic?
According the the 4 relay sketch it should print to serial if an MQTT message is received. This doesn’t seem to happen.

To check traffic like this?

On the serial nothings appears, only:


WiFi connected
IP address:
192.168.100.151
Attempting MQTT connection… MQTT Connected

Yes that’s what I meant, can’t see any obvious issue.
Maybe take the ESP8266 example from the PubSubClient as base sketch, it e.g. uses another method of providing the callback.
Don’t know if that helps, I’m not a PubSubClient user.

1 Like

I tried the same with a public MQTT server, and its running fine. I was able to add widgets and control via hassio UI. I used code from http://osoyoo.com/2016/11/25/remotely-control-led-with-nodemcu-through-mqtt-iot-broker/ ; but its the same code practically, with few changes here and there. In my case as well, I am not able to control nodeMCU via local Rpi broker (with the serial msg showing MQTT connected), but can control via public broker: broker.mqtt-dashboard.com.

Update: I got the thing to run by setting an mqtt username and password. Seems like w/o username and password, the local mqtt client doesnt run properly.