Turn on an LED when you leave the house – portable.

More of a proof of concept, the idea was to set up a passive esp-01 that listened for MQTT messages and turned an LED on or off depending on whether or not I am home. Also, I wanted it portable – mostly for testing.

The esp-01 is connected to my mobile that is acting as a wifi “hotspot”. It has been flashed with a sketch via the Arduino IDE that connects it to my MQTT broker and subscribes it to an MQTT topic I called, “home-assistant/amihome”. For the “am i home” functionality, I used “Home Assistant” (hass.io) configured with “OwnTracks“. Home Assistant is a full automation platform and runs on a Raspberry Pi and logs data, triggers actions based on events (MQTT) and much more. OwnTracks is a mobile app that you configure to push your GPS data to your Home Assistant – it integrates with Home Assistant well and is pretty easy to setup. With the two combined, you can now create GPS “zones” that are triggered when your mobile GPS coordinates fall within the zone. The default zone after setting this up is the “home” zone. After configuring Home Assistant and OwnTracks, I am now successfully logging when I am home and when I am not home via GPS and can set automations accordingly. Next, I added a new “automation” function to Home Assistant to publish an MQTT message over the “amihome” topic to update any listening devices with the updates triggered by my mobile GPS – whether or not I am home. Finally, the esp-01 is listening and toggling the LED on/off accordingly.

In the following post, I will retrace my steps on how I set this up.

Things Needed For This Project:

(*info: most links in the list below link to Amazon items through my Amazon Affiliate account. It’s often less expensive to search on eBay if you don’t mind waiting for shipments from China, etc.) :

Hardware Ingredients

1) Get a self-hosted MQTT broker up.

I followed this tutorial excluding the SSL encryption (skip SSL steps 2,3,4 & 6. It’s a little out of date but works – also it’s incredibly easy to do): https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-the-mosquitto-mqtt-messaging-broker-on-ubuntu-16-04

This will set you up with an MQTT broker on a server. I just set mine up on a new VM. You also need to forward port 1883 on your router to access it outside your local network.

2) Flash the esp-01 with a sketch to connect to your mobile wifi and listen to your MQTT broker for messages over the “…/amihome” topic.

The esp8266-01 library has a feature where you can add multiple wifi AP’s, and the device will connect to the strongest signal. I’ll take advantage of that and add both my home wifi login creds and mobile hot-spot creds to the sketch. This way the battery-operated esp-01 can just switch to my mobile wifi as I walk away from my home.

The following is the full sketch to be flashed onto esp8266-01:

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>   // Include the Wi-Fi-Multi library
#include <PubSubClient.h>
 
ESP8266WiFiMulti wifiMulti;     // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'

#define GPIO2 2

### BEGIN Editable Vars
const char* ssid_from_AP_1 = "<HOME-WIFI-SSID>"; // Home
const char* your_password_for_AP_1 = "<HOME-WIFI-PASSWORD>";  // password
const char* ssid_from_AP_2 = "<MOBILE-WIFI-SSID>"; // Mobile
const char* your_password_for_AP_2 = "<MOBILE-WIFI-PASSWORD>";  // password

const char* mqtt_server = "yourdyns.dynu.com"; // mqqt server
const char* mqtt_user = "homeassistant";      
const char* mqtt_password = "<pass>";  
const char* inTopic = "home-assistant/amihome"; // topic esp will subscribe to 

const char* clientId = "amihome"; // MUST BE UNIQUE OR MQTT WILL NOT WORK
### END Editable Vars

WiFiClient espClient;

long lastMsg = 0;
char msg[50];
int value = 0;

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  String theText = "";
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    theText += (char)payload[i];
  }
  Serial.println();
 
  String message = (char*)payload;

  Serial.println("message");
  Serial.println(theText);
 if ((char)payload[0] == '1') {
  digitalWrite(GPIO2, HIGH);
 } else {
  digitalWrite(GPIO2, LOW);
 }

}

PubSubClient client(mqtt_server, 1883, callback, espClient);
 
void setup()
{
  pinMode(GPIO2, OUTPUT);
  Serial.begin(9600);
  wifiMulti.addAP(ssid_from_AP_1, your_password_for_AP_1);   // add Wi-Fi networks you want to connect to
  wifiMulti.addAP(ssid_from_AP_2, your_password_for_AP_2);
  setup_wifi();  
  
}
 
void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting");
  int i = 0;
  while (wifiMulti.run() != WL_CONNECTED) { // Wait for the Wi-Fi to connect: scan for Wi-Fi networks, and connect to the strongest of the networks above
    delay(1000);
    Serial.print('.');
  }
  Serial.println('\n');
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());              // Tell us what network we're connected to
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());           // Send the IP address of the ESP8266 to the computer
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientId, mqtt_user, mqtt_password)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
//      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe(inTopic);
    } 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();
}

Edit the following variables to match your settings:

### BEGIN Editable Vars
const char* ssid_from_AP_1 = "<HOME-WIFI-SSID>"; // Home
const char* your_password_for_AP_1 = "<HOME-WIFI-PASSWORD>";  // password
const char* ssid_from_AP_2 = "<MOBILE-WIFI-SSID>"; // Mobile
const char* your_password_for_AP_2 = "<MOBILE-WIFI-PASSWORD>";  // password

