Files
Home-Assistant/esphome/ha-remote/ha-remote-1.base.yaml
2026-02-17 07:27:22 -05:00

217 lines
6.5 KiB
YAML

psram:
mode: octal
speed: 80MHz
i2c:
id: i2c_main
sda: 8
scl: 9
frequency: 100kHz
# CH422G I/O expander (Waveshare uses it for LCD reset/backlight/touch reset)
ch422g:
- id: ch422g_hub
# --- Backlight control (CH422G IO2 is common for Waveshare LCD BL) ---
switch:
- platform: gpio
name: "LCD Backlight Raw"
id: lcd_backlight_raw
restore_mode: ALWAYS_ON
pin:
ch422g: ch422g_hub
number: 2
mode:
output: true
# A nicer HA-exposed control (so you can also automate it from HA)
light:
- platform: binary
name: "HA Remote Backlight"
output: lcd_backlight_out
id: ha_remote_backlight
output:
- platform: template
id: lcd_backlight_out
type: binary
write_action:
- if:
condition:
lambda: return state;
then:
- switch.turn_on: lcd_backlight_raw
else:
- switch.turn_off: lcd_backlight_raw
# --- Inactivity tracking (dim/off + wake on touch) ---
globals:
- id: last_activity_ms
type: uint32_t
restore_value: no
initial_value: '0'
- id: last_battery_level_pct
type: float
restore_value: no
initial_value: '-1.0'
- id: battery_charging_inferred
type: bool
restore_value: no
initial_value: 'false'
interval:
- interval: 1s
then:
- lambda: |-
if (id(last_activity_ms) == 0) id(last_activity_ms) = millis();
# Turn off backlight ONCE at 2 minutes idle.
- if:
condition:
lambda: |-
const uint32_t idle_s = (millis() - id(last_activity_ms)) / 1000;
return idle_s == 120;
then:
- light.turn_off: ha_remote_backlight
# --- Display ---
display:
- platform: mipi_rgb
model: ESP32-S3-TOUCH-LCD-7-800X480
id: main_display
update_interval: never
auto_clear_enabled: false
reset_pin:
ch422g: ch422g_hub
number: 3
mode:
output: true
# --- Touch ---
touchscreen:
platform: gt911
id: touch_panel
update_interval: 120ms
reset_pin:
ch422g: ch422g_hub
number: 1
mode:
output: true
on_touch:
then:
- lambda: |-
id(last_activity_ms) = millis();
- light.turn_on: ha_remote_backlight
# --- MDI Icon Font ---
font:
- file: "https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/fonts/materialdesignicons-webfont.ttf"
id: mdi_icons
size: 24
bpp: 4
glyphs:
# Tile icons
- "\U000F0335" # mdi:lightbulb
- "\U000F0425" # mdi:power
- "\U000F0426" # mdi:power-plug
- "\U000F07E9" # mdi:power-socket-us
- "\U000F1A26" # mdi:toggle-switch-variant-off
# Battery status icons
- "\U000F0079" # mdi:battery
- "\U000F12A1" # mdi:battery-low
- "\U000F12A2" # mdi:battery-medium
- "\U000F12A3" # mdi:battery-high
- "\U000F12A4" # mdi:battery-charging-low
- "\U000F12A5" # mdi:battery-charging-medium
- "\U000F12A6" # mdi:battery-charging-high
- "\U000F0091" # mdi:battery-unknown
- "\U000F10CD" # mdi:battery-alert-variant-outline
# Navigation bar icons
- "\U000F04B9" # mdi:sofa
- "\U000F06B5" # mdi:lamp
- "\U000F04DE" # mdi:stove
- "\U000F12BD" # mdi:stairs-up
- "\U000F1239" # mdi:desk
- "\U000F06D9" # mdi:garage
- "\U000F0531" # mdi:tree
# --- LVGL UI ---
# Note: On ESP32-S3-Touch-LCD-7, GPIO14 is used by the RGB display bus,
# so it cannot be reused as ADC for battery telemetry in this display mode.
# --- Battery fuel gauge (MAX17043) ---
sensor:
- platform: max17043
id: max17043_battery
i2c_id: i2c_main
update_interval: 120s
battery_voltage:
name: "Remote Battery Voltage"
id: remote_battery_voltage
entity_category: diagnostic
device_class: voltage
state_class: measurement
accuracy_decimals: 3
on_value:
then:
- lambda: |-
ESP_LOGI("battery", "Voltage: %.3f V", x);
battery_level:
name: "Remote Battery Level"
id: remote_battery_level
entity_category: diagnostic
device_class: battery
state_class: measurement
accuracy_decimals: 0
on_value:
then:
- lambda: |-
const float pct = x;
ESP_LOGI("battery", "Level: %.0f%%", pct);
const bool valid = pct >= 0.0f && pct <= 100.0f;
// Infer charging from SOC trend when no dedicated charge-detect pin exists.
if (valid) {
if (id(last_battery_level_pct) >= 0.0f) {
if (pct > id(last_battery_level_pct) + 0.2f) {
id(battery_charging_inferred) = true;
} else if (pct < id(last_battery_level_pct) - 0.2f) {
id(battery_charging_inferred) = false;
}
}
id(last_battery_level_pct) = pct;
}
const char *icon = "\U000F0091"; // mdi:battery-unknown
if (!valid) {
icon = "\U000F0091"; // mdi:battery-unknown
} else if (pct >= 99.0f) {
icon = "\U000F0079"; // mdi:battery (full)
} else if (id(battery_charging_inferred)) {
if (pct < 40.0f) {
icon = "\U000F12A4"; // mdi:battery-charging-low
} else if (pct < 80.0f) {
icon = "\U000F12A5"; // mdi:battery-charging-medium
} else {
icon = "\U000F12A6"; // mdi:battery-charging-high
}
} else {
if (pct < 15.0f) {
icon = "\U000F10CD"; // mdi:battery-alert-variant-outline
} else if (pct < 40.0f) {
icon = "\U000F12A1"; // mdi:battery-low
} else if (pct < 80.0f) {
icon = "\U000F12A2"; // mdi:battery-medium
} else {
icon = "\U000F12A3"; // mdi:battery-high
}
}
lv_label_set_text(id(nav_battery_icon_home), icon);
lv_label_set_text(id(nav_battery_icon_living_room), icon);
lv_label_set_text(id(nav_battery_icon_kitchen), icon);
lv_label_set_text(id(nav_battery_icon_upstairs), icon);
lv_label_set_text(id(nav_battery_icon_office), icon);
lv_label_set_text(id(nav_battery_icon_garage), icon);
lv_label_set_text(id(nav_battery_icon_outside), icon);