Edit esp-bedside-panel.yaml
This commit is contained in:
+167
-22
@@ -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:
|
||||||
|
# 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.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.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
|
# V0.8s 2026-07-16 Added direct Panasonic preset control and optimistic Nano-X
|
||||||
@@ -74,7 +75,9 @@
|
|||||||
# - Touching the clock:
|
# - Touching the clock:
|
||||||
# - Returns to the Bedroom controls.
|
# - Returns to the Bedroom controls.
|
||||||
# - Restores normal brightness.
|
# - 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:
|
# OFFLINE NOTES:
|
||||||
# - LVGL, the clock, touch and backlight operate locally.
|
# - LVGL, the clock, touch and backlight operate locally.
|
||||||
@@ -91,12 +94,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. 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"
|
device_area: "Bedroom"
|
||||||
|
|
||||||
# Project Naming
|
# Project Naming
|
||||||
project_name: "Guition.JC1060P470C_I_W_Y"
|
project_name: "Guition.JC1060P470C_I_W_Y"
|
||||||
project_version: "v0.8u"
|
project_version: "v1.0"
|
||||||
|
|
||||||
# Passwords & Secrets
|
# Passwords & Secrets
|
||||||
api_key: !secret esp-api_key
|
api_key: !secret esp-api_key
|
||||||
@@ -223,6 +226,7 @@ esphome:
|
|||||||
|
|
||||||
- script.execute: refresh_api_indicator
|
- script.execute: refresh_api_indicator
|
||||||
- script.execute: refresh_button_states
|
- script.execute: refresh_button_states
|
||||||
|
- script.execute: refresh_sleep_timer
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# ESP PLATFORM AND FRAMEWORK:
|
# ESP PLATFORM AND FRAMEWORK:
|
||||||
@@ -783,6 +787,13 @@ globals:
|
|||||||
restore_value: false
|
restore_value: false
|
||||||
initial_value: "-1"
|
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:
|
# SCRIPTS:
|
||||||
# Refresh all state-dependent LVGL button colours
|
# Refresh all state-dependent LVGL button colours
|
||||||
@@ -1121,7 +1132,7 @@ script:
|
|||||||
snprintf(buffer, sizeof(buffer), "%.1f°C", value);
|
snprintf(buffer, sizeof(buffer), "%.1f°C", value);
|
||||||
return std::string(buffer);
|
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:
|
- lvgl.label.update:
|
||||||
id: ceiling_fan_cycle_label
|
id: ceiling_fan_cycle_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
@@ -1132,14 +1143,14 @@ script:
|
|||||||
const float percentage = id(ha_ceiling_fan_percentage).state;
|
const float percentage = id(ha_ceiling_fan_percentage).state;
|
||||||
|
|
||||||
if (isnan(percentage) || percentage < 50.0f) {
|
if (isnan(percentage) || percentage < 50.0f) {
|
||||||
return std::string("Ceiling Fan: 1");
|
return std::string("Ceiling Fan: Low");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (percentage < 85.0f) {
|
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:
|
- lvgl.widget.update:
|
||||||
id: ceiling_fan_cycle_button
|
id: ceiling_fan_cycle_button
|
||||||
@@ -1170,6 +1181,60 @@ script:
|
|||||||
? lv_color_hex(0x5A4778)
|
? lv_color_hex(0x5A4778)
|
||||||
: lv_color_hex(0x28313D);
|
: 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
|
- id: release_climate_profile_optimistic
|
||||||
mode: restart
|
mode: restart
|
||||||
then:
|
then:
|
||||||
@@ -1199,6 +1264,7 @@ script:
|
|||||||
|
|
||||||
- delay: 3500ms
|
- delay: 3500ms
|
||||||
- script.execute: refresh_button_states
|
- script.execute: refresh_button_states
|
||||||
|
- script.execute: refresh_sleep_timer
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# INTERVAL:
|
# INTERVAL:
|
||||||
@@ -1246,6 +1312,32 @@ interval:
|
|||||||
|
|
||||||
return std::string(buffer);
|
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:
|
# TEXT SENSOR COMPONENT:
|
||||||
# https://esphome.io/components/text_sensor/
|
# https://esphome.io/components/text_sensor/
|
||||||
@@ -2249,13 +2341,13 @@ lvgl:
|
|||||||
step: "0.5"
|
step: "0.5"
|
||||||
|
|
||||||
#:################################################################################:#
|
#:################################################################################:#
|
||||||
# CEILING FAN / AIR FILTER / NIGHT POWER
|
# CEILING FAN / AIR FILTER / NIGHT POWER / SLEEP TIMER
|
||||||
#:################################################################################:#
|
#:################################################################################:#
|
||||||
- button:
|
- button:
|
||||||
id: ceiling_fan_cycle_button
|
id: ceiling_fan_cycle_button
|
||||||
x: 25
|
x: 25
|
||||||
y: 356
|
y: 356
|
||||||
width: 306
|
width: 220
|
||||||
height: 100
|
height: 100
|
||||||
bg_color: 0x28313D
|
bg_color: 0x28313D
|
||||||
bg_opa: COVER
|
bg_opa: COVER
|
||||||
@@ -2269,10 +2361,10 @@ lvgl:
|
|||||||
id: ceiling_fan_cycle_label
|
id: ceiling_fan_cycle_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: "Ceiling Fan: Off"
|
text: "Ceiling Fan: Off"
|
||||||
text_font: font_button
|
text_font: font_small
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_click:
|
on_click:
|
||||||
# Off -> speed 1
|
# Off -> Low
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
lambda: |-
|
lambda: |-
|
||||||
@@ -2286,7 +2378,7 @@ lvgl:
|
|||||||
percentage: "33"
|
percentage: "33"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Speed 1 -> speed 2
|
# Low -> Medium
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
lambda: |-
|
lambda: |-
|
||||||
@@ -2306,7 +2398,7 @@ lvgl:
|
|||||||
percentage: "66"
|
percentage: "66"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Speed 2 -> speed 3
|
# Medium -> High
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
lambda: |-
|
lambda: |-
|
||||||
@@ -2322,7 +2414,7 @@ lvgl:
|
|||||||
entity_id: "${ceiling_fan_entity}"
|
entity_id: "${ceiling_fan_entity}"
|
||||||
percentage: "100"
|
percentage: "100"
|
||||||
|
|
||||||
# Speed 3 -> Off
|
# High -> Off
|
||||||
else:
|
else:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: fan.turn_off
|
action: fan.turn_off
|
||||||
@@ -2331,9 +2423,9 @@ lvgl:
|
|||||||
|
|
||||||
- button:
|
- button:
|
||||||
id: air_filter_quiet_button
|
id: air_filter_quiet_button
|
||||||
x: 352
|
x: 272
|
||||||
y: 356
|
y: 356
|
||||||
width: 306
|
width: 220
|
||||||
height: 100
|
height: 100
|
||||||
bg_color: 0x28313D
|
bg_color: 0x28313D
|
||||||
bg_opa: COVER
|
bg_opa: COVER
|
||||||
@@ -2345,8 +2437,8 @@ lvgl:
|
|||||||
widgets:
|
widgets:
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: "Air Filter Quiet"
|
text: "Air Filter: Quiet"
|
||||||
text_font: font_button
|
text_font: font_small
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_click:
|
on_click:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
@@ -2357,9 +2449,9 @@ lvgl:
|
|||||||
|
|
||||||
- button:
|
- button:
|
||||||
id: climate_night_power_button
|
id: climate_night_power_button
|
||||||
x: 679
|
x: 519
|
||||||
y: 356
|
y: 356
|
||||||
width: 307
|
width: 220
|
||||||
height: 100
|
height: 100
|
||||||
bg_color: 0x28313D
|
bg_color: 0x28313D
|
||||||
bg_opa: COVER
|
bg_opa: COVER
|
||||||
@@ -2371,8 +2463,8 @@ lvgl:
|
|||||||
widgets:
|
widgets:
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: "Climate 9pm-12"
|
text: "Climate: 9pm-12am"
|
||||||
text_font: font_button
|
text_font: font_small
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_click:
|
on_click:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
@@ -2380,6 +2472,59 @@ lvgl:
|
|||||||
data:
|
data:
|
||||||
entity_id: "${climate_night_power_entity}"
|
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
|
# BOTTOM NAVIGATION
|
||||||
#:################################################################################:#
|
#:################################################################################:#
|
||||||
|
|||||||
Reference in New Issue
Block a user