(SOLVED) Switch Status Not Updating When MQTT command is sent from other publisher

Hi All

Noob here.

I made good progress in getting my MQTT working on OpenHAB on RPi3 and have a few ESP8266’s communicating and operating well.

I did however reach a stumbling block when it comes to the updating of my Switches in the GUI should the status of the item be changed from another external source (Node-RED etc.)

This ver simple example should explain what I am facing:

My MQtt Switch 2 Status will update perfectly when the device status changed, whether from using the “MQTT Switch 2” or external MQTT publisher but my switch status would only change when the item state has been changed within OpenHAB by clicking on it.

mqtt.items:

Switch mqttsw2 "MQTT Switch 2" (all,mqtt) {mqtt=">[broker:/ESP1/OUT-D5:command:ON:1],>[broker:/ESP1/OUT-D5:command:OFF:0],<[broker:/ESP1/confirmOUT-D5:state:default]"}
String mqttsw2s "MQtt Switch 2 Status [%s]" (all,mqtt) {mqtt="<[broker:/ESP1/confirmOUT-D5:state:default]"}

mqtt.sitemap:

sitemap mqtt label="MQTT-Test"
{
 Frame label="MQTT" 
   {	  
    Switch item=mqttsw2 label="MQTT Switch 2 (raw)"
    Text item=mqttsw2s 
   }
}

This is the Arduino Code for this example ESP8266 that I am testing with:

//ItKindaWorks - Creative Commons 2016
//github.com/ItKindaWorks
//
//Requires PubSubClient found here: https://github.com/knolleary/pubsubclient
//
//ESP8266 Simple MQTT light controller


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


//EDIT THESE LINES TO MATCH YOUR SETUP
#define MQTT_SERVER "192.168.0.123"
const char* ssid = "SSID";
const char* password = "******";

//LED on ESP8266 D5 GPIO14
const int lightPin14 = 14;
const int lightPin2 = 2;

char* lightTopic = "/ESP1/OUT-D5";

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

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

void setup() {
  //initialize the light as an output and set to LOW (off)
  pinMode(lightPin14, OUTPUT);
  digitalWrite(lightPin14, LOW);
  //initialize the light as an output and set to LOW (off)
  pinMode(lightPin2, OUTPUT);
  digitalWrite(lightPin2, LOW);

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


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

  //convert topic to string to make it easier to work with
  String topicStr = topic; 

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

  //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
  if(payload[0] == '1'){
    digitalWrite(lightPin14, HIGH);
    client.publish("/ESP1/confirmOUT-D5", "Light On");

  }

  //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
  else if (payload[0] == '0'){
    digitalWrite(lightPin14, LOW);
    client.publish("/ESP1/confirmOUT-D5", "Light Off");
  }

}




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
      if (client.connect((char*) clientName.c_str())) {
        Serial.print("\tMTQQ Connected");
        client.subscribe(lightTopic);
      }

      //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;
}

Any help would be greatly appreciated!

I think it’s probably receiving the update to both items but the switch doesn’t know what to do with the string “Light on”. Try changing the esp 8266 to pass back 1 for light on and 0 for light off

You can add [%s] into the switch label to see what it’s receiving

Hi @benhelps

This worked perfectly! I have added [%s] into my switch and saw that it was reading “ON” and “OFF”.
I have then updated my ESP8266 publish commands to:

  //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
  if(payload[0] == '1'){
    digitalWrite(lightPin14, HIGH);
    client.publish("/ESP1/confirmOUT-D5", "ON");

  }

  //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
  else if (payload[0] == '0'){
    digitalWrite(lightPin14, LOW);
    client.publish("/ESP1/confirmOUT-D5", "OFF");
  }

}

Thank you so much for your help!!