MQTT Wall Switch (Arduino, ESP8266)

Hi all,

i created this fancy WiFi enabled wall switch, using and ESP8266 with the arduino framework.
It is a broken alarm switch which i found on the garbage.

Video:

Pictures
(The size is not perfect…)

I replaced the original electronic with a new Pushbutton. But i am using the original LED.

What am i doing with this switch?
When i leave my house, i just want to switch off all of my electronics.

I have multiple ways to do it:

  • Using the OpenHAB App/Web Browser,
  • Using NFC Tags glued to the door (Link created with the openHAB App)
  • Using geofence (Owntracks)
  • via my new touchpanel based on Dashing.

But: My visitors don’t have the first three possibilities, therefore this idea was born.

The code:

OpenHAB Rule

(Double checking variables, otherwise the “fast” reset to zero leads to some errors)
It’s not the final code, i did the test with a Hue lamp,
now it’s another Item used for presence detection

rule "MQTT Button"
when
	Item mqttButton changed
then
    if (mqttButton.state==1 && Hue_Switch_4.state==ON){ 
	Hue_Switch_4.sendCommand(OFF)
	mqttButton.sendCommand(0)}
    if (mqttButton.state==1 && Hue_Switch_4.state==OFF){ 
	Hue_Switch_4.sendCommand(ON)
	mqttButton.sendCommand(0)}
end

Arduino Sketch

/***************************************************
  Adafruit MQTT Button Script by Dominic Spatz

  Must use ESP8266 Arduino from:
    https://github.com/esp8266/Arduino

  Works great with Adafruit's Huzzah ESP board:
  ----> https://www.adafruit.com/product/2471
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Tony DiCola for Adafruit Industries.
  Adafruit IO example additions by Todd Treece.
  MIT license, all text above must be included in any redistribution
 ****************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

// function prototypes
void connect(void);

/****************************** Pins ******************************************/

#define BUTTON          0

/************************* WiFi Access Point *********************************/

#define WLAN_SSID       "WLAN"
#define WLAN_PASS       "Your_super_secret_P4SSW0RD"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "172.20.0.1"
#define AIO_SERVERPORT  1883
#define AIO_USERNAME    "mosquitto"

#define AIO_USER_TOPIC  "MQTT_Button"
#define AIO_KEY         "Openhab"
/************ Global State (you don't need to change this!) ******************/

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;

// Store the MQTT server, client ID, username, and password in flash memory.
// This is required for using the Adafruit MQTT library.
const char MQTT_SERVER[] PROGMEM    = AIO_SERVER;
// Set a unique MQTT client ID using the AIO key + the date and time the sketch
// was compiled (so this should be unique across multiple devices for a user,
// alternatively you can manually set this to a GUID or other random value).
const char MQTT_CLIENTID[] PROGMEM  = AIO_USER_TOPIC;
const char MQTT_USERNAME[] PROGMEM  = AIO_USERNAME;
const char MQTT_PASSWORD[] PROGMEM  = AIO_KEY;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_CLIENTID, MQTT_USERNAME, MQTT_PASSWORD);/****************************** Feeds ***************************************/

// Setup a feed called 'button' for publishing changes.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
const char BUTTON_FEED[] PROGMEM = AIO_USER_TOPIC "/feeds/button";
Adafruit_MQTT_Publish button = Adafruit_MQTT_Publish(&mqtt, BUTTON_FEED);

/*************************** Sketch Code ************************************/

// button state
int current = 0;
int last = -1;

unsigned long buttonPushedMillis; // when button was released
unsigned long ledTurnedOnAt; // when led was turned on
unsigned long turnOnDelay = 500; // wait to turn on LED
unsigned long turnOffDelay = 10000; // turn off LED after this time
bool ledReady = false; // flag for when button is let go
bool ledState = false; // for LED is on or not.

void setup() {

  // set button pin as an input
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(5, OUTPUT);  // declare LED as output
  pinMode(LED_BUILTIN, OUTPUT);  // declare LED as output

  Serial.begin(115200);
  delay(10);
  Serial.print(F("Connecting to "));
  Serial.println(WLAN_SSID);
  for (int i = 0; i < 17; i++){
  if (i % 2) {
  digitalWrite(5, HIGH);
  digitalWrite(LED_BUILTIN, LOW);
  } else {
  digitalWrite(5, LOW);
  digitalWrite(LED_BUILTIN, HIGH);
  }
   delay(200);
  }
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println();

  Serial.println(F("WiFi connected"));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());

  // connect to MQTT
  connect();
}

