Edit esp-bedside-panel.yaml

This commit is contained in:
ESPHome Device Builder
2026-07-16 20:16:10 +12:00
parent 497cf553ad
commit cf857f322f
+219 -34
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedside-panel.yaml # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedside-panel.yaml
#:########################################################################################:# #:########################################################################################:#
# VERSIONS: # VERSIONS:
# V0.8o 2026-07-16 Added reliable MDI setpoint arrows and optimistic mutually-exclusive Heat Pump profiles
# V0.8n 2026-07-16 Fixed setpoint arrow icons using LVGL built-in FontAwesome symbols # V0.8n 2026-07-16 Fixed setpoint arrow icons using LVGL built-in FontAwesome symbols
# V0.8m 2026-07-16 Added Quiet / Powerful profiles, Night Power toggle and improved Climate state highlighting # V0.8m 2026-07-16 Added Quiet / Powerful profiles, Night Power toggle and improved Climate state highlighting
# V0.8l 2026-07-16 Completed primary Climate controls, ceiling fan cycle and Air Filter Low # V0.8l 2026-07-16 Completed primary Climate controls, ceiling fan cycle and Air Filter Low
@@ -82,12 +83,12 @@ substitutions:
# Device Naming # Device Naming
device_name: "esp-bedside-panel" device_name: "esp-bedside-panel"
friendly_name: "ESP Bedside Panel" friendly_name: "ESP Bedside Panel"
description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside control panel. Climate controls with LVGL built-in setpoint arrow icons. (Layout V1.1)" description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside control panel. Reliable setpoint icons and optimistic Quiet / Powerful / None profile controls. (Layout V1.1)"
device_area: "Bedroom" device_area: "Bedroom"
# Project Naming # Project Naming
project_name: "Guition.JC1060P470C_I_W_Y" project_name: "Guition.JC1060P470C_I_W_Y"
project_version: "v0.8n" project_version: "v0.8o"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -145,8 +146,7 @@ substitutions:
climate_cool_script: "script.master_bedroom_hvac_cool" climate_cool_script: "script.master_bedroom_hvac_cool"
climate_dry_script: "script.master_bedroom_hvac_dry" climate_dry_script: "script.master_bedroom_hvac_dry"
climate_setpoint_adjust_script: "script.master_bedroom_setpoint_adjust" climate_setpoint_adjust_script: "script.master_bedroom_setpoint_adjust"
climate_quiet_preset: "quiet" climate_profile_next_script: "script.master_bedroom_heat_pump_profile_next"
climate_powerful_preset: "boost"
# Home Assistant Entities - Ceiling Fan / Air Filter / Night Power # Home Assistant Entities - Ceiling Fan / Air Filter / Night Power
ceiling_fan_entity: "fan.tasmo_ifan02_3793_bedrm1_1" ceiling_fan_entity: "fan.tasmo_ifan02_3793_bedrm1_1"
@@ -430,6 +430,15 @@ font:
- "abcdefghijklmnopqrstuvwxyz" - "abcdefghijklmnopqrstuvwxyz"
- "0123456789, .:/-%°+()" - "0123456789, .:/-%°+()"
# Dedicated MDI font for reliable setpoint chevron icons.
- file: "https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/fonts/materialdesignicons-webfont.ttf"
id: font_mdi_setpoint
size: 48
bpp: 4
glyphs:
- "\U000F0140" # mdi-chevron-down
- "\U000F0143" # mdi-chevron-up
#:########################################################################################:# #:########################################################################################:#
# HOME ASSISTANT NUMERIC SENSORS: # HOME ASSISTANT NUMERIC SENSORS:
# https://esphome.io/components/sensor/homeassistant.html # https://esphome.io/components/sensor/homeassistant.html
@@ -725,6 +734,22 @@ binary_sensor:
? std::string("Quiet Time active") ? std::string("Quiet Time active")
: std::string(""); : std::string("");
#:########################################################################################:#
# GLOBALS:
# Local optimistic Heat Pump profile state
#:########################################################################################:#
globals:
# -1 = follow HA, 0 = None, 1 = Quiet, 2 = Powerful / Boost.
- id: climate_profile_optimistic
type: int
restore_value: false
initial_value: "-1"
- id: climate_profile_cycle_attempts
type: int
restore_value: false
initial_value: "0"
#:########################################################################################:# #:########################################################################################:#
# SCRIPTS: # SCRIPTS:
# Refresh all state-dependent LVGL button colours # Refresh all state-dependent LVGL button colours
@@ -940,43 +965,78 @@ script:
? lv_color_hex(0x32677F) ? lv_color_hex(0x32677F)
: lv_color_hex(0x28313D); : lv_color_hex(0x28313D);
# Quiet / Powerful profile buttons. The HA profile helper and actual # Quiet / Powerful are mutually exclusive. While a button action is
# climate preset are both checked so the display remains authoritative. # pending, the optimistic local value is shown immediately. Otherwise,
# the HA profile helper is authoritative, with actual preset as fallback.
- lvgl.widget.update: - lvgl.widget.update:
id: climate_quiet_button id: climate_quiet_button
bg_color: !lambda |- bg_color: !lambda |-
int selected = id(climate_profile_optimistic);
if (selected < 0) {
const auto profile = id(ha_climate_profile).state; const auto profile = id(ha_climate_profile).state;
const auto preset = id(ha_climate_preset_mode).state; const auto preset = id(ha_climate_preset_mode).state;
const bool active = ( if (profile == "Quiet" || profile == "quiet") {
profile == "Quiet" || selected = 1;
profile == "quiet" || } else if (
preset == "Quiet" || profile == "Boost" ||
preset == "quiet" profile == "boost" ||
); profile == "Powerful" ||
profile == "powerful"
) {
selected = 2;
} else if (preset == "quiet" || preset == "Quiet") {
selected = 1;
} else if (
preset == "boost" ||
preset == "Boost" ||
preset == "powerful" ||
preset == "Powerful"
) {
selected = 2;
} else {
selected = 0;
}
}
return active return selected == 1
? lv_color_hex(0x315843) ? lv_color_hex(0x315843)
: lv_color_hex(0x28313D); : lv_color_hex(0x28313D);
- lvgl.widget.update: - lvgl.widget.update:
id: climate_powerful_button id: climate_powerful_button
bg_color: !lambda |- bg_color: !lambda |-
int selected = id(climate_profile_optimistic);
if (selected < 0) {
const auto profile = id(ha_climate_profile).state; const auto profile = id(ha_climate_profile).state;
const auto preset = id(ha_climate_preset_mode).state; const auto preset = id(ha_climate_preset_mode).state;
const bool active = ( if (profile == "Quiet" || profile == "quiet") {
selected = 1;
} else if (
profile == "Boost" || profile == "Boost" ||
profile == "boost" || profile == "boost" ||
profile == "Powerful" || profile == "Powerful" ||
profile == "powerful" || profile == "powerful"
preset == "Boost" || ) {
selected = 2;
} else if (preset == "quiet" || preset == "Quiet") {
selected = 1;
} else if (
preset == "boost" || preset == "boost" ||
preset == "Powerful" || preset == "Boost" ||
preset == "powerful" preset == "powerful" ||
); preset == "Powerful"
) {
selected = 2;
} else {
selected = 0;
}
}
return active return selected == 2
? lv_color_hex(0x6B4A86) ? lv_color_hex(0x6B4A86)
: lv_color_hex(0x28313D); : lv_color_hex(0x28313D);
@@ -1043,6 +1103,69 @@ script:
? lv_color_hex(0x5A4778) ? lv_color_hex(0x5A4778)
: lv_color_hex(0x28313D); : lv_color_hex(0x28313D);
# Apply the optimistic target through the same HA profile-cycle script used
# by the existing dashboard. It checks after each cycle, so no cycle order
# is assumed. At most three cycles are attempted.
- id: apply_climate_profile_target
mode: restart
then:
- lambda: |-
id(climate_profile_cycle_attempts) = 0;
- while:
condition:
lambda: |-
if (id(climate_profile_cycle_attempts) >= 3) {
return false;
}
int current = 0;
const auto profile = id(ha_climate_profile).state;
const auto preset = id(ha_climate_preset_mode).state;
if (profile == "Quiet" || profile == "quiet") {
current = 1;
} else if (
profile == "Boost" ||
profile == "boost" ||
profile == "Powerful" ||
profile == "powerful"
) {
current = 2;
} else if (preset == "quiet" || preset == "Quiet") {
current = 1;
} else if (
preset == "boost" ||
preset == "Boost" ||
preset == "powerful" ||
preset == "Powerful"
) {
current = 2;
}
return current != id(climate_profile_optimistic);
then:
- homeassistant.action:
action: script.turn_on
data:
entity_id: "${climate_profile_next_script}"
- lambda: |-
id(climate_profile_cycle_attempts) += 1;
# Allow the HA script and Panasonic integration to update the
# profile helper before deciding whether another cycle is needed.
- delay: 1800ms
# Keep the optimistic highlight briefly, then return to authoritative HA.
- delay: 1500ms
- lambda: |-
id(climate_profile_optimistic) = -1;
- script.execute: refresh_climate_controls
# Two passes allow time for LVGL creation and Home Assistant state delivery. # Two passes allow time for LVGL creation and Home Assistant state delivery.
- id: startup_button_state_sync - id: startup_button_state_sync
mode: restart mode: restart
@@ -1831,11 +1954,42 @@ lvgl:
text_font: font_button text_font: font_button
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
- homeassistant.action: # Quiet -> None when already active; otherwise select Quiet.
action: climate.set_preset_mode - lambda: |-
data: int selected = id(climate_profile_optimistic);
entity_id: "${climate_entity}"
preset_mode: "${climate_quiet_preset}" if (selected < 0) {
const auto profile = id(ha_climate_profile).state;
const auto preset = id(ha_climate_preset_mode).state;
if (
profile == "Quiet" ||
profile == "quiet" ||
preset == "Quiet" ||
preset == "quiet"
) {
selected = 1;
} else if (
profile == "Boost" ||
profile == "boost" ||
profile == "Powerful" ||
profile == "powerful" ||
preset == "Boost" ||
preset == "boost" ||
preset == "Powerful" ||
preset == "powerful"
) {
selected = 2;
} else {
selected = 0;
}
}
id(climate_profile_optimistic) =
selected == 1 ? 0 : 1;
- script.execute: refresh_climate_controls
- script.execute: apply_climate_profile_target
- button: - button:
id: climate_powerful_button id: climate_powerful_button
@@ -1857,11 +2011,42 @@ lvgl:
text_font: font_button text_font: font_button
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
- homeassistant.action: # Powerful -> None when already active; otherwise select Powerful.
action: climate.set_preset_mode - lambda: |-
data: int selected = id(climate_profile_optimistic);
entity_id: "${climate_entity}"
preset_mode: "${climate_powerful_preset}" if (selected < 0) {
const auto profile = id(ha_climate_profile).state;
const auto preset = id(ha_climate_preset_mode).state;
if (
profile == "Quiet" ||
profile == "quiet" ||
preset == "Quiet" ||
preset == "quiet"
) {
selected = 1;
} else if (
profile == "Boost" ||
profile == "boost" ||
profile == "Powerful" ||
profile == "powerful" ||
preset == "Boost" ||
preset == "boost" ||
preset == "Powerful" ||
preset == "powerful"
) {
selected = 2;
} else {
selected = 0;
}
}
id(climate_profile_optimistic) =
selected == 2 ? 0 : 2;
- script.execute: refresh_climate_controls
- script.execute: apply_climate_profile_target
- button: - button:
id: climate_setpoint_down_button id: climate_setpoint_down_button
@@ -1879,8 +2064,8 @@ lvgl:
widgets: widgets:
- label: - label:
align: CENTER align: CENTER
text: "\uF063" text: "\U000F0140"
text_font: montserrat_36 text_font: font_mdi_setpoint
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
- homeassistant.action: - homeassistant.action:
@@ -1923,8 +2108,8 @@ lvgl:
widgets: widgets:
- label: - label:
align: CENTER align: CENTER
text: "\uF062" text: "\U000F0143"
text_font: montserrat_36 text_font: font_mdi_setpoint
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
- homeassistant.action: - homeassistant.action: