MQTT Light WITH physical button (NodeMCU, ESP8266)

Ok. I need some help from someone with more experience in arduino code. My goal is to get a physical button to toggle a relay (LED for testing purposes) and be able to toggle it over MQTT on a NODEMCU board

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

const char* ssid = "Co Wireless";
const char* password =  "tc11141976";
const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 18339;
const char* mqttUser = "esp8266";
const char* mqttPassword = "esp8266";
int buttonpin = D1;
int OUTPin = D2;
int state = HIGH;
int reading;
int previous = LOW;

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  pinMode(buttonpin, INPUT);
  pinMode(OUTPin, OUTPUT);
  Serial.begin(115200);
  digitalWrite(BUILTIN_LED, HIGH);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected");
    } else {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
  client.publish("esp/room/mainlight", "Roomlight is Online");
  client.subscribe("esp/room/mainlight");
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected");
      client.publish("esp/room/mainlight", "Connected");
      client.subscribe("esp/room/mainlight");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  if ((char)payload[0] == '1' && state == HIGH) {
    state = LOW;
  } else if ((char)payload[0] == '2' && state == LOW) {
    state = HIGH;
  }

  digitalWrite(OUTPin, state);

}

void loop() {
  if (!client.connected()) {
  reconnect();
  }
  client.loop();
  
  reading = digitalRead(buttonpin);
  
  if (reading == HIGH && previous == LOW) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }
  
  digitalWrite(OUTPin, state);
  previous = reading;
  delay(200);
}

The Button part works just fine. I cant get the MQTT to change the LED/ Relay state. I must’ve done something wrong. I think its in the void callback(char* topic, byte* payload, unsigned int length)

You are only subscribing to esp/room/mainlight. Is that the topic you are sending your 1 or 2 to?

I always publish to a /state and sub to a /command myself.

  client.publish("esp/room/mainlight/state",LOW);
  client.subscribe("esp/room/mainlight/command");

Update the /state on change and process the /command to control by MQTT

You’d then re-pub with

client.publish("'esp/room/mainlight/command",state)

on any state changes…

May need to convert state to c_str() on the publish items depending on your vars.

Just how I’ve done it.

Yea, im just using 1 and 2 so I dont need the state

I’d suggest you put several Serial.println(...) statements at the beginning of your callback method printing out the topic, payload and the state.

That way you can see if the callback is called at all and if the input is the one you are expecting.

Ok. Ill give it a try

Do you have this working? Can you share the sketch?

Hi @mario-g0

Try this project: https://github.com/1technophile/OpenMQTTGateway

There are very many uses for the code (a lot of sensors, gateways - RF 433/315, GSM, IR; also, not to forget ADC) however for the specific requirements in this topic, there would be need only for ONOFF (for relay) and GPIOInput (for the button). Just uncomment these two in User_config.h, set the name of the Gateway (if using more than one device this is mandatory otherwise there would be conflicts), wifi SSID, wifi password, IP and connection details for MQTT broker.

Then the default pins can be modified in config_xx for each sensor/gateway (not mandatory, though).