additional esphome devices and fixes
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm1airfilter.yaml
|
||||
#:########################################################################################:#
|
||||
# VERSIONS:
|
||||
# V1.3 2026-04-29 Added restored fan speed so the selected fan speed is remembered
|
||||
# and re-applied after reboot.
|
||||
# V1.2 2026-04-27 Converted filter replacement logic from pulse-count based to kRevs based.
|
||||
# Added editable Replacement Threshold number in kRevs.
|
||||
# Added Reset Replacement Threshold button to restore default 19000 kRevs.
|
||||
@@ -81,7 +83,7 @@ substitutions:
|
||||
|
||||
# Project Naming
|
||||
project_name: "Generic.D1 Mini" # Project Details
|
||||
project_version: "v1.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
||||
project_version: "v1.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
||||
|
||||
# Passwords and Secrets
|
||||
api_key: !secret esp-api_key
|
||||
@@ -177,6 +179,18 @@ esphome:
|
||||
|
||||
# Restore Clean/Dirty state and warning LEDs.
|
||||
- script.execute: update_filter_state
|
||||
# Re-apply the restored fan speed after boot.
|
||||
# The template number restores its value, but this forces the actual
|
||||
# MOSFET/PWM output state to match the restored Home Assistant value.
|
||||
- delay: 1s
|
||||
- number.set:
|
||||
id: fan_speed
|
||||
value: !lambda |-
|
||||
if (isnan(id(fan_speed).state)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return id(fan_speed).state;
|
||||
|
||||
#:########################################################################################:#
|
||||
# ESP PLATFORM AND FRAMEWORK:
|
||||
@@ -297,11 +311,12 @@ button:
|
||||
number:
|
||||
# Slider for Fan Speed 0-6, 0 = Off, 6 = Max
|
||||
- platform: template
|
||||
name: "${friendly_name} Fan Speed"
|
||||
name: "${friendly_name} Speed Level"
|
||||
id: fan_speed
|
||||
icon: mdi:air-filter
|
||||
update_interval: never
|
||||
optimistic: true
|
||||
restore_value: true
|
||||
min_value: 0
|
||||
max_value: 6
|
||||
initial_value: 0
|
||||
|
||||
@@ -264,7 +264,7 @@ preferences:
|
||||
flash_write_interval: 5min
|
||||
|
||||
mdns:
|
||||
disabled: false
|
||||
disabled: true
|
||||
|
||||
##########################################################################################
|
||||
# GLOBAL VARIABLES
|
||||
@@ -696,7 +696,7 @@ text_sensor:
|
||||
return std::string("At Temperature");
|
||||
}
|
||||
if (id(led_standby_red).state) return std::string("Standby");
|
||||
return std::string("Off");
|
||||
return std::string("Standby");
|
||||
on_value:
|
||||
- script.execute: publish_status
|
||||
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
###############################################################################
|
||||
# Bedroom 1 Ikea Air Filter Package
|
||||
# File: /config/packages/bedroom_1_ikea_air_filter.yaml
|
||||
# Version: 1.0
|
||||
# Date: 2026-04-29
|
||||
#
|
||||
# Purpose:
|
||||
# - Creates a dropdown helper called "Bedroom 1 Ikea Fan".
|
||||
# - Auto mode controls the Bedroom 1 Ikea air filter speed by priority.
|
||||
# - Manual dropdown modes set a fixed fan speed and disable auto control.
|
||||
#
|
||||
# Auto priority order:
|
||||
# 1. Quiet time on: fan speed 2
|
||||
# 2. Bedside light on: fan speed 2
|
||||
# 3. Free power time, 21:00 to midnight: fan speed 5
|
||||
# 4. Daytime, 09:00 to 15:00: fan speed 4
|
||||
# 5. Default: fan speed 2
|
||||
###############################################################################
|
||||
|
||||
input_select:
|
||||
bedroom_1_ikea_fan:
|
||||
name: "Bedroom 1 Ikea Fan"
|
||||
icon: mdi:fan
|
||||
options:
|
||||
- "Auto"
|
||||
- "Off"
|
||||
- "High"
|
||||
- "Medium"
|
||||
- "Low"
|
||||
- "Quiet"
|
||||
|
||||
script:
|
||||
bedroom_1_ikea_air_filter_set_speed_if_needed:
|
||||
alias: "Bedroom 1 Ikea Air Filter - Set Speed If Needed"
|
||||
description: >
|
||||
Sets the Bedroom 1 Ikea air filter speed only when the requested speed
|
||||
is different from the current speed.
|
||||
mode: queued
|
||||
fields:
|
||||
target_speed:
|
||||
name: "Target speed"
|
||||
description: "Fan speed level from 0 to 6."
|
||||
example: 2
|
||||
sequence:
|
||||
- variables:
|
||||
fan_speed_entity: number.bedroom_1_air_filter_bedroom_1_air_filter_speed_level
|
||||
fan_current_speed: "{{ states(fan_speed_entity) | float(-1) }}"
|
||||
fan_target_speed: "{{ target_speed | float }}"
|
||||
|
||||
- condition: template
|
||||
value_template: "{{ fan_current_speed != fan_target_speed }}"
|
||||
|
||||
- action: number.set_value
|
||||
target:
|
||||
entity_id: number.bedroom_1_air_filter_bedroom_1_air_filter_speed_level
|
||||
data:
|
||||
value: "{{ fan_target_speed | int }}"
|
||||
|
||||
automation:
|
||||
- id: bedroom_1_ikea_air_filter_auto_control
|
||||
alias: "Bedroom 1 Ikea Air Filter - Auto Control"
|
||||
description: >
|
||||
Automatically controls the Bedroom 1 Ikea air filter speed when the
|
||||
Bedroom 1 Ikea Fan dropdown is set to Auto.
|
||||
mode: restart
|
||||
triggers:
|
||||
# Re-apply the correct speed after Home Assistant restarts.
|
||||
- trigger: homeassistant
|
||||
event: start
|
||||
|
||||
# Highest priority condition.
|
||||
- trigger: state
|
||||
entity_id: input_boolean.quiet_time
|
||||
|
||||
# Bedside lamp should force low speed while on.
|
||||
- trigger: state
|
||||
entity_id: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb
|
||||
|
||||
# Main timing boundaries.
|
||||
- trigger: time
|
||||
at:
|
||||
- "00:00:00"
|
||||
- "09:00:00"
|
||||
- "15:00:00"
|
||||
- "21:00:00"
|
||||
|
||||
# Safety/re-check trigger, especially for the bedside lamp rule.
|
||||
- trigger: time_pattern
|
||||
minutes: "/10"
|
||||
|
||||
conditions:
|
||||
# Manual dropdown modes disable automatic control.
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "Auto"
|
||||
|
||||
actions:
|
||||
- variables:
|
||||
auto_target_speed: >-
|
||||
{% if is_state('input_boolean.quiet_time', 'on') %}
|
||||
2
|
||||
{% elif is_state('light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb', 'on') %}
|
||||
2
|
||||
{% elif now().hour >= 21 %}
|
||||
5
|
||||
{% elif now().hour >= 9 and now().hour < 15 %}
|
||||
4
|
||||
{% else %}
|
||||
2
|
||||
{% endif %}
|
||||
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: "{{ auto_target_speed | int }}"
|
||||
|
||||
- id: bedroom_1_ikea_air_filter_dropdown_control
|
||||
alias: "Bedroom 1 Ikea Air Filter - Dropdown Control"
|
||||
description: >
|
||||
Handles the Bedroom 1 Ikea Fan dropdown. Auto enables the automatic
|
||||
control automation. Manual modes disable automatic control and set
|
||||
the requested fixed speed.
|
||||
mode: restart
|
||||
triggers:
|
||||
# Apply the selected dropdown mode when it changes.
|
||||
- trigger: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
|
||||
# Re-apply the selected dropdown mode after Home Assistant restarts.
|
||||
- trigger: homeassistant
|
||||
event: start
|
||||
|
||||
actions:
|
||||
- choose:
|
||||
- alias: "Auto mode"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "Auto"
|
||||
sequence:
|
||||
- action: automation.turn_on
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
|
||||
# Auto starts at speed 2, then immediately evaluates the
|
||||
# current priority rules.
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: 2
|
||||
|
||||
- delay:
|
||||
seconds: 1
|
||||
|
||||
- action: automation.trigger
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
data:
|
||||
skip_condition: false
|
||||
|
||||
- alias: "Off mode"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "Off"
|
||||
sequence:
|
||||
- action: automation.turn_off
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: 0
|
||||
|
||||
- alias: "High mode"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "High"
|
||||
sequence:
|
||||
- action: automation.turn_off
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: 6
|
||||
|
||||
- alias: "Medium mode"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "Medium"
|
||||
sequence:
|
||||
- action: automation.turn_off
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: 4
|
||||
|
||||
- alias: "Low mode"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "Low"
|
||||
sequence:
|
||||
- action: automation.turn_off
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: 2
|
||||
|
||||
- alias: "Quiet mode"
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.bedroom_1_ikea_fan
|
||||
state: "Quiet"
|
||||
sequence:
|
||||
- action: automation.turn_off
|
||||
target:
|
||||
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
|
||||
|
||||
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
|
||||
data:
|
||||
target_speed: 1
|
||||
@@ -1,6 +1,42 @@
|
||||
# yaml-language-server: $schema=null
|
||||
###############################################################################
|
||||
# PACKAGE: Lounge scenes (delta-only settings) + manual override
|
||||
# PACKAGE: Lounge scenes controller
|
||||
#
|
||||
# PURPOSE:
|
||||
# - Provides selectable lounge lighting scenes from Home Assistant.
|
||||
# - Scenes are selected via input_select.lounge_scene.
|
||||
# - The selector resets back to "Select Scene:" after each scene is applied, so
|
||||
# the same scene can be selected repeatedly.
|
||||
# - Scenes are delta-only: only entities listed in a scene are changed.
|
||||
# - Manual override can block automatic scene changes.
|
||||
# - Last remembered scene is tracked so TV automations can avoid changing lights
|
||||
# when the lounge was deliberately set to All Off.
|
||||
#
|
||||
# SUPPORTED SCENE VALUE TYPES:
|
||||
# - light.*:
|
||||
# 0 = turn off
|
||||
# 1-100 = turn on at brightness percentage
|
||||
# "on" = turn on
|
||||
# "off" = turn off
|
||||
# "toggle" = toggle on/off, using 100 percent when turning on
|
||||
# "toggle_75" = if on, turn off; if off, turn on at 75 percent
|
||||
#
|
||||
# - switch.*:
|
||||
# "on" = turn on
|
||||
# "off" = turn off
|
||||
# "toggle" = toggle on/off
|
||||
#
|
||||
# - number.*:
|
||||
# numeric value is sent using number.set_value
|
||||
#
|
||||
# - input_number.*:
|
||||
# numeric value is sent using input_number.set_value
|
||||
# Example: input_number.openhasp_1_backlight_level: 180
|
||||
#
|
||||
# NOTES:
|
||||
# - Keep on/off/toggle values quoted for clarity.
|
||||
# - Numeric values can be left unquoted.
|
||||
# - Only scenes not listed in excluded_scenes update input_text.lounge_last_scene.
|
||||
###############################################################################
|
||||
|
||||
input_select:
|
||||
@@ -49,7 +85,7 @@ script:
|
||||
data:
|
||||
option: "{{ scene_name }}"
|
||||
|
||||
# NEW: Wait briefly for HA to commit the new state (avoids race)
|
||||
# Wait briefly for HA to commit the new state before reading it.
|
||||
- wait_template: "{{ states('input_select.lounge_scene') == scene_name }}"
|
||||
timeout: "00:00:02"
|
||||
continue_on_timeout: true
|
||||
@@ -62,15 +98,19 @@ script:
|
||||
sequence:
|
||||
- variables:
|
||||
sel: "{{ states('input_select.lounge_scene') }}"
|
||||
|
||||
#####################################################################
|
||||
# EXCLUDED SCENES (these are temp scenes, not remembered as last)
|
||||
# EXCLUDED SCENES
|
||||
# These are temporary/action scenes and are not remembered as last.
|
||||
#####################################################################
|
||||
excluded_scenes:
|
||||
- "Select Scene:"
|
||||
- "Reading On/Off"
|
||||
#- "Night Light"
|
||||
|
||||
#####################################################################
|
||||
# SCENE SETTINGS (delta only - only list entities you want to change)
|
||||
# SCENE SETTINGS
|
||||
# Delta only - only list entities you want to change.
|
||||
#####################################################################
|
||||
scene_settings:
|
||||
Bright:
|
||||
@@ -91,6 +131,7 @@ script:
|
||||
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 100
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 100
|
||||
input_number.openhasp_1_backlight_level: 255
|
||||
|
||||
TV General:
|
||||
light.esp_lounge6chdimmer_couch_spots_left: 60
|
||||
@@ -109,6 +150,7 @@ script:
|
||||
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 60
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 60
|
||||
input_number.openhasp_1_backlight_level: 120
|
||||
|
||||
Movie:
|
||||
light.esp_lounge6chdimmer_couch_spots_left: 20
|
||||
@@ -127,6 +169,7 @@ script:
|
||||
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 40
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 40
|
||||
input_number.openhasp_1_backlight_level: 15
|
||||
|
||||
Reading On/Off:
|
||||
light.esp_lounge6chdimmer_couch_spots_left: "toggle_75"
|
||||
@@ -154,6 +197,7 @@ script:
|
||||
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 5
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 5
|
||||
input_number.openhasp_1_backlight_level: 8
|
||||
|
||||
Warm Cozy:
|
||||
light.esp_lounge6chdimmer_couch_spots_left: 20
|
||||
@@ -170,6 +214,7 @@ script:
|
||||
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 20
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 20
|
||||
input_number.openhasp_1_backlight_level: 12
|
||||
|
||||
All Off:
|
||||
light.esp_lounge6chdimmer_couch_spots_left: 0
|
||||
@@ -188,12 +233,11 @@ script:
|
||||
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 0
|
||||
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 0
|
||||
#input_number.openhasp_1_backlight_level: 100
|
||||
|
||||
#####################################################################
|
||||
#####################################################################
|
||||
#####################################################################
|
||||
|
||||
# Only remember scenes that are not excluded
|
||||
#########################################################################
|
||||
# REMEMBER LAST SCENE
|
||||
#########################################################################
|
||||
- choose:
|
||||
- conditions: "{{ sel not in excluded_scenes }}"
|
||||
sequence:
|
||||
@@ -202,6 +246,9 @@ script:
|
||||
data:
|
||||
value: "{{ sel }}"
|
||||
|
||||
#########################################################################
|
||||
# APPLY SELECTED SCENE
|
||||
#########################################################################
|
||||
- repeat:
|
||||
for_each: "{{ (scene_settings.get(sel, {})).keys() | list }}"
|
||||
sequence:
|
||||
@@ -210,23 +257,32 @@ script:
|
||||
val: "{{ (scene_settings.get(sel, {}))[ent] }}"
|
||||
is_light: "{{ ent.startswith('light.') }}"
|
||||
is_switch: "{{ ent.startswith('switch.') }}"
|
||||
is_number_ent: "{{ ent.startswith('number.') }}"
|
||||
is_input_number_ent: "{{ ent.startswith('input_number.') }}"
|
||||
is_num: "{{ val is number }}"
|
||||
vstr: "{{ (val|string) if not is_num else '' }}"
|
||||
is_toggle: "{{ (not is_num) and (vstr|lower).startswith('toggle') }}"
|
||||
toggle_pct: "{{ (vstr.split('_')|last)|int if ('_' in vstr) else 100 }}"
|
||||
currently_on: "{{ is_state(ent, 'on') }}"
|
||||
is_number_ent: "{{ ent.startswith('number.') }}" # 🔹 NEW
|
||||
|
||||
- choose:
|
||||
# 0) Numbers: set numeric value (e.g. 0..100)
|
||||
- conditions: "{{ is_number_ent and is_num }}" # 🔹 NEW
|
||||
# 0a) Numbers: set numeric value
|
||||
- conditions: "{{ is_number_ent and is_num }}"
|
||||
sequence:
|
||||
- service: number.set_value
|
||||
data:
|
||||
entity_id: "{{ ent }}"
|
||||
value: "{{ val|float }}"
|
||||
|
||||
# 1) Lights: toggle[_NN] -> if on turn off, else turn on to NN (default 100)
|
||||
# 0b) Input numbers: set numeric value
|
||||
- conditions: "{{ is_input_number_ent and is_num }}"
|
||||
sequence:
|
||||
- service: input_number.set_value
|
||||
data:
|
||||
entity_id: "{{ ent }}"
|
||||
value: "{{ val|float }}"
|
||||
|
||||
# 1) Lights: toggle[_NN] -> if on turn off, else turn on to NN
|
||||
- conditions: "{{ is_light and is_toggle }}"
|
||||
sequence:
|
||||
- choose:
|
||||
@@ -248,13 +304,14 @@ script:
|
||||
data:
|
||||
entity_id: "{{ ent }}"
|
||||
|
||||
# 3) Lights: numeric brightness (0 = off)
|
||||
# 3) Lights: numeric brightness, where 0 = off
|
||||
- conditions: "{{ is_light and is_num and (val|int) > 0 }}"
|
||||
sequence:
|
||||
- service: light.turn_on
|
||||
data:
|
||||
entity_id: "{{ ent }}"
|
||||
brightness_pct: "{{ val|int }}"
|
||||
|
||||
- conditions: "{{ is_light and is_num and (val|int) == 0 }}"
|
||||
sequence:
|
||||
- service: light.turn_off
|
||||
@@ -267,6 +324,7 @@ script:
|
||||
- service: light.turn_on
|
||||
data:
|
||||
entity_id: "{{ ent }}"
|
||||
|
||||
- conditions: "{{ is_light and not is_num and (val in [false, 'off', 'Off', 'OFF']) }}"
|
||||
sequence:
|
||||
- service: light.turn_off
|
||||
@@ -279,6 +337,7 @@ script:
|
||||
- service: switch.turn_on
|
||||
data:
|
||||
entity_id: "{{ ent }}"
|
||||
|
||||
- conditions: "{{ is_switch and (val in [false, 'off', 'Off', 'OFF']) }}"
|
||||
sequence:
|
||||
- service: switch.turn_off
|
||||
@@ -322,7 +381,7 @@ automation:
|
||||
- platform: state
|
||||
entity_id: remote.lounge_tv
|
||||
to: "on"
|
||||
for: "00:00:02" #small debounce
|
||||
for: "00:00:02"
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: input_boolean.lounge_manual_override
|
||||
@@ -340,7 +399,7 @@ automation:
|
||||
- platform: state
|
||||
entity_id: remote.lounge_tv
|
||||
to: "off"
|
||||
for: "00:00:02" #small debounce
|
||||
for: "00:00:02"
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: input_boolean.lounge_manual_override
|
||||
|
||||
@@ -4,41 +4,17 @@
|
||||
#
|
||||
# PAGE OBJECTS USED
|
||||
# - p1b1 = main temperature display
|
||||
# - p1b2 = alternating Setpoint / Humidity display
|
||||
# - p1b2 = setpoint display
|
||||
# - p1b3 = setpoint down
|
||||
# - p1b4 = setpoint up
|
||||
# - p1b5 = heater status text
|
||||
# - p1b6 = heater operation / flame button
|
||||
# - p1b7 = humidity display
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# HELPERS
|
||||
###############################################################################
|
||||
input_boolean:
|
||||
hasp_setpoint_hold_active:
|
||||
name: HASP Setpoint Hold Active
|
||||
initial: false
|
||||
|
||||
input_number:
|
||||
# How long Setpoint and Humidity are each shown before rotating
|
||||
hasp_setpoint_humidity_cycle_seconds:
|
||||
name: HASP Setpoint Humidity Cycle Seconds
|
||||
min: 1
|
||||
max: 60
|
||||
step: 1
|
||||
mode: box
|
||||
unit_of_measurement: s
|
||||
initial: 10
|
||||
|
||||
# After the setpoint changes, hold the setpoint screen for this long
|
||||
hasp_setpoint_hold_seconds:
|
||||
name: HASP Setpoint Hold Seconds
|
||||
min: 1
|
||||
max: 60
|
||||
step: 1
|
||||
mode: box
|
||||
unit_of_measurement: s
|
||||
initial: 15
|
||||
|
||||
###############################################################################
|
||||
# MQTT ENTITIES
|
||||
@@ -48,6 +24,14 @@ mqtt:
|
||||
- name: "Lounge Environment Humidity MQTT"
|
||||
unique_id: "lounge_environment_humidity_mqtt"
|
||||
state_topic: "viewroad-status/lounge-environment/humidity"
|
||||
value_template: >
|
||||
{% set raw = value | trim %}
|
||||
{% if raw.startswith('{') %}
|
||||
{% set j = raw | from_json %}
|
||||
{{ j.humidity | default(j.value | default(raw)) }}
|
||||
{% else %}
|
||||
{{ raw | replace('%', '') | trim }}
|
||||
{% endif %}
|
||||
|
||||
###############################################################################
|
||||
# AUTOMATIONS
|
||||
@@ -99,35 +83,53 @@ automation:
|
||||
{{ s if s not in ['unknown', 'unavailable', ''] else 'HEATER --' }}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# When setpoint changes:
|
||||
# - immediately show Setpoint
|
||||
# - hold it for hold_seconds
|
||||
# - then allow normal Setpoint/Humidity rotation again
|
||||
# Setpoint display on left side of centre row
|
||||
# - Strips any existing units so only one °C is shown
|
||||
# -------------------------------------------------------------------------
|
||||
- id: hasp_setpoint_changed_hold_display
|
||||
alias: "HASP: show setpoint immediately and hold"
|
||||
mode: restart
|
||||
- id: hasp_setpoint_to_btn_text
|
||||
alias: "HASP: update setpoint (p1b2.text)"
|
||||
mode: queued
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: sensor.rinnai_neo_gas_heater_setpoint_text
|
||||
action:
|
||||
- service: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.hasp_setpoint_hold_active
|
||||
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.text"
|
||||
payload: >
|
||||
{% set s = states('sensor.rinnai_neo_gas_heater_setpoint_text') %}
|
||||
{{ 'Setpoint: ' ~ (s if s not in ['unknown', 'unavailable', ''] else '--') }}
|
||||
{% set raw = states('sensor.rinnai_neo_gas_heater_setpoint_text') %}
|
||||
{% set cleaned = raw
|
||||
| replace('°C', '')
|
||||
| replace('° C', '')
|
||||
| replace('C', '')
|
||||
| trim %}
|
||||
{% if cleaned not in ['unknown', 'unavailable', '', 'none', 'None'] %}
|
||||
Set: {{ cleaned | float(0) | round(1) }}°C
|
||||
{% else %}
|
||||
Set: -- °C
|
||||
{% endif %}
|
||||
|
||||
- delay:
|
||||
seconds: "{{ states('input_number.hasp_setpoint_hold_seconds') | int(15) }}"
|
||||
|
||||
- service: input_boolean.turn_off
|
||||
target:
|
||||
entity_id: input_boolean.hasp_setpoint_hold_active
|
||||
# -------------------------------------------------------------------------
|
||||
# Humidity display on right side of centre row
|
||||
# -------------------------------------------------------------------------
|
||||
- id: hasp_humidity_to_btn_text
|
||||
alias: "HASP: update humidity (p1b7.text)"
|
||||
mode: queued
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: sensor.lounge_environment_humidity_mqtt
|
||||
action:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b7.text"
|
||||
payload: >
|
||||
{% set raw = states('sensor.lounge_environment_humidity_mqtt') %}
|
||||
{% set cleaned = raw | replace('%', '') | trim %}
|
||||
{% if cleaned in ['unknown', 'unavailable', '', 'none', 'None'] %}
|
||||
Hum: Unknown
|
||||
{% else %}
|
||||
Hum: {{ cleaned }}%
|
||||
{% endif %}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Up / Down buttons on the HASP plate
|
||||
@@ -298,9 +300,6 @@ automation:
|
||||
event: start
|
||||
action:
|
||||
- service: script.hasp_push_static_texts
|
||||
- service: script.turn_on
|
||||
target:
|
||||
entity_id: script.hasp_rotate_setpoint_humidity
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Re-push screen state when panel comes online
|
||||
@@ -316,9 +315,6 @@ automation:
|
||||
action:
|
||||
- delay: "00:00:05"
|
||||
- service: script.hasp_push_static_texts
|
||||
- service: script.turn_on
|
||||
target:
|
||||
entity_id: script.hasp_rotate_setpoint_humidity
|
||||
|
||||
###############################################################################
|
||||
# SCRIPTS
|
||||
@@ -332,6 +328,9 @@ script:
|
||||
alias: "HASP: push static texts"
|
||||
mode: queued
|
||||
sequence:
|
||||
# Push Set/Hum display styling first, so the centre row is not blue
|
||||
- service: script.hasp_style_center_info_buttons
|
||||
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b1.text"
|
||||
@@ -359,8 +358,29 @@ script:
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.text"
|
||||
payload: >
|
||||
{% set s = states('sensor.rinnai_neo_gas_heater_setpoint_text') %}
|
||||
{{ 'Setpoint: ' ~ (s if s not in ['unknown', 'unavailable', ''] else '--') }}
|
||||
{% set raw = states('sensor.rinnai_neo_gas_heater_setpoint_text') %}
|
||||
{% set cleaned = raw
|
||||
| replace('°C', '')
|
||||
| replace('° C', '')
|
||||
| replace('C', '')
|
||||
| trim %}
|
||||
{% if cleaned not in ['unknown', 'unavailable', '', 'none', 'None'] %}
|
||||
Set: {{ cleaned | float(0) | round(1) }}°C
|
||||
{% else %}
|
||||
Set: -- °C
|
||||
{% endif %}
|
||||
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b7.text"
|
||||
payload: >
|
||||
{% set raw = states('sensor.lounge_environment_humidity_mqtt') %}
|
||||
{% set cleaned = raw | replace('%', '') | trim %}
|
||||
{% if cleaned in ['unknown', 'unavailable', '', 'none', 'None'] %}
|
||||
Hum: Unknown
|
||||
{% else %}
|
||||
Hum: {{ cleaned }}%
|
||||
{% endif %}
|
||||
|
||||
# Push middle flame button state
|
||||
- service: mqtt.publish
|
||||
@@ -445,42 +465,45 @@ script:
|
||||
payload: "#0095D9"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Rotate the middle information line between Setpoint and Humidity
|
||||
# Pauses humidity display while the setpoint hold flag is active
|
||||
# Style centre row info buttons as text panels
|
||||
# - p1b2 = setpoint
|
||||
# - p1b7 = humidity
|
||||
# This removes the default blue button styling from these display-only fields.
|
||||
# -------------------------------------------------------------------------
|
||||
hasp_rotate_setpoint_humidity:
|
||||
alias: "HASP: rotate setpoint and humidity"
|
||||
mode: restart
|
||||
hasp_style_center_info_buttons:
|
||||
alias: "HASP: style centre info buttons"
|
||||
mode: queued
|
||||
sequence:
|
||||
- repeat:
|
||||
while:
|
||||
- condition: template
|
||||
value_template: "{{ true }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.text"
|
||||
payload: >
|
||||
{% set s = states('sensor.rinnai_neo_gas_heater_setpoint_text') %}
|
||||
{{ 'Setpoint: ' ~ (s if s not in ['unknown', 'unavailable', ''] else '--') }}
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.text_color"
|
||||
payload: "#FFFFFF"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.bg_color"
|
||||
payload: "#000000"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.bg_grad_color"
|
||||
payload: "#000000"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.border_color"
|
||||
payload: "#000000"
|
||||
|
||||
- delay:
|
||||
seconds: "{{ states('input_number.hasp_setpoint_humidity_cycle_seconds') | int(10) }}"
|
||||
|
||||
- condition: state
|
||||
entity_id: input_boolean.hasp_setpoint_hold_active
|
||||
state: "off"
|
||||
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b2.text"
|
||||
payload: >
|
||||
{% set h = states('sensor.lounge_environment_humidity_mqtt') %}
|
||||
{% if h in ['unknown', 'unavailable', ''] %}
|
||||
Humidity: Unknown
|
||||
{% else %}
|
||||
Humidity: {{ h }}%
|
||||
{% endif %}
|
||||
|
||||
- delay:
|
||||
seconds: "{{ states('input_number.hasp_setpoint_humidity_cycle_seconds') | int(10) }}"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b7.text_color"
|
||||
payload: "#FFFFFF"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b7.bg_color"
|
||||
payload: "#000000"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b7.bg_grad_color"
|
||||
payload: "#000000"
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command/p1b7.border_color"
|
||||
payload: "#000000"
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
###############################################################################
|
||||
# PACKAGE: OpenHASP Lounge 1 Wall Plate Backlight Control
|
||||
# NODE/TOPIC ROOT: hasp/openhasp_1/
|
||||
#
|
||||
# INTENT:
|
||||
# - Keep backlight control separate from the thermostat/heater UI package.
|
||||
# - Avoid using brightness 0 as the main OFF method.
|
||||
# - Wake the panel with "idle off" before applying brightness.
|
||||
#
|
||||
# OPENHASP NOTES:
|
||||
# - backlight brightness range is 1..255
|
||||
# - backlight off is a state, not a brightness level
|
||||
# - idle off clears idle/sleep state and behaves like a wake-up
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# HELPERS
|
||||
###############################################################################
|
||||
input_boolean:
|
||||
openhasp_1_backlight_enable:
|
||||
name: OpenHASP 1 Backlight Enable
|
||||
icon: mdi:television-ambient-light
|
||||
initial: true
|
||||
|
||||
input_number:
|
||||
openhasp_1_backlight_level:
|
||||
name: OpenHASP 1 Backlight Level
|
||||
min: 1
|
||||
max: 255
|
||||
step: 1
|
||||
mode: slider
|
||||
initial: 255
|
||||
|
||||
###############################################################################
|
||||
# AUTOMATIONS
|
||||
###############################################################################
|
||||
automation:
|
||||
# -------------------------------------------------------------------------
|
||||
# Backlight enable helper changed
|
||||
# - ON -> wake panel and apply current brightness level
|
||||
# - OFF -> tell openHASP to switch the backlight off
|
||||
# -------------------------------------------------------------------------
|
||||
- id: openhasp_1_backlight_enable_changed
|
||||
alias: "OpenHASP 1: backlight enable changed"
|
||||
mode: restart
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_boolean.openhasp_1_backlight_enable
|
||||
action:
|
||||
- choose:
|
||||
- conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.openhasp_1_backlight_enable
|
||||
state: "on"
|
||||
sequence:
|
||||
- service: script.openhasp_1_backlight_apply
|
||||
|
||||
default:
|
||||
- service: script.openhasp_1_backlight_off
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Backlight level helper changed
|
||||
# - If backlight is enabled, apply the new level immediately
|
||||
# - If disabled, just store the new level for next time
|
||||
# -------------------------------------------------------------------------
|
||||
- id: openhasp_1_backlight_level_changed
|
||||
alias: "OpenHASP 1: backlight level changed"
|
||||
mode: restart
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_number.openhasp_1_backlight_level
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: input_boolean.openhasp_1_backlight_enable
|
||||
state: "on"
|
||||
action:
|
||||
- service: script.openhasp_1_backlight_apply
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Re-apply requested backlight state when Home Assistant starts
|
||||
# -------------------------------------------------------------------------
|
||||
- id: openhasp_1_backlight_on_ha_start
|
||||
alias: "OpenHASP 1: apply backlight on HA start"
|
||||
mode: queued
|
||||
trigger:
|
||||
- platform: homeassistant
|
||||
event: start
|
||||
action:
|
||||
- delay: "00:00:10"
|
||||
- service: script.openhasp_1_backlight_apply_requested_state
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Re-apply requested backlight state when the panel reconnects
|
||||
# -------------------------------------------------------------------------
|
||||
- id: openhasp_1_backlight_on_panel_online
|
||||
alias: "OpenHASP 1: apply backlight on panel online"
|
||||
mode: queued
|
||||
trigger:
|
||||
- platform: mqtt
|
||||
topic: "hasp/openhasp_1/LWT"
|
||||
condition:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.payload == 'online' }}"
|
||||
action:
|
||||
- delay: "00:00:05"
|
||||
- service: script.openhasp_1_backlight_apply_requested_state
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# If openHASP enters idle while HA says the backlight should be enabled,
|
||||
# wake it and re-apply the requested brightness.
|
||||
#
|
||||
# This is intended to stop the "black until touched" behaviour when the
|
||||
# plate's own idle state has blanked the display.
|
||||
# -------------------------------------------------------------------------
|
||||
- id: openhasp_1_backlight_recover_from_idle
|
||||
alias: "OpenHASP 1: recover backlight from idle"
|
||||
mode: restart
|
||||
trigger:
|
||||
- platform: mqtt
|
||||
topic: "hasp/openhasp_1/state/idle"
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: input_boolean.openhasp_1_backlight_enable
|
||||
state: "on"
|
||||
- condition: template
|
||||
value_template: "{{ trigger.payload | lower != 'off' }}"
|
||||
action:
|
||||
- delay: "00:00:01"
|
||||
- service: script.openhasp_1_backlight_apply
|
||||
|
||||
###############################################################################
|
||||
# SCRIPTS
|
||||
###############################################################################
|
||||
script:
|
||||
# -------------------------------------------------------------------------
|
||||
# Apply current requested brightness.
|
||||
#
|
||||
# Important:
|
||||
# - Send idle off first so the panel is awake.
|
||||
# - Then send a JSON backlight command with state ON and brightness 1..255.
|
||||
# -------------------------------------------------------------------------
|
||||
openhasp_1_backlight_apply:
|
||||
alias: "OpenHASP 1: apply backlight level"
|
||||
mode: restart
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command"
|
||||
payload: "idle off"
|
||||
|
||||
- delay: "00:00:00.25"
|
||||
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command"
|
||||
payload: >
|
||||
backlight {"state":"on","brightness":{{ states('input_number.openhasp_1_backlight_level') | int(255) }}}
|
||||
|
||||
# Send once more shortly after. This helps with panels that miss the
|
||||
# brightness change while coming out of idle.
|
||||
- delay: "00:00:00.75"
|
||||
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command"
|
||||
payload: >
|
||||
backlight {"state":"on","brightness":{{ states('input_number.openhasp_1_backlight_level') | int(255) }}}
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Turn the backlight off using the openHASP backlight OFF state.
|
||||
# Do not set brightness to 0.
|
||||
# -------------------------------------------------------------------------
|
||||
openhasp_1_backlight_off:
|
||||
alias: "OpenHASP 1: backlight off"
|
||||
mode: restart
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "hasp/openhasp_1/command"
|
||||
payload: "backlight off"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Apply either ON/current-level or OFF according to helper state.
|
||||
# Used on HA startup and panel reconnect.
|
||||
# -------------------------------------------------------------------------
|
||||
openhasp_1_backlight_apply_requested_state:
|
||||
alias: "OpenHASP 1: apply requested backlight state"
|
||||
mode: restart
|
||||
sequence:
|
||||
- choose:
|
||||
- conditions:
|
||||
- condition: state
|
||||
entity_id: input_boolean.openhasp_1_backlight_enable
|
||||
state: "on"
|
||||
sequence:
|
||||
- service: script.openhasp_1_backlight_apply
|
||||
|
||||
default:
|
||||
- service: script.openhasp_1_backlight_off
|
||||
Reference in New Issue
Block a user