Receiving Notifications from my Electric Kettle with Tasmota and Home Assistantchain link icon indicating an anchor to a heading

Sometimes, I start my electric kettle with the intention of making tea, but get distracted by some other activity and forget about it until long after it has boiled and cooled down again. Taking my cue from the creators of the first webcam, I decided to solve this problem with technology. Since the kettle determines when the water has boiled and turns itself off, a transition from high to low power draw is an indication that the water is done heating. I combined this fact with a CloudFree smart plug, which runs Tasmota, and Home Assistant to notify me when the kettle boils.

Configuring the Smart Plug

The smart plug is capable of monitoring the current and power draw of its attached device. After connecting it to Home Assistant via WiFi and MQTT (I followed the standard instructions for Tasmota, found here), I investigated its electrical monitoring.

At first, I considered the sensors that automatically appeared in Home Assistant with the Tasmota integration, which include current and power measurements. Unfortunately, these values didn’t seem to update very often; it could be several minutes before Home Assistant was aware that a current change had occurred. This is too slow for an effective notification.

I looked for where these sensor readings were originating and tracked them down to the SENSOR message that Tasmota sends every TelePeriod seconds, which defaults to 300 s (5 minutes). My first thought was to set the TelePeriod to its minimum value, by executing the command TelePeriod 10 at the Tasmota console. This now sent updated current values (among others) to Home Assistant every 10 seconds, but felt inelegant. I’m sure that, on my relatively small network, MQTT messages at that frequency wouldn’t really pose a problem, but I continued to look for a better way.

I eventually discovered the Tasmota current monitoring options, CurrentHigh and CurrentLow, which are set in milliamperes. (There are also equivalent options for low and high power and voltage.) When the current crosses one of these thresholds, a corresponding message is sent out on the MARGINS topic, e.g., when the current rises above the CurrentLow threshold:


Complementarily, when the current falls below the CurrentLow threshold, this message is sent:


Since the state transition I was interested in was “the kettle has boiled,” I decided to use the CurrentLow threshold. I chose the threshold value by running the kettle and inspecting the power draw values in the Tasmota web interface. It measured effectively 0 A when off and around 12 A when on. Setting the threshold to 1 A worked for me, but can be tweaked as necessary: CurrentLow 1000.

Other useful commands for power monitoring are:

  • Status 8 to see the current power values and
  • Status 9 to see the current power monitoring thresholds.

Configuring Home Assistant

Now that the smart plug was sending MQTT messages when the current falls below 1 A, I needed to configure Home Assistant to listen to these messages and take action when they were received.

The Custom Sensor

The MARGINS topic is not monitored by the default Tasmota integration in Home Assistant, so I needed to create a custom binary sensor in the MQTT integration:

# configuration.yaml
      - topic: tele/tasmota_{ID}/LWT
        payload_available: Online
        payload_not_available: Offline
    device_class: running
    icon: mdi:kettle-pour-over
    name: Kettle Running
    # CurrentLow=ON means the kettle is off, so these are reversed
    payload_off: 'ON'
    payload_on: 'OFF'
    state_topic: tele/tasmota_{ID}/MARGINS
    unique_id: {UUID}
    value_template: '{{ value_json["MARGINS"]["CurrentLow"] }}'

The {ID} should be replaced with the ID from your smart plug. The topic names can be found in the MQTT configuration section of the Tasmota web UI. The {UUID} should be replaced with a random UUID; this is used by Home Assistant to disambiguate similar configuration entries.

After making this configuration update, I checked that it was valid by navigating to Developer Tools > YAML in the Home Assistant web UI and choosing “Check Configuration.” Then, since the configuration was indeed valid, I chose “Restart” to restart Home Assistant. Once it came back up, I verified that the new “Kettle Running” sensor appeared under Settings > Devices & Services > Entities.

When I turned the kettle on, the sensor turned on.

The Automation

Now, I just needed to send a notification when the kettle boiled.

I created this automation in the Home Assistant web UI, but have provided the YAML here since it is much easier to share that than a step-by-step description for using the GUI.

alias: Notify When Kettle Finished
description: ''
  - platform: state
    entity_id: binary_sensor.kettle_running
    from: 'on'
    to: 'off'
  - condition: template
    value_template: >-
      {{ ((now() - (trigger.from_state.last_changed or as_datetime(0))) |
      default(timedelta(60))) > timedelta(seconds=30) }}
  - choose:
      - conditions:
          - condition: state
            entity_id: person.scott
            state: home
          - service: notify.mobile_app_scotts_iphone
              message: The kettle has boiled!
    default: []
  - choose:
      - conditions:
          - condition: state
            entity_id: person.someone_else
            state: home
          - service: notify.mobile_app_someone_elses_iphone
              message: The kettle has boiled!
    default: []
  # continue to add actions for any other notifications to send,
  # or any other action you want to take
  # - choose:
  #     - conditions:
  #         etc.
mode: single

This was fairly straightforward to write. The only tricky bit is the top-level value_template condition: I wanted the notification to fire only if the kettle had been heating for more than 30 seconds before turning off. (I didn’t want to get sent a notification if it was already so close to boiling that I didn’t have time to walk away before it boiled again. This was mainly to avoid spamming anyone else on the notification list with a repeated notification.) As always, nested structures in Jinja templates can get confusing, and it took me a few tries to get the parentheses correct. Here is the template broken out in a more readable way:

value_template: >-
      now() - (
        trigger.from_state.last_changed or as_datetime(0)
    ) | default(timedelta(60))
  ) > timedelta(seconds=30)

The idea here is to check when the state change that triggered the automation was last changed (the change before the one that triggered it). last_changed may be None in some cases, so this is guarded against with or as_datetime(0); in such cases, I assumed that it has been “long enough” and so used the epoch time. This protects for falsey last_changed values, but the state could also be undefined, which would result in an error when trying to access its last_changed attribute at all. In order to protect against that, I used the default filter to use a large timedelta so that the condition would be true, again assuming that it has been “long enough.”


And now it’s done! This has been running in my Home Assistant for several months now with no glitches. I’m very happy with these notifications.