Edit esp-bedside-panel.yaml

This commit is contained in:
ESPHome Device Builder
2026-07-16 20:48:57 +12:00
parent 20a40b2b3f
commit 95835550de
+153 -211
View File
@@ -84,12 +84,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. Reliable setpoint icons and optimistic Quiet / Boost / None profile controls. (Layout V1.1)" description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside control panel. Direct Quiet / Boost / Normal selection, Nano-X and aligned Climate 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.8p" project_version: "v0.8q"
# Passwords & Secrets # Passwords & Secrets
api_key: !secret esp-api_key api_key: !secret esp-api_key
@@ -147,12 +147,12 @@ 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_profile_next_script: "script.master_bedroom_heat_pump_profile_next"
# 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"
air_filter_level_entity: "number.bedroom_1_air_filter_bedroom_1_air_filter_speed_level" air_filter_level_entity: "number.bedroom_1_air_filter_bedroom_1_air_filter_speed_level"
climate_night_power_entity: "input_boolean.master_bedroom_night_power_mode" climate_night_power_entity: "input_boolean.master_bedroom_night_power_mode"
nanoe_entity: "switch.master_bedroom_nanoe"
#:########################################################################################:# #:########################################################################################:#
# PACKAGES: # PACKAGES:
@@ -715,6 +715,14 @@ binary_sensor:
then: then:
- script.execute: refresh_climate_controls - script.execute: refresh_climate_controls
- platform: homeassistant
id: ha_nanoe
entity_id: "${nanoe_entity}"
internal: true
on_state:
then:
- script.execute: refresh_climate_controls
- platform: homeassistant - platform: homeassistant
id: ha_quiet_time id: ha_quiet_time
entity_id: "${quiet_time_entity}" entity_id: "${quiet_time_entity}"
@@ -740,13 +748,8 @@ binary_sensor:
# Local optimistic Heat Pump profile state # Local optimistic Heat Pump profile state
#:########################################################################################:# #:########################################################################################:#
globals: globals:
# -1 = follow HA, 0 = None, 1 = Quiet, 2 = Boost / Boost. # 0 = Normal, 1 = Quiet, 2 = Boost.
- id: climate_profile_optimistic - id: climate_profile_optimistic
type: int
restore_value: false
initial_value: "-1"
- id: climate_profile_cycle_attempts
type: int type: int
restore_value: false restore_value: false
initial_value: "0" initial_value: "0"
@@ -966,73 +969,28 @@ script:
? lv_color_hex(0x32677F) ? lv_color_hex(0x32677F)
: lv_color_hex(0x28313D); : lv_color_hex(0x28313D);
# Quiet / Boost are mutually exclusive. While a button action is # Quiet / Boost are mutually exclusive. Normal means neither is lit.
# 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); return id(climate_profile_optimistic) == 1
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") {
selected = 1;
} else if (
profile == "Boost" ||
profile == "boost"
) {
selected = 2;
} else if (preset == "quiet" || preset == "Quiet") {
selected = 1;
} else if (
preset == "boost" ||
preset == "Boost"
) {
selected = 2;
} else {
selected = 0;
}
}
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_boost_button id: climate_boost_button
bg_color: !lambda |- bg_color: !lambda |-
int selected = id(climate_profile_optimistic); return id(climate_profile_optimistic) == 2
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") {
selected = 1;
} else if (
profile == "Boost" ||
profile == "boost"
) {
selected = 2;
} else if (preset == "quiet" || preset == "Quiet") {
selected = 1;
} else if (
preset == "boost" ||
preset == "Boost"
) {
selected = 2;
} else {
selected = 0;
}
}
return selected == 2
? lv_color_hex(0x6B4A86) ? lv_color_hex(0x6B4A86)
: lv_color_hex(0x28313D); : lv_color_hex(0x28313D);
- lvgl.widget.update:
id: climate_nanoe_button
bg_color: !lambda |-
return id(ha_nanoe).state
? lv_color_hex(0x315E82)
: lv_color_hex(0x28313D);
# Heat-pump target setpoint. # Heat-pump target setpoint.
- lvgl.label.update: - lvgl.label.update:
id: climate_setpoint_value_label id: climate_setpoint_value_label
@@ -1096,65 +1054,6 @@ 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"
) {
current = 2;
} else if (preset == "quiet" || preset == "Quiet") {
current = 1;
} else if (
preset == "boost" ||
preset == "Boost"
) {
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
@@ -1234,23 +1133,22 @@ text_sensor:
then: then:
- script.execute: refresh_climate_controls - script.execute: refresh_climate_controls
# Existing HA profile helper uses values such as Quiet and Boost. # Authoritative Heat Pump profile helper: Boost / Quiet / Normal.
- platform: homeassistant - platform: homeassistant
id: ha_climate_profile id: ha_climate_profile
entity_id: "${climate_profile_entity}" entity_id: "${climate_profile_entity}"
internal: true internal: true
on_value: on_value:
then: then:
- script.execute: refresh_climate_controls - lambda: |-
if (x == "Quiet" || x == "quiet") {
id(climate_profile_optimistic) = 1;
} else if (x == "Boost" || x == "boost") {
id(climate_profile_optimistic) = 2;
} else {
id(climate_profile_optimistic) = 0;
}
# Actual climate preset provides an additional authoritative profile state.
- platform: homeassistant
id: ha_climate_preset_mode
entity_id: "${climate_entity}"
attribute: preset_mode
internal: true
on_value:
then:
- script.execute: refresh_climate_controls - script.execute: refresh_climate_controls
- platform: version - platform: version
@@ -1912,12 +1810,12 @@ lvgl:
entity_id: "${climate_dry_script}" entity_id: "${climate_dry_script}"
#:################################################################################:# #:################################################################################:#
# HEAT-PUMP PROFILE / SETPOINT # HEAT-PUMP PROFILE / NANO-X / SETPOINT
#:################################################################################:# #:################################################################################:#
- label: - label:
x: 535 x: 625
y: 187 y: 187
width: 270 width: 230
text: "Setpoint" text: "Setpoint"
text_font: font_small text_font: font_small
text_align: CENTER text_align: CENTER
@@ -1927,7 +1825,7 @@ lvgl:
id: climate_quiet_button id: climate_quiet_button
x: 25 x: 25
y: 218 y: 218
width: 170 width: 145
height: 105 height: 105
bg_color: 0x28313D bg_color: 0x28313D
bg_opa: COVER bg_opa: COVER
@@ -1943,44 +1841,37 @@ lvgl:
text_font: font_button text_font: font_button
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
# Quiet -> None when already active; otherwise select Quiet. # Quiet toggles between Quiet and Normal.
- lambda: |- - lambda: |-
int selected = id(climate_profile_optimistic);
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" ||
preset == "Boost" ||
preset == "boost"
) {
selected = 2;
} else {
selected = 0;
}
}
id(climate_profile_optimistic) = id(climate_profile_optimistic) =
selected == 1 ? 0 : 1; id(climate_profile_optimistic) == 1 ? 0 : 1;
- script.execute: refresh_climate_controls - script.execute: refresh_climate_controls
- script.execute: apply_climate_profile_target
- if:
condition:
lambda: |-
return id(climate_profile_optimistic) == 1;
then:
- homeassistant.action:
action: input_select.select_option
data:
entity_id: "${climate_profile_entity}"
option: "Quiet"
else:
- homeassistant.action:
action: input_select.select_option
data:
entity_id: "${climate_profile_entity}"
option: "Normal"
- button: - button:
id: climate_boost_button id: climate_boost_button
x: 205 x: 180
y: 218 y: 218
width: 170 width: 145
height: 105 height: 105
bg_color: 0x28313D bg_color: 0x28313D
bg_opa: COVER bg_opa: COVER
@@ -1996,44 +1887,62 @@ lvgl:
text_font: font_button text_font: font_button
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
# Boost -> None when already active; otherwise select Boost. # Boost toggles between Boost and Normal.
- lambda: |- - lambda: |-
int selected = id(climate_profile_optimistic);
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" ||
preset == "Boost" ||
preset == "boost"
) {
selected = 2;
} else {
selected = 0;
}
}
id(climate_profile_optimistic) = id(climate_profile_optimistic) =
selected == 2 ? 0 : 2; id(climate_profile_optimistic) == 2 ? 0 : 2;
- script.execute: refresh_climate_controls - script.execute: refresh_climate_controls
- script.execute: apply_climate_profile_target
- if:
condition:
lambda: |-
return id(climate_profile_optimistic) == 2;
then:
- homeassistant.action:
action: input_select.select_option
data:
entity_id: "${climate_profile_entity}"
option: "Boost"
else:
- homeassistant.action:
action: input_select.select_option
data:
entity_id: "${climate_profile_entity}"
option: "Normal"
- button:
id: climate_nanoe_button
x: 335
y: 218
width: 145
height: 105
bg_color: 0x28313D
bg_opa: COVER
border_width: 2
border_color: 0x47789B
radius: 18
pressed:
bg_color: 0x315E82
widgets:
- label:
align: CENTER
text: "Nano-X"
text_font: font_button
text_color: 0xFFFFFF
on_click:
- homeassistant.action:
action: switch.toggle
data:
entity_id: "${nanoe_entity}"
- button: - button:
id: climate_setpoint_down_button id: climate_setpoint_down_button
x: 405 x: 505
y: 218 y: 218
width: 120 width: 110
height: 105 height: 105
bg_color: 0x28313D bg_color: 0x28313D
bg_opa: COVER bg_opa: COVER
@@ -2056,9 +1965,9 @@ lvgl:
- button: - button:
id: climate_setpoint_display id: climate_setpoint_display
x: 535 x: 625
y: 218 y: 218
width: 270 width: 230
height: 105 height: 105
bg_color: 0x1C2632 bg_color: 0x1C2632
bg_opa: COVER bg_opa: COVER
@@ -2075,7 +1984,7 @@ lvgl:
- button: - button:
id: climate_setpoint_up_button id: climate_setpoint_up_button
x: 815 x: 865
y: 218 y: 218
width: 120 width: 120
height: 105 height: 105
@@ -2105,7 +2014,7 @@ lvgl:
id: ceiling_fan_cycle_button id: ceiling_fan_cycle_button
x: 25 x: 25
y: 356 y: 356
width: 310 width: 306
height: 100 height: 100
bg_color: 0x28313D bg_color: 0x28313D
bg_opa: COVER bg_opa: COVER
@@ -2181,9 +2090,9 @@ lvgl:
- button: - button:
id: air_filter_quiet_button id: air_filter_quiet_button
x: 357 x: 352
y: 356 y: 356
width: 310 width: 306
height: 100 height: 100
bg_color: 0x28313D bg_color: 0x28313D
bg_opa: COVER bg_opa: COVER
@@ -2207,9 +2116,9 @@ lvgl:
- button: - button:
id: climate_night_power_button id: climate_night_power_button
x: 689 x: 679
y: 356 y: 356
width: 310 width: 307
height: 100 height: 100
bg_color: 0x28313D bg_color: 0x28313D
bg_opa: COVER bg_opa: COVER
@@ -2230,23 +2139,26 @@ lvgl:
data: data:
entity_id: "${climate_night_power_entity}" entity_id: "${climate_night_power_entity}"
#:################################################################################:#
# BOTTOM NAVIGATION
#:################################################################################:#
- button: - button:
id: climate_back_button id: climate_back_button
x: 365 x: 612
y: 490 y: 475
width: 294 width: 190
height: 78 height: 92
bg_color: 0x315843 bg_color: 0x315843
bg_opa: COVER bg_opa: COVER
border_width: 2 border_width: 2
border_color: 0x548C6C border_color: 0x548C6C
radius: 18 radius: 16
pressed: pressed:
bg_color: 0x416F55 bg_color: 0x416F55
widgets: widgets:
- label: - label:
align: CENTER align: CENTER
text: "Back to Bedroom" text: "Back"
text_font: font_button text_font: font_button
text_color: 0xFFFFFF text_color: 0xFFFFFF
on_click: on_click:
@@ -2255,6 +2167,36 @@ lvgl:
animation: MOVE_RIGHT animation: MOVE_RIGHT
time: 220ms time: 220ms
- button:
id: climate_clock_button
x: 810
y: 475
width: 190
height: 92
bg_color: 0x214F72
bg_opa: COVER
border_width: 2
border_color: 0x3E7FA7
radius: 16
pressed:
bg_color: 0x2E6A96
widgets:
- label:
align: CENTER
text: "Clock"
text_font: font_button
text_color: 0xFFFFFF
on_click:
- lvgl.page.show:
id: clock_page
animation: FADE_IN
time: 250ms
- light.turn_on:
id: display_backlight
brightness: "${clock_brightness}"
transition_length: 1500ms
#:####################################################################################:# #:####################################################################################:#
# CLOCK PAGE # CLOCK PAGE
#:####################################################################################:# #:####################################################################################:#