MQTT Button using ESP8266

Hello All,
I’ve been trying to implement a relatively simple device akin to this ESP8266 IFTTT Button project (hackster.io/noelportugal/if … 6&offset=1) only it would be configured to trigger a single automation rule via MQTT. While it seemed like it should be pretty straight forward enough, it ended up being really difficult to find up-to-date documentation for an Arduino-based ESP8266-compatible MQTT library that wasn’t specifically configured for a subscription web service.
Has anybody else had any luck setting up physical triggers (via Arduino or anything similar) for MQTT-Home Assistant? I’ve used the PUBSUBClient arduino library in the past but IIRC I couldnt get it to connect to my local Mosquitto Broker running on my RPi… Part of THAT had to do with the scarcity of resources on Mosquitto-RPi usage in general, a problem that does not appear to have been rectified… Thoughts?

1 Like

See our blog post about sending sensor data over MQTT to Home Assistant: home-assistant.io/blog/2015/10/ … t-to-mqtt/

MQTT works really well with ESP8266.
I have a few doing various tasks:

  • controlling switches
  • report air quality and humidity
  • RF -sender/receiver connected to wifi
  • RFID Sensor connected to my alarm system.

All using MQTT

Here is the code using arduino for simple controlling of a switch:

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

// Wifi Connection
const char* ssid = "YOUR SSID";
const char* password = "SSID PASSWORD";

// MQTT Server address
const char* mqtt_server = "Your MQTT IP Address ";

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