void loop() {
  // ping adafruit io a few times to make sure we remain connected
  if(! mqtt.ping(3)) {
    // reconnect to adafruit io
    if(! mqtt.connected())
      connect();
  }

  
   // get the time at the start of this loop()
 unsigned long currentMillis = millis(); 

   // make sure this code isn't checked until after button has been let go
 if (ledReady) {
   //this is typical millis code here:
   if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay) {
     // okay, enough time has passed since the button was let go.
     digitalWrite(5, HIGH);
     digitalWrite(LED_BUILTIN, LOW);
     // setup our next "state"
     ledState = true;
     // save when the LED turned on
     ledTurnedOnAt = currentMillis;
     // wait for next button press
     ledReady = false;
   }
 }
  
 // see if we are watching for the time to turn off LED
 if (ledState) {
   // okay, led on, check for now long
   if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
     ledState = false;
     digitalWrite(5, LOW);
     digitalWrite(LED_BUILTIN, HIGH);
   }
 }

  // grab the current state of the button
  current = digitalRead(BUTTON);

  // return if the value hasn't changed
  if(current == last)
    return;

  int32_t value = (current == LOW ? 1 : 0);
 
 // check the button
    if(value==0){
  // update the time when button was pushed
  buttonPushedMillis = currentMillis;
  ledReady = true;
 }
  
  if (! button.publish(value))
    Serial.println(F("Failed."));
  else
    Serial.print(value);
    Serial.println(F(" Success!"));

  // save the button state
  last = current;

}

void connect() {

  Serial.println(F("Connecting to MQTT... "));

  int8_t ret;

  while ((ret = mqtt.connect()) != 0) {

    switch (ret) {
      case 1: Serial.println(F("Wrong protocol")); break;
      case 2: Serial.println(F("ID rejected")); break;
      case 3: Serial.println(F("Server unavail")); break;
      case 4: Serial.println(F("Bad user/pass")); break;
      case 5: Serial.println(F("Not authed")); break;
      case 6: Serial.println(F("Failed to subscribe")); break;
      default: Serial.println(F("Connection failed")); break;
    }

    if(ret >= 0)
      mqtt.disconnect();

    Serial.println(F("Retrying connection..."));
    delay(5000);

  }

  Serial.println(F("MQTT Connected!"));
  Serial.println();

}
2 Likes

Nice gadget :slight_smile:

I own this one (got it from a firefighter as a present, more than 3 decades ago)


It’s a shame I have no space for hanging it yet :wink:
It has an enormous bell inside, coupled with a phone which dials it’s number to the control room in case of emergency - of course it’s 100% mechanic :slight_smile: and 100% functional…

1 Like

Very cool guys!!!

1 Like

When I use this code, the 0 and 1 publishes every time. I haven’t set up open hab to reach to it yet, but I assume it would constantly turn the lights on and off every 10 seconds unless mosquitto is sending a response to update the variables on the huzzah. But your rule doesn’t state that. And the sketch isn’t looking for a response other than the local button. Should I be seeing the 1 success, 0 success message in the console every 10 seconds? The only behavior I do get to change is if I’m holding the button in. Then it does nothing until I let go. But then it just seems the same two messages. This is on the console but in MQTT.fx it reads 1,0 every time. It’s been a while since I’ve worked with arduino, but am I missing something obvious?

Thanks

Thats right, because the item is just for the exact button state (If its pressed, it will stay at one)

It can be done when you use the rule.
It is triggered when the button changes to 1 (which means the button is pressed)
No reaction when the button is set to zero, which is either done by the button or by the rule.

rule "MQTT Button"
when
	Item mqttButton changed
then
    if (mqttButton.state==1 && Hue_Switch_4.state==ON){ 
	Hue_Switch_4.sendCommand(OFF)
	mqttButton.sendCommand(0)}
    if (mqttButton.state==1 && Hue_Switch_4.state==OFF){ 
	Hue_Switch_4.sendCommand(ON)
	mqttButton.sendCommand(0)}
end

But it publishes 1 every loop, so wouldn’t that turn the light off every 10 seconds and then on every other 10 seconds? I’m not trying to be a bother, just can’t understand how it’s working for you.

Never mind. It’s looking for a state change in openhab. Should have paid more attention. Also should eat lunch. Distracted easily when hungry

1 Like

The led in the alarm button is only lit 10s
The state changes only when the button state is changed.
but that was necessary for my setup :slight_smile:

This is a thing of beauty, and exactly what I want to do with my system, only replacing the light switches/fan controls for an ESP8266 in each room.