From c07d58c98b99ef884e062a69dd3fddbdc04e243f Mon Sep 17 00:00:00 2001 From: Joshua King Date: Fri, 27 Feb 2026 22:08:02 -0500 Subject: [PATCH] Add chore tracker configuration for kids' chores with reset buttons and notifications --- .../chore-tracker/chore-tracker-esphome.yaml | 1757 +++++++++++++++++ esphome/chore-tracker/chore-tracker-ha.yaml | 258 +++ esphome/chore-tracker/generate.py | 2 +- 3 files changed, 2016 insertions(+), 1 deletion(-) create mode 100644 esphome/chore-tracker/chore-tracker-esphome.yaml create mode 100644 esphome/chore-tracker/chore-tracker-ha.yaml diff --git a/esphome/chore-tracker/chore-tracker-esphome.yaml b/esphome/chore-tracker/chore-tracker-esphome.yaml new file mode 100644 index 0000000..a108b5d --- /dev/null +++ b/esphome/chore-tracker/chore-tracker-esphome.yaml @@ -0,0 +1,1757 @@ +################################################################################ +# chore-tracker-esphome.yaml (AUTO-GENERATED — edit chores_config.yaml) +# Kids: Jordyn, Declan, Chloe +# +# HOME SCREEN BEHAVIOUR: +# Red outline = chores incomplete +# Solid green = all chores done ✓ +# Resets to red automatically at midnight +################################################################################ + +esphome: + name: chore-tracker + friendly_name: "Chore Tracker" + +esp32: + board: esp32s3box + framework: + type: esp-idf + +wifi: + ssid: !secret wifi_iot_ssid + password: !secret wifi_password + ap: + ssid: "Chore Tracker Hotspot" + password: "choretracker" + +captive_portal: +logger: + level: INFO + +api: + encryption: + key: !secret api_encryption_key + +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: + number: GPIO40 + ignore_strapping_warning: true + hsync_pin: + number: GPIO39 + ignore_strapping_warning: true + 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: + - id: i2c_touch + sda: GPIO19 + scl: GPIO20 + frequency: 400kHz + +output: + - platform: ledc + pin: GPIO17 + id: backlight_output + +light: + - platform: monochromatic + output: backlight_output + name: "Display Backlight" + id: backlight + restore_mode: ALWAYS_ON + +# ── Midnight reset ──────────────────────────────────────────────────────────── +time: + - platform: homeassistant + id: ha_time + on_time: + - hours: 0 + minutes: 0 + seconds: 0 + then: + - lambda: |- + id(reset_jordyn_chores).execute(); + id(reset_declan_chores).execute(); + id(reset_chloe_chores).execute(); + - lvgl.page.show: page_home + +font: + - file: "gfonts://Nunito:wght@900" + id: font_title + size: 40 + - file: "gfonts://Nunito:wght@800" + id: font_name + size: 30 + - file: "gfonts://Nunito:wght@700" + id: font_med + size: 22 + - file: "gfonts://Nunito:wght@600" + id: font_small + size: 17 + - file: "gfonts://Nunito:wght@600" + id: font_tiny + size: 13 + +# ── Switches — one per chore per kid, synced to HA ─────────────────────────── +switch: + + # ── Jordyn's chores ────────────────────────── - platform: template + name: "Jordyn - Make Bed" + id: jordyn_make_bed + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_jordyn_make_bed + on_turn_off: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_jordyn_make_bed + - platform: template + name: "Jordyn - Brush Teeth" + id: jordyn_brush_teeth + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_jordyn_brush_teeth + on_turn_off: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_jordyn_brush_teeth + - platform: template + name: "Jordyn - Tidy Room" + id: jordyn_tidy_room + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_jordyn_tidy_room + on_turn_off: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_jordyn_tidy_room + - platform: template + name: "Jordyn - Homework" + id: jordyn_homework + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_jordyn_homework + on_turn_off: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_jordyn_homework + - platform: template + name: "Jordyn - Feed Dog" + id: jordyn_feed_dog + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_jordyn_feed_dog + on_turn_off: + then: + - script.execute: update_jordyn_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_jordyn_feed_dog + + # ── Declan's chores ────────────────────────── - platform: template + name: "Declan - Make Bed" + id: declan_make_bed + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_declan_make_bed + on_turn_off: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_declan_make_bed + - platform: template + name: "Declan - Brush Teeth" + id: declan_brush_teeth + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_declan_brush_teeth + on_turn_off: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_declan_brush_teeth + - platform: template + name: "Declan - Set Table" + id: declan_set_table + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_declan_set_table + on_turn_off: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_declan_set_table + - platform: template + name: "Declan - Take Out Trash" + id: declan_take_out_trash + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_declan_take_out_trash + on_turn_off: + then: + - script.execute: update_declan_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_declan_take_out_trash + + # ── Chloe's chores ────────────────────────── - platform: template + name: "Chloe - Make Bed" + id: chloe_make_bed + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_chloe_make_bed + on_turn_off: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_chloe_make_bed + - platform: template + name: "Chloe - Brush Teeth" + id: chloe_brush_teeth + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_chloe_brush_teeth + on_turn_off: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_chloe_brush_teeth + - platform: template + name: "Chloe - Water Plants" + id: chloe_water_plants + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_chloe_water_plants + on_turn_off: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_chloe_water_plants + - platform: template + name: "Chloe - Homework" + id: chloe_homework + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_chloe_homework + on_turn_off: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_chloe_homework + - platform: template + name: "Chloe - Tidy Room" + id: chloe_tidy_room + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_chloe_tidy_room + on_turn_off: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_chloe_tidy_room + - platform: template + name: "Chloe - Practice Piano" + id: chloe_practice_piano + icon: mdi:checkbox-marked-circle + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_on + data: + entity_id: switch.chore_tracker_chloe_practice_piano + on_turn_off: + then: + - script.execute: update_chloe_ui + - homeassistant.service: + service: switch.turn_off + data: + entity_id: switch.chore_tracker_chloe_practice_piano + + +# ── Sensors — reported to HA ───────────────────────────────────────────────── +sensor: + - platform: template + name: "Jordyn Chores Done" + id: jordyn_chores_done + accuracy_decimals: 0 + update_interval: 2s + lambda: |- + int done = 0; + if (id(jordyn_make_bed).state) done++; + if (id(jordyn_brush_teeth).state) done++; + if (id(jordyn_tidy_room).state) done++; + if (id(jordyn_homework).state) done++; + if (id(jordyn_feed_dog).state) done++; + return done; + + - platform: template + name: "Declan Chores Done" + id: declan_chores_done + accuracy_decimals: 0 + update_interval: 2s + lambda: |- + int done = 0; + if (id(declan_make_bed).state) done++; + if (id(declan_brush_teeth).state) done++; + if (id(declan_set_table).state) done++; + if (id(declan_take_out_trash).state) done++; + return done; + + - platform: template + name: "Chloe Chores Done" + id: chloe_chores_done + accuracy_decimals: 0 + update_interval: 2s + lambda: |- + int done = 0; + if (id(chloe_make_bed).state) done++; + if (id(chloe_brush_teeth).state) done++; + if (id(chloe_water_plants).state) done++; + if (id(chloe_homework).state) done++; + if (id(chloe_tidy_room).state) done++; + if (id(chloe_practice_piano).state) done++; + return done; + + + +# ── Scripts — reset + UI update ─────────────────────────────────────────────── +script: + - id: reset_jordyn_chores + mode: single + then: + - lambda: |- + id(jordyn_make_bed).turn_off(); + id(jordyn_brush_teeth).turn_off(); + id(jordyn_tidy_room).turn_off(); + id(jordyn_homework).turn_off(); + id(jordyn_feed_dog).turn_off(); + - script.execute: update_jordyn_ui + + + - id: update_jordyn_ui + mode: single + then: + - lambda: |- + int done = (id(jordyn_make_bed).state ? 1 : 0) + (id(jordyn_brush_teeth).state ? 1 : 0) + (id(jordyn_tidy_room).state ? 1 : 0) + (id(jordyn_homework).state ? 1 : 0) + (id(jordyn_feed_dog).state ? 1 : 0); + int total = 5; + char buf[24]; + + // Progress bar + label + lv_bar_set_value(id(progress_bar_jordyn), done, LV_ANIM_ON); + snprintf(buf, sizeof(buf), "%d / 5", done); + 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!" : ""); + + // Home button colour + 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); + lv_obj_set_style_border_width(id(home_btn_jordyn), 0, LV_PART_MAIN); + lv_label_set_text(id(home_status_jordyn), "\u2713 all done!"); + lv_obj_set_style_text_color(id(home_status_jordyn), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + } else { + lv_obj_set_style_bg_opa(id(home_btn_jordyn), LV_OPA_TRANSP, LV_PART_MAIN); + lv_obj_set_style_border_color(id(home_btn_jordyn), lv_color_hex(0xFF4757), LV_PART_MAIN); + lv_obj_set_style_border_width(id(home_btn_jordyn), 5, LV_PART_MAIN); + snprintf(buf, sizeof(buf), "%d left", total - done); + lv_label_set_text(id(home_status_jordyn), buf); + lv_obj_set_style_text_color(id(home_status_jordyn), lv_color_hex(0xFF4757), LV_PART_MAIN); + } + + // Card colours + if (id(jordyn_make_bed).state) { + lv_obj_set_style_bg_color(id(card_jordyn_make_bed), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_make_bed), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_make_bed), 3, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_make_bed), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_jordyn_make_bed), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_make_bed), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_make_bed), 2, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_make_bed), ""); + } + if (id(jordyn_brush_teeth).state) { + lv_obj_set_style_bg_color(id(card_jordyn_brush_teeth), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_brush_teeth), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_brush_teeth), 3, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_brush_teeth), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_jordyn_brush_teeth), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_brush_teeth), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_brush_teeth), 2, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_brush_teeth), ""); + } + if (id(jordyn_tidy_room).state) { + lv_obj_set_style_bg_color(id(card_jordyn_tidy_room), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_tidy_room), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_tidy_room), 3, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_tidy_room), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_jordyn_tidy_room), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_tidy_room), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_tidy_room), 2, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_tidy_room), ""); + } + if (id(jordyn_homework).state) { + lv_obj_set_style_bg_color(id(card_jordyn_homework), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_homework), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_homework), 3, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_homework), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_jordyn_homework), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_homework), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_homework), 2, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_homework), ""); + } + if (id(jordyn_feed_dog).state) { + lv_obj_set_style_bg_color(id(card_jordyn_feed_dog), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_feed_dog), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_feed_dog), 3, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_feed_dog), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_jordyn_feed_dog), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_jordyn_feed_dog), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_jordyn_feed_dog), 2, LV_PART_MAIN); + lv_label_set_text(id(check_jordyn_feed_dog), ""); + } + + + - id: reset_declan_chores + mode: single + then: + - lambda: |- + id(declan_make_bed).turn_off(); + id(declan_brush_teeth).turn_off(); + id(declan_set_table).turn_off(); + id(declan_take_out_trash).turn_off(); + - script.execute: update_declan_ui + + + - id: update_declan_ui + mode: single + then: + - lambda: |- + int done = (id(declan_make_bed).state ? 1 : 0) + (id(declan_brush_teeth).state ? 1 : 0) + (id(declan_set_table).state ? 1 : 0) + (id(declan_take_out_trash).state ? 1 : 0); + int total = 4; + char buf[24]; + + // Progress bar + label + lv_bar_set_value(id(progress_bar_declan), done, LV_ANIM_ON); + snprintf(buf, sizeof(buf), "%d / 4", done); + 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!" : ""); + + // Home button colour + 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); + lv_obj_set_style_border_width(id(home_btn_declan), 0, LV_PART_MAIN); + lv_label_set_text(id(home_status_declan), "\u2713 all done!"); + lv_obj_set_style_text_color(id(home_status_declan), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + } else { + lv_obj_set_style_bg_opa(id(home_btn_declan), LV_OPA_TRANSP, LV_PART_MAIN); + lv_obj_set_style_border_color(id(home_btn_declan), lv_color_hex(0xFF4757), LV_PART_MAIN); + lv_obj_set_style_border_width(id(home_btn_declan), 5, LV_PART_MAIN); + snprintf(buf, sizeof(buf), "%d left", total - done); + lv_label_set_text(id(home_status_declan), buf); + lv_obj_set_style_text_color(id(home_status_declan), lv_color_hex(0xFF4757), LV_PART_MAIN); + } + + // Card colours + if (id(declan_make_bed).state) { + lv_obj_set_style_bg_color(id(card_declan_make_bed), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_make_bed), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_make_bed), 3, LV_PART_MAIN); + lv_label_set_text(id(check_declan_make_bed), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_declan_make_bed), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_make_bed), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_make_bed), 2, LV_PART_MAIN); + lv_label_set_text(id(check_declan_make_bed), ""); + } + if (id(declan_brush_teeth).state) { + lv_obj_set_style_bg_color(id(card_declan_brush_teeth), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_brush_teeth), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_brush_teeth), 3, LV_PART_MAIN); + lv_label_set_text(id(check_declan_brush_teeth), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_declan_brush_teeth), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_brush_teeth), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_brush_teeth), 2, LV_PART_MAIN); + lv_label_set_text(id(check_declan_brush_teeth), ""); + } + if (id(declan_set_table).state) { + lv_obj_set_style_bg_color(id(card_declan_set_table), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_set_table), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_set_table), 3, LV_PART_MAIN); + lv_label_set_text(id(check_declan_set_table), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_declan_set_table), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_set_table), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_set_table), 2, LV_PART_MAIN); + lv_label_set_text(id(check_declan_set_table), ""); + } + if (id(declan_take_out_trash).state) { + lv_obj_set_style_bg_color(id(card_declan_take_out_trash), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_take_out_trash), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_take_out_trash), 3, LV_PART_MAIN); + lv_label_set_text(id(check_declan_take_out_trash), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_declan_take_out_trash), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_declan_take_out_trash), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_declan_take_out_trash), 2, LV_PART_MAIN); + lv_label_set_text(id(check_declan_take_out_trash), ""); + } + + + - id: reset_chloe_chores + mode: single + then: + - lambda: |- + id(chloe_make_bed).turn_off(); + id(chloe_brush_teeth).turn_off(); + id(chloe_water_plants).turn_off(); + id(chloe_homework).turn_off(); + id(chloe_tidy_room).turn_off(); + id(chloe_practice_piano).turn_off(); + - script.execute: update_chloe_ui + + + - id: update_chloe_ui + mode: single + then: + - lambda: |- + int done = (id(chloe_make_bed).state ? 1 : 0) + (id(chloe_brush_teeth).state ? 1 : 0) + (id(chloe_water_plants).state ? 1 : 0) + (id(chloe_homework).state ? 1 : 0) + (id(chloe_tidy_room).state ? 1 : 0) + (id(chloe_practice_piano).state ? 1 : 0); + int total = 6; + char buf[24]; + + // Progress bar + label + lv_bar_set_value(id(progress_bar_chloe), done, LV_ANIM_ON); + snprintf(buf, sizeof(buf), "%d / 6", done); + 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!" : ""); + + // Home button colour + 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); + lv_obj_set_style_border_width(id(home_btn_chloe), 0, LV_PART_MAIN); + lv_label_set_text(id(home_status_chloe), "\u2713 all done!"); + lv_obj_set_style_text_color(id(home_status_chloe), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + } else { + lv_obj_set_style_bg_opa(id(home_btn_chloe), LV_OPA_TRANSP, LV_PART_MAIN); + lv_obj_set_style_border_color(id(home_btn_chloe), lv_color_hex(0xFF4757), LV_PART_MAIN); + lv_obj_set_style_border_width(id(home_btn_chloe), 5, LV_PART_MAIN); + snprintf(buf, sizeof(buf), "%d left", total - done); + lv_label_set_text(id(home_status_chloe), buf); + lv_obj_set_style_text_color(id(home_status_chloe), lv_color_hex(0xFF4757), LV_PART_MAIN); + } + + // Card colours + if (id(chloe_make_bed).state) { + lv_obj_set_style_bg_color(id(card_chloe_make_bed), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_make_bed), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_make_bed), 3, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_make_bed), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_chloe_make_bed), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_make_bed), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_make_bed), 2, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_make_bed), ""); + } + if (id(chloe_brush_teeth).state) { + lv_obj_set_style_bg_color(id(card_chloe_brush_teeth), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_brush_teeth), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_brush_teeth), 3, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_brush_teeth), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_chloe_brush_teeth), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_brush_teeth), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_brush_teeth), 2, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_brush_teeth), ""); + } + if (id(chloe_water_plants).state) { + lv_obj_set_style_bg_color(id(card_chloe_water_plants), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_water_plants), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_water_plants), 3, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_water_plants), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_chloe_water_plants), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_water_plants), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_water_plants), 2, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_water_plants), ""); + } + if (id(chloe_homework).state) { + lv_obj_set_style_bg_color(id(card_chloe_homework), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_homework), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_homework), 3, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_homework), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_chloe_homework), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_homework), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_homework), 2, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_homework), ""); + } + if (id(chloe_tidy_room).state) { + lv_obj_set_style_bg_color(id(card_chloe_tidy_room), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_tidy_room), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_tidy_room), 3, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_tidy_room), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_chloe_tidy_room), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_tidy_room), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_tidy_room), 2, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_tidy_room), ""); + } + if (id(chloe_practice_piano).state) { + lv_obj_set_style_bg_color(id(card_chloe_practice_piano), lv_color_hex(0xF0FFF4), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_practice_piano), lv_color_hex(0x6BCB77), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_practice_piano), 3, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_practice_piano), "\u2705"); + } else { + lv_obj_set_style_bg_color(id(card_chloe_practice_piano), lv_color_hex(0xFFFFFF), LV_PART_MAIN); + lv_obj_set_style_border_color(id(card_chloe_practice_piano), lv_color_hex(0xEEEEEE), LV_PART_MAIN); + lv_obj_set_style_border_width(id(card_chloe_practice_piano), 2, LV_PART_MAIN); + lv_label_set_text(id(check_chloe_practice_piano), ""); + } + + + +# ── LVGL UI ─────────────────────────────────────────────────────────────────── +lvgl: + displays: + - main_display + touchscreens: + - touch + theme: + btn: + radius: 20 + border_width: 0 + pages: + - id: page_home + bg_color: 0xFFF9F0 + widgets: + - label: + x: 0 + y: 36 + width: 800 + align: TOP_MID + text: "Chore Tracker" + text_font: font_title + text_color: 0x2D3436 + - label: + x: 0 + y: 90 + width: 800 + align: TOP_MID + text: "Tap a name to check off chores" + text_font: font_small + text_color: 0xB2BEC3 + - btn: + x: 640 + y: 424 + width: 148 + height: 40 + bg_color: 0xFF4757 + radius: 12 + on_click: + then: + - script.execute: reset_jordyn_chores + - script.execute: reset_declan_chores + - script.execute: reset_chloe_chores + widgets: + - label: + align: CENTER + text: "↺ Reset All" + text_color: 0xFFFFFF + text_font: font_tiny + - btn: + id: home_btn_jordyn + x: 80 + y: 130 + width: 200 + height: 210 + bg_color: 0xFFFFFF + bg_opa: TRANSP + border_color: 0xFF4757 + border_width: 5 + radius: 24 + on_click: + then: + - lvgl.page.show: page_jordyn + widgets: + - label: + align: CENTER + y: -45 + text: "😺" + text_font: font_title + - label: + align: CENTER + y: 22 + text: "Jordyn" + text_font: font_name + text_color: 0x2D3436 + - label: + id: home_status_jordyn + align: CENTER + y: 66 + text: "not done" + text_font: font_tiny + text_color: 0xFF4757 + + - btn: + id: home_btn_declan + x: 300 + y: 130 + width: 200 + height: 210 + bg_color: 0xFFFFFF + bg_opa: TRANSP + border_color: 0xFF4757 + border_width: 5 + radius: 24 + on_click: + then: + - lvgl.page.show: page_declan + widgets: + - label: + align: CENTER + y: -45 + text: "🤓" + text_font: font_title + - label: + align: CENTER + y: 22 + text: "Declan" + text_font: font_name + text_color: 0x2D3436 + - label: + id: home_status_declan + align: CENTER + y: 66 + text: "not done" + text_font: font_tiny + text_color: 0xFF4757 + + - btn: + id: home_btn_chloe + x: 520 + y: 130 + width: 200 + height: 210 + bg_color: 0xFFFFFF + bg_opa: TRANSP + border_color: 0xFF4757 + border_width: 5 + radius: 24 + on_click: + then: + - lvgl.page.show: page_chloe + widgets: + - label: + align: CENTER + y: -45 + text: "🌝" + text_font: font_title + - label: + align: CENTER + y: 22 + text: "Chloe" + text_font: font_name + text_color: 0x2D3436 + - label: + id: home_status_chloe + align: CENTER + y: 66 + text: "not done" + text_font: font_tiny + text_color: 0xFF4757 + + + - id: page_jordyn + bg_color: 0xFFF9F0 + widgets: + + # ── Sidebar ────────────────────────────────────────────────────────── + - obj: + x: 0 + y: 0 + width: 172 + height: 480 + bg_color: 0x4D96FF + border_width: 0 + radius: 0 + pad_all: 0 + widgets: + - label: + x: 0 + y: 22 + width: 172 + align: TOP_MID + text: "😺" + text_font: font_title + - label: + x: 0 + y: 76 + width: 172 + align: TOP_MID + text: "Jordyn" + text_font: font_name + text_color: 0xFFFFFF + - bar: + id: progress_bar_jordyn + x: 14 + y: 132 + width: 144 + height: 16 + bg_color: 0x2A6FCC + indicator: + bg_color: 0xFFFFFF + value: 0 + min_value: 0 + max_value: 5 + - label: + id: progress_label_jordyn + x: 0 + y: 156 + width: 172 + align: TOP_MID + text: "0 / 5" + text_font: font_small + text_color: 0xDDEEFF + - label: + id: all_done_label_jordyn + x: 0 + y: 192 + width: 172 + align: TOP_MID + text: "" + text_font: font_small + text_color: 0xFFFFFF + - btn: + x: 14 + y: 364 + width: 144 + height: 44 + bg_color: 0xFF4757 + radius: 14 + on_click: + then: + - script.execute: reset_jordyn_chores + widgets: + - label: + align: CENTER + text: "↺ Reset" + text_color: 0xFFFFFF + text_font: font_small + - btn: + x: 14 + y: 420 + width: 144 + height: 44 + bg_color: 0x2A6FCC + radius: 14 + on_click: + then: + - lvgl.page.show: page_home + widgets: + - label: + align: CENTER + text: "◀ Home" + text_color: 0xFFFFFF + text_font: font_small + + # ── Chore cards ─────────────────────────────────────────────────────── + - btn: + id: card_jordyn_make_bed + x: 182 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: jordyn_make_bed + widgets: + - label: + id: check_jordyn_make_bed + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🛏️" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Make Bed" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_jordyn_brush_teeth + x: 388 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: jordyn_brush_teeth + widgets: + - label: + id: check_jordyn_brush_teeth + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🦷" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Brush Teeth" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_jordyn_tidy_room + x: 594 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: jordyn_tidy_room + widgets: + - label: + id: check_jordyn_tidy_room + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🧹" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Tidy Room" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_jordyn_homework + x: 182 + y: 158 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: jordyn_homework + widgets: + - label: + id: check_jordyn_homework + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "📚" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Homework" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_jordyn_feed_dog + x: 388 + y: 158 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: jordyn_feed_dog + widgets: + - label: + id: check_jordyn_feed_dog + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🐾" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Feed Dog" + text_font: font_small + text_color: 0x2D3436 + + + - id: page_declan + bg_color: 0xFFF9F0 + widgets: + + # ── Sidebar ────────────────────────────────────────────────────────── + - obj: + x: 0 + y: 0 + width: 172 + height: 480 + bg_color: 0xC77DFF + border_width: 0 + radius: 0 + pad_all: 0 + widgets: + - label: + x: 0 + y: 22 + width: 172 + align: TOP_MID + text: "🤓" + text_font: font_title + - label: + x: 0 + y: 76 + width: 172 + align: TOP_MID + text: "Declan" + text_font: font_name + text_color: 0xFFFFFF + - bar: + id: progress_bar_declan + x: 14 + y: 132 + width: 144 + height: 16 + bg_color: 0x8B42CC + indicator: + bg_color: 0xFFFFFF + value: 0 + min_value: 0 + max_value: 4 + - label: + id: progress_label_declan + x: 0 + y: 156 + width: 172 + align: TOP_MID + text: "0 / 4" + text_font: font_small + text_color: 0xDDEEFF + - label: + id: all_done_label_declan + x: 0 + y: 192 + width: 172 + align: TOP_MID + text: "" + text_font: font_small + text_color: 0xFFFFFF + - btn: + x: 14 + y: 364 + width: 144 + height: 44 + bg_color: 0xFF4757 + radius: 14 + on_click: + then: + - script.execute: reset_declan_chores + widgets: + - label: + align: CENTER + text: "↺ Reset" + text_color: 0xFFFFFF + text_font: font_small + - btn: + x: 14 + y: 420 + width: 144 + height: 44 + bg_color: 0x8B42CC + radius: 14 + on_click: + then: + - lvgl.page.show: page_home + widgets: + - label: + align: CENTER + text: "◀ Home" + text_color: 0xFFFFFF + text_font: font_small + + # ── Chore cards ─────────────────────────────────────────────────────── + - btn: + id: card_declan_make_bed + x: 182 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: declan_make_bed + widgets: + - label: + id: check_declan_make_bed + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🛏️" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Make Bed" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_declan_brush_teeth + x: 388 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: declan_brush_teeth + widgets: + - label: + id: check_declan_brush_teeth + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🦷" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Brush Teeth" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_declan_set_table + x: 594 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: declan_set_table + widgets: + - label: + id: check_declan_set_table + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🍽️" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Set Table" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_declan_take_out_trash + x: 182 + y: 158 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: declan_take_out_trash + widgets: + - label: + id: check_declan_take_out_trash + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🗑️" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Take Out Trash" + text_font: font_small + text_color: 0x2D3436 + + + - id: page_chloe + bg_color: 0xFFF9F0 + widgets: + + # ── Sidebar ────────────────────────────────────────────────────────── + - obj: + x: 0 + y: 0 + width: 172 + height: 480 + bg_color: 0xFF6B9D + border_width: 0 + radius: 0 + pad_all: 0 + widgets: + - label: + x: 0 + y: 22 + width: 172 + align: TOP_MID + text: "🌝" + text_font: font_title + - label: + x: 0 + y: 76 + width: 172 + align: TOP_MID + text: "Chloe" + text_font: font_name + text_color: 0xFFFFFF + - bar: + id: progress_bar_chloe + x: 14 + y: 132 + width: 144 + height: 16 + bg_color: 0xCC3A6F + indicator: + bg_color: 0xFFFFFF + value: 0 + min_value: 0 + max_value: 6 + - label: + id: progress_label_chloe + x: 0 + y: 156 + width: 172 + align: TOP_MID + text: "0 / 6" + text_font: font_small + text_color: 0xDDEEFF + - label: + id: all_done_label_chloe + x: 0 + y: 192 + width: 172 + align: TOP_MID + text: "" + text_font: font_small + text_color: 0xFFFFFF + - btn: + x: 14 + y: 364 + width: 144 + height: 44 + bg_color: 0xFF4757 + radius: 14 + on_click: + then: + - script.execute: reset_chloe_chores + widgets: + - label: + align: CENTER + text: "↺ Reset" + text_color: 0xFFFFFF + text_font: font_small + - btn: + x: 14 + y: 420 + width: 144 + height: 44 + bg_color: 0xCC3A6F + radius: 14 + on_click: + then: + - lvgl.page.show: page_home + widgets: + - label: + align: CENTER + text: "◀ Home" + text_color: 0xFFFFFF + text_font: font_small + + # ── Chore cards ─────────────────────────────────────────────────────── + - btn: + id: card_chloe_make_bed + x: 182 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: chloe_make_bed + widgets: + - label: + id: check_chloe_make_bed + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🛏️" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Make Bed" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_chloe_brush_teeth + x: 388 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: chloe_brush_teeth + widgets: + - label: + id: check_chloe_brush_teeth + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🦷" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Brush Teeth" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_chloe_water_plants + x: 594 + y: 10 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: chloe_water_plants + widgets: + - label: + id: check_chloe_water_plants + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🌱" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Water Plants" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_chloe_homework + x: 182 + y: 158 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: chloe_homework + widgets: + - label: + id: check_chloe_homework + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "📚" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Homework" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_chloe_tidy_room + x: 388 + y: 158 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: chloe_tidy_room + widgets: + - label: + id: check_chloe_tidy_room + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🧹" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Tidy Room" + text_font: font_small + text_color: 0x2D3436 + + - btn: + id: card_chloe_practice_piano + x: 594 + y: 158 + width: 196 + height: 138 + bg_color: 0xFFFFFF + border_color: 0xEEEEEE + border_width: 2 + radius: 20 + shadow_color: 0xCCCCCC + shadow_width: 4 + shadow_ofs_y: 3 + on_click: + then: + - switch.toggle: chloe_practice_piano + widgets: + - label: + id: check_chloe_practice_piano + align: TOP_RIGHT + x: -10 + y: 8 + text: "" + text_font: font_med + - label: + align: CENTER + y: -34 + text: "🎹" + text_font: font_med + - label: + align: CENTER + y: 17 + text: "Practice Piano" + text_font: font_small + text_color: 0x2D3436 + + diff --git a/esphome/chore-tracker/chore-tracker-ha.yaml b/esphome/chore-tracker/chore-tracker-ha.yaml new file mode 100644 index 0000000..b4dd7d1 --- /dev/null +++ b/esphome/chore-tracker/chore-tracker-ha.yaml @@ -0,0 +1,258 @@ +################################################################################ +# chore-tracker-ha.yaml (AUTO-GENERATED — edit chores_config.yaml) +# Kids: Jordyn, Declan, Chloe +# +# BIDIRECTIONAL SYNC: +# Screen → HA: Each switch calls homeassistant.service on toggle +# HA → Screen: ESPHome native API handles this automatically +################################################################################ + +input_button: + jordyn_reset_chores: + name: "Reset Jordyn's Chores" + icon: mdi:restart + declan_reset_chores: + name: "Reset Declan's Chores" + icon: mdi:restart + chloe_reset_chores: + name: "Reset Chloe's Chores" + icon: mdi:restart + reset_all_chores: + name: "Reset All Chores" + icon: mdi:restart-alert + +template: + - sensor: + - name: "Jordyn Chores Done Today" + unique_id: jordyn_chores_done_today + icon: mdi:check-circle + state: > + {% set chores = [states('switch.chore_tracker_jordyn_make_bed'), states('switch.chore_tracker_jordyn_brush_teeth'), states('switch.chore_tracker_jordyn_tidy_room'), states('switch.chore_tracker_jordyn_homework'), states('switch.chore_tracker_jordyn_feed_dog')] %} + {{ chores | select('equalto', 'on') | list | count }} + + - name: "Jordyn All Chores Done" + unique_id: jordyn_all_chores_done + icon: mdi:check-all + state: > + {{ states('sensor.jordyn_chores_done_today') | int == 5 }} + + - name: "Declan Chores Done Today" + unique_id: declan_chores_done_today + icon: mdi:check-circle + state: > + {% set chores = [states('switch.chore_tracker_declan_make_bed'), states('switch.chore_tracker_declan_brush_teeth'), states('switch.chore_tracker_declan_set_table'), states('switch.chore_tracker_declan_take_out_trash')] %} + {{ chores | select('equalto', 'on') | list | count }} + + - name: "Declan All Chores Done" + unique_id: declan_all_chores_done + icon: mdi:check-all + state: > + {{ states('sensor.declan_chores_done_today') | int == 4 }} + + - name: "Chloe Chores Done Today" + unique_id: chloe_chores_done_today + icon: mdi:check-circle + state: > + {% set chores = [states('switch.chore_tracker_chloe_make_bed'), states('switch.chore_tracker_chloe_brush_teeth'), states('switch.chore_tracker_chloe_water_plants'), states('switch.chore_tracker_chloe_homework'), states('switch.chore_tracker_chloe_tidy_room'), states('switch.chore_tracker_chloe_practice_piano')] %} + {{ chores | select('equalto', 'on') | list | count }} + + - name: "Chloe All Chores Done" + unique_id: chloe_all_chores_done + icon: mdi:check-all + state: > + {{ states('sensor.chloe_chores_done_today') | int == 6 }} + + +automation: + - id: jordyn_reset_from_ha + alias: "Chore Tracker — Reset Jordyn's chores from HA" + trigger: + - platform: state + entity_id: input_button.jordyn_reset_chores + action: + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_make_bed + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_brush_teeth + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_tidy_room + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_homework + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_feed_dog + + - id: declan_reset_from_ha + alias: "Chore Tracker — Reset Declan's chores from HA" + trigger: + - platform: state + entity_id: input_button.declan_reset_chores + action: + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_make_bed + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_brush_teeth + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_set_table + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_take_out_trash + + - id: chloe_reset_from_ha + alias: "Chore Tracker — Reset Chloe's chores from HA" + trigger: + - platform: state + entity_id: input_button.chloe_reset_chores + action: + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_make_bed + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_brush_teeth + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_water_plants + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_homework + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_tidy_room + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_practice_piano + + - id: reset_all_from_ha + alias: "Chore Tracker — Reset ALL chores from HA" + trigger: + - platform: state + entity_id: input_button.reset_all_chores + action: + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_make_bed + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_brush_teeth + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_tidy_room + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_homework + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_jordyn_feed_dog + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_make_bed + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_brush_teeth + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_set_table + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_declan_take_out_trash + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_make_bed + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_brush_teeth + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_water_plants + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_homework + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_tidy_room + - service: switch.turn_off + target: + entity_id: switch.chore_tracker_chloe_practice_piano + + - id: jordyn_all_done_notify + alias: "Chore Tracker — Jordyn all done!" + trigger: + - platform: state + entity_id: sensor.jordyn_all_chores_done + to: "True" + action: + - service: notify.notify + data: + title: "🎉 Jordyn finished all chores!" + message: "Jordyn completed all 5 chores today!" + + - id: declan_all_done_notify + alias: "Chore Tracker — Declan all done!" + trigger: + - platform: state + entity_id: sensor.declan_all_chores_done + to: "True" + action: + - service: notify.notify + data: + title: "🎉 Declan finished all chores!" + message: "Declan completed all 4 chores today!" + + - id: chloe_all_done_notify + alias: "Chore Tracker — Chloe all done!" + trigger: + - platform: state + entity_id: sensor.chloe_all_chores_done + to: "True" + action: + - service: notify.notify + data: + title: "🎉 Chloe finished all chores!" + message: "Chloe completed all 6 chores today!" + + - id: chore_reminder_evening + alias: "Chore Tracker — Evening reminder" + trigger: + - platform: time + at: "18:00:00" + action: + - if: + condition: template + value_template: "{{ states('sensor.jordyn_all_chores_done') != 'True' }}" + then: + - service: notify.notify + data: + title: "📋 Jordyn has unfinished chores" + message: > + Jordyn has done + {{ states('sensor.jordyn_chores_done_today') }}/5 chores today. + - if: + condition: template + value_template: "{{ states('sensor.declan_all_chores_done') != 'True' }}" + then: + - service: notify.notify + data: + title: "📋 Declan has unfinished chores" + message: > + Declan has done + {{ states('sensor.declan_chores_done_today') }}/4 chores today. + - if: + condition: template + value_template: "{{ states('sensor.chloe_all_chores_done') != 'True' }}" + then: + - service: notify.notify + data: + title: "📋 Chloe has unfinished chores" + message: > + Chloe has done + {{ states('sensor.chloe_chores_done_today') }}/6 chores today. + + diff --git a/esphome/chore-tracker/generate.py b/esphome/chore-tracker/generate.py index 4038820..f93848e 100644 --- a/esphome/chore-tracker/generate.py +++ b/esphome/chore-tracker/generate.py @@ -222,7 +222,7 @@ time: {reset_calls} - lvgl.page.show: page_home -fonts: +font: - file: "gfonts://Nunito:wght@900" id: font_title size: 40