Automating ESP8266 Firmware Deployments

Not too long ago I wrote about ESPHomeYAML – a YAML based firmware generator for microcontrollers. What if I told you that you can use this tool to automatically update your entire fleet of ESP8266-based home automation IoT devices from one central server?

The tool itself allows you to define your microcontroller firmware declaratively using a YAML configuration file. It generates C++ source code on the fly and compile it into a firmware.bin file and upload it to the controller over the air.

Most devices on my network run the same firmware that only differ by a device identifier to be used in Home Assistant. The software to control simple relays and temperature sensors is so simple that it can be defined declaratively in YAML. This YAML definition in turn, can be generated on the fly from input paramters (a template) and compiled/uploaded in bulk.

Deployment from central server Running the script allows automatic over-the-air deployment of ESP8266 micro-controller firmwares to a fleet of IoT devices.

I wrote a Python script which takes a list of devices (and their specific properties) as input, generates a YAML firmware definition file, and then calls the esphomeyaml temp_config.yaml run --no-logs command to compile and upload the firmware to the device. The devices.yaml input file looks like this:

devices:
  - id: table_lamp
    name: "Table Lamp"
  - id: tv_led_strip
  - id: bedroom_socket_switch

The Python script loops through each device in the configuration file and performs what would otherwise be a manual process of creating and substituting in values for each device:

import yaml;
import io;
import os;

def replace(device):
    # Read in the file
    with open('configuration.yaml', 'r') as file :
      filedata = file.read()

    # Replace the target string
    filedata = filedata.replace('<light_id>', device['id'])
    
    # Write the file out again
    with open('temp_config.yaml', 'w') as file:
      file.write(filedata)

# Read YAML file
with open("devices.yaml", 'r') as stream:
    data_loaded = yaml.load(stream)

for device in data_loaded['devices']:
    print(device)
    replace(device)
    os.system('esphomeyaml temp_config.yaml run --no-logs')

You can define your own variables to be substituted in your ESPHomeYAML configuration file depending on your need. In my case, I only substitute the string <light_id> with the id field.

Using this script allows you to implement and push updates to your entire fleet of IoT devices from a central location. You could even perform this as part of a cron job or a Home Assistant automation to keep the firmware updated and patched from security vulnerabilities.

Update: I can not recommend this method any more. Just flash the Tasmota firmware, which is much more stable, feature-rich and reliable.