various tidyups and esphome adds

This commit is contained in:
root
2026-02-16 22:13:42 +13:00
parent d7884770fe
commit 83e4040b84
16 changed files with 2251 additions and 113 deletions
-95
View File
@@ -1,95 +0,0 @@
# input_select for dropdown menu to select the timer duration or cancel
input_select:
master_bedroom_climate_timer_duration:
name: Master Bedroom Aircon Sleep
options:
- "1 hour"
- "2 hours"
- "3 hours"
- "Cancel sleep timer"
initial: "Cancel sleep timer"
icon: mdi:timer-outline
# Single timer for managing the countdown
timer:
master_bedroom_climate_timer:
name: Master Bedroom Aircon Timer
duration: "00:00:00" # Initial duration; will be set dynamically
# Automation to start or cancel the timer based on the dropdown selection
automation:
- alias: "Start or Cancel Master Bedroom Climate Timer"
trigger:
- platform: state
entity_id: input_select.master_bedroom_climate_timer_duration
action:
- service: timer.cancel
entity_id: timer.master_bedroom_climate_timer
- choose:
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "1 hour"
sequence:
- service: timer.start
data:
entity_id: timer.master_bedroom_climate_timer
duration: "01:00:00"
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "1 minute"
sequence:
- service: timer.start
data:
entity_id: timer.master_bedroom_climate_timer
duration: "00:01:00"
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "2 hours"
sequence:
- service: timer.start
data:
entity_id: timer.master_bedroom_climate_timer
duration: "02:00:00"
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "3 hours"
sequence:
- service: timer.start
data:
entity_id: timer.master_bedroom_climate_timer
duration: "03:00:00"
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "Cancel sleep timer"
sequence:
- service: timer.cancel
entity_id: timer.master_bedroom_climate_timer
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
# Automation to turn off the climate entity when the timer finishes
- alias: "Turn Off Master Bedroom Climate on Timer Completion"
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.master_bedroom_climate_timer
action:
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
- service: input_select.select_option
data:
entity_id: input_select.master_bedroom_climate_timer_duration
option: "Cancel sleep timer" # Reset to the initial value
@@ -0,0 +1,120 @@
# ------------------------------
# TIMER HELPER (define in YAML so it definitely exists)
# ------------------------------
timer:
master_bedroom_climate_timer:
name: Master Bedroom Climate Timer
duration: "00:00:00"
# ------------------------------
# DROPDOWN (sleep timer)
# ------------------------------
input_select:
master_bedroom_climate_timer_duration:
name: Master Bedroom Aircon Sleep
options:
- "1 hour"
- "2 hours"
- "3 hours"
- "6 hours"
- "Cancel timer"
initial: "Cancel timer"
icon: mdi:timer-outline
# ------------------------------
# LIVE REMAINING (updates immediately on selection, and every minute)
# ------------------------------
template:
- trigger:
# Update once per minute (suits hh:mm display)
- platform: time_pattern
minutes: "/1"
# Update when timer STATE changes (idle/active/paused)
- platform: state
entity_id: timer.master_bedroom_climate_timer
# Update immediately when user changes the dropdown
- platform: state
entity_id: input_select.master_bedroom_climate_timer_duration
sensor:
- name: "Master Bedroom Climate Timer Remaining"
unique_id: master_bedroom_climate_timer_remaining
icon: mdi:timer
state: >-
{% set st = states('timer.master_bedroom_climate_timer') | lower %}
{% if st == 'idle' %}
0:00
{% else %}
{% set fa = state_attr('timer.master_bedroom_climate_timer', 'finishes_at') %}
{% if fa %}
{% set end = as_datetime(fa) %}
{% set sec = (end - now()).total_seconds() | int(0) %}
{% if sec < 0 %}{% set sec = 0 %}{% endif %}
{% set hh = (sec // 3600) | int %}
{% set mm = ((sec % 3600) // 60) | int %}
{{ hh }}:{{ '%02d' | format(mm) }}
{% else %}
0:00
{% endif %}
{% endif %}
# ------------------------------
# AUTOMATION: start/cancel timer when dropdown changes
# ------------------------------
automation:
- alias: "Start or Cancel Master Bedroom Climate Timer"
mode: restart
trigger:
- platform: state
entity_id: input_select.master_bedroom_climate_timer_duration
variables:
opt: "{{ states('input_select.master_bedroom_climate_timer_duration') }}"
dur_map:
"1 hour": "01:00:00"
"2 hours": "02:00:00"
"3 hours": "03:00:00"
"6 hours": "06:00:00"
action:
- choose:
- conditions:
- condition: template
value_template: "{{ opt in dur_map }}"
sequence:
- service: timer.cancel
target:
entity_id: timer.master_bedroom_climate_timer
- delay: "00:00:01"
- service: timer.start
target:
entity_id: timer.master_bedroom_climate_timer
data:
duration: "{{ dur_map[opt] }}"
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "Cancel timer"
sequence:
- service: timer.cancel
target:
entity_id: timer.master_bedroom_climate_timer
- alias: "Turn Off Master Bedroom Climate on Timer Completion"
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.master_bedroom_climate_timer
action:
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_climate_timer_duration
data:
option: "Cancel timer"
+17
View File
@@ -0,0 +1,17 @@
input_boolean:
moon_phase_percent_overlay:
name: Moon phase percent overlay
icon: mdi:percent
script:
moon_phase_percent_overlay_10s:
alias: Moon phase percent overlay (10s)
mode: restart
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.moon_phase_percent_overlay
- delay: "00:00:10"
- service: input_boolean.turn_off
target:
entity_id: input_boolean.moon_phase_percent_overlay
+115
View File
@@ -0,0 +1,115 @@
input_boolean:
downstairs_flat_occupied:
name: Downstairs Guest Occupied
icon: mdi:briefcase-plus-outline
script:
downstairs_light_toggle_lounge_main:
alias: Downstairs Light Toggle - Lounge Main Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstloungemain_relay_1_main_lights
downstairs_light_toggle_lounge_back_wall:
alias: Downstairs Light Toggle - Lounge Back Wall Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstloungemain_relay_2_back_wall_lights
downstairs_light_toggle_main_bedroom_main:
alias: Downstairs Light Toggle - Main Bedroom Main Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstmasterbedrmlights_relay_1_main_lights
downstairs_light_toggle_small_bedroom_main:
alias: Downstairs Light Toggle - Small Bedroom Room Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstbedrm2lights_relay_1_main_lights
downstairs_light_toggle_kitchen:
alias: Downstairs Light Toggle - Kitchen Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstkitchlights_relay_2_kitchen_light
downstairs_light_toggle_dining:
alias: Downstairs Light Toggle - Dining Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstkitchlights_relay_1_dining_light
downstairs_light_toggle_bathroom_main:
alias: Downstairs Light Toggle - Bathroom Main Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstbathswitch_relay_1_main_lights
downstairs_light_toggle_bathroom_cabinet:
alias: Downstairs Light Toggle - Bathroom Cabinet Lights
mode: queued
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- service: switch.toggle
target:
entity_id: switch.esp_downstbathswitch_relay_2_cabinet_light
downstairs_light_toggle_all_group:
alias: Downstairs Lights - All On/Off
mode: single
sequence:
- condition: state
entity_id: input_boolean.downstairs_flat_occupied
state: "off"
- choose:
- conditions:
- condition: state
entity_id: group.downstairs_flat_lights
state: "on"
sequence:
- service: homeassistant.turn_off
target:
entity_id: group.downstairs_flat_lights
default:
- service: homeassistant.turn_on
target:
entity_id: group.downstairs_flat_lights
+34
View File
@@ -62,3 +62,37 @@ automation:
"1hr top-up now":"boost", "Charge now until full":"now-full", "Stop charging now":"stop" } %} {% set dta = trigger.to_state.state %}
{{ mapping[dta] }}
'
template:
- trigger:
# Update at least every 10 seconds (and also on HA start)
- platform: time_pattern
seconds: "/10"
- platform: homeassistant
event: start
binary_sensor:
- name: "32A EV Charger Charging"
unique_id: ev_charger_32a_charging
icon: mdi:car-electric
state: >-
{{ (states('sensor.32a_ev_wallcharger_power') | float(0)) > 0.1 }}
delay_on:
seconds: 60
delay_off:
seconds: 60
- name: "16A EV Charger Charging"
unique_id: ev_charger_16a_charging
icon: mdi:car-electric
state: >-
{{ (states('sensor.16a_ev_wallcharger_power') | float(0)) > 0.1 }}
delay_on:
seconds: 60
delay_off:
seconds: 60
- binary_sensor:
- name: 32A EV Charger Charging UI
unique_id: ev_charger_charging_ui
state: "{{ is_state('sensor.32a_ev_charger_charging', 'on') }}"
icon: mdi:car-electric
-4
View File
@@ -1,4 +0,0 @@
input_boolean:
foxhole_occupied:
name: Foxhole Guest Occupied
icon: mdi:briefcase-plus-outline
+309
View File
@@ -0,0 +1,309 @@
##########################################################################################
# heat_pump_helpers.yaml
#
# Panasonic Comfort Cloud (panasonic_cc) helpers for Heat/Cool control + presets.
#
# Purpose:
# - Provide "optimistic" UI feedback for cloud/slow mode changes
# - Provide one-tap scripts for Off/Heat/Cool/Dehumid
# - Provide a 3-step "Profile" cycler (Normal/Boost/Quiet) using preset_mode:
# * preset_mode: boost -> Powerful ON (we label this "Boost")
# * preset_mode: eco -> Quiet ON (we label this "Quiet")
# * preset_mode: none -> Powerful OFF + Quiet OFF (we label this "Normal")
#
# Notes:
# - Your climate entity supports preset_modes: [none, eco, boost]
# - The switch.lounge_ai_eco entity appears to be read-only (cannot be controlled),
# so "Eco" and "Eco/Quiet" profiles have been removed.
# - When turning the heat pump OFF, we also force preset_mode to "none" so that
# Boost/Quiet are cleared.
##########################################################################################
input_select:
# Used by your dashboard buttons to "light up" instantly (optimistic state).
# When set to something other than "none", the UI can treat that as "pending".
master_bedroom_hvac_requested_mode:
name: Master Bedroom HVAC Requested Mode
options:
- "none"
- "off"
- "heat"
- "cool"
- "dry"
initial: "none"
# Heat pump profile selector shown on the dashboard and cycled with one tap.
master_bedroom_heat_pump_profile:
name: Master Bedroom Heat Pump Profile
options:
- Normal
- Boost
- Quiet
initial: Normal
script:
########################################################################################
# One-tap HVAC mode scripts
# These set the optimistic helper first, then call the real climate services.
#
# IMPORTANT:
# - Off also clears Boost/Quiet by forcing preset_mode to "none".
########################################################################################
master_bedroom_hvac_off:
alias: Master Bedroom HVAC - Off
mode: restart
sequence:
# Optimistic UI: show "Off" immediately
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "off"
# Turn the unit off (more reliable than set_hvac_mode off on many cloud integrations)
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
# Clear Panasonic preset flags: none = Boost OFF + Quiet OFF
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "none"
master_bedroom_hvac_heat:
alias: Master Bedroom HVAC - Heat
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "heat"
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_hvac_mode
target:
entity_id: climate.master_bedroom
data:
hvac_mode: "heat"
master_bedroom_hvac_cool:
alias: Master Bedroom HVAC - Cool
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "cool"
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_hvac_mode
target:
entity_id: climate.master_bedroom
data:
hvac_mode: "cool"
master_bedroom_hvac_dry:
alias: Master Bedroom HVAC - Dehumid
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "dry"
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_hvac_mode
target:
entity_id: climate.master_bedroom
data:
hvac_mode: "dry"
########################################################################################
# Profile logic: Apply + Cycle
#
# Profile definitions (Panasonic CC / panasonic_cc):
# - Normal -> preset_mode none (Boost OFF, Quiet OFF)
# - Boost -> preset_mode boost (Powerful ON)
# - Quiet -> preset_mode eco (Quiet ON)
#
# The profile selector is kept in-sync with the actual preset_mode via automation.
########################################################################################
master_bedroom_heat_pump_profile_apply:
alias: Master Bedroom Heat Pump - Apply Profile
mode: restart
fields:
profile:
description: Profile name (Normal, Boost, Quiet)
example: Normal
sequence:
- variables:
p: "{{ profile | default(states('input_select.master_bedroom_heat_pump_profile')) }}"
preset_for_profile: >-
{% if p == 'Normal' %}none
{% elif p == 'Boost' %}boost
{% elif p == 'Quiet' %}eco
{% else %}none
{% endif %}
# Optional: ensure the unit is on when applying a profile.
# Comment out if you want profile selection while the unit is off.
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
# Set preset explicitly every time so Boost/Quiet are mutually exclusive
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "{{ preset_for_profile }}"
master_bedroom_heat_pump_profile_next:
alias: Master Bedroom Heat Pump - Next Profile
mode: restart
sequence:
- variables:
cur: "{{ states('input_select.master_bedroom_heat_pump_profile') }}"
nxt: >-
{% if cur == 'Normal' %}Boost
{% elif cur == 'Boost' %}Quiet
{% else %}Normal
{% endif %}
# Store the new selection (UI)
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_heat_pump_profile
data:
option: "{{ nxt }}"
# Apply it to the heat pump
- service: script.turn_on
target:
entity_id: script.master_bedroom_heat_pump_profile_apply
data:
variables:
profile: "{{ nxt }}"
automation:
########################################################################################
# Clear "requested mode" once the climate entity catches up, so the UI reflects reality.
# This prevents two mode buttons appearing lit due to stale cloud attributes.
########################################################################################
- id: master_bedroom_hvac_clear_requested_mode
alias: Master Bedroom HVAC - Clear Requested Mode
mode: restart
trigger:
- platform: state
entity_id: climate.master_bedroom
- platform: state
entity_id: input_select.master_bedroom_hvac_requested_mode
to:
- "off"
- "heat"
- "cool"
- "dry"
condition:
- condition: template
value_template: >
{{ states('input_select.master_bedroom_hvac_requested_mode') != 'none' }}
action:
# Small delay to allow the cloud integration to reflect the change
- delay: "00:00:03"
- choose:
- conditions:
- condition: template
value_template: >
{% set req = states('input_select.master_bedroom_hvac_requested_mode') %}
{% set mode = states('climate.master_bedroom') %}
{% set action = (state_attr('climate.master_bedroom','hvac_action') or '') %}
{{ (req == 'off' and (mode == 'off' or action == 'off'))
or (req in ['heat','cool','dry'] and mode == req) }}
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "none"
default:
# Failsafe: if the cloud entity is slow or ambiguous, clear after a while anyway
- delay: "00:00:25"
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "none"
########################################################################################
# Sync the Profile selector from actual device preset_mode (including changes made in
# the Panasonic app). This keeps the UI truthful.
#
# Mapping:
# - preset boost -> Boost
# - preset eco -> Quiet
# - preset none -> Normal
########################################################################################
- id: master_bedroom_heat_pump_profile_sync_from_entities
alias: Master Bedroom Heat Pump - Sync Profile From Entities
mode: restart
trigger:
- platform: state
entity_id: climate.master_bedroom
action:
- delay: "00:00:02"
- variables:
preset: "{{ state_attr('climate.master_bedroom', 'preset_mode') or 'none' }}"
new_profile: >-
{% if preset == 'boost' %}
Boost
{% elif preset == 'eco' %}
Quiet
{% else %}
Normal
{% endif %}
- choose:
- conditions:
- condition: template
value_template: "{{ states('input_select.master_bedroom_heat_pump_profile') != new_profile }}"
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_heat_pump_profile
data:
option: "{{ new_profile }}"
template:
- sensor:
- name: Master Bedroom Heat Pump Profile Tile
unique_id: master_bedroom_heat_pump_profile_tile
state: "{{ states('input_select.master_bedroom_heat_pump_profile') }}"
icon: >
{% set p = states('input_select.master_bedroom_heat_pump_profile') %}
{% if p == 'Boost' %}
mdi:rocket-launch
{% elif p == 'Quiet' %}
mdi:leaf
{% else %}
mdi:gauge
{% endif %}
@@ -0,0 +1,480 @@
##########################################################################################
# heat_pump_master_bedroom_helpers.yaml
#
# Master Bedroom Panasonic Comfort Cloud Heat Pump Helpers
#
# Combines:
# - Setpoint helpers (optimistic cloud control)
# - HVAC mode helpers (Off / Heat / Cool / Dry)
# - Profile logic (Normal / Boost / Quiet)
# - Sleep timer system
# - Sync automations
#
# Designed for:
# climate.master_bedroom (Panasonic Comfort Cloud)
#
##########################################################################################
##########################################################################################
# TIMER (Sleep Timer Entity)
##########################################################################################
timer:
master_bedroom_climate_timer:
name: Master Bedroom Climate Timer
duration: "00:00:00"
##########################################################################################
# INPUT HELPERS
##########################################################################################
input_select:
# Sleep timer dropdown
master_bedroom_climate_timer_duration:
name: Master Bedroom Aircon Sleep
options:
- "1 hour"
- "2 hours"
- "3 hours"
- "6 hours"
- "Cancel timer"
initial: "Cancel timer"
icon: mdi:timer-outline
# Optimistic requested HVAC mode (used by dashboard buttons)
master_bedroom_hvac_requested_mode:
name: Master Bedroom HVAC Requested Mode
options:
- "none"
- "off"
- "heat"
- "cool"
- "dry"
initial: "none"
# Heat pump profile selector
master_bedroom_heat_pump_profile:
name: Master Bedroom Heat Pump Profile
options:
- Normal
- Boost
- Quiet
initial: Normal
input_number:
# Optimistic UI setpoint helper
master_bedroom_setpoint_ui:
name: Master Bedroom Setpoint UI
min: 10
max: 30
step: 0.5
mode: box
unit_of_measurement: "°C"
icon: mdi:thermometer
##########################################################################################
# TEMPLATE SENSORS
##########################################################################################
template:
############################################################################
# Sleep Timer Remaining (HH:MM display)
############################################################################
- trigger:
- platform: time_pattern
minutes: "/1"
- platform: state
entity_id:
- timer.master_bedroom_climate_timer
- input_select.master_bedroom_climate_timer_duration
sensor:
- name: "Master Bedroom Climate Timer Remaining"
unique_id: master_bedroom_climate_timer_remaining
icon: mdi:timer
state: >-
{% set st = states('timer.master_bedroom_climate_timer') | lower %}
{% if st == 'idle' %}
0:00
{% else %}
{% set fa = state_attr('timer.master_bedroom_climate_timer', 'finishes_at') %}
{% if fa %}
{% set end = as_datetime(fa) %}
{% set sec = (end - now()).total_seconds() | int(0) %}
{% if sec < 0 %}{% set sec = 0 %}{% endif %}
{% set hh = (sec // 3600) | int %}
{% set mm = ((sec % 3600) // 60) | int %}
{{ hh }}:{{ '%02d' | format(mm) }}
{% else %}
0:00
{% endif %}
{% endif %}
############################################################################
# Profile tile sensor (for dashboard icon)
############################################################################
- sensor:
- name: Master Bedroom Heat Pump Profile Tile
unique_id: master_bedroom_heat_pump_profile_tile
state: "{{ states('input_select.master_bedroom_heat_pump_profile') }}"
icon: >
{% set p = states('input_select.master_bedroom_heat_pump_profile') %}
{% if p == 'Boost' %}
mdi:rocket-launch
{% elif p == 'Quiet' %}
mdi:leaf
{% else %}
mdi:gauge
{% endif %}
##########################################################################################
# SCRIPTS
##########################################################################################
script:
############################################################################
# SETPOINT SYNC (cloud → UI helper)
############################################################################
master_bedroom_setpoint_sync_from_climate:
alias: Master Bedroom Setpoint Sync From Climate
mode: restart
sequence:
- variables:
sp: "{{ state_attr('climate.master_bedroom', 'temperature') | float(0) }}"
- service: input_number.set_value
target:
entity_id: input_number.master_bedroom_setpoint_ui
data:
value: "{{ sp }}"
############################################################################
# SETPOINT ADJUST (Chevron buttons)
############################################################################
master_bedroom_setpoint_adjust:
alias: Master Bedroom Setpoint Adjust
mode: queued
fields:
step:
description: "Step in degrees C, e.g. -0.5 or 0.5"
example: -0.5
sequence:
- condition: template
value_template: >
{% set s = states('climate.master_bedroom') | lower %}
{{ s not in ['off','unavailable','unknown','none',''] }}
- variables:
cur_ui: "{{ states('input_number.master_bedroom_setpoint_ui') | float(0) }}"
cur_cl: "{{ state_attr('climate.master_bedroom', 'temperature') | float(0) }}"
cur: "{{ cur_ui if cur_ui > 0 else cur_cl }}"
raw: "{{ cur + (step | float(0)) }}"
new: "{{ [30, [10, raw] | max] | min | round(1) }}"
- service: input_number.set_value
target:
entity_id: input_number.master_bedroom_setpoint_ui
data:
value: "{{ new }}"
- service: climate.set_temperature
target:
entity_id: climate.master_bedroom
data:
temperature: "{{ new }}"
############################################################################
# HVAC MODE SCRIPTS
############################################################################
master_bedroom_hvac_off:
alias: Master Bedroom HVAC - Off
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "off"
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "none"
master_bedroom_hvac_heat:
alias: Master Bedroom HVAC - Heat
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "heat"
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_hvac_mode
target:
entity_id: climate.master_bedroom
data:
hvac_mode: "heat"
master_bedroom_hvac_cool:
alias: Master Bedroom HVAC - Cool
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "cool"
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_hvac_mode
target:
entity_id: climate.master_bedroom
data:
hvac_mode: "cool"
master_bedroom_hvac_dry:
alias: Master Bedroom HVAC - Dehumid
mode: restart
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "dry"
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_hvac_mode
target:
entity_id: climate.master_bedroom
data:
hvac_mode: "dry"
############################################################################
# PROFILE SCRIPTS
############################################################################
master_bedroom_heat_pump_profile_apply:
alias: Master Bedroom Heat Pump - Apply Profile
mode: restart
fields:
profile:
description: Profile name (Normal, Boost, Quiet)
sequence:
- variables:
p: "{{ profile | default(states('input_select.master_bedroom_heat_pump_profile')) }}"
preset_for_profile: >-
{% if p == 'Normal' %}none
{% elif p == 'Boost' %}boost
{% elif p == 'Quiet' %}eco
{% else %}none
{% endif %}
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "{{ preset_for_profile }}"
master_bedroom_heat_pump_profile_next:
alias: Master Bedroom Heat Pump - Next Profile
mode: restart
sequence:
- variables:
cur: "{{ states('input_select.master_bedroom_heat_pump_profile') }}"
nxt: >-
{% if cur == 'Normal' %}Boost
{% elif cur == 'Boost' %}Quiet
{% else %}Normal
{% endif %}
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_heat_pump_profile
data:
option: "{{ nxt }}"
- service: script.turn_on
target:
entity_id: script.master_bedroom_heat_pump_profile_apply
data:
variables:
profile: "{{ nxt }}"
##########################################################################################
# AUTOMATIONS
##########################################################################################
automation:
############################################################################
# Sleep Timer Start / Cancel
############################################################################
- alias: "Start or Cancel Master Bedroom Climate Timer"
mode: restart
trigger:
- platform: state
entity_id: input_select.master_bedroom_climate_timer_duration
variables:
opt: "{{ states('input_select.master_bedroom_climate_timer_duration') }}"
dur_map:
"1 hour": "01:00:00"
"2 hours": "02:00:00"
"3 hours": "03:00:00"
"6 hours": "06:00:00"
action:
- choose:
- conditions:
- condition: template
value_template: "{{ opt in dur_map }}"
sequence:
- service: timer.cancel
target:
entity_id: timer.master_bedroom_climate_timer
- delay: "00:00:01"
- service: timer.start
target:
entity_id: timer.master_bedroom_climate_timer
data:
duration: "{{ dur_map[opt] }}"
- conditions:
- condition: state
entity_id: input_select.master_bedroom_climate_timer_duration
state: "Cancel timer"
sequence:
- service: timer.cancel
target:
entity_id: timer.master_bedroom_climate_timer
############################################################################
# Turn off heat pump when timer finishes
############################################################################
- alias: "Turn Off Master Bedroom Climate on Timer Completion"
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.master_bedroom_climate_timer
action:
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_climate_timer_duration
data:
option: "Cancel timer"
############################################################################
# Sync setpoint from climate → UI helper
############################################################################
- id: master_bedroom_setpoint_sync
alias: Master Bedroom Setpoint Sync
mode: restart
trigger:
- platform: state
entity_id: climate.master_bedroom
- platform: homeassistant
event: start
action:
- service: script.master_bedroom_setpoint_sync_from_climate
############################################################################
# Clear requested HVAC mode when cloud catches up
############################################################################
- id: master_bedroom_hvac_clear_requested_mode
alias: Master Bedroom HVAC - Clear Requested Mode
mode: restart
trigger:
- platform: state
entity_id: climate.master_bedroom
- platform: state
entity_id: input_select.master_bedroom_hvac_requested_mode
to: ["off", "heat", "cool", "dry"]
condition:
- condition: template
value_template: >
{{ states('input_select.master_bedroom_hvac_requested_mode') != 'none' }}
action:
- delay: "00:00:03"
- choose:
- conditions:
- condition: template
value_template: >
{% set req = states('input_select.master_bedroom_hvac_requested_mode') %}
{% set mode = states('climate.master_bedroom') %}
{% set action = (state_attr('climate.master_bedroom','hvac_action') or '') %}
{{ (req == 'off' and (mode == 'off' or action == 'off'))
or (req in ['heat','cool','dry'] and mode == req) }}
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "none"
default:
- delay: "00:00:25"
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_hvac_requested_mode
data:
option: "none"
############################################################################
# Sync Profile from actual preset_mode
############################################################################
- id: master_bedroom_heat_pump_profile_sync_from_entities
alias: Master Bedroom Heat Pump - Sync Profile From Entities
mode: restart
trigger:
- platform: state
entity_id: climate.master_bedroom
action:
- delay: "00:00:02"
- variables:
preset: "{{ state_attr('climate.master_bedroom', 'preset_mode') or 'none' }}"
new_profile: >-
{% if preset == 'boost' %}
Boost
{% elif preset == 'eco' %}
Quiet
{% else %}
Normal
{% endif %}
- choose:
- conditions:
- condition: template
value_template: "{{ states('input_select.master_bedroom_heat_pump_profile') != new_profile }}"
sequence:
- service: input_select.select_option
target:
entity_id: input_select.master_bedroom_heat_pump_profile
data:
option: "{{ new_profile }}"
@@ -0,0 +1,218 @@
##########################################################################################
# heat_pump_master_bedroom_schedules.yaml
##########################################################################################
##########################################################################################
# HELPERS
##########################################################################################
input_boolean:
master_bedroom_night_power_mode:
name: Night Power Mode
icon: mdi:weather-night
master_bedroom_9pm_on:
name: 9pm On
icon: mdi:clock-start
master_bedroom_midnight_off:
name: Midnight Off
icon: mdi:clock-end
master_bedroom_boost_restore_off:
name: Master Bedroom Boost Restore Off
icon: mdi:power
##########################################################################################
# TIMERS
##########################################################################################
timer:
master_bedroom_boost_timer:
name: Master Bedroom Boost Timer
duration: "00:00:00"
##########################################################################################
# SCRIPTS
##########################################################################################
script:
master_bedroom_boost_1hr:
alias: Master Bedroom Boost 1hr
mode: restart
sequence:
# Remember if the heat pump was OFF when boost started
- service: input_boolean.turn_off
target:
entity_id: input_boolean.master_bedroom_boost_restore_off
- choose:
- conditions:
- condition: state
entity_id: climate.master_bedroom
state: "off"
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.master_bedroom_boost_restore_off
# Start boost (this will turn it on if it was off)
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "boost"
- service: timer.start
target:
entity_id: timer.master_bedroom_boost_timer
data:
duration: "01:00:00"
##########################################################################################
# AUTOMATIONS
##########################################################################################
automation:
##########################################################################################
# CANCEL LOGIC
##########################################################################################
- alias: MB Cancel Others When Night Power Enabled
trigger:
- platform: state
entity_id: input_boolean.master_bedroom_night_power_mode
to: "on"
action:
- service: input_boolean.turn_off
target:
entity_id:
- input_boolean.master_bedroom_9pm_on
- input_boolean.master_bedroom_midnight_off
- alias: MB Cancel Night Power If 9pm On Enabled
trigger:
- platform: state
entity_id: input_boolean.master_bedroom_9pm_on
to: "on"
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.master_bedroom_night_power_mode
- alias: MB Cancel Night Power If Midnight Off Enabled
trigger:
- platform: state
entity_id: input_boolean.master_bedroom_midnight_off
to: "on"
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.master_bedroom_night_power_mode
##########################################################################################
# 9PM LOGIC
##########################################################################################
- alias: MB 9PM Start Logic
trigger:
- platform: time
at: "21:00:00"
action:
- choose:
- conditions:
- condition: state
entity_id: input_boolean.master_bedroom_night_power_mode
state: "on"
sequence:
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "boost"
- service: timer.start
target:
entity_id: timer.master_bedroom_boost_timer
data:
duration: "00:30:00"
- conditions:
- condition: state
entity_id: input_boolean.master_bedroom_9pm_on
state: "on"
sequence:
- service: climate.turn_on
target:
entity_id: climate.master_bedroom
##########################################################################################
# MIDNIGHT LOGIC
##########################################################################################
- alias: MB Midnight Off Logic
trigger:
- platform: time
at: "00:00:00"
action:
- choose:
- conditions:
- condition: or
conditions:
- condition: state
entity_id: input_boolean.master_bedroom_midnight_off
state: "on"
- condition: state
entity_id: input_boolean.master_bedroom_night_power_mode
state: "on"
sequence:
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
##########################################################################################
# BOOST TIMER FINISHED
##########################################################################################
- alias: MB Boost Timer Finished
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.master_bedroom_boost_timer
action:
- choose:
# If boost started while the heat pump was OFF, ensure it ends OFF
- conditions:
- condition: state
entity_id: input_boolean.master_bedroom_boost_restore_off
state: "on"
sequence:
- service: climate.turn_off
target:
entity_id: climate.master_bedroom
# Otherwise, revert to Normal (preset_mode none) and keep running
- conditions:
- condition: state
entity_id: input_boolean.master_bedroom_boost_restore_off
state: "off"
sequence:
- service: climate.set_preset_mode
target:
entity_id: climate.master_bedroom
data:
preset_mode: "none"
# Always clear the helper
- service: input_boolean.turn_off
target:
entity_id: input_boolean.master_bedroom_boost_restore_off
@@ -0,0 +1,76 @@
input_number:
master_bedroom_setpoint_ui:
name: Master Bedroom Setpoint UI
min: 10
max: 30
step: 0.5
mode: box
unit_of_measurement: "°C"
icon: mdi:thermometer
script:
master_bedroom_setpoint_sync_from_climate:
alias: Master Bedroom Setpoint Sync From Climate
mode: restart
sequence:
- variables:
sp: "{{ state_attr('climate.master_bedroom', 'temperature') | float(0) }}"
- service: input_number.set_value
target:
entity_id: input_number.master_bedroom_setpoint_ui
data:
value: "{{ sp }}"
master_bedroom_setpoint_adjust:
alias: Master Bedroom Setpoint Adjust
mode: queued
fields:
step:
description: "Step in degrees C, e.g. -0.5 or 0.5"
example: -0.5
sequence:
# ─────────────────────────────
# GUARD: only block when climate is OFF/unavailable/unknown
# (Do NOT use hvac_action == idle - Panasonic cloud often reports idle)
# ─────────────────────────────
- condition: template
value_template: >
{% set s = states('climate.master_bedroom') | lower %}
{{ s not in ['off', 'unavailable', 'unknown', 'none', ''] }}
# ─────────────────────────────
# Compute new setpoint
# Prefer UI helper if valid, otherwise use climate temp
# ─────────────────────────────
- variables:
cur_ui: "{{ states('input_number.master_bedroom_setpoint_ui') | float(0) }}"
cur_cl: "{{ state_attr('climate.master_bedroom', 'temperature') | float(0) }}"
cur: "{{ cur_ui if cur_ui > 0 else cur_cl }}"
raw: "{{ cur + (step | float(0)) }}"
new: "{{ [30, [10, raw] | max] | min | round(1) }}"
# Update UI immediately
- service: input_number.set_value
target:
entity_id: input_number.master_bedroom_setpoint_ui
data:
value: "{{ new }}"
# Send to climate (cloud may lag)
- service: climate.set_temperature
target:
entity_id: climate.master_bedroom
data:
temperature: "{{ new }}"
automation:
- id: master_bedroom_setpoint_sync
alias: Master Bedroom Setpoint Sync
mode: restart
trigger:
- platform: state
entity_id: climate.master_bedroom
- platform: homeassistant
event: start
action:
- service: script.master_bedroom_setpoint_sync_from_climate
View File
+121 -9
View File
@@ -1,3 +1,11 @@
##########################################################################################
# MASTER BEDROOM FAN (Tasmota / Sonoff iFan02)
# Improvements:
# - Numeric speed entity (0-3) reflecting actual device state via MQTT
# - Button to cycle speed 1,2,3,0
# - Keep input_select in sync with actual FanSpeed (incl after reboots)
##########################################################################################
input_select:
master_bedroom_fan_set:
name: Master Bedroom Fan Speed
@@ -24,21 +32,121 @@ input_select:
- "Medium"
- "High"
##########################################################################################
# MASTER BEDROOM FAN - Helpers
##########################################################################################
input_number:
master_bedroom_fan_speed_numeric:
name: Master Bedroom Fan Speed (Numeric)
min: 0
max: 3
step: 1
mode: box
template:
- button:
- name: Bedroom 1 Fan Speed Change
unique_id: bedroom_1_fan_speed_change
icon: mdi:fan
press:
- variables:
cur: "{{ states('input_number.master_bedroom_fan_speed_numeric') | int(0) }}"
nxt: "{{ (cur + 1) if (cur < 3) else 0 }}"
- service: mqtt.publish
data:
topic: cmnd/tasmo-ifan02-3793-bedrm1-1/FanSpeed
payload: "{{ nxt }}"
# Optimistic local update (MQTT will correct if needed)
- service: input_number.set_value
data:
entity_id: input_number.master_bedroom_fan_speed_numeric
value: "{{ nxt }}"
- service: input_select.select_option
data:
entity_id: input_select.master_bedroom_fan_set
option: >-
{% set m = {0:'Off',1:'Low',2:'Medium',3:'High'} %}
{{ m[nxt] }}
automation:
########################################################################################
# MASTER BEDROOM FAN - Query on HA start (fixes wrong value after reboots)
########################################################################################
- id: master_bedroom_fan_query_on_ha_start
initial_state: true
alias: Master Bedroom Fan - Query FanSpeed on HA Start
trigger:
- platform: homeassistant
event: start
action:
- service: mqtt.publish
data:
topic: cmnd/tasmo-ifan02-3793-bedrm1-1/FanSpeed
payload: ""
########################################################################################
# MASTER BEDROOM FAN - Sync helpers from Tasmota MQTT
########################################################################################
- id: master_bedroom_fan_sync_from_mqtt
initial_state: true
alias: Master Bedroom Fan - Sync Helpers From MQTT FanSpeed
trigger:
- platform: mqtt
topic: stat/tasmo-ifan02-3793-bedrm1-1/RESULT
- platform: mqtt
topic: tele/tasmo-ifan02-3793-bedrm1-1/STATE
condition:
- condition: template
value_template: "{{ trigger.payload_json is defined and (trigger.payload_json.FanSpeed is defined) }}"
action:
- variables:
spd: "{{ trigger.payload_json.FanSpeed | int(0) }}"
opt: >-
{% set m = {0:'Off',1:'Low',2:'Medium',3:'High'} %}
{{ m[spd] }}
- service: input_number.set_value
data:
entity_id: input_number.master_bedroom_fan_speed_numeric
value: "{{ spd }}"
# Only update dropdown if it differs (avoid loops)
- condition: template
value_template: "{{ states('input_select.master_bedroom_fan_set') != opt }}"
- service: input_select.select_option
data:
entity_id: input_select.master_bedroom_fan_set
option: "{{ opt }}"
########################################################################################
# MASTER BEDROOM FAN - Set speed from dropdown (improved)
########################################################################################
- id: set_the_master_bedroom_fan
initial_state: true
alias: Set the Master Bedroom Fan
trigger:
entity_id: input_select.master_bedroom_fan_set
platform: state
- platform: state
entity_id: input_select.master_bedroom_fan_set
variables:
desired: >-
{% set mapping = { 'Off':0, 'Low':1, 'Medium':2, 'High':3 } %}
{{ mapping.get(trigger.to_state.state, 0) }}
current: "{{ states('input_number.master_bedroom_fan_speed_numeric') | int(0) }}"
condition:
- condition: template
value_template: "{{ desired != current }}"
action:
service: mqtt.publish
data:
topic: cmnd/tasmo-ifan02-3793-bedrm1-1/FanSpeed
payload: '{% set mapping = { "Off":"0", "Low":"1",
"Medium":"2", "High":"3" } %} {% set dta = trigger.to_state.state %}
{{ mapping[dta] }}
'
- service: mqtt.publish
data:
topic: cmnd/tasmo-ifan02-3793-bedrm1-1/FanSpeed
payload: "{{ desired }}"
# Optimistic local update (MQTT will correct if needed)
- service: input_number.set_value
data:
entity_id: input_number.master_bedroom_fan_speed_numeric
value: "{{ desired }}"
########################################################################################
# BEDROOM 2 FAN - Unchanged
########################################################################################
- id: set_bedroom_2_fan
initial_state: true
alias: Set Bedroom 2 Fan Speed
@@ -53,6 +161,10 @@ automation:
"Medium":"2", "High":"3" } %} {% set dta = trigger.to_state.state %}
{{ mapping[dta] }}
'
########################################################################################
# BEDROOM 3 FAN - Unchanged
########################################################################################
- id: set_bedroom_3_fan
initial_state: true
alias: Set Bedroom 3 Fan Speed