void setup() {
  
    // prepare GPIO4
  pinMode(4, OUTPUT);
  digitalWrite(4, 1);

  Serial.begin(9600);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void setup_wifi() {

  delay(2);
  // We start by connecting to a WiFi network
  Serial.println();
  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) {
  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 LED if an 1 was received as first character
  int val;
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    val = 1;
    digitalWrite(4, val);
    // but actually the LED is on; this is because
    // it is acive low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
    val = 0;
    digitalWrite(4, val);
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("/switch/relay/state", "connected");
      // ... and resubscribe
      client.subscribe("/switch/relay/switch");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void loop() {

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

  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
    snprintf (msg, 75, "connected", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("/switch/relay/state", msg);
  }
}
1 Like

Awesome! Thank you for that!
On Line 9 where it says-

// MQTT Server address const char* mqtt_server = "Your MQTT IP Address ";
Do you just print the basic ip or the ip+ port number? Specifically, I’m running Mosquitto, NodeRED and HASS on the same Raspberry Pi so they all have the same IP but use different ports. So NodeRED is served up at 192.168.1.:1880, HASS at 192.168.1.:8123 and Mosquitto I assume would be at 192.168.1.*:1883? Is this how it should be entered? Will the shared IP complicate matters?

Look at the setup method, it seems that it will connect to port 1883 (default unencrypted port for MQTT).

So just the IP address will do.

[quote=“thaijames”]MQTT works really well with ESP8266.
I have a few doing various tasks:

  • controlling switches
  • report air quality and humidity
  • RF -sender/receiver connected to wifi
  • RFID Sensor connected to my alarm system.

All using MQTT

Here is the code using arduino for simple controlling of a switch:

[code]
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

[…]
[/code][/quote]

Thanks again for the code! Would you mind sharing a little more about the wiring you used to run the sketch posted above? I’m just trying to wire a circuit with an on/off pushbutton and an indicator LED and it seems like no two wiring diagrams I find are the same. Most diagrams I’ve found use some form of pull-up resistor between GPIO0 or GPIO2 but I noticed your code has an LED connected to GPIO4? Are you using an ESP8266 v01? I thought v01 only had two GPIOs?

Also regarding the MQTT config… If my topic tree was exactly the same as the MQTT Switch component example-https://home-assistant.io/components/switch.mqtt/ would I change “/switch/relay/switch” to “home/bedroom/switch1” and “/switch/relay/state” to “home/bedroom/switch1/set” or vice versa (or neither?)

Thanks in advance! I’m learning the hard way that being a relatively advanced Arduino user doesn’t necessarily guarantee an easy time getting started with the ESP8266 since there are so many different ways to program it…

You can configure your topics for the MQTT switch to whatever you want, just make sure you setup the correct values in the config.

Just to be clear… I was only using the topics from the MQTT Switch component page as an example. I’m aware that topics can be setup in any way. My question is related to how you add the topics within the arduino sketch since the pubsubclient library doesn’t let you add topics as definitions IIRC.
So if my topic tree were (for example) identical to that on the MQTT switch component page home/bedroom/switch1 and home/bedroom/switch1/set I’m trying to figure out how the arduino sketch would be changed to reflect that.

This schematic from this tutorial http://lawrencejeff.blogspot.com/2015/02/esp8266-and-openhab.html is the closest I could yet find to what I’m trying to do-


However, I would much rather use a method based on the sketch posted by @thaijames earlier in the thread. The problem is the wiring in the OpenHAB tutorial presumes only two GPIO ports will be available which is why GPIO0 must be set to high on boot. My controller is the same as the one pictured (ESP8266 v01) but I’m wondering if the sketch is intended for a more advanced version like the Node MCU or Adafruit Huzzah? Otherwise I can’t make sense of the references to GPIO4 and a built-in LED?
@thaijames- Will your sketch work with a generic ESP8266 v01?

Okay… I think I’m getting closer… It looks like the most challenging part of learning ESP8266 at present is in finding the most up-to-date documentation as it appears most of the earlier tutorials were written before the ESP boards were officially supported by the Arduino IDE. Many of which recommend overly complicated methods which have now been deprecated. I also had to sift through a lot of conflicting information about power sources for which my UartSBee/FTDI adapter functioned perfectly in 3.3v mode.
As of the present I have it wired akin to the following diagram-

This way the button can also double as a reset by pulling GPIO0 to ground-

Next I’ll try modifying the ESPwificlient sketch to accept GPIO0 as the input before sketching out my wiring for the physical button. Ideally, I’d like to use some Neopixel leds in place of the standard single color version but this may be farther down the road…

I’m probably getting ahead of myself here but I just thought of a much more interesting physical button setup… It would be similar enough to my current physical MQTT trigger button, only it would also incorporate a rotary pot and a neopixel ring. The form would be like a combination of a pushbutton LED and a rotary thermostat. A rotating ring around the plastic center globe would be connected to a potentiometer which would in turn change colors on a Neopixel ring. When the users selects a desired color, the pushbutton would send the color value to HASS using MQTT, which in turn triggers the corresponding color on the home lighting component.
While it might be possible to accomplish all of this with a single ESP8266, I’m probably going to use either an Arduino Yun or an Arduino+NRF24 transceiver for the time being.
In any case, I need to finish my first project before I can do anything else but I’m interested to hear what others think of this concept.

I found at least one example of someone using a rotary encoder to control automations via MQTT though its only a small part of a massive wall controller for OpenHAB- github.com/hazymat/fleetwood/bl … July15.ino
Looking over the code, it isnt hard to see that why OpenHAB isnt exactly known for its efficiency… Glad I made the choice to go with Home-Assistant!
Anyway, I’d never heard of an encoder library for Arduino before, so that might be a good place to start. After all, as far as MQTT and HASS is concerned, the Neopixel ring doesn’t have to exist as long as it knows to read the encoder after the button is pressed.

Back to the original project for the time being… Using the wiring I posted earlier, I was indeed able to successfully load a version of the Arduino sketch posted earlier with just a few modifications to match my network preferences and MQTT topics.

[code]#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Wifi Connection
const char* ssid = “ssid”;
const char* password = “pass”;

// MQTT Server address
const char* mqtt_server = “192.168.1.1”;

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

void setup() {

// prepare GPIO4

pinMode(0, OUTPUT);
digitalWrite(0, 1);

Serial.begin(9600);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}

void setup_wifi() {

delay(2);
// We start by connecting to a WiFi network
Serial.println();
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) {
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 LED if an 1 was received as first character
int val;
if ((char)payload[0] == ‘1’) {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
val = 1;
digitalWrite(0, val);
// but actually the LED is on; this is because
// it is acive low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
val = 0;
digitalWrite(0, val);
}

}

void reconnect() {
// Loop until we’re reconnected
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
// Attempt to connect
if (client.connect(“ESP8266Client”)) {
Serial.println(“connected”);
// Once connected, publish an announcement…
client.publish(“home/bedroom/buttonswitch/set”, “connected”);
// … and resubscribe
client.subscribe(“home/bedroom/buttonswitch”);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop() {

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

long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, 75, “connected”, value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish(“home/bedroom/buttonswitch”, msg);
}
}[/code]

Then on the HASS side I added the switch to my config.yaml

switch: platform: mqtt name: "Bedroom Switch" state_topic: "home/bedroom/buttonswitch" command_topic: "home/bedroom/buttonswitch/set" qos: 0 payload_on: "ON" payload_off: "OFF" optimistic: false state_format:

I then created two new scenes of which one is the default “lights out” mode while we’re all sleeping and the other wherein the MQTT button will turn the lights on.

[code]- name: ‘Baby Change’
entities:
light.bedlamp:
state: on
brightness: 100
rgb_color: [255, 0, 0]
light.bedroom:
state: on
brightness: 100
rgb_color: [255, 0, 0]
light.bathroom:
state: on
brightness: 50
rgb_color: [20, 50, 200]

  • name: ‘Sleep’
    entities:
    light.bedlamp:
    state: off
    brightness: 0
    light.bedroom:
    state: off
    brightness: 0
    light.bathroom:
    state: on
    brightness: 50
    rgb_color: [20, 50, 200][/code]

Lastly, I created the following automation for the MQTT trigger itself-

[code]automation:

  • alias: ‘Baby Wake’

    trigger:

    • platform: mqtt
      topic: home/bedroom/buttonswitch/set

      Optional

      payload: ‘on’

    action:
    service: scene.turn_on
    entity_id: scene.baby_change

automation:

  • alias: ‘Baby Wake’

    trigger:

    • platform: mqtt
      topic: home/bedroom/buttonswitch/set

      Optional

      payload: ‘off’

    action:
    service: scene.turn_off
    entity_id: scene.sleep[/code]

While I was able to see the messages while connected to the Arduino Serial Monitor, the actions did not seem to be recognized by Home Assistant. So I’m definitely missing something. Is there any additional configuartion that needs to be done through the MQTT Broker (Mosquitto in my case?). Do I need to publish each topic and subtopic directly to Mosquitto or will it automatically publish from the config.yaml?

My current (scrubbed) config.yaml can be found at my pastebin if anybody would like to take a look- pastebin.com/hjeJm3xa

I guess I’ll continue to update my progress for future reference even if it seems like I’m in an echo chamber…

I was able to confirm through the CLI on the Mosquitto broker that the sketch is indeed working. It is continually sending out to the state topic home/bedroom/buttonswitch and home/bedroom/buttonswitch/set when the button is pressed… I can’t quite figure out from the MQTT-Switch component docs whether it is supposed to be this way or not… If not, then I need to rewrite the Arduino sketch to only publish when the button is pressed. If using an Arduino, I would do so with the following sketch-

[code]#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#include <util.h>
#include <ctype.h>

#define CLIENTID “ArduinoSensor”
#define TOPICNAME “switch/signal”
#define POLLINTERVAL 120000

#define PORT 80
//Connect to MQTT server
byte server1 [] = {192, 168, 1, 4};
byte mac[] = {0x5e, 0xa4, 0x18, 0xf0, 0x8a, 0xf6};

IPAddress arduinoIP(192, 168, 1, 67);
IPAddress dnsIP(203, 145, 184, 32);
IPAddress gatewayIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);
EthernetServer server(PORT);

EthernetClient ethClient;
PubSubClient arduinoClient(server1, 8081, callback, ethClient);
void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}
int inPin1 = 2;
int inPin2 = 0;// the number of the input pin
int outPin = 7; // the number of the output pi

int state = HIGH; // the current state of the output pin
int reading; // the current reading from the input pin
int previous = LOW; // the previous reading from the input pin

// the follow variables are long’s because the time, measured in milliseconds
// will quickly become a bigger number than can be stored in an int.
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers

int state2 = HIGH; // the current state of the output pin
int reading2; // the current reading from the input pin
int previous2 = LOW; // the previous reading from the input pin

// the follow variables are long’s because the time, measured in milliseconds
// will quickly become a bigger number than can be stored in an int.
long time2 = 0; // the last time the output pin was toggled
long debounce2 = 200; // the debounce time, increase if the output flickers
void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, arduinoIP, dnsIP, gatewayIP, subnetIP);
pinMode(inPin1, INPUT);
pinMode(inPin2, INPUT);
pinMode(outPin, OUTPUT);
beginConnection() ;
}

