Edit esp-bedside-panel.yaml

This commit is contained in:
ESPHome Device Builder
2026-07-16 22:03:57 +12:00
parent ee08838c1f
commit 8b31b780b0
+167 -22
View File
@@ -6,6 +6,7 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedside-panel.yaml
#:########################################################################################:#
# VERSIONS:
# V1.0 2026-07-16 First full Bedroom/Climate/Clock release; added 2-hour Sleep timer
# V0.8u 2026-07-16 Enlarged Clock and date; moved environment readings lower
# V0.8t 2026-07-16 Corrected Panasonic presets to quiet / powerful / none
# V0.8s 2026-07-16 Added direct Panasonic preset control and optimistic Nano-X
@@ -74,7 +75,9 @@
# - Touching the clock:
# - Returns to the Bedroom controls.
# - Restores normal brightness.
# - The Climate page contains working Off, Heat, Cool and Dehumid controls.
# - The Climate page contains heat-pump, ceiling-fan, air-filter and Night Power controls.
# - Sleep: 2 hrs starts a local 120-minute countdown and turns the heat pump off.
# - Pressing the active Sleep button again cancels the countdown.
#:########################################################################################:#
# OFFLINE NOTES:
# - LVGL, the clock, touch and backlight operate locally.
@@ -91,12 +94,12 @@ substitutions:
# Device Naming
device_name: "esp-bedside-panel"
friendly_name: "ESP Bedside Panel"
description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside control panel. Larger bedside clock and date with lower environment status row. (Layout V1.1)"
description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside control panel. V1.0 Bedroom, Climate and Clock release with local 2-hour Sleep timer. (Layout V1.1)"
device_area: "Bedroom"
# Project Naming
project_name: "Guition.JC1060P470C_I_W_Y"
project_version: "v0.8u"
project_version: "v1.0"
# Passwords & Secrets
api_key: !secret esp-api_key
@@ -223,6 +226,7 @@ esphome:
- script.execute: refresh_api_indicator
- script.execute: refresh_button_states
- script.execute: refresh_sleep_timer
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK:
@@ -783,6 +787,13 @@ globals:
restore_value: false
initial_value: "-1"
# Unix timestamp at which the 2-hour Sleep timer expires.
# A value of 0 means that the timer is inactive.
- id: sleep_timer_end_epoch
type: uint32_t
restore_value: true
initial_value: "0"
#:########################################################################################:#
# SCRIPTS:
# Refresh all state-dependent LVGL button colours
@@ -1121,7 +1132,7 @@ script:
snprintf(buffer, sizeof(buffer), "%.1f°C", value);
return std::string(buffer);
# One-button ceiling-fan cycle: Off -> 1 -> 2 -> 3 -> Off.
# One-button ceiling-fan cycle: Off -> Low -> Medium -> High -> Off.
- lvgl.label.update:
id: ceiling_fan_cycle_label
text: !lambda |-
@@ -1132,14 +1143,14 @@ script:
const float percentage = id(ha_ceiling_fan_percentage).state;
if (isnan(percentage) || percentage < 50.0f) {
return std::string("Ceiling Fan: 1");
return std::string("Ceiling Fan: Low");
}
if (percentage < 85.0f) {
return std::string("Ceiling Fan: 2");
return std::string("Ceiling Fan: Medium");
}
return std::string("Ceiling Fan: 3");
return std::string("Ceiling Fan: High");
- lvgl.widget.update:
id: ceiling_fan_cycle_button
@@ -1170,6 +1181,60 @@ script:
? lv_color_hex(0x5A4778)
: lv_color_hex(0x28313D);
# Update the Sleep timer label and active button colour.
- id: refresh_sleep_timer
mode: restart
then:
- if:
condition:
lambda: |-
return id(lvgl_ready);
then:
- lvgl.label.update:
id: sleep_timer_button_label
text: !lambda |-
const auto now = id(ha_time).now();
if (
id(sleep_timer_end_epoch) == 0 ||
!now.is_valid() ||
now.timestamp >= id(sleep_timer_end_epoch)
) {
return std::string("Sleep: 2 hrs (0)");
}
const uint32_t seconds_remaining =
id(sleep_timer_end_epoch) - now.timestamp;
const uint32_t minutes_remaining =
(seconds_remaining + 59) / 60;
char buffer[32];
snprintf(
buffer,
sizeof(buffer),
"Sleep: 2 hrs (%u)",
static_cast<unsigned>(minutes_remaining)
);
return std::string(buffer);
- lvgl.widget.update:
id: sleep_timer_button
bg_color: !lambda |-
const auto now = id(ha_time).now();
const bool active = (
id(sleep_timer_end_epoch) > 0 &&
now.is_valid() &&
now.timestamp < id(sleep_timer_end_epoch)
);
return active
? lv_color_hex(0x6B4A86)
: lv_color_hex(0x28313D);
- id: release_climate_profile_optimistic
mode: restart
then:
@@ -1199,6 +1264,7 @@ script:
- delay: 3500ms
- script.execute: refresh_button_states
- script.execute: refresh_sleep_timer
#:########################################################################################:#
# INTERVAL:
@@ -1246,6 +1312,32 @@ interval:
return std::string(buffer);
# Maintain the local two-hour Sleep countdown.
- if:
condition:
lambda: |-
const auto now = id(ha_time).now();
return (
id(sleep_timer_end_epoch) > 0 &&
now.is_valid() &&
now.timestamp >= id(sleep_timer_end_epoch)
);
then:
- lambda: |-
id(sleep_timer_end_epoch) = 0;
- homeassistant.action:
action: script.turn_on
data:
entity_id: "${climate_off_script}"
- script.execute: refresh_sleep_timer
else:
- script.execute: refresh_sleep_timer
#:########################################################################################:#
# TEXT SENSOR COMPONENT:
# https://esphome.io/components/text_sensor/
@@ -2249,13 +2341,13 @@ lvgl:
step: "0.5"
#:################################################################################:#
# CEILING FAN / AIR FILTER / NIGHT POWER
# CEILING FAN / AIR FILTER / NIGHT POWER / SLEEP TIMER
#:################################################################################:#
- button:
id: ceiling_fan_cycle_button
x: 25
y: 356
width: 306
width: 220
height: 100
bg_color: 0x28313D
bg_opa: COVER
@@ -2269,10 +2361,10 @@ lvgl:
id: ceiling_fan_cycle_label
align: CENTER
text: "Ceiling Fan: Off"
text_font: font_button
text_font: font_small
text_color: 0xFFFFFF
on_click:
# Off -> speed 1
# Off -> Low
- if:
condition:
lambda: |-
@@ -2286,7 +2378,7 @@ lvgl:
percentage: "33"
else:
# Speed 1 -> speed 2
# Low -> Medium
- if:
condition:
lambda: |-
@@ -2306,7 +2398,7 @@ lvgl:
percentage: "66"
else:
# Speed 2 -> speed 3
# Medium -> High
- if:
condition:
lambda: |-
@@ -2322,7 +2414,7 @@ lvgl:
entity_id: "${ceiling_fan_entity}"
percentage: "100"
# Speed 3 -> Off
# High -> Off
else:
- homeassistant.action:
action: fan.turn_off
@@ -2331,9 +2423,9 @@ lvgl:
- button:
id: air_filter_quiet_button
x: 352
x: 272
y: 356
width: 306
width: 220
height: 100
bg_color: 0x28313D
bg_opa: COVER
@@ -2345,8 +2437,8 @@ lvgl:
widgets:
- label:
align: CENTER
text: "Air Filter Quiet"
text_font: font_button
text: "Air Filter: Quiet"
text_font: font_small
text_color: 0xFFFFFF
on_click:
- homeassistant.action:
@@ -2357,9 +2449,9 @@ lvgl:
- button:
id: climate_night_power_button
x: 679
x: 519
y: 356
width: 307
width: 220
height: 100
bg_color: 0x28313D
bg_opa: COVER
@@ -2371,8 +2463,8 @@ lvgl:
widgets:
- label:
align: CENTER
text: "Climate 9pm-12"
text_font: font_button
text: "Climate: 9pm-12am"
text_font: font_small
text_color: 0xFFFFFF
on_click:
- homeassistant.action:
@@ -2380,6 +2472,59 @@ lvgl:
data:
entity_id: "${climate_night_power_entity}"
- button:
id: sleep_timer_button
x: 766
y: 356
width: 220
height: 100
bg_color: 0x28313D
bg_opa: COVER
border_width: 2
border_color: 0x80619B
radius: 18
pressed:
bg_color: 0x6B4A86
widgets:
- label:
id: sleep_timer_button_label
align: CENTER
text: "Sleep: 2 hrs (0)"
text_font: font_small
text_color: 0xFFFFFF
on_click:
# Pressing an active Sleep timer cancels it. Otherwise, start
# a new 120-minute countdown.
- if:
condition:
lambda: |-
const auto now = id(ha_time).now();
return (
id(sleep_timer_end_epoch) > 0 &&
now.is_valid() &&
now.timestamp < id(sleep_timer_end_epoch)
);
then:
- lambda: |-
id(sleep_timer_end_epoch) = 0;
else:
- if:
condition:
lambda: |-
return id(ha_time).now().is_valid();
then:
- lambda: |-
const auto now = id(ha_time).now();
id(sleep_timer_end_epoch) =
now.timestamp + (120 * 60);
- script.execute: refresh_sleep_timer
#:################################################################################:#
# BOTTOM NAVIGATION
#:################################################################################:#