[SOLVED] MQTT from nodeMCU to Openhab two relays

Hello everyone
I have this problem, when I command (subscribes) from OH on / off, both the “relay_luci” and the “relay_foto” buttons always activate the same relay, the one assigned to “relay_foto”.
While working from external buttons (publish) everything works properly.
the item file:

Switch relay_luci                  "light"               <light>          (office)         { mqtt=">[mosquitto:openhab/out/ufficio/luci/command:command:*:default], <[mosquitto:openhab/in/ufficio/luci/state:state:default]" }
Switch foto                        "foto"                <niveau> 	      (office)         { mqtt=">[mosquitto:openhab/out/ufficio/foto/command:command:*:default], <[mosquitto:openhab/in/ufficio/foto/state:state:default]" }

the sitemap file:

Switch item=relay_luci                  mappings=[ON="ON", OFF="OFF"]
Switch item=foto                        mappings=[ON="ON", OFF="OFF"]

the nodeMCU code:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Bounce2.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

IPAddress staticIP(xxx, xxx, x, xxx); //ESP static ip
IPAddress gateway(xxx, xxx, x, x);
IPAddress subnet(255, 255, 255, 0);//IP Address of your WiFi Router (Gateway)

const char* ssid = "xxxx"; //SSID WIFI Access Point
const char* password = "xxxx"; //Access Point Password
const char* mqtt_server = "xxxxxxxx"; //IP address MQTT server

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

const char* inTopic_luci = "openhab/out/ufficio/luci/command";  // MQTT Topic this switch subscribes
const char* inTopic_foto = "openhab/out/ufficio/foto/command";  // MQTT Topic this switch subscribes
const char* switchTopic_luci = "openhab/in/ufficio/luci/state"; //MQTT Topic wall switch publish
const char* switchTopic_foto = "openhab/in/ufficio/foto/state"; //MQTT Topic wall switch publish

const int relay_luci = 5; //Pin for Relay
const int button_luci = 12; //Pin for button
const int relay_foto  = 13; //pin fotocopiatore
const int button_foto = 16; //Pin for

bool relayState_luci = HIGH;
bool relayState_foto = HIGH;

Bounce debouncer = Bounce(button_luci, 50);
Bounce debouncer2 = Bounce(button_foto, 50);

unsigned long previousMillis = 0;  // will store last time STATUS was send to MQTT
const long interval = 60000; //one minute for status refresh

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.config(staticIP, gateway, subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    for (int i = 0; i < 500; i++) {
      delay(1);
    }
    Serial.print(".");
  }
  digitalWrite(2, LOW);
  delay(500);
  digitalWrite(2, HIGH);
  delay(500);
  digitalWrite(2, LOW);
  delay(500);
  digitalWrite(2, HIGH);
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback_luci(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  // Switch on the RELAY if an "1" was received as first character or OFF if first character was a "0" or toggle relay when received a "2"
  if ((char)payload[1] == 'F')  {
    digitalWrite(relay_luci, LOW);
    Serial.println(relay_luci);// Turn the RELAY OFF
    relayState_luci = LOW;
  } else if ((char)payload[1] == 'N') {
    digitalWrite(relay_luci, HIGH);  // Turn the RELAY ON by making the voltage HIGH
    relayState_luci = HIGH;
    Serial.println();
  }
}

void callback_foto(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  // Switch on the RELAY if an "1" was received as first character or OFF if first character was a "0" or toggle relay when received a "2"
  if ((char)payload[1] == 'F')  {
    digitalWrite(relay_foto, LOW);
    Serial.println(relay_foto);// Turn the RELAY OFF
    relayState_foto = LOW;
  } else if ((char)payload[1] == 'N') {
    digitalWrite(relay_foto, HIGH);  // Turn the RELAY ON by making the voltage HIGH
    relayState_foto = HIGH;
  }
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ufficio")) {
      Serial.println("connected");
      //Subscribe to incoming commands
      client.subscribe(inTopic_luci);
      client.subscribe(inTopic_foto);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      for (int i = 0; i < 5000; i++) {
        // extButton_luci();
        // extButton_foto();
        delay(1);
      }
    }
  }
}

