From b8681f7741d8a5de2ac8e04ee0d75654c648df5e Mon Sep 17 00:00:00 2001 From: ESPHome Device Builder Date: Thu, 16 Jul 2026 19:25:20 +1200 Subject: [PATCH] Edit esp-bedside-panel.yaml --- esphome/esp-bedside-panel.yaml | 428 ++++++++++++++++++++++++++++----- 1 file changed, 364 insertions(+), 64 deletions(-) diff --git a/esphome/esp-bedside-panel.yaml b/esphome/esp-bedside-panel.yaml index 4e9c5d3..e62a09c 100644 --- a/esphome/esp-bedside-panel.yaml +++ b/esphome/esp-bedside-panel.yaml @@ -6,6 +6,7 @@ # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedside-panel.yaml #:########################################################################################:# # VERSIONS: +# V0.8l 2026-07-16 Completed primary Climate controls, ceiling fan cycle and Air Filter Low # V0.8k 2026-07-16 Revised Bedroom header and added five-button navigation row # V0.8j 2026-07-16 Added delayed Home Assistant state synchronisation for button highlighting at startup # V0.8i 2026-07-16 Moved Clock date upward, added missing value glyphs and increased Clock to 190px @@ -79,12 +80,12 @@ substitutions: # Device Naming device_name: "esp-bedside-panel" friendly_name: "ESP Bedside Panel" - description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside clock and Home Assistant control panel. Compact Bedroom status header and five-button navigation row. (Layout V1.1)" + description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside clock and Home Assistant control panel. Heat-pump setpoint, ceiling-fan and air-filter controls. (Layout V1.1)" device_area: "Bedroom" # Project Naming project_name: "Guition.JC1060P470C_I_W_Y" - project_version: "v0.8k" + project_version: "v0.8l" # Passwords & Secrets api_key: !secret esp-api_key @@ -133,11 +134,18 @@ substitutions: # Home Assistant Entities - Actions bedtime_button_entity: "input_button.bedtime_mode" - # Home Assistant Entities - Climate Actions + # Home Assistant Entities - Climate + climate_entity: "climate.master_bedroom" + climate_requested_mode_entity: "input_select.master_bedroom_hvac_requested_mode" climate_off_script: "script.master_bedroom_hvac_off" climate_heat_script: "script.master_bedroom_hvac_heat" climate_cool_script: "script.master_bedroom_hvac_cool" climate_dry_script: "script.master_bedroom_hvac_dry" + climate_setpoint_adjust_script: "script.master_bedroom_setpoint_adjust" + + # Home Assistant Entities - Ceiling Fan / Air Filter + ceiling_fan_entity: "fan.tasmo_ifan02_3793_bedrm1_1" + air_filter_level_entity: "number.bedroom_1_air_filter_bedroom_1_air_filter_speed_level" #:########################################################################################:# # PACKAGES: @@ -398,7 +406,7 @@ font: glyphs: - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - - "0123456789, .:/-%°" + - "0123456789, .:/-%°+()" - file: "gfonts://Roboto" id: font_button @@ -406,7 +414,7 @@ font: glyphs: - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - - "0123456789 .:/-%°" + - "0123456789 .:/-%°+()" - file: "gfonts://Roboto" id: font_small @@ -414,7 +422,7 @@ font: glyphs: - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - - "0123456789, .:/-%°" + - "0123456789, .:/-%°+()" #:########################################################################################:# # HOME ASSISTANT NUMERIC SENSORS: @@ -503,6 +511,35 @@ sensor: format: "%.0f%%" args: [x] + # Current heat-pump target temperature. + - platform: homeassistant + id: ha_climate_setpoint + entity_id: "${climate_entity}" + attribute: temperature + internal: true + on_value: + then: + - script.execute: refresh_climate_controls + + # Current ceiling-fan percentage, normally 33 / 66 / 100. + - platform: homeassistant + id: ha_ceiling_fan_percentage + entity_id: "${ceiling_fan_entity}" + attribute: percentage + internal: true + on_value: + then: + - script.execute: refresh_climate_controls + + # Current bedroom air-filter speed level. + - platform: homeassistant + id: ha_air_filter_level + entity_id: "${air_filter_level_entity}" + internal: true + on_value: + then: + - script.execute: refresh_climate_controls + #:########################################################################################:# # HOME ASSISTANT BINARY SENSORS: # Imported states used to colour LVGL buttons @@ -646,6 +683,14 @@ binary_sensor: ? lv_color_hex(0x1668A8) : lv_color_hex(0x28313D); + - platform: homeassistant + id: ha_ceiling_fan_on + entity_id: "${ceiling_fan_entity}" + internal: true + on_state: + then: + - script.execute: refresh_climate_controls + - platform: homeassistant id: ha_quiet_time entity_id: "${quiet_time_entity}" @@ -769,6 +814,101 @@ script: ? std::string("Quiet Time active") : std::string(""); + - script.execute: refresh_climate_controls + + # Update Climate-page labels and highlight the currently selected settings. + - id: refresh_climate_controls + mode: restart + then: + # Heat-pump mode buttons. + - lvgl.widget.update: + id: climate_off_button + bg_color: !lambda |- + const auto mode = id(ha_climate_requested_mode).state; + return (mode == "Off" || mode == "off") + ? lv_color_hex(0x548C6C) + : lv_color_hex(0x28313D); + + - lvgl.widget.update: + id: climate_heat_button + bg_color: !lambda |- + const auto mode = id(ha_climate_requested_mode).state; + return (mode == "Heat" || mode == "heat") + ? lv_color_hex(0xB76822) + : lv_color_hex(0x28313D); + + - lvgl.widget.update: + id: climate_cool_button + bg_color: !lambda |- + const auto mode = id(ha_climate_requested_mode).state; + return (mode == "Cool" || mode == "cool") + ? lv_color_hex(0x2E6A96) + : lv_color_hex(0x28313D); + + - lvgl.widget.update: + id: climate_dry_button + bg_color: !lambda |- + const auto mode = id(ha_climate_requested_mode).state; + return ( + mode == "Dry" || + mode == "dry" || + mode == "Dehumidify" || + mode == "dehumidify" + ) + ? lv_color_hex(0x32677F) + : lv_color_hex(0x28313D); + + # Heat-pump target setpoint. + - lvgl.label.update: + id: climate_setpoint_value_label + text: !lambda |- + const float value = id(ha_climate_setpoint).state; + + if (isnan(value)) { + return std::string("--.-°C"); + } + + char buffer[16]; + snprintf(buffer, sizeof(buffer), "%.1f°C", value); + return std::string(buffer); + + # One-button ceiling-fan cycle: Off -> 1 -> 2 -> 3 -> Off. + - lvgl.label.update: + id: ceiling_fan_cycle_label + text: !lambda |- + if (!id(ha_ceiling_fan_on).state) { + return std::string("Ceiling Fan: Off"); + } + + const float percentage = id(ha_ceiling_fan_percentage).state; + + if (isnan(percentage) || percentage < 50.0f) { + return std::string("Ceiling Fan: 1"); + } + + if (percentage < 85.0f) { + return std::string("Ceiling Fan: 2"); + } + + return std::string("Ceiling Fan: 3"); + + - lvgl.widget.update: + id: ceiling_fan_cycle_button + bg_color: !lambda |- + return id(ha_ceiling_fan_on).state + ? lv_color_hex(0x315E82) + : lv_color_hex(0x28313D); + + # Air-filter Low is active when the HA number is set to level 2. + - lvgl.widget.update: + id: air_filter_low_button + bg_color: !lambda |- + const float level = id(ha_air_filter_level).state; + + return (!isnan(level) && level > 1.5f && level < 2.5f) + ? lv_color_hex(0x315843) + : lv_color_hex(0x28313D); + # Two passes allow time for LVGL creation and Home Assistant state delivery. - id: startup_button_state_sync mode: restart @@ -830,6 +970,15 @@ interval: # https://esphome.io/components/text_sensor/ #:########################################################################################:# text_sensor: + # Requested heat-pump mode used for button highlighting. + - platform: homeassistant + id: ha_climate_requested_mode + entity_id: "${climate_requested_mode_entity}" + internal: true + on_value: + then: + - script.execute: refresh_climate_controls + - platform: version name: "${friendly_name} ESPHome Version" hide_timestamp: true @@ -1371,34 +1520,36 @@ lvgl: widgets: - label: - x: 35 - y: 24 + x: 28 + y: 18 text: "Bedroom Climate" text_font: font_title text_color: 0xFFFFFF - label: align: TOP_RIGHT - x: -38 - y: 31 - text: "Mode controls" + x: -30 + y: 27 + text: "Heat Pump" text_font: font_small text_color: 0x8FA0B3 - # HVAC mode row + #:################################################################################:# + # HEAT-PUMP MODES + #:################################################################################:# - button: id: climate_off_button - x: 35 - y: 105 + x: 25 + y: 72 width: 220 - height: 140 - bg_color: 0x31443A + height: 96 + bg_color: 0x28313D bg_opa: COVER border_width: 2 border_color: 0x5A7A68 - radius: 18 + radius: 17 pressed: - bg_color: 0x456052 + bg_color: 0x548C6C widgets: - label: align: CENTER @@ -1413,17 +1564,17 @@ lvgl: - button: id: climate_heat_button - x: 280 - y: 105 + x: 272 + y: 72 width: 220 - height: 140 - bg_color: 0x6A401B + height: 96 + bg_color: 0x28313D bg_opa: COVER border_width: 2 border_color: 0xA6672B - radius: 18 + radius: 17 pressed: - bg_color: 0x8A5625 + bg_color: 0xB76822 widgets: - label: align: CENTER @@ -1438,15 +1589,15 @@ lvgl: - button: id: climate_cool_button - x: 525 - y: 105 + x: 519 + y: 72 width: 220 - height: 140 - bg_color: 0x214F72 + height: 96 + bg_color: 0x28313D bg_opa: COVER border_width: 2 border_color: 0x3E7FA7 - radius: 18 + radius: 17 pressed: bg_color: 0x2E6A96 widgets: @@ -1463,15 +1614,15 @@ lvgl: - button: id: climate_dry_button - x: 770 - y: 105 + x: 766 + y: 72 width: 220 - height: 140 - bg_color: 0x244C60 + height: 96 + bg_color: 0x28313D bg_opa: COVER border_width: 2 border_color: 0x427B96 - radius: 18 + radius: 17 pressed: bg_color: 0x32677F widgets: @@ -1486,49 +1637,198 @@ lvgl: data: entity_id: "${climate_dry_script}" - # Lightweight placeholders for the next stage - - button: - id: climate_setpoint_placeholder - x: 120 - y: 295 - width: 340 - height: 135 - bg_color: 0x28313D - bg_opa: COVER - border_width: 2 - border_color: 0x445365 - radius: 18 - widgets: - - label: - align: CENTER - text: "Setpoint - More Soon" - text_font: font_button - text_color: 0xAEB8C4 + #:################################################################################:# + # HEAT-PUMP SETPOINT + #:################################################################################:# + - label: + align: TOP_MID + y: 187 + text: "Setpoint" + text_font: font_small + text_color: 0x8FA0B3 - button: - id: climate_fan_timer_placeholder - x: 564 - y: 295 - width: 340 - height: 135 + id: climate_setpoint_down_button + x: 100 + y: 218 + width: 190 + height: 105 bg_color: 0x28313D bg_opa: COVER border_width: 2 - border_color: 0x445365 + border_color: 0x526276 radius: 18 + pressed: + bg_color: 0x38485A widgets: - label: align: CENTER - text: "Fan and Timer - More Soon" + text: "-0.5" + text_font: font_title + text_color: 0xFFFFFF + on_click: + - homeassistant.action: + action: "${climate_setpoint_adjust_script}" + data: + step: "-0.5" + + - button: + id: climate_setpoint_display + x: 315 + y: 218 + width: 394 + height: 105 + bg_color: 0x1C2632 + bg_opa: COVER + border_width: 2 + border_color: 0x5A6C82 + radius: 18 + widgets: + - label: + id: climate_setpoint_value_label + align: CENTER + text: "--.-°C" + text_font: font_title + text_color: 0xFFFFFF + + - button: + id: climate_setpoint_up_button + x: 734 + y: 218 + width: 190 + height: 105 + bg_color: 0x28313D + bg_opa: COVER + border_width: 2 + border_color: 0x526276 + radius: 18 + pressed: + bg_color: 0x38485A + widgets: + - label: + align: CENTER + text: "+0.5" + text_font: font_title + text_color: 0xFFFFFF + on_click: + - homeassistant.action: + action: "${climate_setpoint_adjust_script}" + data: + step: "0.5" + + #:################################################################################:# + # CEILING FAN / AIR FILTER + #:################################################################################:# + - button: + id: ceiling_fan_cycle_button + x: 65 + y: 356 + width: 430 + height: 100 + bg_color: 0x28313D + bg_opa: COVER + border_width: 2 + border_color: 0x47789B + radius: 18 + pressed: + bg_color: 0x315E82 + widgets: + - label: + id: ceiling_fan_cycle_label + align: CENTER + text: "Ceiling Fan: Off" text_font: font_button - text_color: 0xAEB8C4 + text_color: 0xFFFFFF + on_click: + # Off -> speed 1 + - if: + condition: + lambda: |- + return !id(ha_ceiling_fan_on).state; + + then: + - homeassistant.action: + action: fan.set_percentage + data: + entity_id: "${ceiling_fan_entity}" + percentage: "33" + + else: + # Speed 1 -> speed 2 + - if: + condition: + lambda: |- + const float percentage = + id(ha_ceiling_fan_percentage).state; + + return ( + isnan(percentage) || + percentage < 50.0f + ); + + then: + - homeassistant.action: + action: fan.set_percentage + data: + entity_id: "${ceiling_fan_entity}" + percentage: "66" + + else: + # Speed 2 -> speed 3 + - if: + condition: + lambda: |- + return ( + id(ha_ceiling_fan_percentage).state < + 85.0f + ); + + then: + - homeassistant.action: + action: fan.set_percentage + data: + entity_id: "${ceiling_fan_entity}" + percentage: "100" + + # Speed 3 -> Off + else: + - homeassistant.action: + action: fan.turn_off + data: + entity_id: "${ceiling_fan_entity}" + + - button: + id: air_filter_low_button + x: 529 + y: 356 + width: 430 + height: 100 + bg_color: 0x28313D + bg_opa: COVER + border_width: 2 + border_color: 0x548C6C + radius: 18 + pressed: + bg_color: 0x315843 + widgets: + - label: + align: CENTER + text: "Air Filter Low" + text_font: font_button + text_color: 0xFFFFFF + on_click: + - homeassistant.action: + action: number.set_value + data: + entity_id: "${air_filter_level_entity}" + value: "2" - button: id: climate_back_button - align: BOTTOM_MID - y: -55 - width: 360 - height: 90 + x: 365 + y: 490 + width: 294 + height: 78 bg_color: 0x315843 bg_opa: COVER border_width: 2