################################################################################ # 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 fonts: - 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