mensi.ch

Custom firmware for an Athom Smart Plug

I got a couple of Athom Smart Plugs to measure the power consumption of some appliances. They come with either Tasmota or ESPHome pre-flashed. Mine came with ESPHome - but my main goal is to just have them report data via MQTT so I can get it into my InfluxDB + Grafana stack. ESPHome seems to have a philosophy where pretty much only the Wifi credentials are configurable, but something like setting an MQTT server doesn't seem possible.

So I also tried Tasmota by just flashing it via the web-based firmware upgrade which worked without issues. Tasmota however seemed to publish new values to MQTT very infrequently and didn't seem to have any options to change that.

Luckily, it looks like Athom publishes their ESPHome configs on Github, so we don't have to start from scratch.

Customizing the config

Since I only want to publish data to MQTT, I don't need the Homeassistant API, so I removed the api: and dashboard_import: sections. Instead, I added a section for MQTT:

mqtt:
  topic_prefix: smart_plug/some_appliance
  broker: 192.168.1.2
  port: 1883

The broker: IP address is the address of my MQTT broker and topic_prefix: is prepended to the MQTT topics for the measured data.

I also wanted that the relay is always turned on - imagine for example if you use this to measure the power consumption of your freezer - you don't want to accidentally turn it off. So I turned the switch: into an output: like this:

output:
  - platform: gpio
    pin: GPIO12
    id: relay

The power button on the side can also be used to toggle the relay, so I made it toggle the blue LED instead:

    on_multi_click:
      - timing:
        - ON for at most 1s
        - OFF for at least 0.2s
        then:
          - light.toggle: blue_led
      - timing:
        - ON for at least 4s
        then:
          - button.press: Reset

There's also an overcurrent protection. While one could argue that that's a good thing, your circuits in the house should be properly fused and this should be quite redundant. So I simply removed this block:

      on_value_range:
        - above: ${current_limit}
          then:
            - switch.turn_off: relay

Finally, we need to turn our output on when the plug boots. To do so, just append this to the esphome: section:

  on_boot:
    - priority: 90
      then:
      - output.turn_on: relay

Compiling the firmware

ESPHome provides a docker container with all the prerequisites for compiling ESPHome, so we can be lazy and just use that:

$ docker pull ghcr.io/esphome/esphome
$ docker run --rm -v "${PWD}":/config -it ghcr.io/esphome/esphome compile athom-smart-plug-v2.yaml

The compiled firmware will end up in .esphome/build/athom-smart-plug-v2/.pioenvs/athom-smart-plug-v2/firmware.bin

You can flash it via the web UI of your smart plug. In case the firmware is too large, just flash Tasmota's tasmota-minimal.bin firmware first so you have more space available to flash your custom ESPHome firmware.

MQTT data

The topics published to MQTT will look something like this:

smart_plug/some_appliance/sensor/voltage/state 233.4
smart_plug/some_appliance/sensor/current/state 0.00
smart_plug/some_appliance/sensor/power/state 0.0
smart_plug/some_appliance/sensor/total_energy/state 0.000
smart_plug/some_appliance/sensor/total_daily_energy/state 0.000

and more - use mosquitto_sub or your favorite MQTT client to listen to smart_plug/#.

Telegraf

I'm using Telegraf to subscribe to MQTT and push the data into InfluxDB. The config for it looks like this:

[[inputs.mqtt_consumer]]
  servers = ["tcp://192.168.1.2:1883"]
  topics = [
    "smart_plug/+/sensor/power/state",
    "smart_plug/+/sensor/voltage/state",
    "smart_plug/+/sensor/power_factor/state",
    "smart_plug/+/sensor/current/state",
    "smart_plug/+/sensor/apparent_power/state",
    "smart_plug/+/sensor/total_energy/state",
  ]
  data_format="value"
  data_type="float"

  [[inputs.mqtt_consumer.topic_parsing]]
    topic = "smart_plug/+/sensor/+/state"
    measurement = "_/_/_/measurement/_"
    tags = "_/location/_/_/_"

Getting the topic_parsing right was a bit tricky since the documentation on it seemed a bit sparse. The idea is to use measurement and tags to extract parts of the topic to be either the _measurement or a tag for the stored timeseries data.

Final Thoughts

During my research for this project, I found some threads where people were complaining about Athom, basically accusing them of just using Open Source projects like ESPHome or Tasmota and shifting the support burden to those projects instead of supporting the products themselves.

I personally prefer if customizing the behavior of bought hardware is this easy. Instead of spending endless hours on reverse engineering, I was just able to customize their config, compile and flash it in a short amount of time.

On the other hand, it feels like both Tasmota and ESPHome are not terribly user friendly. I don't have much of an issue myself, but I wouldn't want to see any non-techy person trying to do this. So my conclusion would be that I'd want more userfriendlyness in Tasmota/ESPHome rather than trying to make higher barriers for their use.