# ################################################################################ # # 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) # ################################################################################ # substitutions: # device_name: chore-tracker # friendly_name: "Chore Tracker" # esphome: # name: ${device_name} # friendly_name: ${friendly_name} # on_boot: # priority: -10 # then: # - light.turn_on: backlight # - lvgl.page.show: page_home # esp32: # board: esp32-s3-devkitc-1 # framework: # type: esp-idf # psram: # mode: octal # speed: 80MHz # wifi: # ssid: !secret wifi_iot_ssid # password: !secret wifi_password # manual_ip: # static_ip: 192.168.69.115 # gateway: 192.168.69.1 # subnet: 255.255.255.0 # ap: # ssid: "Chore Tracker Hotspot" # password: "choretracker" # # Prevents aggressive reconnection attempts # power_save_mode: none # Use 'light' for battery devices # # Slower but more reliable connection # fast_connect: true # # Handle connection failures gracefully # on_connect: # - logger.log: "Wi-Fi connected!" # on_disconnect: # - logger.log: "Wi-Fi disconnected!" # mdns: # disabled: true # safe_mode: # disabled: true # #captive_portal: # logger: # level: DEBUG # api: # encryption: # key: !secret api_encryption_key # reboot_timeout: 0s # ota: # - platform: esphome # password: !secret ota_password # web_server: # port: 8080 # # ── 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; # # Diagnostic sensors # - platform: wifi_signal # name: "${device_name} WiFi Signal" # update_interval: 60s # - platform: uptime # name: "${device_name} Uptime" # update_interval: 60s # text_sensor: # - platform: wifi_info # ip_address: # name: "${device_name} IP Address" # ssid: # name: "${device_name} Connected SSID" # bssid: # name: "${device_name} BSSID" # # Watchdog to auto-reboot if things go wrong # # Note: interval fires on first tick (t≈0), so guard with millis() to ensure # # the device has actually been running for 5+ minutes before triggering. # interval: # - interval: 5min # then: # - if: # condition: # and: # - lambda: 'return millis() > 300000;' # >5 min uptime # - not: # wifi.connected: # then: # - logger.log: "Wi-Fi not connected for 5 min, rebooting..." # - delay: 10s # - lambda: 'App.safe_reboot();' # # ── 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: 776 # align: TOP_MID # text: "Chore Tracker" # text_font: font_title # text_color: 0x2D3436 # - label: # x: 0 # y: 90 # width: 776 # align: TOP_MID # text: "Tap a name to check off chores" # text_font: font_small # text_color: 0xB2BEC3 # - button: # x: 640 # y: 428 # 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: 0x5F5980 # 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: 0x2F3061 # 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: 374 # 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: 424 # width: 144 # height: 44 # bg_color: 0x2F3061 # 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: 12 # width: 195 # 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 # text_color: 0x5F5980 # - label: # align: CENTER # y: 17 # text: "Put on underwear" # text_font: font_small # text_color: 0x2D3436 # - button: # id: card_jordyn_brush_teeth # x: 387 # y: 12 # width: 195 # 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 # text_color: 0x5F5980 # - label: # align: CENTER # y: 17 # text: "Brush Teeth" # text_font: font_small # text_color: 0x2D3436 # - button: # id: card_jordyn_fill_water_bowls # x: 592 # y: 12 # width: 195 # 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 # text_color: 0x5F5980 # - 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: 160 # width: 195 # 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 # text_color: 0x5F5980 # - 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: 0x720026 # 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: 0x4F000B # 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: 374 # 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: 424 # width: 144 # height: 44 # bg_color: 0x4F000B # 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: 12 # width: 195 # 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 # text_color: 0x720026 # - label: # align: CENTER # y: 17 # text: "Take morning pill" # text_font: font_small # text_color: 0x2D3436 # - button: # id: card_declan_scoop_dog_poop # x: 387 # y: 12 # width: 195 # 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 # text_color: 0x720026 # - 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: 0x73683B # 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: 0x583E23 # 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: 374 # 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: 424 # width: 144 # height: 44 # bg_color: 0x583E23 # 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: 12 # width: 195 # 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 # text_color: 0x73683B # - label: # align: CENTER # y: 17 # text: "Fill kitty feeders" # text_font: font_small # text_color: 0x2D3436 # - button: # id: card_chloe_scoop_kitty_litter # x: 387 # y: 12 # width: 195 # 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 # text_color: 0x73683B # - 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: 592 # y: 12 # width: 195 # 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 # text_color: 0x73683B # - label: # align: CENTER # y: 17 # text: "Replace Kitty Litter Bags" # text_font: font_small # text_color: 0x2D3436