Hi cttime,
Glad to hear you like my solution. I’ll try to explain in more detail how I’ve set things up.
My two Mitsubishi heat pumps are controlled via ESPHome using Wemos D1 minis connected to the serial port inside the heat pumps. Very cute with no noticeable hardware visible on the outside.
Below in an example for one of them:
substitutions:
devicename: Hallway heat pump
esphome:
name: hallway-heat-pump
platform: ESP8266
board: d1_mini
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Hallway Heat Pump"
password: "-"
captive_portal:
# Enable logging
logger:
# ESP8266 only - disable serial port logging, as the HeatPump component
# needs the sole hardware UART on the ESP8266
baud_rate: 0
# Enable Home Assistant API
api:
services:
- service: set_remote_temperature
variables:
temperature: float
then:
- lambda: 'id(hp).set_remote_temperature(temperature);'
- service: use_internal_temperature
then:
- lambda: 'id(hp).set_remote_temperature(0);'
ota:
# Enable Web server.
web_server:
port: 80
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
# Text sensors with general information.
text_sensor:
# Expose ESPHome version as sensor.
- platform: version
name: ${devicename} version
# Expose WiFi information as sensors.
- platform: wifi_info
ip_address:
name: ${devicename} ip
ssid:
name: ${devicename} ssid
bssid:
name: ${devicename} bssid
# Sensors with general information.
sensor:
# Uptime sensor.
- platform: uptime
name: ${devicename} uptime
# WiFi Signal sensor.
- platform: wifi_signal
name: ${devicename} wifi signal
update_interval: 60s
external_components:
- source: github://geoffdavis/esphome-mitsubishiheatpump
climate:
- platform: mitsubishi_heatpump
name: ${devicename}
id: hp
switch:
- platform: restart
name: ${devicename} restart
The heat pump get the readback value from a remote sensor that I can select from a drop down list in HA using an input_select in configuration.yaml. I’ve fallen in love with the Aqara Zigbee temperature sensors powered by 2032 cells. They last 12-18 months on one battery.
input_select:
hallway_heat_pump_sensor:
name: Hallway heat pump sensor
options:
- Bedroom
- Kitchen
- Library
- Living room
- Guest room 1
- Guest room 2
The input_select controls which sensor that should be used as feedback for the PID loop of the heat pump. I’ve created a few template sensors for the heat pump that is useful.
- platform: template
sensors:
hallway_heat_pump_hvac_action:
friendly_name: "Hallway heat pump action"
value_template: "{{ state_attr('climate.hallway_heat_pump', 'hvac_action') }}"
availability_template: >
{{states('climate.hallway_heat_pump') not in ['unknown','unavailable']}}
hallway_heat_pump_current_temperature:
friendly_name: "Hallway heat pump current temperature"
unit_of_measurement: "°C"
value_template: "{{ state_attr('climate.hallway_heat_pump', 'current_temperature') }}"
availability_template: >
{{states('climate.hallway_heat_pump') not in ['unknown','unavailable']}}
hallway_heat_pump_sensor:
unit_of_measurement: "°C"
value_template: >
{% if is_state('input_select.hallway_heat_pump_sensor', 'Bedroom') %}
{{ states('sensor.bedroom_temperature') }}
{% elif is_state('input_select.hallway_heat_pump_sensor', 'Kitchen') %}
{{ states('sensor.kitchen_temperature') }}
{% elif is_state('input_select.hallway_heat_pump_sensor', 'Library') %}
{{ states('sensor.library_temperature') }}
{% elif is_state('input_select.hallway_heat_pump_sensor', 'Living room') %}
{{ states('sensor.living_room_temperature') }}
{% elif is_state('input_select.hallway_heat_pump_sensor', 'Guest room 1') %}
{{ states('sensor.guest_room_1_temperature') }}
{% elif is_state('input_select.hallway_heat_pump_sensor', 'Guest room 2') %}
{{ states('sensor.guest_room_2_temperature') }}
{% endif %}
availability_template: >
{% set items = ['sensor.bedroom_temperature', 'sensor.kitchen_temperature', 'sensor.library_temperature', 'sensor.living_room_temperature', 'sensor.guest_room_1_temperature', 'sensor.guest_room_2_temperature'] %}
{{expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count}}
The heat pumps need to get updated values from the selected temperature sensors via an automation:
alias: Update heat pumps external sensors
description: ""
trigger:
- platform: time_pattern
minutes: /1
condition: []
action:
- service: esphome.hallway_heat_pump_set_remote_temperature
data_template:
temperature: "{{states.sensor.hallway_heat_pump_sensor.state}}"
- service: esphome.recreation_room_heat_pump_set_remote_temperature
data_template:
temperature: "{{states.sensor.recreation_room_heat_pump_sensor.state}}"
mode: single
I’ve created a setpoint for the heat pumps using a helper in Lovelace.
I use the input_number setpoint to manipulate the ESPHome integration for the heat pumps using the price level and 5 automations. The example below is for when it is very expensive in which case I lower the setpoint by 1.0 degrees.
alias: Heat pump - Very expensive
description: ""
trigger:
- platform: state
entity_id:
- sensor.electricity_price_level
to: VERY_EXPENSIVE
- platform: state
entity_id:
- input_number.hallway_heat_pump_setpoint
- input_number.recreation_room_heat_pump_setpoint
condition:
- condition: state
entity_id: sensor.electricity_price_level
state: VERY_EXPENSIVE
action:
- service: climate.set_temperature
data:
temperature: "{{ states('input_number.hallway_heat_pump_setpoint') | float -1.0 }}"
target:
entity_id: climate.hallway_heat_pump
- service: climate.set_temperature
data:
temperature: >-
{{ states('input_number.recreation_room_heat_pump_setpoint') | float
-1.0 }}
target:
entity_id: climate.recreation_room_heat_pump
mode: single
The elecricity price level sensor is using the Nordpool integration sensor and is defined as below:
- platform: template
sensors:
electricity_price_level:
friendly_name: "Electricity price level"
value_template: >-
{% set price_cur = states('sensor.nordpool_kwh_se3_sek_3_10_025') | float(0) %}
{% set price_avg = state_attr('sensor.nordpool_kwh_se3_sek_3_10_025', 'average') | float(0) %}
{% if price_cur == 0 or price_avg == 0 %}
unknown
{% else %}
{% set price_ratio = (price_cur / price_avg) %}
{% if price_ratio >= 1.4 %}
VERY_EXPENSIVE
{% elif price_ratio >= 1.15 %}
EXPENSIVE
{% elif price_ratio <= 0.6 %}
VERY_CHEAP
{% elif price_ratio <= 0.9 %}
CHEAP
{% else %}
NORMAL
{% endif %}
{% endif %}
availability_template: >
{{states('sensor.nordpool_kwh_se3_sek_3_10_025') not in ['unknown','unavailable']}}
My user interface has setpoints for the heat pumps as shown below:
And I can monitor how the price level affect the HVAC state during the day and how the climate varies over time:
I also have automations that detect if we use our fireplaces and automatically switch our heat pumps to fan mode to keep circulating the air instead of just turning off when the temperature goes up.
The two fire place automations for the hallway pump are shown below:
alias: >-
Switch hallway heat pump from heating to fan only if (current temperature -
setpoint) > 2 degrees
description: ""
trigger:
- platform: template
value_template: >-
{% if not state_attr('climate.hallway_heat_pump',
'current_temperature')|float(default=0) and
state_attr('climate.hallway_heat_pump', 'temperature')|float(default=0) %}
False
{% else %}
{{ (state_attr('climate.hallway_heat_pump', 'current_temperature')|float(default=0) - state_attr('climate.hallway_heat_pump', 'temperature')|float(default=0)) > 2 }}
{% endif %}
condition:
- condition: state
entity_id: climate.hallway_heat_pump
state: idle
attribute: hvac_action
- condition: state
entity_id: input_boolean.hallway_fireplace_automation
state: "on"
action:
- service: climate.set_hvac_mode
data:
hvac_mode: fan_only
target:
entity_id:
- climate.hallway_heat_pump
mode: single
and
alias: >-
Switch hallway heat pump from fan only to heating if (current temperature -
setpoint) < 2 degrees
description: ""
trigger:
- platform: template
value_template: >-
{% if not state_attr('climate.hallway_heat_pump',
'current_temperature')|float(default=0) and
state_attr('climate.hallway_heat_pump', 'temperature')|float(default=0) %}
False
{% else %}
{{ (state_attr('climate.hallway_heat_pump', 'current_temperature')|float(default=0) - state_attr('climate.hallway_heat_pump', 'temperature')|float(default=0)) < 2 }}
{% endif %}
condition:
- condition: state
entity_id: climate.hallway_heat_pump
state: fan
attribute: hvac_action
- condition: state
entity_id: input_boolean.hallway_fireplace_automation
state: "on"
action:
- service: climate.set_hvac_mode
data:
hvac_mode: heat
target:
entity_id:
- climate.hallway_heat_pump
mode: single
The heat pump for the recreation room has identical automations to handle the basement fireplace.
I hope this help you towards adapting it for your purposes. Let me know if anything is unclear or if you find an improvement that you want to share!
Warmly, Per