void beginConnection() {
Serial.begin(9600);
//Ethernet.begin(mac) ;
int connRC = arduinoClient.connect(CLIENTID) ;
if (!connRC) {
Serial.println(connRC) ;
Serial.println(“Could not connect to MQTT Server”);
Serial.println(“Please reset the arduino to try again”);
delay(100);
exit(-1);
}
else {
Serial.println(“Connected to MQTT Server…”);

}}

void loop()
{

reading = digitalRead(inPin1);

// if the input just went from LOW and HIGH and we’ve waited long enough
// to ignore any noise on the circuit, toggle the output pin and remember
// the time
if (reading == HIGH && previous == LOW && millis() - time > debounce) {
if (state == HIGH){
state = LOW;
arduinoClient.publish(TOPICNAME, “Button A is Pressed”) ;
Serial.println(“Button A is Pressed and message published”);}
else
{
state = HIGH;
arduinoClient.publish(TOPICNAME, “Button A is Pressed”) ;
Serial.println(“Button A is Pressed and message published”);
}
time = millis();
}
digitalWrite(outPin, state);

previous = reading;

reading2 = digitalRead(inPin2);

// if the input just went from LOW and HIGH and we’ve waited long enough
// to ignore any noise on the circuit, toggle the output pin and remember
// the time
if (reading2 == HIGH && previous2 == LOW && millis() - time2 > debounce2) {
if (state2 == HIGH){
state2 = LOW;
arduinoClient.publish(TOPICNAME, “Button B is Pressed”) ;
Serial.println(“Button B is Pressed and message published”);}
else
{
state2 = HIGH;
arduinoClient.publish(TOPICNAME, “Button B is Pressed”) ;
Serial.println(“Button B is Pressed and message published”);
}
time2 = millis();
}
digitalWrite(outPin, state2);

previous2 = reading2;

}[/code]