const char* mqtt_server = "yourdyns.dynu.com"; // mqqt server
const char* mqtt_user = "homeassistant";      
const char* mqtt_password = "<pass>";  
const char* inTopic = "home-assistant/amihome"; // topic esp will subscribe to 

const char* clientId = "amihome"; // MUST BE UNIQUE OR MQTT WILL NOT WORK
### END Editable Vars

The above variable settings are pretty straight forward. Just keep in mind that your MQTT broker must be accessible outside your network or else you will not be able to access it from your mobile wifi (open ports and use something like dynu.com).

Test it.

With your esp-01 flashed with the updated sketch, power it up and test it using “mosquitto_pub” on your MQTT broker machine. Like you did in the previous digitalocean.com tutorial on setting up the MQTT broker, send a few test messages out on the “…/amihome” topic to any listening devices – your newly flashed esp-01 should be listening.

[email protected]:~$ mosquitto_pub -h localhost -t home-assistant/amihome -m 1  -u "mqtt-user" -P "mqtt-password"

You can change the “-m” value in the above command from “1” to “0” to filp the on-board esp-01 LED on/off.

If everything worked, the above command should have successfully published an MQTT message over the “home-assistant/amihome” channel to the broker. The newly flashed esp-01 (if powered up and ready) should be connected to wifi and listening to the “…/amihome” channel through the broker and should have received the message payload and toggled the on-board LED accordingly.

That’s pretty much it for hardware! Now you can wire it up and connect an LED to GPIO2.

Here is mine after wiring it up:

esp8266 LED thing wired up
esp8266 LED “amihome” thing wired up.

And here it is powered up with the LED activated (the LED was triggered on by manually publishing an MQTT message as seen previously):

esp8266 LED working.

Success! Now let’s set up a system (Home Assistant) to track specified events and trigger actions accordingly.

3) Setup Home Assistant + OwnTracks to track your GPS location and trigger “automations” if a condition is met (GPS zone trigger).

There are already great resources out there to help you set these things up. Follow the tutorials and come back here to configure Home Assistant:

https://www.home-assistant.io/getting-started/

https://www.home-assistant.io/components/owntracks/

Note: For setting this up, I did not configure OwnTracks to use MQTT for data. I am using unencrypted HTTP (as explained in the tutorial). This is easy to set up so maybe start here and remember to encrypt later.

4) Configure Home Assistant to listen to your self-hosted MQTT broker.

It is important to explore the docs/forums for Home Assistant to understand how to do things but let’s just setup “hass.io” (Home Assistant) to listen to our MQTT broker.

Go to the Home Assistant configuration directory and find the “configuration.yaml” file. This will be the most important file we’ll be working with. Add your MQTT broker info to that file:

mqtt:
  broker: 192.168.1.125
  port: 1883
  username: homeassistant
  password: !secret mqtt_pass

Notice that I used “!secret mqtt_pass” rather than my clear text password. This is a convenient way to keep all your creds out of configuration files. Let’s continue with this workflow.

Open up “secrets.yaml” and add your password there:

mqtt_pass: thisismypassword

5) Add an “automation” function to the configuration to send MQTT messages based on whether or not I am home.

Now that Home Assistant is wired up to the MQTT broker, we need to add an “automation” function that ties into whether or not I am home and triggers an action accordingly.

In the “configuration.yaml” we edited previously, add something like this (updating the values to fit your setup):

automation 1:
- alias: Justin is gone - turn on LED # Update this
  trigger:
    platform: state
    entity_id: device_tracker.justin_motoe4 # Update this
    from: 'home'
    to: 'not_home'
    
  action:
    service: mqtt.publish
    data_template:
      topic: home-assistant/amihome
      payload: "1"

- alias: Justin is home - turn off LED # Update this
  trigger:
    platform: state
    entity_id: device_tracker.justin_motoe4 # Update this
    from: 'not_home'
    to: 'home'

  action:
    service: mqtt.publish
    data_template:
      topic: home-assistant/amihome
      payload: "0"

The main value that needs to be edited in the above is:

entity_id: device_tracker.justin_motoe4

Replace that with the value of your mobile devices’ “entity_id” that was made in Home Assistant when you set up OwnTracks.

Now that everything is set up, these new automations should be triggered by your GPS location as you leave/enter your “home” zone. The “automation 1” function we added triggers actions that we defined to publish an MQTT message over the “home-assistant/amihome” channel with a payload of either “1” or “0” depending on whether or not I am home. Finally, my esp-01 device is powered on and listening for MQTT messages to act accordingly. Everything is ready.

Here is a screengrab of Home Assistant and some recent activity with everything working:

Home Assistant UI

Again, here it is on a walk with the pupper:

Conclusion

The esp8266 and “Home Assistant” are a great pair. Configured with “OwnTracks” to track your location (for triggering zone automations) is just amazing. Making the device portable by powering it by battery makes testing much easier.

Leave a Reply

Your email address will not be published. Required fields are marked *