void extButton_luci() {
  debouncer.update();
  if ( debouncer.fell() ) {
    Serial.println("Debouncer luci");
    relayState_luci = !relayState_luci;
    digitalWrite(relay_luci, relayState_luci);
    if (relayState_luci == 1) {
      client.publish(switchTopic_luci, "ON", false);
    }
    else if (relayState_luci == 0) {
      client.publish(switchTopic_luci, "OFF", false);
    }
  }
}

void extButton_foto() {
  debouncer2.update();
  if ( debouncer2.fell() ) {
    Serial.println("Debouncer foto");
    relayState_foto = !relayState_foto;
    digitalWrite(relay_foto, relayState_foto);
    if (relayState_foto == 1) {
      client.publish(switchTopic_foto, "ON", false);
    }
    else if (relayState_foto == 0) {
      client.publish(switchTopic_foto, "OFF", false);
    }
  }
}

//*************************************SETUP*****************************************//
//***********************************************************************************//
void setup() {
  String line = "";
  pinMode(relay_luci, OUTPUT);     // Initialize the relay pin as an output
  pinMode(button_luci, INPUT);     // Initialize the relay pin as an input
  pinMode(relay_foto, OUTPUT);
  pinMode(button_foto, INPUT);
  pinMode(2, OUTPUT);            // Initialize the onboard LED as output

  debouncer.attach(button_luci);   // Use the bounce2 library to debounce the built in button
  debouncer.interval(50);         // Input must be low for 50 ms
  debouncer2.attach(button_foto);
  debouncer2.interval(50);

  digitalWrite(2, LOW);          // Blink to indicate setup
  delay(50);
  digitalWrite(2, HIGH);
  delay(50);

  Serial.begin(115200);
  setup_wifi();                   // Connect to wifi

  client.setServer(mqtt_server, 1883); //connect to MQTT
  client.setCallback(callback_luci);
  client.setCallback(callback_foto);

  // Port defaults to 8266: ArduinoOTA.setPort(8266);
  ArduinoOTA.setHostname("office");
  ArduinoOTA.setPassword((const char *)"xxxxx");
  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();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  ArduinoOTA.handle();

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

thanks for the help

What is the nodeMCU serial output when you send the messages?
Do you use an MQTT monitor like MQTTfx? What topics and messages does OH sends?
What do the ESP sends?

message from serial output:
if push light ON from OH: “Message arrived [openhab/out/ufficio/luci/command] ON” and the relay_foto switch
if I push light OFF from OH: “Message arrived [openhab/out/ufficio/foto/command] OFF” and the relay_foto switch
if I push foto ON from OH: “Message arrived [openhab/out/ufficio/foto/command] ON” switch relay_foto
if I push foto OFF from OH:“Message arrived [openhab/out/ufficio/foto/command] OFF” and the relay_foto switch
…always switch the relay_foto.
External button: light button: “Debouncer luci” switch the right relay
foto button:" Debouncer foto" switch the right relay

As a monitor I use MQTTlens. I used it correctly in another project. But in this project, despite the broker carries the data, because OH notification ON / OFF, I see nothing on MQTTlens
I do not know why

updating
in reviewing the photo MQTTlens I realized an error. Now MQTT correctly maps broker data.
And the messages that transit are right … lights ON … message ON lights OFF … message OFF … but always switches the wrong relay.
I also added a:
Serial.println (relay_luci);
Serial.println (relay_foto);
to see which pin was activated, and it is always 13 (D7) that relative to relay_foto

Try changing the luci relay pin

done a few minutes ago. nothing changes

That means that your two const have the same value for some reason…

MAybe change the names completely

const int luci_relay = 5; //Pin for Relay
const int button_luci = 12; //Pin for button
const int relay_foto  = 13; //pin fotocopiatore
const int button_foto = 16; //Pin for

And recompile Before uploading
Then upload on serial not OTA

I found you error:

  client.setCallback(callback_luci);
  client.setCallback(callback_foto);

The client can have only one call back
So it is allways doing the second one!!

You need to change your callback function
Remove the callback_luci

Change the other one:

String topicString = "";
...

...
void callback(char* topic, byte* payload, unsigned int length) {
  var topicString = topic;
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if topicString = "openhab/out/ufficio/luci/command" {
  // Switch on the RELAY if an "1" was received as first character or OFF if first character was a "0" or toggle relay when received a "2"
    if ((char)payload[1] == 'F')  {
      digitalWrite(relay_luci, LOW);
      Serial.println(relay_luci);// Turn the RELAY OFF
      relayState_luci = LOW;
    } else if ((char)payload[1] == 'N') {
      digitalWrite(relay_luci, HIGH);  // Turn the RELAY ON by making the voltage HIGH
      relayState_luci = HIGH;
    }
  }
  // foto
  if topicString = "openhab/out/ufficio/foto/command" {
  // Switch on the RELAY if an "1" was received as first character or OFF if first character was a "0" or toggle relay when received a "2"
    if ((char)payload[1] == 'F')  {
      digitalWrite(relay_foto, LOW);
      Serial.println(relay_foto);// Turn the RELAY OFF
      relayState_luci = LOW;
    } else if ((char)payload[1] == 'N') {
      digitalWrite(relay_foto, HIGH);  // Turn the RELAY ON by making the voltage HIGH
      relayState_foto = HIGH;
    }
  }
}
...

...
client.setCallback(callback);

Did you solve your problem?

I’m filling it out, but there are mistakes
var topicString = topic;
arduino does not accept var as variable, I used
String topicString = topic;
but now it commands both relays at the same time

Post you code as it is now, please

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Bounce2.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

IPAddress staticIP(xxxxx); //ESP static ip
IPAddress gateway(xxxxx);
IPAddress subnet(255, 255, 255, 0);//IP Address of your WiFi Router (Gateway)

const char* ssid = "xxxxx"; //SSID WIFI Access Point
const char* password = "xxxxx"; //Access Point Password
const char* mqtt_server = "xxxxx"; //IP address MQTT server

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

const char* inTopic_luci = "openhab/out/ufficio/luci/command";  // MQTT Topic this switch subscribes
const char* inTopic_foto = "openhab/out/ufficio/foto/command";  // MQTT Topic this switch subscribes
const char* switchTopic_luci = "openhab/in/ufficio/luci/state"; //MQTT Topic wall switch publish
const char* switchTopic_foto = "openhab/in/ufficio/foto/state"; //MQTT Topic wall switch publish

const int relay_luci = 0;   //D3 Pin for Relay
const int button_luci = 12; //D6 Pin for button
const int relay_foto  = 13; //D7 pin fotocopiatore
const int button_foto = 16; //D0 Pin for

bool relayState_luci = HIGH;
bool relayState_foto = HIGH;

Bounce debouncer = Bounce(button_luci, 50);
Bounce debouncer2 = Bounce(button_foto, 50);

unsigned long previousMillis = 0;  // will store last time STATUS was send to MQTT
const long interval = 60000; //one minute for status refresh
String topicString = "";

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.config(staticIP, gateway, subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    for (int i = 0; i < 500; i++) {
      delay(1);
    }
    Serial.print(".");
  }
  digitalWrite(2, LOW);
  delay(500);
  digitalWrite(2, HIGH);
  delay(500);
  digitalWrite(2, LOW);
  delay(500);
  digitalWrite(2, HIGH);
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  String topicString = topic;
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if (topicString = "openhab/out/ufficio/luci/command") {
    if ((char)payload[1] == 'F')  {
      digitalWrite(relay_luci, LOW);
      Serial.println(relay_luci);// Turn the RELAY OFF
      relayState_luci = LOW;
    } else if ((char)payload[1] == 'N') {
      digitalWrite(relay_luci, HIGH);
      Serial.println(relay_luci);// Turn the RELAY ON by making the voltage HIGH
      relayState_luci = HIGH;
    }
  }
  // foto
  if (topicString = "openhab/out/ufficio/foto/command") {
    if ((char)payload[1] == 'F')  {
      digitalWrite(relay_foto, LOW);
      Serial.println(relay_foto);// Turn the RELAY OFF
      relayState_luci = LOW;
    } else if ((char)payload[1] == 'N') {
      digitalWrite(relay_foto, HIGH);
      Serial.println(relay_foto);// Turn the RELAY ON by making the voltage HIGH
      relayState_foto = HIGH;
    }
  }
}