Unfortunately, the PUBSUBCLIENT library works somewhat differently with an ESP8266 so its not quite as simple as changing some of the parameters…

If on the other hand, the MQTT comms are working as they should, then the problem is in the scene configuration as I would’ve expected to see start/stop_scene available under services… But it is not…

humblehacker, sorry for not getting back to you earlier.

I will try to send you pics of the wiring tommorrow when I get back home.
In regards to a button I have implemented something similar however using an RIFD reader.
In this example it reads the Token and if the token is allowed it either turns on or off the alarm system.
However you could adapt it to act as a button only.

Please note that I use an ESP8266 (ESP-12) much easier to use and program.
Here is the example:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SPI.h>
#include "MFRC522.h"

/* wiring the MFRC522 to ESP8266 (ESP-12)
RST     = GPIO4
SDA(SS) = GPIO2 
MOSI    = GPIO13
MISO    = GPIO12
SCK     = GPIO14
GND     = GND
3.3V    = 3.3V
*/

#define RST_PIN  4 // RST-PIN GPIO4 
#define SS_PIN  2  // SDA-PIN GPIO2 

MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

// Wifi Connection details
const char* ssid = "SSID";
const char* password = "PASSWORD";

// MQTT Server address
const char* mqtt_server = "SERVER_IP";

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



void setup() {
  Serial.begin(9600);

  SPI.begin();           // Init SPI bus
  mfrc522.PCD_Init();    // Init MFRC522
    
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}


// Connect to Wifi
void setup_wifi() {

  pinMode(5, OUTPUT); // Red LED
  pinMode(5, HIGH); 
  pinMode(0, OUTPUT); // Greem :LED
  pinMode(0, HIGH);

  delay(2);
  // We start by connecting to a WiFi network
  Serial.println();
  
  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());
}


// Check for incoming messages
void callback(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]);
  }


  // Alarm is on
  if ((char)payload[1] == 'n') {
    Serial.println();
    Serial.print("Alarm is on");
    Serial.println();
    state=1;
    on_red_led();    
  } 
  
  // Alarm is off
  if ((char)payload[1] == 'f') {
    Serial.println();
    Serial.print("Alarm is off");
    Serial.println();
    state=0;
    on_green_led();    
  } 
  
  // Alarm is arming
  if ((char)payload[2] == 'm') {
    Serial.println();
    Serial.print("Alarm is arming");
    Serial.println();
    state=2;
    flash_red_led();    
  }   

  // Alarm is disarming
  if ((char)payload[2] == 's') {
    Serial.println();
    Serial.print("Alarm is disarming");
    Serial.println();
    state=2;
    flash_green_led();    
  } 

  // Error
  if ((char)payload[3] == 'o') {
    Serial.println();
    Serial.print("Error wrong token");
    Serial.println();
    state=3;
    blink_red_led();    
  }

}


// Reconnect to wifi if connection lost
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("/rfid/state", "connected");
      // ... and resubscribe
      client.subscribe("/alarm/state");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}


// Main functions
void loop() {

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

  client.loop();
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    delay(50);
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    delay(50);
    return;
  }

  // if still arming or disarming then return
  if (state == 2) { 
  return; 
  }

  // if error delay
  if (state == 3) { 
  delay(2000); 
  }
  
  // Show some details of the PICC (that is: the tag/card)
  Serial.print(F("Card UID:"));
  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
  Serial.println();

  // Send data to MQTT
  String rfidUid = "";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    rfidUid += String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
    rfidUid += String(mfrc522.uid.uidByte[i], HEX);
  }
  const char* id = rfidUid.c_str();

  // Blink led once
  if (state == 1) { 
  beep_red_led(); 
  }
  if (state != 1) { 
  beep_green_led();  
  }
  
  client.publish("/rfid/user", id);
  //delay(2000);
}


