Two of the features which most impressed me of the Particle Photon were its built-in WiFi, and the possibility of updating the device over the air (OTA). However, using a Photon as, say, a simple temperature sensor is quite expensive at over EUR 23.00 when purchased here.

Dirt cheap in comparison is one of the ESP family of microcontrollers and development boards, and I ordered a few so-called NodeMCU dev kits (right in photo at EUR 3.89 a piece) and Wemos D1 (center, at EUR 3.63 per unit). I have not made a mistake on the price tags; they even include postage and handling from China. All we need is a fortnight’s patience. (And while waiting you find that the adorable Wemos-D1 has a boat-load of shields which you should also have ordered … :-)

Wemos-D1 and NodeMCU

Both of these are based on the ESP8266, and as such they have on-board WiFi. The NodeMCU can be flashed with firmware which supports the Lua programming language (or even BASIC I hear). I’ve settled on using an environment I’m more or less comfortable with, namely the Arduino for ESP8266 firmware which is trivial to install through the Arduino IDE.

These little microcontrollers just work, but what is a bit of a chore is having to invent boilerplate code which enables reconnection, reboot on error, etc.

I stumbled over a project called homie-esp8266 created by Marvin Roger. It’s basically a small framework which couples the ESP8266 to MQTT and provides automatic connection/reconnection handling, JSON configuration, an optional Web UI to configure the microcontroller which starts up in Access Point mode initially, and Over-The-Air support for updating the code I create for the ESP8266. Yes: OTA support, and TLS.

Martin has obviously carefully thought about how a device should interact with its environment, and the code reflects this. So, as an example, when one of my sensors launches, it will publish these retained MQTT messages:

sensors/homie/cf3a07e0/$nodes light:light,temperature:temperature,relay:relay
sensors/homie/cf3a07e0/$online true
sensors/homie/cf3a07e0/$name Livingroom bookshelf
sensors/homie/cf3a07e0/$fwname h-sensor
sensors/homie/cf3a07e0/$fwversion 1.0.1
sensors/homie/cf3a07e0/temperature/unit c
sensors/homie/cf3a07e0/$signal 96
sensors/homie/cf3a07e0/temperature/degrees 23.38

$nodes inform the consumer about the type of endpoints I’ve made available on the device. $online indicates whether the device is currently alive, $name is a description I initially assign to the device, $signal is an indication of WiFi coverage as seen by the microcontroller, etc. Then the device starts publishing a temperature and whatever other sensor data I wish to make available from the device.

The homie-esp8266 framework also listens for messages: for example, I can switch a relay I have connected to a Wemos-D1 with the following command:

mosquitto_pub -t 'sensors/homie/cf3a07e0/relay/on/set' -m true

The code I create for the device is invoked when Homie receives above publish, and it can then do something, e.g. switch the relay on, and instruct Homie to note that the action occurred, whereupon Homie will publish a retained value indicating the current state to (note the missing /set at the end of this topic):

sensors/homie/cf3a07e0/relay/on true

Using the homie-esp8266 framework makes this trivial to do:

#include <Homie.h>

#define RELAY_PIN 16

HomieNode relayNode("relay", "relay");

bool relayHandler(String message)
    if (message == "true") {
        digitalWrite(RELAY_PIN, HIGH);
        Homie.setNodeProperty(relayNode, "on", "true");
    } else if (message == "false") {
        digitalWrite(RELAY_PIN, LOW);
        Homie.setNodeProperty(relayNode, "on", "false");
    } else {
        return false;

    return true;

void setup()
    pinMode(RELAY_PIN, OUTPUT);
    digitalWrite(RELAY_PIN, LOW);

    Homie.setFirmware("h-sensor", "1.0.1");
    relayNode.subscribe("on", relayHandler);

void loop()

I mentioned above that Homie, can be configured via a Web-based interface when a device initially starts (to be quite clear: the site in the screenshot justs hosts the HTML to talk to your Homie ESP; the device itself doesn’t talk to the cloud):


Once that is done, the device connects to the WiFi network you specify during configuration, and starts operating on that. Alternatively, we can upload a JSON configuration file to the flash file system on the device or create that programatically (which is what I did, using a small sketch). The great advantage of storing the configuration separately from the actual Homie firmware is I can reflash (for example OTA) a different sketch onto the device and it will use the previous configuration settings (e.g. for MQTT broker, port, etc.).

OTA updates are triggered by publishing a version number to the $ota endpoint; Homie then verifies the version it’s received is higher than the one it’s running, and instructs the ESP to boot and get the update via HTTP/HTTPS. (How this works is rather well explained here.) I think it’s important to mention that the homie-esp8266 framework is cloudless; it doesn’t require a cloud service, and it talks exactly to the servers you configure it to speak to.

Homie’s documentation is good and plentiful, and there are examples to get us started quickly. Marvin has been tremendously helpful, and he very quickly implemented the possibility to define a base_topic for MQTT publishes when I asked him to.

A stamp-sized chip with on-board WiFi and 4MB of flash which speaks MQTT over TLS and can be updated OTA for under EUR 4.00. Exciting times.

Further reading:

MQTT and IoT :: 22 Mar 2016 :: e-mail