From c2ad832a8287fbedd9d20f9d33cc78434beb0a9d Mon Sep 17 00:00:00 2001 From: Joshua King Date: Sat, 28 Feb 2026 08:49:25 -0500 Subject: [PATCH] Refactor chore tracker configuration for improved consistency and clarity --- esphome/chore-tracker-esphome.yaml | 133 ++++++++----- .../chore-tracker-dashboard.yaml | 20 +- esphome/chore-tracker/generate.py | 182 ++++++++++-------- packages/chore-tracker-ha.yaml | 32 +-- 4 files changed, 209 insertions(+), 158 deletions(-) diff --git a/esphome/chore-tracker-esphome.yaml b/esphome/chore-tracker-esphome.yaml index 2c31951..cb1b5db 100644 --- a/esphome/chore-tracker-esphome.yaml +++ b/esphome/chore-tracker-esphome.yaml @@ -4,19 +4,30 @@ # # HOME SCREEN BEHAVIOUR: # Red outline = chores incomplete -# Solid green = all chores done ✓ +# Solid green = all chores done # Resets to red automatically at midnight +# +# Hardware: Waveshare ESP32-S3-Touch-LCD-7 (800x480) ################################################################################ esphome: name: chore-tracker friendly_name: "Chore Tracker" + on_boot: + priority: -10 + then: + - light.turn_on: backlight + - lvgl.page.show: page_home esp32: board: esp32-s3-devkitc-1 framework: type: esp-idf +psram: + mode: octal + speed: 80MHz + wifi: ssid: !secret wifi_iot_ssid password: !secret wifi_password @@ -36,50 +47,58 @@ ota: - platform: esphome password: !secret ota_password -# ── Display — Waveshare ESP32-S3 7" (adjust pins for your board revision) ───── -display: - - platform: rpi_dpi_rgb - id: main_display - auto_clear_enabled: false - color_order: RGB - dimensions: - width: 800 - height: 480 - de_pin: GPIO40 - hsync_pin: GPIO39 - vsync_pin: - number: GPIO41 - pclk_pin: GPIO42 - data_pins: - red: [GPIO45, GPIO48, GPIO47, GPIO21, GPIO14] - green: [GPIO5, GPIO6, GPIO7, GPIO15, GPIO16, GPIO4] - blue: [GPIO8, GPIO3, GPIO46, GPIO9, GPIO1] - -touchscreen: - - platform: gt911 - id: touch - display: main_display - i2c_id: i2c_touch - interrupt_pin: GPIO2 - reset_pin: GPIO38 - +# ── I2C ─────────────────────────────────────────────────────────────────────── i2c: - - id: i2c_touch - sda: GPIO19 - scl: GPIO20 - frequency: 400kHz + sda: 8 + scl: 9 +# ── CH422G IO Expander (controls LCD reset, touch reset, backlight) ─────────── +ch422g: + - id: ch422g_hub + +# ── 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 + +# ── Touchscreen ─────────────────────────────────────────────────────────────── +touchscreen: + platform: gt911 + id: touch + update_interval: 120ms + reset_pin: + ch422g: ch422g_hub + number: 1 + mode: + output: true + +# ── Backlight ───────────────────────────────────────────────────────────────── output: - - platform: ledc - pin: GPIO17 - id: 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 light: - - platform: monochromatic - output: backlight_output + - platform: binary name: "Display Backlight" + output: lcd_backlight_out id: backlight - restore_mode: ALWAYS_ON # ── Midnight reset ──────────────────────────────────────────────────────────── time: @@ -96,6 +115,7 @@ time: id(reset_chloe_chores).execute(); - lvgl.page.show: page_home +# ── Fonts (place files in /config/esphome/fonts/) ──────────────────────────── font: - file: "fonts/Nunito-Black.ttf" id: font_title @@ -113,8 +133,17 @@ font: id: font_tiny size: 13 -# ── Switches — one per chore per kid, synced to HA ─────────────────────────── +# ── Switches — backlight raw + one per chore per kid ───────────────────────── switch: + - platform: gpio + id: lcd_backlight_raw + name: "LCD Backlight Raw" + restore_mode: ALWAYS_ON + pin: + ch422g: ch422g_hub + number: 2 + mode: + output: true # ── Jordyn's chores ────────────────────────── - platform: template @@ -497,9 +526,9 @@ script: lv_label_set_text(id(progress_label_jordyn), buf); // All-done message in sidebar - lv_label_set_text(id(all_done_label_jordyn), done == total ? "\U0001F389 All done!" : ""); + lv_label_set_text(id(all_done_label_jordyn), done == total ? "All done!" : ""); - // Home button colour + // Home button: RED outline = incomplete, SOLID GREEN = all done if (done == total) { lv_obj_set_style_bg_opa(id(home_btn_jordyn), LV_OPA_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_jordyn), lv_color_hex(0x6BCB77), LV_PART_MAIN); @@ -598,9 +627,9 @@ script: lv_label_set_text(id(progress_label_declan), buf); // All-done message in sidebar - lv_label_set_text(id(all_done_label_declan), done == total ? "\U0001F389 All done!" : ""); + lv_label_set_text(id(all_done_label_declan), done == total ? "All done!" : ""); - // Home button colour + // Home button: RED outline = incomplete, SOLID GREEN = all done if (done == total) { lv_obj_set_style_bg_opa(id(home_btn_declan), LV_OPA_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_declan), lv_color_hex(0x6BCB77), LV_PART_MAIN); @@ -690,9 +719,9 @@ script: lv_label_set_text(id(progress_label_chloe), buf); // All-done message in sidebar - lv_label_set_text(id(all_done_label_chloe), done == total ? "\U0001F389 All done!" : ""); + lv_label_set_text(id(all_done_label_chloe), done == total ? "All done!" : ""); - // Home button colour + // Home button: RED outline = incomplete, SOLID GREEN = all done if (done == total) { lv_obj_set_style_bg_opa(id(home_btn_chloe), LV_OPA_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_chloe), lv_color_hex(0x6BCB77), LV_PART_MAIN); @@ -823,7 +852,7 @@ lvgl: widgets: - label: align: CENTER - text: "↺ Reset All" + text: "Reset All" text_color: 0xFFFFFF text_font: font_tiny - button: @@ -1002,7 +1031,7 @@ lvgl: widgets: - label: align: CENTER - text: "↺ Reset" + text: "Reset" text_color: 0xFFFFFF text_font: font_small - button: @@ -1018,7 +1047,7 @@ lvgl: widgets: - label: align: CENTER - text: "◀ Home" + text: "Home" text_color: 0xFFFFFF text_font: font_small @@ -1277,7 +1306,7 @@ lvgl: widgets: - label: align: CENTER - text: "↺ Reset" + text: "Reset" text_color: 0xFFFFFF text_font: font_small - button: @@ -1293,7 +1322,7 @@ lvgl: widgets: - label: align: CENTER - text: "◀ Home" + text: "Home" text_color: 0xFFFFFF text_font: font_small @@ -1516,7 +1545,7 @@ lvgl: widgets: - label: align: CENTER - text: "↺ Reset" + text: "Reset" text_color: 0xFFFFFF text_font: font_small - button: @@ -1532,7 +1561,7 @@ lvgl: widgets: - label: align: CENTER - text: "◀ Home" + text: "Home" text_color: 0xFFFFFF text_font: font_small diff --git a/esphome/chore-tracker/chore-tracker-dashboard.yaml b/esphome/chore-tracker/chore-tracker-dashboard.yaml index 9334dc7..13f0b05 100644 --- a/esphome/chore-tracker/chore-tracker-dashboard.yaml +++ b/esphome/chore-tracker/chore-tracker-dashboard.yaml @@ -15,7 +15,7 @@ views: content: > ### 😺 Jordyn {{ - '✅ All done!' if states('sensor.jordyn_all_chores_done') == 'True' + 'All done!' if states('sensor.jordyn_all_chores_done') == 'True' else states('sensor.jordyn_chores_done_today') ~ '/5 chores done' }} @@ -23,7 +23,7 @@ views: content: > ### 🤓 Declan {{ - '✅ All done!' if states('sensor.declan_all_chores_done') == 'True' + 'All done!' if states('sensor.declan_all_chores_done') == 'True' else states('sensor.declan_chores_done_today') ~ '/4 chores done' }} @@ -31,12 +31,12 @@ views: content: > ### 🌝 Chloe {{ - '✅ All done!' if states('sensor.chloe_all_chores_done') == 'True' + 'All done!' if states('sensor.chloe_all_chores_done') == 'True' else states('sensor.chloe_chores_done_today') ~ '/6 chores done' }} - type: button - name: "↺ Reset ALL Chores" + name: "Reset ALL Chores" icon: mdi:restart-alert tap_action: action: call-service @@ -64,9 +64,9 @@ views: - entity: sensor.jordyn_chores_done_today name: "Chores done today" - entity: sensor.jordyn_all_chores_done - name: "✅ All Done?" + name: "All Done?" - type: button - name: "↺ Reset Jordyn's Chores" + name: "Reset Jordyn's Chores" tap_action: action: call-service service: input_button.press @@ -90,9 +90,9 @@ views: - entity: sensor.declan_chores_done_today name: "Chores done today" - entity: sensor.declan_all_chores_done - name: "✅ All Done?" + name: "All Done?" - type: button - name: "↺ Reset Declan's Chores" + name: "Reset Declan's Chores" tap_action: action: call-service service: input_button.press @@ -122,9 +122,9 @@ views: - entity: sensor.chloe_chores_done_today name: "Chores done today" - entity: sensor.chloe_all_chores_done - name: "✅ All Done?" + name: "All Done?" - type: button - name: "↺ Reset Chloe's Chores" + name: "Reset Chloe's Chores" tap_action: action: call-service service: input_button.press diff --git a/esphome/chore-tracker/generate.py b/esphome/chore-tracker/generate.py index 3e83b2b..ff4e790 100644 --- a/esphome/chore-tracker/generate.py +++ b/esphome/chore-tracker/generate.py @@ -7,12 +7,14 @@ Reads chores_config.yaml and generates: • chore-tracker-ha.yaml (Home Assistant config) • chore-tracker-dashboard.yaml (Lovelace dashboard) +Target hardware: Waveshare ESP32-S3-Touch-LCD-7 (800x480) + Home screen behaviour: - Each kid's button has a RED outline while any chores remain undone - Button turns SOLID GREEN when ALL chores are complete - Resets to red automatically at midnight -No star tracking — chores are simply done or not done. +Each kid must define their own chores list in chores_config.yaml. Usage: python3 generate.py @@ -48,7 +50,6 @@ def ha_switch(kid: dict, chore: dict) -> str: return f"switch.chore_tracker_{eid(kid, chore)}" def get_chores(kid: dict) -> list: - """Each kid must define their own chore list.""" return kid["chores"] @@ -57,10 +58,10 @@ def get_chores(kid: dict) -> list: # ───────────────────────────────────────────────────────────────────────────── def gen_esphome(cfg: dict) -> str: - s = cfg["settings"] + s = cfg["settings"] kids = cfg["kids"] - # ── Switches ────────────────────────────────────────────────────────────── + # ── Switches (one per chore per kid) ────────────────────────────────────── switch_blocks = [] for kid in kids: chores = get_chores(kid) @@ -91,7 +92,7 @@ def gen_esphome(cfg: dict) -> str: entity_id: switch.chore_tracker_{e} """) - # ── Sensors (chores-done count only) ────────────────────────────────────── + # ── Sensors (chores-done count only — no stars) ──────────────────────── sensor_blocks = [] for kid in kids: chores = get_chores(kid) @@ -112,7 +113,7 @@ def gen_esphome(cfg: dict) -> str: """) - # ── Midnight reset ──────────────────────────────────────────────────────── + # ── Midnight reset calls ────────────────────────────────────────────────── reset_calls = "\n".join( f" id(reset_{kid_slug(k)}_chores).execute();" for k in kids @@ -128,19 +129,30 @@ def gen_esphome(cfg: dict) -> str: # # HOME SCREEN BEHAVIOUR: # Red outline = chores incomplete -# Solid green = all chores done ✓ +# Solid green = all chores done # Resets to red automatically at midnight +# +# Hardware: Waveshare ESP32-S3-Touch-LCD-7 (800x480) ################################################################################ esphome: name: {s["device_name"]} friendly_name: "{s["friendly_name"]}" + on_boot: + priority: -10 + then: + - light.turn_on: backlight + - lvgl.page.show: page_home esp32: board: esp32-s3-devkitc-1 framework: type: esp-idf +psram: + mode: octal + speed: 80MHz + wifi: ssid: {s["wifi_ssid"]} password: {s["wifi_password"]} @@ -160,50 +172,58 @@ ota: - platform: esphome password: {s["ota_password"]} -# ── Display — Waveshare ESP32-S3 7" (adjust pins for your board revision) ───── -display: - - platform: rpi_dpi_rgb - id: main_display - auto_clear_enabled: false - color_order: RGB - dimensions: - width: 800 - height: 480 - de_pin: GPIO40 - hsync_pin: GPIO39 - vsync_pin: - number: GPIO41 - pclk_pin: GPIO42 - data_pins: - red: [GPIO45, GPIO48, GPIO47, GPIO21, GPIO14] - green: [GPIO5, GPIO6, GPIO7, GPIO15, GPIO16, GPIO4] - blue: [GPIO8, GPIO3, GPIO46, GPIO9, GPIO1] - -touchscreen: - - platform: gt911 - id: touch - display: main_display - i2c_id: i2c_touch - interrupt_pin: GPIO2 - reset_pin: GPIO38 - +# ── I2C ─────────────────────────────────────────────────────────────────────── i2c: - - id: i2c_touch - sda: GPIO19 - scl: GPIO20 - frequency: 400kHz + sda: 8 + scl: 9 +# ── CH422G IO Expander (controls LCD reset, touch reset, backlight) ─────────── +ch422g: + - id: ch422g_hub + +# ── 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 + +# ── Touchscreen ─────────────────────────────────────────────────────────────── +touchscreen: + platform: gt911 + id: touch + update_interval: 120ms + reset_pin: + ch422g: ch422g_hub + number: 1 + mode: + output: true + +# ── Backlight ───────────────────────────────────────────────────────────────── output: - - platform: ledc - pin: GPIO17 - id: 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 light: - - platform: monochromatic - output: backlight_output + - platform: binary name: "Display Backlight" + output: lcd_backlight_out id: backlight - restore_mode: ALWAYS_ON # ── Midnight reset ──────────────────────────────────────────────────────────── time: @@ -218,6 +238,7 @@ time: {reset_calls} - lvgl.page.show: page_home +# ── Fonts (place files in /config/esphome/fonts/) ──────────────────────────── font: - file: "fonts/Nunito-Black.ttf" id: font_title @@ -235,8 +256,17 @@ font: id: font_tiny size: 13 -# ── Switches — one per chore per kid, synced to HA ─────────────────────────── +# ── Switches — backlight raw + one per chore per kid ───────────────────────── switch: + - platform: gpio + id: lcd_backlight_raw + name: "LCD Backlight Raw" + restore_mode: ALWAYS_ON + pin: + ch422g: ch422g_hub + number: 2 + mode: + output: true {"".join(switch_blocks)} # ── Sensors — reported to HA ───────────────────────────────────────────────── @@ -270,8 +300,8 @@ def _gen_lvgl_pages(kids: list) -> str: pages = [] # ── HOME PAGE ───────────────────────────────────────────────────────────── - n = len(kids) - btn_w = min(200, max(140, (760 - 20 * (n - 1)) // n)) + n = len(kids) + btn_w = min(200, max(140, (760 - 20 * (n - 1)) // n)) total_w = btn_w * n + 20 * (n - 1) start_x = (800 - total_w) // 2 btn_y = 130 @@ -356,7 +386,7 @@ def _gen_lvgl_pages(kids: list) -> str: widgets: - label: align: CENTER - text: "↺ Reset All" + text: "Reset All" text_color: 0xFFFFFF text_font: font_tiny {home_btns}""") @@ -497,7 +527,7 @@ def _gen_lvgl_pages(kids: list) -> str: widgets: - label: align: CENTER - text: "↺ Reset" + text: "Reset" text_color: 0xFFFFFF text_font: font_small - button: @@ -513,7 +543,7 @@ def _gen_lvgl_pages(kids: list) -> str: widgets: - label: align: CENTER - text: "◀ Home" + text: "Home" text_color: 0xFFFFFF text_font: font_small @@ -556,7 +586,6 @@ def _gen_scripts(kids: list) -> str: f" id({eid(kid,c)}).turn_off();" for c in chores ) - # Reset script blocks.append(f"""\ - id: reset_{ks}_chores mode: single @@ -567,7 +596,6 @@ def _gen_scripts(kids: list) -> str: """) - # UI update script blocks.append(f"""\ - id: update_{ks}_ui mode: single @@ -583,9 +611,9 @@ def _gen_scripts(kids: list) -> str: lv_label_set_text(id(progress_label_{ks}), buf); // All-done message in sidebar - lv_label_set_text(id(all_done_label_{ks}), done == total ? "\\U0001F389 All done!" : ""); + lv_label_set_text(id(all_done_label_{ks}), done == total ? "All done!" : ""); - // Home button colour + // Home button: RED outline = incomplete, SOLID GREEN = all done if (done == total) {{ lv_obj_set_style_bg_opa(id(home_btn_{ks}), LV_OPA_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_{ks}), lv_color_hex(0x6BCB77), LV_PART_MAIN); @@ -613,7 +641,7 @@ def _gen_scripts(kids: list) -> str: # ───────────────────────────────────────────────────────────────────────────── def gen_ha(cfg: dict) -> str: - s = cfg["settings"] + s = cfg["settings"] kids = cfg["kids"] sensor_blocks = [] @@ -639,7 +667,6 @@ def gen_ha(cfg: dict) -> str: """) - # input_button helpers input_buttons = "".join(f"""\ {kid_slug(k)}_reset_chores: name: "Reset {k['name']}'s Chores" @@ -651,10 +678,8 @@ def gen_ha(cfg: dict) -> str: icon: mdi:restart-alert """ - # Automations auto_blocks = [] - # Per-kid HA reset button for kid in kids: ks = kid_slug(kid) off_calls = "\n".join( @@ -663,7 +688,7 @@ def gen_ha(cfg: dict) -> str: ) auto_blocks.append(f"""\ - id: {ks}_reset_from_ha - alias: "Chore Tracker — Reset {kid['name']}'s chores from HA" + alias: "Chore Tracker - Reset {kid['name']}'s chores from HA" trigger: - platform: state entity_id: input_button.{ks}_reset_chores @@ -672,29 +697,27 @@ def gen_ha(cfg: dict) -> str: """) - # Reset All from HA - all_off_calls = "\n".join( + all_off = "\n".join( f" - service: switch.turn_off\n target:\n entity_id: {ha_switch(kid, c)}" for kid in kids for c in get_chores(kid) ) auto_blocks.append(f"""\ - id: reset_all_from_ha - alias: "Chore Tracker — Reset ALL chores from HA" + alias: "Chore Tracker - Reset ALL chores from HA" trigger: - platform: state entity_id: input_button.reset_all_chores action: -{all_off_calls} +{all_off} """) - # All-done notification for kid in kids: ks = kid_slug(kid) n = len(get_chores(kid)) auto_blocks.append(f"""\ - id: {ks}_all_done_notify - alias: "Chore Tracker — {kid['name']} all done!" + alias: "Chore Tracker - {kid['name']} all done!" trigger: - platform: state entity_id: sensor.{ks}_all_chores_done @@ -702,12 +725,11 @@ def gen_ha(cfg: dict) -> str: action: - service: {s['notify_service']} data: - title: "🎉 {kid['name']} finished all chores!" + title: "{kid['name']} finished all chores!" message: "{kid['name']} completed all {n} chores today!" """) - # Evening reminder reminder_actions = "".join(f"""\ - if: condition: template @@ -715,7 +737,7 @@ def gen_ha(cfg: dict) -> str: then: - service: {s['notify_service']} data: - title: "📋 {k['name']} has unfinished chores" + title: "{k['name']} has unfinished chores" message: > {k['name']} has done {{{{ states('sensor.{kid_slug(k)}_chores_done_today') }}}}/{len(get_chores(k))} chores today. @@ -723,7 +745,7 @@ def gen_ha(cfg: dict) -> str: auto_blocks.append(f"""\ - id: chore_reminder_evening - alias: "Chore Tracker — Evening reminder" + alias: "Chore Tracker - Evening reminder" trigger: - platform: time at: "{s['reminder_time']}:00" @@ -737,8 +759,8 @@ def gen_ha(cfg: dict) -> str: # Kids: {", ".join(k["name"] for k in kids)} # # BIDIRECTIONAL SYNC: -# Screen → HA: Each switch calls homeassistant.service on toggle -# HA → Screen: ESPHome native API handles this automatically +# Screen to HA: Each switch calls homeassistant.service on toggle +# HA to Screen: ESPHome native API handles this automatically ################################################################################ input_button: @@ -763,7 +785,7 @@ def gen_dashboard(cfg: dict) -> str: content: > ### {kid['avatar']} {kid['name']} {{{{ - '✅ All done!' if states('sensor.{kid_slug(kid)}_all_chores_done') == 'True' + 'All done!' if states('sensor.{kid_slug(kid)}_all_chores_done') == 'True' else states('sensor.{kid_slug(kid)}_chores_done_today') ~ '/{len(get_chores(kid))} chores done' }}}} """ for kid in kids) @@ -785,9 +807,9 @@ def gen_dashboard(cfg: dict) -> str: - entity: sensor.{ks}_chores_done_today name: "Chores done today" - entity: sensor.{ks}_all_chores_done - name: "✅ All Done?" + name: "All Done?" - type: button - name: "↺ Reset {kid['name']}'s Chores" + name: "Reset {kid['name']}'s Chores" tap_action: action: call-service service: input_button.press @@ -811,7 +833,7 @@ views: cards: {summary_cards} - type: button - name: "↺ Reset ALL Chores" + name: "Reset ALL Chores" icon: mdi:restart-alert tap_action: action: call-service @@ -855,7 +877,6 @@ def main(): print("❌ No kids defined in config!") sys.exit(1) - # Validate every kid has their own chore list errors = [k["name"] for k in kids if "chores" not in k or not k["chores"]] if errors: print(f"❌ These kids have no chores defined: {', '.join(errors)}") @@ -866,7 +887,8 @@ def main(): print(f"✅ Config loaded: {len(kids)} kid(s), {total_chores} total chores") for k in kids: chores = get_chores(k) - print(f" {k['avatar']} {k['name']}: {len(chores)} chores — {', '.join(c['name'] for c in chores)}") + print(f" {k['avatar']} {k['name']}: {len(chores)} chores" + f" — {', '.join(c['name'] for c in chores)}") print() files = { @@ -882,9 +904,9 @@ def main(): print() print("✅ Done!") - print(" 1. Flash chore-tracker-esphome.yaml → ESPHome dashboard") - print(" 2. Merge chore-tracker-ha.yaml → HA config + restart HA") - print(" 3. Paste chore-tracker-dashboard.yaml → New HA dashboard") + print(" 1. Flash chore-tracker-esphome.yaml -> ESPHome dashboard") + print(" 2. Merge chore-tracker-ha.yaml -> HA config + restart HA") + print(" 3. Paste chore-tracker-dashboard.yaml -> New HA dashboard") if __name__ == "__main__": diff --git a/packages/chore-tracker-ha.yaml b/packages/chore-tracker-ha.yaml index b4dd7d1..eefd123 100644 --- a/packages/chore-tracker-ha.yaml +++ b/packages/chore-tracker-ha.yaml @@ -3,8 +3,8 @@ # Kids: Jordyn, Declan, Chloe # # BIDIRECTIONAL SYNC: -# Screen → HA: Each switch calls homeassistant.service on toggle -# HA → Screen: ESPHome native API handles this automatically +# Screen to HA: Each switch calls homeassistant.service on toggle +# HA to Screen: ESPHome native API handles this automatically ################################################################################ input_button: @@ -65,7 +65,7 @@ template: automation: - id: jordyn_reset_from_ha - alias: "Chore Tracker — Reset Jordyn's chores from HA" + alias: "Chore Tracker - Reset Jordyn's chores from HA" trigger: - platform: state entity_id: input_button.jordyn_reset_chores @@ -87,7 +87,7 @@ automation: entity_id: switch.chore_tracker_jordyn_feed_dog - id: declan_reset_from_ha - alias: "Chore Tracker — Reset Declan's chores from HA" + alias: "Chore Tracker - Reset Declan's chores from HA" trigger: - platform: state entity_id: input_button.declan_reset_chores @@ -106,7 +106,7 @@ automation: entity_id: switch.chore_tracker_declan_take_out_trash - id: chloe_reset_from_ha - alias: "Chore Tracker — Reset Chloe's chores from HA" + alias: "Chore Tracker - Reset Chloe's chores from HA" trigger: - platform: state entity_id: input_button.chloe_reset_chores @@ -131,7 +131,7 @@ automation: entity_id: switch.chore_tracker_chloe_practice_piano - id: reset_all_from_ha - alias: "Chore Tracker — Reset ALL chores from HA" + alias: "Chore Tracker - Reset ALL chores from HA" trigger: - platform: state entity_id: input_button.reset_all_chores @@ -183,7 +183,7 @@ automation: entity_id: switch.chore_tracker_chloe_practice_piano - id: jordyn_all_done_notify - alias: "Chore Tracker — Jordyn all done!" + alias: "Chore Tracker - Jordyn all done!" trigger: - platform: state entity_id: sensor.jordyn_all_chores_done @@ -191,11 +191,11 @@ automation: action: - service: notify.notify data: - title: "🎉 Jordyn finished all chores!" + title: "Jordyn finished all chores!" message: "Jordyn completed all 5 chores today!" - id: declan_all_done_notify - alias: "Chore Tracker — Declan all done!" + alias: "Chore Tracker - Declan all done!" trigger: - platform: state entity_id: sensor.declan_all_chores_done @@ -203,11 +203,11 @@ automation: action: - service: notify.notify data: - title: "🎉 Declan finished all chores!" + title: "Declan finished all chores!" message: "Declan completed all 4 chores today!" - id: chloe_all_done_notify - alias: "Chore Tracker — Chloe all done!" + alias: "Chore Tracker - Chloe all done!" trigger: - platform: state entity_id: sensor.chloe_all_chores_done @@ -215,11 +215,11 @@ automation: action: - service: notify.notify data: - title: "🎉 Chloe finished all chores!" + title: "Chloe finished all chores!" message: "Chloe completed all 6 chores today!" - id: chore_reminder_evening - alias: "Chore Tracker — Evening reminder" + alias: "Chore Tracker - Evening reminder" trigger: - platform: time at: "18:00:00" @@ -230,7 +230,7 @@ automation: then: - service: notify.notify data: - title: "📋 Jordyn has unfinished chores" + title: "Jordyn has unfinished chores" message: > Jordyn has done {{ states('sensor.jordyn_chores_done_today') }}/5 chores today. @@ -240,7 +240,7 @@ automation: then: - service: notify.notify data: - title: "📋 Declan has unfinished chores" + title: "Declan has unfinished chores" message: > Declan has done {{ states('sensor.declan_chores_done_today') }}/4 chores today. @@ -250,7 +250,7 @@ automation: then: - service: notify.notify data: - title: "📋 Chloe has unfinished chores" + title: "Chloe has unfinished chores" message: > Chloe has done {{ states('sensor.chloe_chores_done_today') }}/6 chores today.