// LED Loop
void blink_red_led(){
  Serial.println("Blinking Red");
  digitalWrite(0, LOW);
  // Flash 6 times:
  for(int i = 0; i < 5; i++)
  {
  digitalWrite(5, HIGH);
  delay(200);
}}

void flash_green_led(){
  Serial.println("Flashing Green LED");
  digitalWrite(5, LOW);
  // Flash 15 times:
  for(int i = 0; i < 14; i++)
  {
  digitalWrite(0, HIGH);
  delay(1000);
  digitalWrite(0, LOW);
  delay(500);
}}


void beep_red_led(){
  Serial.println("Beep Red LED");
  digitalWrite(5, LOW);
  delay(500);
  digitalWrite(5, HIGH);
}

void beep_green_led(){
  Serial.println("Beep Red LED");
  digitalWrite(0, LOW);
  delay(500);
  digitalWrite(0, HIGH);
}

void flash_red_led(){
  Serial.println("Flashing Red LED");
  digitalWrite(0, LOW);
  // Flash 20 times:
  for(int i = 0; i < 19; i++)
  {
  digitalWrite(5, HIGH);
  delay(1000);
  digitalWrite(5, LOW);
  delay(500);
}}


void on_green_led(){
  Serial.println("Turning on green led");
  digitalWrite(5, LOW);
  digitalWrite(0, HIGH);
}

void on_red_led(){
  Serial.println("Turning on red led");
  digitalWrite(0, LOW);
  digitalWrite(5, HIGH);
}


// Helper routine to dump a byte array as hex values to Serial
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

Thank you @thaijames!!! I think I’ve got the wiring down and I was able to load the first example sketch you provided earlier but I’m a little confused about the how they use state and command topics in the MQTT Switch component. As I have it at present, the switch is continuously publishing “home/bedroom/buttonswitch connected” about once every second. Assuming I have the button set correctly etc… it will publish “home/bedroom/buttonswitch/set” on button press though sometimes it can be finicky. Anyway, I don’t know if this is how its supposed to work or not but it doesn’t seem like the best setup to me as theres nowhere to add an “on” or “off” payload to trigger a scene…

Thanks to user @fabaff on the Gitter chat I think I’m getting a little closer.

His original sketch-

[code]/*
Basic ESP8266 MQTT example NodeMCU ESP8266-12E development board
*/

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

int inputPins[] = { 1, 3, 12, 13, 14, 15 };
int pinInputCount = 6;

int outputPins[] = { 0, 2, 4, 5 };
int pinOutputCount = 4;

// Update these with values suitable for your network.
const char* ssid = “…”;
const char* password = “”;
const char* mqtt_server = “…”;

char* deviceId = “unit007”;
char* stateTopic = “home/unit007”;
char* commandTopic = “home/unit007/set”;
int sensorPin = A0;
char buf[4];
int updateInterval = 2000;

char* stateTopicA0 = “home/unit007/a0”;
char* stateTopic0 = “home/unit007/0”;
char* stateTopic1 = “home/unit007/1”;
char* stateTopic2 = “home/unit007/2”;
char* stateTopic3 = “home/unit007/3”;
char* stateTopic4 = “home/unit007/4”;
char* stateTopic5 = “home/unit007/5”;
char* stateTopic12 = “home/unit007/12”;
char* stateTopic13 = “home/unit007/13”;
char* stateTopic14 = “home/unit007/14”;
char* stateTopic15 = “home/unit007/15”;
char* stateTopic16 = “home/unit007/16”;

char* commandTopic0 = “home/unit007/0/set”;
char* commandTopic2 = “home/unit007/2/set”;
char* commandTopic4 = “home/unit007/4/set”;
char* commandTopic5 = “home/unit007/5/set”;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msga0[20];
char msg0[20];
char msg1[20];
char msg2[20];
char msg3[20];
char msg4[20];
char msg5[20];
char msg12[20];
char msg13[20];
char msg14[20];
char msg15[20];
char msg16[20];
int sensorValue = 0;

const int buttonPin1 = 12;
const int buttonPin2 = 13;

const int ledPin1 = 2;
const int ledPin2 = 5;

int buttonState1 = 0;
int buttonState2 = 0;

int lastButtonState1 = 0;
int lastButtonState2 = 0;