/*
  void callback_luci(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if ((char)payload[1] == 'F')  {
    digitalWrite(relay_luci, LOW);
    Serial.println(relay_luci);// Turn the RELAY OFF
    relayState_luci = LOW;
  } else if ((char)payload[1] == 'N') {
    digitalWrite(relay_luci, HIGH);
    Serial.println(relay_luci);// Turn the RELAY ON by making the voltage HIGH
    relayState_luci = HIGH;
    Serial.println();
  }
  }

  void callback_foto(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if ((char)payload[1] == 'F')  {
    digitalWrite(relay_foto, LOW);
    Serial.println(relay_foto);// Turn the RELAY OFF
    relayState_foto = LOW;
  } else if ((char)payload[1] == 'N') {
    digitalWrite(relay_foto, HIGH);
    Serial.println(relay_foto);// Turn the RELAY ON by making the voltage HIGH
    relayState_foto = HIGH;
  }
  }
*/
void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("pippo")) {
      Serial.println("connected");
      //Subscribe to incoming commands
      client.subscribe(inTopic_luci);
      client.subscribe(inTopic_foto);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      for (int i = 0; i < 5000; i++) {
        // extButton_luci();
        // extButton_foto();
        delay(1);
      }
    }
  }
}

void extButton_luci() {
  debouncer.update();
  if ( debouncer.fell() ) {
    Serial.println("Debouncer luci");
    relayState_luci = !relayState_luci;
    digitalWrite(relay_luci, relayState_luci);
    if (relayState_luci == 1) {
      client.publish(switchTopic_luci, "ON", false);
    }
    else if (relayState_luci == 0) {
      client.publish(switchTopic_luci, "OFF", false);
    }
  }
}

