Receiving Notifications from my Electric Kettle with Tasmota and Home Assistant
Receiving Notifications from my Electric Kettle with Tasmota and Home Assistant
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 …
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:
{"MARGINS":{"CurrentLow":"OFF"}}
Complementarily, when the current falls below the CurrentLow
threshold, this message is sent:
{"MARGINS":{"CurrentLow":"ON"}}
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 andStatus 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
mqtt:
binary_sensor:
availability:
- 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: ''
trigger:
- platform: state
entity_id: binary_sensor.kettle_running
from: 'on'
to: 'off'
condition:
- condition: template
value_template: >-
{{ ((now() - (trigger.from_state.last_changed or as_datetime(0))) |
default(timedelta(60))) > timedelta(seconds=30) }}
action:
- choose:
- conditions:
- condition: state
entity_id: person.scott
state: home
sequence:
- service: notify.mobile_app_scotts_iphone
data:
message: The kettle has boiled!
default: []
- choose:
- conditions:
- condition: state
entity_id: person.someone_else
state: home
sequence:
- service: notify.mobile_app_someone_elses_iphone
data:
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.”
Conclusion
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.