Arduino Mega, ESP8266, MQTT - callback function not working

Hi all,

I started to make an home automation with Arduino Mega connected to MQTT server through ESP8266.
I manage to send temperature and humidity received from a weather station through nRF24 with MySensors library.
My problem is when i want to send data(light switch) from home-assistant to Arduino, in log i can see that the command is executed but on Arduino i dont receive anything.
I hope someone can help to figure out why i can’t receive the comand.
Thanks in advance.
Here is the Arduino code:

#include <WiFiEspClient.h>
#include <WiFiEsp.h>
#include <WiFiEspUdp.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <DallasTemperature.h>
#include <OneWire.h>
float t = 0;
float h = 0;
bool rain = false;
#define WIFI_AP "xxxx"
#define WIFI_PASSWORD "xxxxx"
#define temperature_topic "/sensor/temperature/"  //Topic temperature
#define humidity_topic "/sensor/humidity/"        //Topic humidity
#define inside_temperature_topic "/sensor/inside_temperature/"
#define rain_topic "/binary_sensor/rain_sensor/"
#define MQTT_LIGHT_STATE_TOPIC  "/office/light1/status/";
#define MQTT_LIGHT_COMMAND_TOPIC  "/office/light1/switch/";
const char* LIGHT_ON = "ON";
const char* LIGHT_OFF = "OFF";
char message_buff[100];
long lastMsg = 0;
long lastRecu = 0;
bool debug = true;  //Display log message if True
#include <DallasTemperature.h>
#include <OneWire.h>
#define ONE_WIRE_BUS 21

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


OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);




WiFiEspClient espClient;
#define mqtt_server "192.168.1.xxx"
#define mqtt_user "xxxx"     
#define mqtt_password "xxxx"  

PubSubClient client(mqtt_server, 1883, callback, espClient);

#define soft Serial3
int status = WL_IDLE_STATUS;
unsigned long lastSend;
#define MY_RF24_CE_PIN 47
#define MY_RF24_CS_PIN 45
//#define MY_DEBUG
String topicStr;

#define MY_RADIO_NRF24
#define MY_RF24_PA_LEVEL RF24_PA_MAX
#define MY_GATEWAY_SERIAL
boolean m_light_state = false;



#include <MySensors.h>

void setup()
{
  sensors.begin();

  Serial.begin(115200);



  InitWiFi();

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

  lastSend = 0;
}

void presentation()
{

}

void loop() {


  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;


    if (rain == 1) {
      rain_status = "ON";
    }
    if (rain == 0) {
      rain_status = "OFF";
    }
    // Read humidity
    sensors.requestTemperatures();
    float t0 = sensors.getTempCByIndex(0);

    client.publish(temperature_topic, String(t).c_str(), true);   // Publish temperature on temperature_topic
    client.publish(humidity_topic, String(h).c_str(), true);
    client.publish(inside_temperature_topic, String(t0).c_str(), true);
    client.publish(rain_topic, String(rain_status).c_str(), true);

  }
}

void receive(const MyMessage &message) {

  if (message.type == V_TEMP) {
    t = message.getFloat();
  }
  if (message.type == V_HUM) {
    h = message.getFloat();
  }
  if (message.type == V_LIGHT) {
    rain = message.getBool();
  }

}

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

  String topicStr = topic;

  Serial.print("Topic: ");
  Serial.println(topicStr);


  if (topicStr == "/office/light1/switch/")
  {

    //turn the switch on if the payload is '1' and publish to the MQTT server a confirmation message
    if (payload[0] == 'ON') {
      Serial.println("light on");
      client.publish("/office/light1/status/", "ON");
    }

    //turn the switch off if the payload is '0' and publish to the MQTT server a confirmation message
    else if (payload[0] == 'OFF') {
      Serial.println("light off");
      client.publish("/office/light1/status/", "OFF");
    }
  }
}




void InitWiFi()
{
  // initialize serial for ESP module
  soft.begin(9600);
  // initialize ESP module
  WiFi.init(&soft);
  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  }

  Serial.println("Connecting to AP ...");
  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(WIFI_AP);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(WIFI_AP, WIFI_PASSWORD);
    delay(500);
  }
  Serial.println("Connected to AP");
}

void reconnect() {

  while (!client.connected()) {
    Serial.print("Connecting to MQTT broker ...");
    String clientId = "home-assistant-";
    clientId += String(random(0xffff), HEX);

    if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
      Serial.println("OK");
      client.subscribe("/office/light1/switch/");
    } else {
      Serial.print("KO, error : ");
      Serial.print(client.state());
      Serial.println(" Wait 5 secondes before to retry");
      delay(5000);
    }
  }
}

Here is the configuration code:

light:
      platform: mqtt
      name: "Office light"
      state_topic: "office/light1/status"
      command_topic: "office/light1/switch"
      payload_on: "ON"
      payload_off: "OFF"
      optimistic: false

your state and command topics are different. /office is not the same as office

1 Like

I found the problem, the serial cannot receive the message through serial because of client loop is executed too often, an delay of 100 ms before or after client loop is an solution but too reliable

1 Like

Same issue like my issue here:

Its solved.