void extButton_foto() {
  debouncer2.update();
  if ( debouncer2.fell() ) {
    Serial.println("Debouncer foto");
    relayState_foto = !relayState_foto;
    digitalWrite(relay_foto, relayState_foto);
    if (relayState_foto == 1) {
      client.publish(switchTopic_foto, "ON", false);
    }
    else if (relayState_foto == 0) {
      client.publish(switchTopic_foto, "OFF", false);
    }
  }
}

//*************************************SETUP*****************************************//
//***********************************************************************************//
void setup() {
  String line = "";

  pinMode(relay_luci, OUTPUT);     // Initialize the relay pin as an output
  pinMode(button_luci, INPUT);     // Initialize the relay pin as an input
  pinMode(relay_foto, OUTPUT);
  pinMode(button_foto, INPUT);
  pinMode(2, OUTPUT);            // Initialize the onboard LED as output

  debouncer.attach(button_luci);   // Use the bounce2 library to debounce the built in button
  debouncer.interval(50);         // Input must be low for 50 ms
  debouncer2.attach(button_foto);
  debouncer2.interval(50);

  digitalWrite(2, LOW);          // Blink to indicate setup
  delay(50);
  digitalWrite(2, HIGH);
  delay(50);

  Serial.begin(115200);
  setup_wifi();                   // Connect to wifi

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

  // Port defaults to 8266: ArduinoOTA.setPort(8266);
  ArduinoOTA.setHostname("Domotica ufficio 2.0");
  ArduinoOTA.setPassword((const char *)"xxxxx");
  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();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  ArduinoOTA.handle();

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

topicString = topic;

and == instead of = in the if topic lines… Sorry

void callback(char* topic, byte* payload, unsigned int length) {
  topicString = topic;
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if (topicString == "openhab/out/ufficio/luci/command") {
    if ((char)payload[1] == 'F')  {
      digitalWrite(relay_luci, LOW);
      Serial.println(relay_luci);// Turn the RELAY OFF
      relayState_luci = LOW;
    } else if ((char)payload[1] == 'N') {
      digitalWrite(relay_luci, HIGH);
      Serial.println(relay_luci);// Turn the RELAY ON by making the voltage HIGH
      relayState_luci = HIGH;
    }
  }
  // foto
  if (topicString == "openhab/out/ufficio/foto/command") {
    if ((char)payload[1] == 'F')  {
      digitalWrite(relay_foto, LOW);
      Serial.println(relay_foto);// Turn the RELAY OFF
      relayState_luci = LOW;
    } else if ((char)payload[1] == 'N') {
      digitalWrite(relay_foto, HIGH);
      Serial.println(relay_foto);// Turn the RELAY ON by making the voltage HIGH
      relayState_foto = HIGH;
    }
  }
  topicString = "";
}
1 Like

NOW IT’S WORKS !!! GREAT !!!
thank you very much, your help was a great Christmas present.
I’ve been going crazy for more than two weeks !!!
Thanks again
Merry Christmas!!
Davide