int ledState1 = 0;
int ledState2 = 0;

void setup_wifi() {
delay(10);
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) {
Serial.print("Message arrived: “);
Serial.print(topic);
Serial.print(” ");

String recieveTopic = (char*)topic;

Serial.print("Payload: ");
Serial.write(payload, length);
Serial.println();

char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
String message§;

if (recieveTopic == (char*)commandTopic0) {
if (message.equals(“1”)) {
digitalWrite(0, HIGH);
} else {
digitalWrite(0, LOW);
}
} else if (recieveTopic == (char*)commandTopic2) {
if (message.equals(“1”)) {
digitalWrite(2, HIGH);
} else {
digitalWrite(2, LOW);
}
} else if (recieveTopic == (char*)commandTopic4) {
if (message.equals(“1”)) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
}
} else if (recieveTopic == (char*)commandTopic5) {
if (message.equals(“1”)) {
digitalWrite(5, HIGH);
} else {
digitalWrite(5, LOW);
}
} else {
Serial.print(“Topic unknown”);
}
}

void reconnect() {
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
if (client.connect(deviceId)) {
Serial.println(“connected”);
client.publish(stateTopic, “ready”);
client.subscribe(commandTopic0);
client.subscribe(commandTopic2);
client.subscribe(commandTopic4);
client.subscribe(commandTopic5);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}

void setup() {
// Input pins
for (int thisPin = 0; thisPin < pinInputCount; thisPin++) {
pinMode(inputPins[thisPin], INPUT);
}
// Output pins
for (int thisPin = 0; thisPin < pinOutputCount; thisPin++) {
pinMode(outputPins[thisPin], OUTPUT);
}

Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}

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

buttonState1 = digitalRead(buttonPin1);
if (buttonState1 != lastButtonState1) {
if (buttonState1 == HIGH) {
if(ledState1 == HIGH) {
ledState1 = LOW;
} else {
ledState1 = HIGH;
}
}
lastButtonState1 = buttonState1;
}
digitalWrite(ledPin1, ledState1);
delay(20);

buttonState2 = digitalRead(buttonPin2);
if (buttonState2 != lastButtonState2) {
if (buttonState2 == HIGH) {
if(ledState2 == HIGH) {
ledState2 = LOW;
} else {
ledState2 = HIGH;
}
}
lastButtonState2 = buttonState2;
}
digitalWrite(ledPin2, ledState2);
delay(20);
//////////////////////////////////////////////////////////////
long now = millis();
if (now - lastMsg > updateInterval) {
lastMsg = now;

snprintf (msga0, 75, "%ld", analogRead(sensorPin));
client.publish(stateTopicA0, msga0);

// Input pins
snprintf(msg0, 75, "%ld", digitalRead(0));
client.publish(stateTopic0, msg0);

snprintf(msg1, 75, "%ld", digitalRead(1));
client.publish(stateTopic1, msg1);

snprintf(msg2, 75, "%ld", digitalRead(2));
client.publish(stateTopic2, msg2);

snprintf(msg3, 75, "%ld", digitalRead(3));
client.publish(stateTopic0, msg3);

snprintf(msg4, 75, "%ld", digitalRead(4));
client.publish(stateTopic4, msg4);

snprintf(msg5, 75, "%ld", digitalRead(5));
client.publish(stateTopic5, msg5);

snprintf(msg12, 75, "%ld", digitalRead(12));
client.publish(stateTopic12, msg12);

snprintf(msg13, 75, "%ld", digitalRead(13));
client.publish(stateTopic13, msg13);

snprintf(msg14, 75, "%ld", digitalRead(14));
client.publish(stateTopic14, msg14);

snprintf(msg15, 75, "%ld", digitalRead(15));
client.publish(stateTopic15, msg15);

snprintf(msg16, 75, "%ld", digitalRead(16));
client.publish(stateTopic16, msg16);    

}
}[/code]

His code was written for the NodeMCU board however which has many more open ports, so I had to modify for the ESP v01 with only two open pins. My current version is as follows-

[code]/*
Basic ESP8266 MQTT example NodeMCU ESP8266-12E development board
*/

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

int inputPins[] = { 0 };
int pinInputCount = 1;

int outputPins[] = { 2 };
int pinOutputCount = 4;

// Update these with values suitable for your network.
const char* ssid = “ssid”;
const char* password = “password”;
const char* mqtt_server = “192.168.1.1”;

char* deviceId = “Button”;
char* stateTopic = “home/bedroom/buttonswitch”;
char* commandTopic = “home/bedroom/buttonswitch/set”;
int sensorPin = A0;
char buf[4];
int updateInterval = 2000;

char* stateTopicA0 = “home/bedroom/buttonswitch/a0”;
char* stateTopic0 = “home/bedroom/buttonswitch/0”;
char* stateTopic1 = “home/bedroom/buttonswitch/1”;

char* commandTopic0 = “home/bedroom/buttonswitch/0/set”;
char* commandTopic2 = “home/bedroom/buttonswitch/2/set”;
char* commandTopic4 = “home/bedroom/buttonswitch/4/set”;
char* commandTopic5 = “home/bedroom/buttonswitch/5/set”;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msga0[20];
char msg0[20];
char msg1[20];
char msg2[20];
char msg3[20];
char msg4[20];
char msg5[20];
char msg12[20];
char msg13[20];
char msg14[20];
char msg15[20];
char msg16[20];
int sensorValue = 0;

const int buttonPin1 = 0;

const int ledPin1 = 2;

int buttonState1 = 0;
int buttonState2 = 0;

int lastButtonState1 = 0;
int lastButtonState2 = 0;

int ledState1 = 0;
int ledState2 = 0;

void setup_wifi() {
delay(10);
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) {
Serial.print("Message arrived: “);
Serial.print(topic);
Serial.print(” ");

String recieveTopic = (char*)topic;

Serial.print("Payload: ");
Serial.write(payload, length);
Serial.println();

char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
String message§;

if (recieveTopic == (char*)commandTopic0) {
if (message.equals(“1”)) {
digitalWrite(0, HIGH);
} else {
digitalWrite(0, LOW);
}
} else if (recieveTopic == (char*)commandTopic2) {
if (message.equals(“1”)) {
digitalWrite(2, HIGH);
} else {
digitalWrite(2, LOW);
}
} else if (recieveTopic == (char*)commandTopic4) {
if (message.equals(“1”)) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
}
} else if (recieveTopic == (char*)commandTopic5) {
if (message.equals(“1”)) {
digitalWrite(5, HIGH);
} else {
digitalWrite(5, LOW);
}
} else {
Serial.print(“Topic unknown”);
}
}

void reconnect() {
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
if (client.connect(deviceId)) {
Serial.println(“connected”);
client.publish(stateTopic, “ready”);
client.subscribe(commandTopic0);
client.subscribe(commandTopic2);
client.subscribe(commandTopic4);
client.subscribe(commandTopic5);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}

void setup() {
// Input pins
for (int thisPin = 0; thisPin < pinInputCount; thisPin++) {
pinMode(inputPins[thisPin], INPUT);
}
// Output pins
for (int thisPin = 0; thisPin < pinOutputCount; thisPin++) {
pinMode(outputPins[thisPin], OUTPUT);
}

Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}

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

buttonState1 = digitalRead(buttonPin1);
if (buttonState1 != lastButtonState1) {
if (buttonState1 == HIGH) {
if(ledState1 == HIGH) {
ledState1 = LOW;
} else {
ledState1 = HIGH;
}
}
lastButtonState1 = buttonState1;
}
digitalWrite(ledPin1, ledState1);
delay(20);

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

snprintf (msga0, 75, "%ld", analogRead(sensorPin));
client.publish(stateTopicA0, msga0);

// Input pins
snprintf(msg0, 75, "%ld", digitalRead(0));
client.publish(stateTopic0, msg0);

snprintf(msg1, 75, "%ld", digitalRead(1));
client.publish(stateTopic1, msg1);

snprintf(msg3, 75, "%ld", digitalRead(3));
client.publish(stateTopic0, msg3);

 }

}[/code]

Now, in the Mosquitto CLI, at least instead of publishing a “connection” message every other second, I get a string of digits like so-

[quote]1
0
0
47
1
0
0
46[/quote]

When I push the button I get-

[quote]1
0
0
47
ready
1
0
0
46[/quote]

This is the updated and stripped version of the sketch I posted before. Button connected to buttonPin1 and a LED on ledPin1. After one press the ESP8266 send every 2 s its state (1) to the broker and switch the LED on. The next press will switch the LED off and change the state to 0.

This

[code]binary_sensor:

  • platform: mqtt
    name: Physical button
    state_topic: “home/node019”
    payload_on: “1”
    payload_off: “0”[/code]

and the sketch

[code]#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = “SSID”;
const char* password = “PASSWORD”;
const char* mqtt_server = “BROKER”;

char* deviceId = “node019”;
char* stateTopic = “home/node019”;
char* commandTopic = “home/unit019/set”;
char buf[4];
int updateInterval = 2000;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg0[20];

const int buttonPin1 = 12;
const int ledPin1 = 2;

int buttonState1 = 0;
int lastButtonState1 = 0;
int ledState1 = 0;

void setup_wifi() {
delay(10);
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) {
Serial.print("Message arrived: “);
Serial.print(topic);
Serial.print(” ");

String recieveTopic = (char*)topic;

Serial.print("Payload: ");
Serial.write(payload, length);
Serial.println();

char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
String message§;

if (recieveTopic == (char*)commandTopic) {
if (message.equals(“1”)) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
}
} else {
Serial.print(“Topic unknown”);
}
}

void reconnect() {
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
if (client.connect(deviceId)) {
Serial.println(“connected”);
client.publish(stateTopic, “ready”);
client.subscribe(commandTopic);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}

void setup() {
pinMode(buttonPin1, INPUT);
pinMode(ledPin1, OUTPUT);
pinMode(4, OUTPUT);

Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}

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

buttonState1 = digitalRead(buttonPin1);
if (buttonState1 != lastButtonState1) {
if (buttonState1 == HIGH) {
if (ledState1 == HIGH) {
ledState1 = LOW;
} else {
ledState1 = HIGH;
}
}
lastButtonState1 = buttonState1;
}
digitalWrite(ledPin1, ledState1);
delay(20);

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

snprintf(msg0, 75, "%ld", ledState1);
client.publish(stateTopic, msg0);

}
}[/code]

I didn’t remove the command topic but toggle an additional LED (nodemcu has more pins than an ESP-01).

humblehacker,

Sorry if I am still confused about what you are trying to do . I am assuming that you want to trigger different scenes or actions remotely using wifi. However I note that you only have one button, but you are trying to publish a number of different values as MQTT topics. Don’t you need one button for each value or topic?

So that when a button is pressed it only publishes that one value or to that one topic?

I would think that you would only want one value published in MQTT at a time so that home assistant can react to it. Otherwise if a number of values are being published rapidly then only the last value will be used.

1
0
0
47
ready
1
0
0
46

Am I understanding you correctly?

Later today I will write a new topic on the process of setting up an RFID reader to interface with an alarm system.
That might give you more insight on how I made it work.

[quote=“fabaff”]This is the updated and stripped version of the sketch I posted before. Button connected to buttonPin1 and a LED on ledPin1. After one press the ESP8266 send every 2 s its state (1) to the broker and switch the LED on. The next press will switch the LED off and change the state to 0.

I didn’t remove the command topic but toggle an additional LED (nodemcu has more pins than an ESP-01).[/quote]

Strange… The code compiled and uploaded just fine but the Mosquitto CLI still just keeps showing-

Even stranger is the fact that the LED will turn off when I push the button but then it comes back on again after about 5 seconds…?

After changing the wifi and topics this is the sketch I uploaded-

[code]#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = “myssid”;
const char* password = “mypassword”;
const char* mqtt_server = “192.168.1.1”;

char* deviceId = “buttonswitch”;
char* stateTopic = “home/bedroom/buttonswitch”;
char* commandTopic = “home/bedroom/buttonswitch/set”;
char buf[4];
int updateInterval = 2000;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg0[20];

const int buttonPin1 = 0;
const int ledPin1 = 2;

int buttonState1 = 0;
int lastButtonState1 = 0;
int ledState1 = 0;

void setup_wifi() {
delay(10);
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) {
Serial.print("Message arrived: “);
Serial.print(topic);
Serial.print(” ");

String recieveTopic = (char*)topic;

Serial.print("Payload: ");
Serial.write(payload, length);
Serial.println();

char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
String message(p);

if (recieveTopic == (char*)commandTopic) {
if (message.equals(“1”)) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
}
} else {
Serial.print(“Topic unknown”);
}
}

void reconnect() {
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
if (client.connect(deviceId)) {
Serial.println(“connected”);
client.publish(stateTopic, “ready”);
client.subscribe(commandTopic);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}

void setup() {
pinMode(buttonPin1, INPUT);
pinMode(ledPin1, OUTPUT);
pinMode(4, OUTPUT);

Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}

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

buttonState1 = digitalRead(buttonPin1);
if (buttonState1 != lastButtonState1) {
if (buttonState1 == HIGH) {
if (ledState1 == HIGH) {
ledState1 = LOW;
} else {
ledState1 = HIGH;
}
}
lastButtonState1 = buttonState1;
}
digitalWrite(ledPin1, ledState1);
delay(20);

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

snprintf(msg0, 75, "%ld", ledState1);
client.publish(stateTopic, msg0);

}
}[/code]