Hi there. I’m often posting on these forums with questions and now feels like the time to give back to the community that has given so much. Below is a write up of a how I turned my cheap, dumb electric blanket into a Wifi, temperature controlled bed warmer.
Bill of materials
- Cheap electric blanket that can be turned on and off via the power outlet.
- Mirabella Genio Wifi power switch
- Xiaomi Aqara temperature sensor (zigbee)
My Home Assistant setup
- Home Assistant supervised on Ubuntu 18.04
- Deconz conbee II, running from Home Assistant add-on
- ESPHome
Step 1: Flash your Mirabella Genio Wifi Switch with ESPHome/tuyaconvert
I won’t go into how to flash this, as it’s been explained to death in other posts and YouTube videos. Here’s my yaml for it:
esphome:
name: electric_blanket
platform: ESP8266
board: esp01_1m
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: xxx
password: xxx
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
binary_sensor:
- platform: gpio
pin:
number: GPIO13
mode: INPUT_PULLUP
inverted: true
name: "Electric Blanket Power Button"
on_press:
- switch.toggle: relay
- platform: status
name: Status
switch:
- platform: gpio
id: red_led
pin:
number: GPIO4
inverted: true
- platform: gpio
name: "Electric Blanket Switch"
pin: GPIO12
id: relay
# Turn on red LED
on_turn_on:
- switch.turn_on: red_led
# Turns off red LED
on_turn_off:
- switch.turn_off: red_led
restore_mode: RESTORE_DEFAULT_OFF
Step 2: Make an input_number for your thermostat input
This is driven off an input_number which takes user input for the value of the thermostat. This takes away the need to hardcode the thresholds and gives anyone the opportunity to change the value.
input_number:
electric_blanket_thermostat_set:
name: Electric Blanket Thermostat
min: 15
max: 30
mode: slider
unit_of_measurement: °
icon: mdi:thermostat
Step 3: Make an input_boolean for when the thermostat is active
I chose to use an input_boolean to drive the script being run. This acts as a validation to make sure the script only runs when triggered from the automation.
input_boolean:
electric_blanket_on:
name: Electric Blanket On
I also chose to add in a holiday mode switch, so this wouldn’t turn on if I’m away from home for a while.
input_boolean:
holiday_mode:
name: Holiday Mode
icon: mdi:beach
Step 4: Automate your thermostat script trigger
What I did here was make an automation which triggers at 8:30pm, which is enough time to warm the bed before we hit the hay every night. It also only works when we’re home and not on holidays. This triggers a script loop, which I’ll explain in the next step.
- alias: Electric blanket trigger
trigger:
- platform: time
at: '20:30'
- platform: state
entity_id: group.us
to: 'home'
- platform: state
entity_id: input_number.electric_blanket_thermostat_set
condition:
- condition: state
entity_id: group.us
state: home
- condition: state
entity_id: input_boolean.holiday_mode
state: 'off'
- condition: time
after: '20:30'
before: '22:59'
- condition: numeric_state
entity_id: sensor.bed_temperature
below: input_number.electric_blanket_thermostat_set
action:
- service: switch.turn_on
entity_id: switch.electric_blanket_switch
- service: input_boolean.turn_on
entity_id: input_boolean.electric_blanket_on
- service: script.turn_on
entity_id: script.electric_blanket_thermostat_off
Step 5: Create script loop to turn the blanket on and off
Starting with the script that’s triggered from the automation above, this script uses a wait_template to wait for the bed’s temperature to reach the temperature specified in the input_number, to then switch the electric blanket off.
electric_blanket_thermostat_off:
alias: Thermostat off
icon: mdi:thermostat-box
sequence:
- condition: state
entity_id: input_boolean.electric_blanket_on
state: 'on'
- wait_template: "{{ states('sensor.bed_temperature') | float > states('input_number.electric_blanket_thermostat_set') | float }}"
- service: switch.turn_off
entity_id: switch.electric_blanket_switch
- wait_template: "{{ states('sensor.bed_temperature') | float < states('input_number.electric_blanket_thermostat_set') | float }}"
- service: script.turn_on
entity_id: script.electric_blanket_thermostat_on
It’ll then wait for the bed’s temperature to drop below the specified value, before calling the script that turns the blanket back on.
electric_blanket_thermostat_on:
alias: Thermostat on
icon: mdi:thermostat-box
sequence:
- condition: state
entity_id: input_boolean.electric_blanket_on
state: 'on'
- wait_template: "{{ states('sensor.bed_temperature') | float < states('input_number.electric_blanket_thermostat_set') | float }}"
- service: switch.turn_on
entity_id: switch.electric_blanket_switch
- wait_template: "{{ states('sensor.bed_temperature') | float > states('input_number.electric_blanket_thermostat_set') | float }}"
- service: script.turn_on
entity_id: script.electric_blanket_thermostat_off
These two scripts will continue to loop between each other until the input_boolean.electric_blanket_on is turned off, which I do when I go to bed via my goodnight routine.
Step 6 (Optional): Automate a kill switch
I’ve added a kill-switch to stop the blanket from turning on after 11pm.
- alias: Electric blanket kill switch
trigger:
- platform: time
at: '23:00'
action:
- service: switch.turn_off
entity_id: switch.electric_blanket_switch
- service: script.turn_off
entity_id: script.electric_blanket_on, script.electric_blanket_off
- service: input_boolean.turn_off
entity_id: input_boolean.electric_blanket_on
Conclusion
Hopping into a temperature-controlled bed makes a huge difference to your night’s sleep and this gives you an energy-saving and smart way to make sure you put your best sleep forward!
This is just one of many ways to achieve this outcome. You could probably make this much simpler by making automations that trigger based on the drop and rise of the temperature. However, I prefer this method, as I’m given a bit more control over how it works. Let me know if you have any other ideas!