################################################################################ # 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 # # 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_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 # ── I2C ─────────────────────────────────────────────────────────────────────── i2c: 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: 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: binary name: "Display Backlight" output: lcd_backlight_out id: backlight # ── 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 # ── Fonts (place files in /config/esphome/fonts/) ──────────────────────────── font: - file: "fonts/Nunito-Black.ttf" id: font_title size: 40 - file: "fonts/Nunito-ExtraBold.ttf" id: font_name size: 30 - file: "fonts/Nunito-Bold.ttf" id: font_med size: 22 - file: "fonts/Nunito-SemiBold.ttf" id: font_small size: 17 - file: "fonts/Nunito-SemiBold.ttf" id: font_tiny size: 13 # MDI icon font — used for chore icons and kid avatars - file: "fonts/materialdesignicons-webfont.ttf" id: font_mdi_large size: 48 bpp: 4 glyphs: 󰄛󰆫󰇷󰊩󰋣󰐂󰦩󱑷󱚣󱜜 - file: "fonts/materialdesignicons-webfont.ttf" id: font_mdi_small size: 32 bpp: 4 glyphs: 󰄛󰆫󰇷󰊩󰋣󰐂󰦩󱑷󱚣󱜜 # ── 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 name: "Jordyn - Put on underwear" id: jordyn_put_on_underwear 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_put_on_underwear on_turn_off: then: - script.execute: update_jordyn_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_jordyn_put_on_underwear - 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 - Fill water bowls" id: jordyn_fill_water_bowls 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_fill_water_bowls on_turn_off: then: - script.execute: update_jordyn_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_jordyn_fill_water_bowls - platform: template name: "Jordyn - Restock Cat Food Cans" id: jordyn_restock_cat_food_cans 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_restock_cat_food_cans on_turn_off: then: - script.execute: update_jordyn_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_jordyn_restock_cat_food_cans # ── Declan's chores ────────────────────────── - platform: template name: "Declan - Take morning pill" id: declan_take_morning_pill 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_morning_pill on_turn_off: then: - script.execute: update_declan_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_declan_take_morning_pill - platform: template name: "Declan - Scoop Dog Poop" id: declan_scoop_dog_poop 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_scoop_dog_poop on_turn_off: then: - script.execute: update_declan_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_declan_scoop_dog_poop # ── Chloe's chores ────────────────────────── - platform: template name: "Chloe - Fill kitty feeders" id: chloe_fill_kitty_feeders 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_fill_kitty_feeders on_turn_off: then: - script.execute: update_chloe_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_chloe_fill_kitty_feeders - platform: template name: "Chloe - Scoop Kitty Litter" id: chloe_scoop_kitty_litter 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_scoop_kitty_litter on_turn_off: then: - script.execute: update_chloe_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_chloe_scoop_kitty_litter - platform: template name: "Chloe - Replace Kitty Litter Bags" id: chloe_replace_kitty_litter_bags 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_replace_kitty_litter_bags on_turn_off: then: - script.execute: update_chloe_ui - homeassistant.service: service: switch.turn_off data: entity_id: switch.chore_tracker_chloe_replace_kitty_litter_bags # ── 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_put_on_underwear).state) done++; if (id(jordyn_brush_teeth).state) done++; if (id(jordyn_fill_water_bowls).state) done++; if (id(jordyn_restock_cat_food_cans).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_take_morning_pill).state) done++; if (id(declan_scoop_dog_poop).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_fill_kitty_feeders).state) done++; if (id(chloe_scoop_kitty_litter).state) done++; if (id(chloe_replace_kitty_litter_bags).state) done++; return done; # ── Scripts — reset + UI update ─────────────────────────────────────────────── script: - id: reset_jordyn_chores mode: single then: - lambda: |- id(jordyn_put_on_underwear).turn_off(); id(jordyn_brush_teeth).turn_off(); id(jordyn_fill_water_bowls).turn_off(); id(jordyn_restock_cat_food_cans).turn_off(); - script.execute: update_jordyn_ui - id: update_jordyn_ui mode: single then: - lambda: |- int done = (id(jordyn_put_on_underwear).state ? 1 : 0) + (id(jordyn_brush_teeth).state ? 1 : 0) + (id(jordyn_fill_water_bowls).state ? 1 : 0) + (id(jordyn_restock_cat_food_cans).state ? 1 : 0); int total = 4; char buf[24]; // Progress bar + label lv_bar_set_value(id(progress_bar_jordyn), done, LV_ANIM_ON); snprintf(buf, sizeof(buf), "%d / 4", 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 ? "All done!" : ""); // 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); 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_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_jordyn), lv_color_hex(0xFF4757), LV_PART_MAIN); lv_obj_set_style_border_width(id(home_btn_jordyn), 0, 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_put_on_underwear).state) { lv_obj_set_style_bg_color(id(card_jordyn_put_on_underwear), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_jordyn_put_on_underwear), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_jordyn_put_on_underwear), 3, LV_PART_MAIN); lv_label_set_text(id(check_jordyn_put_on_underwear), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_jordyn_put_on_underwear), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_jordyn_put_on_underwear), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_jordyn_put_on_underwear), 2, LV_PART_MAIN); lv_label_set_text(id(check_jordyn_put_on_underwear), ""); } 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_fill_water_bowls).state) { lv_obj_set_style_bg_color(id(card_jordyn_fill_water_bowls), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_jordyn_fill_water_bowls), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_jordyn_fill_water_bowls), 3, LV_PART_MAIN); lv_label_set_text(id(check_jordyn_fill_water_bowls), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_jordyn_fill_water_bowls), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_jordyn_fill_water_bowls), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_jordyn_fill_water_bowls), 2, LV_PART_MAIN); lv_label_set_text(id(check_jordyn_fill_water_bowls), ""); } if (id(jordyn_restock_cat_food_cans).state) { lv_obj_set_style_bg_color(id(card_jordyn_restock_cat_food_cans), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_jordyn_restock_cat_food_cans), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_jordyn_restock_cat_food_cans), 3, LV_PART_MAIN); lv_label_set_text(id(check_jordyn_restock_cat_food_cans), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_jordyn_restock_cat_food_cans), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_jordyn_restock_cat_food_cans), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_jordyn_restock_cat_food_cans), 2, LV_PART_MAIN); lv_label_set_text(id(check_jordyn_restock_cat_food_cans), ""); } - id: reset_declan_chores mode: single then: - lambda: |- id(declan_take_morning_pill).turn_off(); id(declan_scoop_dog_poop).turn_off(); - script.execute: update_declan_ui - id: update_declan_ui mode: single then: - lambda: |- int done = (id(declan_take_morning_pill).state ? 1 : 0) + (id(declan_scoop_dog_poop).state ? 1 : 0); int total = 2; char buf[24]; // Progress bar + label lv_bar_set_value(id(progress_bar_declan), done, LV_ANIM_ON); snprintf(buf, sizeof(buf), "%d / 2", 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 ? "All done!" : ""); // 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); 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_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_declan), lv_color_hex(0xFF4757), LV_PART_MAIN); lv_obj_set_style_border_width(id(home_btn_declan), 0, 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_take_morning_pill).state) { lv_obj_set_style_bg_color(id(card_declan_take_morning_pill), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_declan_take_morning_pill), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_declan_take_morning_pill), 3, LV_PART_MAIN); lv_label_set_text(id(check_declan_take_morning_pill), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_declan_take_morning_pill), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_declan_take_morning_pill), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_declan_take_morning_pill), 2, LV_PART_MAIN); lv_label_set_text(id(check_declan_take_morning_pill), ""); } if (id(declan_scoop_dog_poop).state) { lv_obj_set_style_bg_color(id(card_declan_scoop_dog_poop), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_declan_scoop_dog_poop), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_declan_scoop_dog_poop), 3, LV_PART_MAIN); lv_label_set_text(id(check_declan_scoop_dog_poop), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_declan_scoop_dog_poop), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_declan_scoop_dog_poop), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_declan_scoop_dog_poop), 2, LV_PART_MAIN); lv_label_set_text(id(check_declan_scoop_dog_poop), ""); } - id: reset_chloe_chores mode: single then: - lambda: |- id(chloe_fill_kitty_feeders).turn_off(); id(chloe_scoop_kitty_litter).turn_off(); id(chloe_replace_kitty_litter_bags).turn_off(); - script.execute: update_chloe_ui - id: update_chloe_ui mode: single then: - lambda: |- int done = (id(chloe_fill_kitty_feeders).state ? 1 : 0) + (id(chloe_scoop_kitty_litter).state ? 1 : 0) + (id(chloe_replace_kitty_litter_bags).state ? 1 : 0); int total = 3; char buf[24]; // Progress bar + label lv_bar_set_value(id(progress_bar_chloe), done, LV_ANIM_ON); snprintf(buf, sizeof(buf), "%d / 3", 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 ? "All done!" : ""); // 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); 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_COVER, LV_PART_MAIN); lv_obj_set_style_bg_color(id(home_btn_chloe), lv_color_hex(0xFF4757), LV_PART_MAIN); lv_obj_set_style_border_width(id(home_btn_chloe), 0, 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_fill_kitty_feeders).state) { lv_obj_set_style_bg_color(id(card_chloe_fill_kitty_feeders), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_chloe_fill_kitty_feeders), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_chloe_fill_kitty_feeders), 3, LV_PART_MAIN); lv_label_set_text(id(check_chloe_fill_kitty_feeders), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_chloe_fill_kitty_feeders), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_chloe_fill_kitty_feeders), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_chloe_fill_kitty_feeders), 2, LV_PART_MAIN); lv_label_set_text(id(check_chloe_fill_kitty_feeders), ""); } if (id(chloe_scoop_kitty_litter).state) { lv_obj_set_style_bg_color(id(card_chloe_scoop_kitty_litter), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_chloe_scoop_kitty_litter), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_chloe_scoop_kitty_litter), 3, LV_PART_MAIN); lv_label_set_text(id(check_chloe_scoop_kitty_litter), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_chloe_scoop_kitty_litter), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_chloe_scoop_kitty_litter), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_chloe_scoop_kitty_litter), 2, LV_PART_MAIN); lv_label_set_text(id(check_chloe_scoop_kitty_litter), ""); } if (id(chloe_replace_kitty_litter_bags).state) { lv_obj_set_style_bg_color(id(card_chloe_replace_kitty_litter_bags), lv_color_hex(0xF0FFF4), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_chloe_replace_kitty_litter_bags), lv_color_hex(0x6BCB77), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_chloe_replace_kitty_litter_bags), 3, LV_PART_MAIN); lv_label_set_text(id(check_chloe_replace_kitty_litter_bags), "\u2705"); } else { lv_obj_set_style_bg_color(id(card_chloe_replace_kitty_litter_bags), lv_color_hex(0xFFFFFF), LV_PART_MAIN); lv_obj_set_style_border_color(id(card_chloe_replace_kitty_litter_bags), lv_color_hex(0xEEEEEE), LV_PART_MAIN); lv_obj_set_style_border_width(id(card_chloe_replace_kitty_litter_bags), 2, LV_PART_MAIN); lv_label_set_text(id(check_chloe_replace_kitty_litter_bags), ""); } # ── LVGL UI ─────────────────────────────────────────────────────────────────── lvgl: displays: - main_display touchscreens: - touch theme: button: 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 - button: 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 - button: id: home_btn_jordyn x: 80 y: 130 width: 200 height: 210 bg_color: 0xFF4757 bg_opa: COVER border_width: 0 radius: 24 on_click: then: - lvgl.page.show: page_jordyn widgets: - label: align: CENTER y: -45 text: "󰄛" text_font: font_mdi_large - label: align: CENTER y: 22 text: "Jordyn" text_font: font_name text_color: 0xFFFFFF - label: id: home_status_jordyn align: CENTER y: 66 text: "not done" text_font: font_tiny text_color: 0xFFFFFF - button: id: home_btn_declan x: 300 y: 130 width: 200 height: 210 bg_color: 0xFF4757 bg_opa: COVER border_width: 0 radius: 24 on_click: then: - lvgl.page.show: page_declan widgets: - label: align: CENTER y: -45 text: "󱑷" text_font: font_mdi_large - label: align: CENTER y: 22 text: "Declan" text_font: font_name text_color: 0xFFFFFF - label: id: home_status_declan align: CENTER y: 66 text: "not done" text_font: font_tiny text_color: 0xFFFFFF - button: id: home_btn_chloe x: 520 y: 130 width: 200 height: 210 bg_color: 0xFF4757 bg_opa: COVER border_width: 0 radius: 24 on_click: then: - lvgl.page.show: page_chloe widgets: - label: align: CENTER y: -45 text: "󱚣" text_font: font_mdi_large - label: align: CENTER y: 22 text: "Chloe" text_font: font_name text_color: 0xFFFFFF - label: id: home_status_chloe align: CENTER y: 66 text: "not done" text_font: font_tiny text_color: 0xFFFFFF - 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_mdi_large - 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: 4 - label: id: progress_label_jordyn x: 0 y: 156 width: 172 align: TOP_MID text: "0 / 4" 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 - button: 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 - button: 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 ─────────────────────────────────────────────────────── - button: id: card_jordyn_put_on_underwear 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_put_on_underwear widgets: - label: id: check_jordyn_put_on_underwear align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰋣" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Put on underwear" text_font: font_small text_color: 0x2D3436 - button: 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_mdi_small - label: align: CENTER y: 17 text: "Brush Teeth" text_font: font_small text_color: 0x2D3436 - button: id: card_jordyn_fill_water_bowls 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_fill_water_bowls widgets: - label: id: check_jordyn_fill_water_bowls align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰆫" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Fill water bowls" text_font: font_small text_color: 0x2D3436 - button: id: card_jordyn_restock_cat_food_cans 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_restock_cat_food_cans widgets: - label: id: check_jordyn_restock_cat_food_cans align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󱜜" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Restock Cat Food Cans" 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_mdi_large - 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: 2 - label: id: progress_label_declan x: 0 y: 156 width: 172 align: TOP_MID text: "0 / 2" 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 - button: 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 - button: 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 ─────────────────────────────────────────────────────── - button: id: card_declan_take_morning_pill 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_take_morning_pill widgets: - label: id: check_declan_take_morning_pill align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰐂" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Take morning pill" text_font: font_small text_color: 0x2D3436 - button: id: card_declan_scoop_dog_poop 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_scoop_dog_poop widgets: - label: id: check_declan_scoop_dog_poop align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰇷" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Scoop Dog Poop" 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_mdi_large - 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: 3 - label: id: progress_label_chloe x: 0 y: 156 width: 172 align: TOP_MID text: "0 / 3" 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 - button: 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 - button: 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 ─────────────────────────────────────────────────────── - button: id: card_chloe_fill_kitty_feeders 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_fill_kitty_feeders widgets: - label: id: check_chloe_fill_kitty_feeders align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰊩" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Fill kitty feeders" text_font: font_small text_color: 0x2D3436 - button: id: card_chloe_scoop_kitty_litter 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_scoop_kitty_litter widgets: - label: id: check_chloe_scoop_kitty_litter align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰇷" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Scoop Kitty Litter" text_font: font_small text_color: 0x2D3436 - button: id: card_chloe_replace_kitty_litter_bags 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_replace_kitty_litter_bags widgets: - label: id: check_chloe_replace_kitty_litter_bags align: TOP_RIGHT x: -10 y: 8 text: "" text_font: font_med - label: align: CENTER y: -34 text: "󰇷" text_font: font_mdi_small - label: align: CENTER y: 17 text: "Replace Kitty Litter Bags" text_font: font_small text_color: 0x2D3436