Edit esp-bedside-panel.yaml
This commit is contained in:
+462
-131
@@ -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.9 2026-07-17 Corrected Atto lock/climate/setpoint controls and added vehicle icons
|
||||||
# V1.8 2026-07-17 Added hold-to-open Atto Vehicles page and vehicle controls
|
# V1.8 2026-07-17 Added hold-to-open Atto Vehicles page and vehicle controls
|
||||||
# V1.7 2026-07-17 Added Bedroom button icons and corrected Panasonic Nanoe-X naming
|
# V1.7 2026-07-17 Added Bedroom button icons and corrected Panasonic Nanoe-X naming
|
||||||
# V1.6 2026-07-17 Reordered the nine Bedroom control buttons
|
# V1.6 2026-07-17 Reordered the nine Bedroom control buttons
|
||||||
@@ -106,12 +107,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. Bedroom, Vehicles, Climate, Security and Clock pages. (Layout V1.1)"
|
description_comment: "Guition JC1060P470C_I_W_Y ESP32-P4 bedside control panel. Vehicles page with corrected BYD lock, climate and setpoint 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: "v1.8"
|
project_version: "v1.9"
|
||||||
|
|
||||||
# Passwords & Secrets
|
# Passwords & Secrets
|
||||||
api_key: !secret esp-api_key
|
api_key: !secret esp-api_key
|
||||||
@@ -185,9 +186,7 @@ substitutions:
|
|||||||
nanoe_entity: "switch.master_bedroom_nanoe"
|
nanoe_entity: "switch.master_bedroom_nanoe"
|
||||||
|
|
||||||
# Home Assistant Entities - Vehicles / Atto 3
|
# Home Assistant Entities - Vehicles / Atto 3
|
||||||
atto_locked_sensor_entity: "binary_sensor.atto_3_locked"
|
# BYD Vehicle integration lock entity; used for both status and control.
|
||||||
# BYD Vehicle integration lock entity. Adjust only if HA generated a
|
|
||||||
# different entity_id for the Atto 3 lock control.
|
|
||||||
atto_lock_entity: "lock.atto_3_lock"
|
atto_lock_entity: "lock.atto_3_lock"
|
||||||
atto_driver_seat_heating_entity: "select.atto_3_driver_seat_heating"
|
atto_driver_seat_heating_entity: "select.atto_3_driver_seat_heating"
|
||||||
atto_passenger_seat_heating_entity: "select.atto_3_passenger_seat_heating"
|
atto_passenger_seat_heating_entity: "select.atto_3_passenger_seat_heating"
|
||||||
@@ -529,6 +528,23 @@ font:
|
|||||||
- "\U000F06D9" # mdi-garage
|
- "\U000F06D9" # mdi-garage
|
||||||
- "\U000F1054" # mdi-outdoor-lamp
|
- "\U000F1054" # mdi-outdoor-lamp
|
||||||
|
|
||||||
|
# Compact Vehicles-page icon font.
|
||||||
|
- file: "https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/fonts/materialdesignicons-webfont.ttf"
|
||||||
|
id: font_mdi_vehicle
|
||||||
|
size: 27
|
||||||
|
bpp: 4
|
||||||
|
glyphs:
|
||||||
|
- "\U000F033E" # mdi-lock
|
||||||
|
- "\U000F0FC6" # mdi-lock-open-variant
|
||||||
|
- "\U000F0084" # mdi-battery-charging
|
||||||
|
- "\U000F00F0" # mdi-calendar-clock
|
||||||
|
- "\U000F08F0" # mdi-map-marker-distance
|
||||||
|
- "\U000F0079" # mdi-battery
|
||||||
|
- "\U000F050F" # mdi-thermometer
|
||||||
|
- "\U000F0FA6" # mdi-car-seat-heater
|
||||||
|
- "\U000F0238" # mdi-fire
|
||||||
|
- "\U000F0717" # mdi-snowflake
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# HOME ASSISTANT NUMERIC SENSORS:
|
# HOME ASSISTANT NUMERIC SENSORS:
|
||||||
# https://esphome.io/components/sensor/homeassistant.html
|
# https://esphome.io/components/sensor/homeassistant.html
|
||||||
@@ -679,6 +695,12 @@ sensor:
|
|||||||
internal: true
|
internal: true
|
||||||
on_value:
|
on_value:
|
||||||
then:
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
if (!isnan(x)) {
|
||||||
|
id(atto_setpoint_local) = x;
|
||||||
|
id(atto_setpoint_optimistic) = false;
|
||||||
|
}
|
||||||
|
|
||||||
- script.execute: refresh_vehicle_controls
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
@@ -689,14 +711,6 @@ binary_sensor:
|
|||||||
#:######################################################################################:#
|
#:######################################################################################:#
|
||||||
# ATTO 3 BINARY STATES
|
# ATTO 3 BINARY STATES
|
||||||
#:######################################################################################:#
|
#:######################################################################################:#
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_atto_locked
|
|
||||||
entity_id: "${atto_locked_sensor_entity}"
|
|
||||||
internal: true
|
|
||||||
on_state:
|
|
||||||
then:
|
|
||||||
- script.execute: refresh_vehicle_controls
|
|
||||||
|
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: ha_atto_charging
|
id: ha_atto_charging
|
||||||
entity_id: "${atto_charging_entity}"
|
entity_id: "${atto_charging_entity}"
|
||||||
@@ -921,6 +935,29 @@ globals:
|
|||||||
restore_value: false
|
restore_value: false
|
||||||
initial_value: "-1"
|
initial_value: "-1"
|
||||||
|
|
||||||
|
# Atto lock optimistic state: -1 follows HA, 0 unlocked, 1 locked.
|
||||||
|
- id: atto_lock_optimistic
|
||||||
|
type: int
|
||||||
|
restore_value: false
|
||||||
|
initial_value: "-1"
|
||||||
|
|
||||||
|
# Atto climate direction: -1 follows HA preset, 1 max heat, 2 max cool.
|
||||||
|
- id: atto_climate_optimistic
|
||||||
|
type: int
|
||||||
|
restore_value: false
|
||||||
|
initial_value: "-1"
|
||||||
|
|
||||||
|
# Local target is used so repeated presses do not work from stale cloud data.
|
||||||
|
- id: atto_setpoint_local
|
||||||
|
type: float
|
||||||
|
restore_value: false
|
||||||
|
initial_value: "21.0"
|
||||||
|
|
||||||
|
- id: atto_setpoint_optimistic
|
||||||
|
type: bool
|
||||||
|
restore_value: false
|
||||||
|
initial_value: "false"
|
||||||
|
|
||||||
# Unix timestamp at which the 2-hour Sleep timer expires.
|
# Unix timestamp at which the 2-hour Sleep timer expires.
|
||||||
# A value of 0 means that the timer is inactive.
|
# A value of 0 means that the timer is inactive.
|
||||||
- id: sleep_timer_end_epoch
|
- id: sleep_timer_end_epoch
|
||||||
@@ -1082,20 +1119,63 @@ script:
|
|||||||
return id(lvgl_ready);
|
return id(lvgl_ready);
|
||||||
|
|
||||||
then:
|
then:
|
||||||
|
# Lock state and optimistic lock/unlock feedback.
|
||||||
- lvgl.label.update:
|
- lvgl.label.update:
|
||||||
id: atto_lock_button_label
|
id: atto_lock_button_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
return id(ha_atto_locked).state
|
if (id(atto_lock_optimistic) == 1) {
|
||||||
? std::string("Locked (Hold)")
|
return std::string("Locked (Hold)");
|
||||||
: std::string("Unlocked (Hold)");
|
}
|
||||||
|
|
||||||
|
if (id(atto_lock_optimistic) == 0) {
|
||||||
|
return std::string("Unlocked (Hold)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto state = id(ha_atto_lock_state).state;
|
||||||
|
|
||||||
|
if (state == "locked") {
|
||||||
|
return std::string("Locked (Hold)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == "locking") {
|
||||||
|
return std::string("Locking...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == "unlocking") {
|
||||||
|
return std::string("Unlocking...");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string("Unlocked (Hold)");
|
||||||
|
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: atto_lock_icon_label
|
||||||
|
text: !lambda |-
|
||||||
|
bool locked = id(atto_lock_optimistic) == 1;
|
||||||
|
|
||||||
|
if (id(atto_lock_optimistic) < 0) {
|
||||||
|
const auto state = id(ha_atto_lock_state).state;
|
||||||
|
locked = state == "locked" || state == "locking";
|
||||||
|
}
|
||||||
|
|
||||||
|
return locked
|
||||||
|
? std::string("\U000F033E")
|
||||||
|
: std::string("\U000F0FC6");
|
||||||
|
|
||||||
- lvgl.widget.update:
|
- lvgl.widget.update:
|
||||||
id: atto_lock_button
|
id: atto_lock_button
|
||||||
bg_color: !lambda |-
|
bg_color: !lambda |-
|
||||||
return id(ha_atto_locked).state
|
bool locked = id(atto_lock_optimistic) == 1;
|
||||||
|
|
||||||
|
if (id(atto_lock_optimistic) < 0) {
|
||||||
|
const auto state = id(ha_atto_lock_state).state;
|
||||||
|
locked = state == "locked" || state == "locking";
|
||||||
|
}
|
||||||
|
|
||||||
|
return locked
|
||||||
? lv_color_hex(0x315843)
|
? lv_color_hex(0x315843)
|
||||||
: lv_color_hex(0x6B3A3A);
|
: lv_color_hex(0x6B3A3A);
|
||||||
|
|
||||||
|
# Charging and schedule status.
|
||||||
- lvgl.label.update:
|
- lvgl.label.update:
|
||||||
id: atto_charging_label
|
id: atto_charging_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
@@ -1117,6 +1197,7 @@ script:
|
|||||||
? lv_color_hex(0x315E82)
|
? lv_color_hex(0x315E82)
|
||||||
: lv_color_hex(0x28313D);
|
: lv_color_hex(0x28313D);
|
||||||
|
|
||||||
|
# Vehicle values.
|
||||||
- lvgl.label.update:
|
- lvgl.label.update:
|
||||||
id: atto_range_label
|
id: atto_range_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
@@ -1156,49 +1237,21 @@ script:
|
|||||||
snprintf(buffer, sizeof(buffer), "Cabin Temp\n%.1f°C", value);
|
snprintf(buffer, sizeof(buffer), "Cabin Temp\n%.1f°C", value);
|
||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
|
|
||||||
- lvgl.label.update:
|
# Seat-heating states.
|
||||||
id: atto_driver_seat_button_label
|
|
||||||
text: !lambda |-
|
|
||||||
const auto value = id(ha_atto_driver_seat_heating).state;
|
|
||||||
|
|
||||||
if (value == "low" || value == "Low") {
|
|
||||||
return std::string("Drive Seat Heat (Hold)\nLow");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == "high" || value == "High") {
|
|
||||||
return std::string("Drive Seat Heat (Hold)\nHigh");
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string("Drive Seat Heat (Hold)\nOff");
|
|
||||||
|
|
||||||
- lvgl.widget.update:
|
|
||||||
id: atto_driver_seat_button
|
|
||||||
bg_color: !lambda |-
|
|
||||||
const auto value = id(ha_atto_driver_seat_heating).state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
value == "low" ||
|
|
||||||
value == "Low" ||
|
|
||||||
value == "high" ||
|
|
||||||
value == "High"
|
|
||||||
)
|
|
||||||
? lv_color_hex(0x7A4A22)
|
|
||||||
: lv_color_hex(0x28313D);
|
|
||||||
|
|
||||||
- lvgl.label.update:
|
- lvgl.label.update:
|
||||||
id: atto_passenger_seat_button_label
|
id: atto_passenger_seat_button_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
const auto value = id(ha_atto_passenger_seat_heating).state;
|
const auto value = id(ha_atto_passenger_seat_heating).state;
|
||||||
|
|
||||||
if (value == "low" || value == "Low") {
|
if (value == "low" || value == "Low") {
|
||||||
return std::string("Passenger Seat Heat (Hold)\nLow");
|
return std::string("Passenger Seat (Hold)\nLow");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == "high" || value == "High") {
|
if (value == "high" || value == "High") {
|
||||||
return std::string("Passenger Seat Heat (Hold)\nHigh");
|
return std::string("Passenger Seat (Hold)\nHigh");
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string("Passenger Seat Heat (Hold)\nOff");
|
return std::string("Passenger Seat (Hold)\nOff");
|
||||||
|
|
||||||
- lvgl.widget.update:
|
- lvgl.widget.update:
|
||||||
id: atto_passenger_seat_button
|
id: atto_passenger_seat_button
|
||||||
@@ -1214,33 +1267,124 @@ script:
|
|||||||
? lv_color_hex(0x7A4A22)
|
? lv_color_hex(0x7A4A22)
|
||||||
: lv_color_hex(0x28313D);
|
: lv_color_hex(0x28313D);
|
||||||
|
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: atto_driver_seat_button_label
|
||||||
|
text: !lambda |-
|
||||||
|
const auto value = id(ha_atto_driver_seat_heating).state;
|
||||||
|
|
||||||
|
if (value == "low" || value == "Low") {
|
||||||
|
return std::string("Driver Seat (Hold)\nLow");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == "high" || value == "High") {
|
||||||
|
return std::string("Driver Seat (Hold)\nHigh");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string("Driver Seat (Hold)\nOff");
|
||||||
|
|
||||||
|
- lvgl.widget.update:
|
||||||
|
id: atto_driver_seat_button
|
||||||
|
bg_color: !lambda |-
|
||||||
|
const auto value = id(ha_atto_driver_seat_heating).state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
value == "low" ||
|
||||||
|
value == "Low" ||
|
||||||
|
value == "high" ||
|
||||||
|
value == "High"
|
||||||
|
)
|
||||||
|
? lv_color_hex(0x7A4A22)
|
||||||
|
: lv_color_hex(0x28313D);
|
||||||
|
|
||||||
|
# BYD heating/cooling intent is represented by max presets.
|
||||||
- lvgl.widget.update:
|
- lvgl.widget.update:
|
||||||
id: atto_heat_button
|
id: atto_heat_button
|
||||||
bg_color: !lambda |-
|
bg_color: !lambda |-
|
||||||
return id(ha_atto_climate_mode).state == "heat"
|
int selected = id(atto_climate_optimistic);
|
||||||
|
|
||||||
|
if (selected < 0) {
|
||||||
|
selected =
|
||||||
|
id(ha_atto_climate_preset).state == "max_heat"
|
||||||
|
? 1
|
||||||
|
: (
|
||||||
|
id(ha_atto_climate_preset).state == "max_cool"
|
||||||
|
? 2
|
||||||
|
: 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected == 1
|
||||||
? lv_color_hex(0xB76822)
|
? lv_color_hex(0xB76822)
|
||||||
: lv_color_hex(0x28313D);
|
: lv_color_hex(0x28313D);
|
||||||
|
|
||||||
- lvgl.widget.update:
|
- lvgl.widget.update:
|
||||||
id: atto_cool_button
|
id: atto_cool_button
|
||||||
bg_color: !lambda |-
|
bg_color: !lambda |-
|
||||||
return id(ha_atto_climate_mode).state == "cool"
|
int selected = id(atto_climate_optimistic);
|
||||||
|
|
||||||
|
if (selected < 0) {
|
||||||
|
selected =
|
||||||
|
id(ha_atto_climate_preset).state == "max_heat"
|
||||||
|
? 1
|
||||||
|
: (
|
||||||
|
id(ha_atto_climate_preset).state == "max_cool"
|
||||||
|
? 2
|
||||||
|
: 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected == 2
|
||||||
? lv_color_hex(0x2E6A96)
|
? lv_color_hex(0x2E6A96)
|
||||||
: lv_color_hex(0x28313D);
|
: lv_color_hex(0x28313D);
|
||||||
|
|
||||||
|
# Use the local value while a command is pending, then HA again.
|
||||||
- lvgl.label.update:
|
- lvgl.label.update:
|
||||||
id: atto_setpoint_value_label
|
id: atto_setpoint_value_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
const float value = id(ha_atto_setpoint).state;
|
float value = id(atto_setpoint_local);
|
||||||
|
|
||||||
|
if (!id(atto_setpoint_optimistic)) {
|
||||||
|
value = id(ha_atto_setpoint).state;
|
||||||
|
}
|
||||||
|
|
||||||
if (isnan(value)) {
|
if (isnan(value)) {
|
||||||
return std::string("--.-°C");
|
return std::string("--.-°C");
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[16];
|
char buffer[16];
|
||||||
snprintf(buffer, sizeof(buffer), "%.1f°C", value);
|
snprintf(buffer, sizeof(buffer), "%.0f°C", value);
|
||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
|
|
||||||
|
- id: release_atto_lock_optimistic
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- delay: 8s
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_lock_optimistic) = -1;
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
|
- id: release_atto_climate_optimistic
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- delay: 10s
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_climate_optimistic) = -1;
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
|
- id: release_atto_setpoint_optimistic
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- delay: 12s
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_setpoint_optimistic) = false;
|
||||||
|
|
||||||
|
const float actual = id(ha_atto_setpoint).state;
|
||||||
|
if (!isnan(actual)) {
|
||||||
|
id(atto_setpoint_local) = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
# Update Climate-page labels and highlight the currently selected settings.
|
# Update Climate-page labels and highlight the currently selected settings.
|
||||||
- id: refresh_climate_controls
|
- id: refresh_climate_controls
|
||||||
mode: restart
|
mode: restart
|
||||||
@@ -1788,6 +1932,18 @@ text_sensor:
|
|||||||
#:######################################################################################:#
|
#:######################################################################################:#
|
||||||
# ATTO 3 TEXT STATES
|
# ATTO 3 TEXT STATES
|
||||||
#:######################################################################################:#
|
#:######################################################################################:#
|
||||||
|
# The lock entity state is locked/unlocked/locking/unlocking.
|
||||||
|
- platform: homeassistant
|
||||||
|
id: ha_atto_lock_state
|
||||||
|
entity_id: "${atto_lock_entity}"
|
||||||
|
internal: true
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_lock_optimistic) = -1;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: ha_atto_driver_seat_heating
|
id: ha_atto_driver_seat_heating
|
||||||
entity_id: "${atto_driver_seat_heating_entity}"
|
entity_id: "${atto_driver_seat_heating_entity}"
|
||||||
@@ -1812,6 +1968,19 @@ text_sensor:
|
|||||||
then:
|
then:
|
||||||
- script.execute: refresh_vehicle_controls
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
|
# BYD exposes heating/cooling intent as max_heat / max_cool presets.
|
||||||
|
- platform: homeassistant
|
||||||
|
id: ha_atto_climate_preset
|
||||||
|
entity_id: "${atto_climate_entity}"
|
||||||
|
attribute: preset_mode
|
||||||
|
internal: true
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_climate_optimistic) = -1;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
# Requested heat-pump mode helper used while a mode change is pending.
|
# Requested heat-pump mode helper used while a mode change is pending.
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: ha_climate_requested_mode
|
id: ha_climate_requested_mode
|
||||||
@@ -2615,32 +2784,58 @@ lvgl:
|
|||||||
pressed:
|
pressed:
|
||||||
bg_color: 0x416F55
|
bg_color: 0x416F55
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: atto_lock_icon_label
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F033E"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_lock_button_label
|
id: atto_lock_button_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 10
|
||||||
text: "Locked (Hold)"
|
text: "Locked (Hold)"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_long_press:
|
on_long_press:
|
||||||
then:
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
bool locked = false;
|
||||||
|
|
||||||
|
if (id(atto_lock_optimistic) >= 0) {
|
||||||
|
locked = id(atto_lock_optimistic) == 1;
|
||||||
|
} else {
|
||||||
|
const auto state = id(ha_atto_lock_state).state;
|
||||||
|
locked = state == "locked" || state == "locking";
|
||||||
|
}
|
||||||
|
|
||||||
|
id(atto_lock_optimistic) = locked ? 0 : 1;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ha_atto_locked).state;
|
return id(atto_lock_optimistic) == 1;
|
||||||
|
|
||||||
then:
|
then:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: lock.unlock
|
action: lock.lock
|
||||||
data:
|
data:
|
||||||
entity_id: "${atto_lock_entity}"
|
entity_id: "${atto_lock_entity}"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: lock.lock
|
action: lock.unlock
|
||||||
data:
|
data:
|
||||||
entity_id: "${atto_lock_entity}"
|
entity_id: "${atto_lock_entity}"
|
||||||
|
|
||||||
|
- script.execute: release_atto_lock_optimistic
|
||||||
|
|
||||||
- button:
|
- button:
|
||||||
id: atto_charging_status
|
id: atto_charging_status
|
||||||
x: 272
|
x: 272
|
||||||
@@ -2653,9 +2848,18 @@ lvgl:
|
|||||||
border_color: 0x548C6C
|
border_color: 0x548C6C
|
||||||
radius: 17
|
radius: 17
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F0084"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_charging_label
|
id: atto_charging_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 10
|
||||||
text: "Atto Charging\nNot Charging"
|
text: "Atto Charging\nNot Charging"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
@@ -2675,8 +2879,17 @@ lvgl:
|
|||||||
pressed:
|
pressed:
|
||||||
bg_color: 0x315E82
|
bg_color: 0x315E82
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F00F0"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 10
|
||||||
text: "Schedule Enabled"
|
text: "Schedule Enabled"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
@@ -2699,9 +2912,18 @@ lvgl:
|
|||||||
border_color: 0x526276
|
border_color: 0x526276
|
||||||
radius: 17
|
radius: 17
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F08F0"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_range_label
|
id: atto_range_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 10
|
||||||
text: "Atto Range\n-- km"
|
text: "Atto Range\n-- km"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
@@ -2722,9 +2944,18 @@ lvgl:
|
|||||||
border_color: 0x526276
|
border_color: 0x526276
|
||||||
radius: 17
|
radius: 17
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F0079"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_battery_label
|
id: atto_battery_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 10
|
||||||
text: "Battery Level\n--%"
|
text: "Battery Level\n--%"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
@@ -2742,16 +2973,26 @@ lvgl:
|
|||||||
border_color: 0x526276
|
border_color: 0x526276
|
||||||
radius: 17
|
radius: 17
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F050F"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_cabin_temperature_label
|
id: atto_cabin_temperature_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 10
|
||||||
text: "Cabin Temp\n--.-°C"
|
text: "Cabin Temp\n--.-°C"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
|
# Passenger seat is intentionally before Driver seat.
|
||||||
- button:
|
- button:
|
||||||
id: atto_driver_seat_button
|
id: atto_passenger_seat_button
|
||||||
x: 519
|
x: 519
|
||||||
y: 130
|
y: 130
|
||||||
width: 220
|
width: 220
|
||||||
@@ -2765,76 +3006,18 @@ lvgl:
|
|||||||
bg_color: 0x7A4A22
|
bg_color: 0x7A4A22
|
||||||
widgets:
|
widgets:
|
||||||
- label:
|
- label:
|
||||||
id: atto_driver_seat_button_label
|
align: TOP_LEFT
|
||||||
align: CENTER
|
x: 10
|
||||||
text: "Drive Seat Heat (Hold)\nOff"
|
y: 8
|
||||||
text_font: font_small
|
text: "\U000F0FA6"
|
||||||
text_align: CENTER
|
text_font: font_mdi_vehicle
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_long_press:
|
|
||||||
then:
|
|
||||||
- if:
|
|
||||||
condition:
|
|
||||||
lambda: |-
|
|
||||||
const auto value =
|
|
||||||
id(ha_atto_driver_seat_heating).state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
value == "off" ||
|
|
||||||
value == "Off" ||
|
|
||||||
value == "unknown" ||
|
|
||||||
value == "unavailable" ||
|
|
||||||
value.empty()
|
|
||||||
);
|
|
||||||
|
|
||||||
then:
|
|
||||||
- homeassistant.action:
|
|
||||||
action: select.select_option
|
|
||||||
data:
|
|
||||||
entity_id: "${atto_driver_seat_heating_entity}"
|
|
||||||
option: "low"
|
|
||||||
|
|
||||||
else:
|
|
||||||
- if:
|
|
||||||
condition:
|
|
||||||
lambda: |-
|
|
||||||
const auto value =
|
|
||||||
id(ha_atto_driver_seat_heating).state;
|
|
||||||
|
|
||||||
return value == "low" || value == "Low";
|
|
||||||
|
|
||||||
then:
|
|
||||||
- homeassistant.action:
|
|
||||||
action: select.select_option
|
|
||||||
data:
|
|
||||||
entity_id: "${atto_driver_seat_heating_entity}"
|
|
||||||
option: "high"
|
|
||||||
|
|
||||||
else:
|
|
||||||
- homeassistant.action:
|
|
||||||
action: select.select_option
|
|
||||||
data:
|
|
||||||
entity_id: "${atto_driver_seat_heating_entity}"
|
|
||||||
option: "off"
|
|
||||||
|
|
||||||
- button:
|
|
||||||
id: atto_passenger_seat_button
|
|
||||||
x: 766
|
|
||||||
y: 130
|
|
||||||
width: 220
|
|
||||||
height: 92
|
|
||||||
bg_color: 0x28313D
|
|
||||||
bg_opa: COVER
|
|
||||||
border_width: 2
|
|
||||||
border_color: 0xA6672B
|
|
||||||
radius: 17
|
|
||||||
pressed:
|
|
||||||
bg_color: 0x7A4A22
|
|
||||||
widgets:
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_passenger_seat_button_label
|
id: atto_passenger_seat_button_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: "Passenger Seat Heat (Hold)\nOff"
|
x: 10
|
||||||
|
text: "Passenger Seat (Hold)\nOff"
|
||||||
text_font: font_small
|
text_font: font_small
|
||||||
text_align: CENTER
|
text_align: CENTER
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
@@ -2884,6 +3067,82 @@ lvgl:
|
|||||||
entity_id: "${atto_passenger_seat_heating_entity}"
|
entity_id: "${atto_passenger_seat_heating_entity}"
|
||||||
option: "off"
|
option: "off"
|
||||||
|
|
||||||
|
- button:
|
||||||
|
id: atto_driver_seat_button
|
||||||
|
x: 766
|
||||||
|
y: 130
|
||||||
|
width: 220
|
||||||
|
height: 92
|
||||||
|
bg_color: 0x28313D
|
||||||
|
bg_opa: COVER
|
||||||
|
border_width: 2
|
||||||
|
border_color: 0xA6672B
|
||||||
|
radius: 17
|
||||||
|
pressed:
|
||||||
|
bg_color: 0x7A4A22
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: TOP_LEFT
|
||||||
|
x: 10
|
||||||
|
y: 8
|
||||||
|
text: "\U000F0FA6"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
|
- label:
|
||||||
|
id: atto_driver_seat_button_label
|
||||||
|
align: CENTER
|
||||||
|
x: 10
|
||||||
|
text: "Driver Seat (Hold)\nOff"
|
||||||
|
text_font: font_small
|
||||||
|
text_align: CENTER
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
on_long_press:
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
const auto value =
|
||||||
|
id(ha_atto_driver_seat_heating).state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
value == "off" ||
|
||||||
|
value == "Off" ||
|
||||||
|
value == "unknown" ||
|
||||||
|
value == "unavailable" ||
|
||||||
|
value.empty()
|
||||||
|
);
|
||||||
|
|
||||||
|
then:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: select.select_option
|
||||||
|
data:
|
||||||
|
entity_id: "${atto_driver_seat_heating_entity}"
|
||||||
|
option: "low"
|
||||||
|
|
||||||
|
else:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
const auto value =
|
||||||
|
id(ha_atto_driver_seat_heating).state;
|
||||||
|
|
||||||
|
return value == "low" || value == "Low";
|
||||||
|
|
||||||
|
then:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: select.select_option
|
||||||
|
data:
|
||||||
|
entity_id: "${atto_driver_seat_heating_entity}"
|
||||||
|
option: "high"
|
||||||
|
|
||||||
|
else:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: select.select_option
|
||||||
|
data:
|
||||||
|
entity_id: "${atto_driver_seat_heating_entity}"
|
||||||
|
option: "off"
|
||||||
|
|
||||||
#:################################################################################:#
|
#:################################################################################:#
|
||||||
# ATTO CLIMATE / SETPOINT
|
# ATTO CLIMATE / SETPOINT
|
||||||
#:################################################################################:#
|
#:################################################################################:#
|
||||||
@@ -2910,18 +3169,33 @@ lvgl:
|
|||||||
pressed:
|
pressed:
|
||||||
bg_color: 0xB76822
|
bg_color: 0xB76822
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: LEFT_MID
|
||||||
|
x: 18
|
||||||
|
text: "\U000F0238"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 15
|
||||||
text: "Heat (Hold)"
|
text: "Heat (Hold)"
|
||||||
text_font: font_button
|
text_font: font_button
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_long_press:
|
on_long_press:
|
||||||
then:
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_climate_optimistic) = 1;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: climate.set_hvac_mode
|
action: climate.set_preset_mode
|
||||||
data:
|
data:
|
||||||
entity_id: "${atto_climate_entity}"
|
entity_id: "${atto_climate_entity}"
|
||||||
hvac_mode: "heat"
|
preset_mode: "max_heat"
|
||||||
|
|
||||||
|
- script.execute: release_atto_climate_optimistic
|
||||||
|
|
||||||
- button:
|
- button:
|
||||||
id: atto_cool_button
|
id: atto_cool_button
|
||||||
@@ -2937,18 +3211,33 @@ lvgl:
|
|||||||
pressed:
|
pressed:
|
||||||
bg_color: 0x2E6A96
|
bg_color: 0x2E6A96
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: LEFT_MID
|
||||||
|
x: 18
|
||||||
|
text: "\U000F0717"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
|
x: 15
|
||||||
text: "Cool (Hold)"
|
text: "Cool (Hold)"
|
||||||
text_font: font_button
|
text_font: font_button
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_long_press:
|
on_long_press:
|
||||||
then:
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(atto_climate_optimistic) = 2;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: climate.set_hvac_mode
|
action: climate.set_preset_mode
|
||||||
data:
|
data:
|
||||||
entity_id: "${atto_climate_entity}"
|
entity_id: "${atto_climate_entity}"
|
||||||
hvac_mode: "cool"
|
preset_mode: "max_cool"
|
||||||
|
|
||||||
|
- script.execute: release_atto_climate_optimistic
|
||||||
|
|
||||||
- button:
|
- button:
|
||||||
id: atto_setpoint_down_button
|
id: atto_setpoint_down_button
|
||||||
@@ -2970,6 +3259,22 @@ lvgl:
|
|||||||
text_font: font_mdi_setpoint
|
text_font: font_mdi_setpoint
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_click:
|
on_click:
|
||||||
|
- lambda: |-
|
||||||
|
float current = id(atto_setpoint_local);
|
||||||
|
|
||||||
|
if (!id(atto_setpoint_optimistic)) {
|
||||||
|
const float actual = id(ha_atto_setpoint).state;
|
||||||
|
if (!isnan(actual)) {
|
||||||
|
current = actual;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id(atto_setpoint_local) =
|
||||||
|
std::max(15.0f, current - 1.0f);
|
||||||
|
id(atto_setpoint_optimistic) = true;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: climate.set_temperature
|
action: climate.set_temperature
|
||||||
data:
|
data:
|
||||||
@@ -2978,8 +3283,9 @@ lvgl:
|
|||||||
temperature: "{{ target_temperature }}"
|
temperature: "{{ target_temperature }}"
|
||||||
variables:
|
variables:
|
||||||
target_temperature: |-
|
target_temperature: |-
|
||||||
const float current = id(ha_atto_setpoint).state;
|
return id(atto_setpoint_local);
|
||||||
return isnan(current) ? 22.0f : current - 0.5f;
|
|
||||||
|
- script.execute: release_atto_setpoint_optimistic
|
||||||
|
|
||||||
- button:
|
- button:
|
||||||
id: atto_setpoint_display
|
id: atto_setpoint_display
|
||||||
@@ -2993,10 +3299,18 @@ lvgl:
|
|||||||
border_color: 0x5A6C82
|
border_color: 0x5A6C82
|
||||||
radius: 18
|
radius: 18
|
||||||
widgets:
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: LEFT_MID
|
||||||
|
x: 18
|
||||||
|
text: "\U000F050F"
|
||||||
|
text_font: font_mdi_vehicle
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
- label:
|
- label:
|
||||||
id: atto_setpoint_value_label
|
id: atto_setpoint_value_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: "--.-°C"
|
x: 15
|
||||||
|
text: "--°C"
|
||||||
text_font: font_title
|
text_font: font_title
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
|
|
||||||
@@ -3020,6 +3334,22 @@ lvgl:
|
|||||||
text_font: font_mdi_setpoint
|
text_font: font_mdi_setpoint
|
||||||
text_color: 0xFFFFFF
|
text_color: 0xFFFFFF
|
||||||
on_click:
|
on_click:
|
||||||
|
- lambda: |-
|
||||||
|
float current = id(atto_setpoint_local);
|
||||||
|
|
||||||
|
if (!id(atto_setpoint_optimistic)) {
|
||||||
|
const float actual = id(ha_atto_setpoint).state;
|
||||||
|
if (!isnan(actual)) {
|
||||||
|
current = actual;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id(atto_setpoint_local) =
|
||||||
|
std::min(31.0f, current + 1.0f);
|
||||||
|
id(atto_setpoint_optimistic) = true;
|
||||||
|
|
||||||
|
- script.execute: refresh_vehicle_controls
|
||||||
|
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: climate.set_temperature
|
action: climate.set_temperature
|
||||||
data:
|
data:
|
||||||
@@ -3028,8 +3358,9 @@ lvgl:
|
|||||||
temperature: "{{ target_temperature }}"
|
temperature: "{{ target_temperature }}"
|
||||||
variables:
|
variables:
|
||||||
target_temperature: |-
|
target_temperature: |-
|
||||||
const float current = id(ha_atto_setpoint).state;
|
return id(atto_setpoint_local);
|
||||||
return isnan(current) ? 22.0f : current + 0.5f;
|
|
||||||
|
- script.execute: release_atto_setpoint_optimistic
|
||||||
|
|
||||||
#:################################################################################:#
|
#:################################################################################:#
|
||||||
# BOTTOM NAVIGATION
|
# BOTTOM NAVIGATION
|
||||||
|
|||||||
Reference in New Issue
Block a user