Do you struggle keeping track of the household chores assigned to your kids? Or motivating them to complete their tasks? At one point, we used a whiteboard to keep track of tasks. But it's analogue, got limited space, got no time tracking, can't notify me, it's easy to forget to reset and hard to calculate the weekly allowance based on completed chores. The kids see no progress; except maybe some stickers...
So I thought, why not create a special dashboards for the kids, where they kan keep track of their tasks, their weekly allowance and throw in an element of gamification?
This article outlines a proposal on how you can implement this for your kids. It builds on the basic idea of how I manage repeating household chores, and adds a personalised gamification layer on top of it.
The first step is to create the tasks for each kid. I will use input booleans and a strict naming convention to make it possible to assign the right task to the right kid.
input boolean:
vacuum_<kid1>_household_chore:
name: Vacuum the house
bedlinens_<kid1>_household_chore:
name: Change your bed linens
settable_<kid1>_household_chore:
name: Set the dinner table
dishes_<kid2>_household_chore:
name: Do the dishes
bedlinens_<kid2>_household_chore:
name: Change your bed linens
cleartable_<kid2>_household_chore:
name: Clear the dinner table
This way, by looking at the entity_id, we know what input boolean belongs to what kid and what task it represents.
Some chores can be expected to be completed every day; like setting or clearing the table. While other chores make sense to do on school days, or every twice week or whatever. This you can control with automations, where you set the tasks to "due" by turning the respective input booleans "off".
automation:
- alias: Chores - every day
trigger:
- platform: time
at: 06:00:00
action:
- service: input_boolean.turn_off
data: {}
target:
entity_id:
- input_boolean.settable_<kid1>_household_chore
- input_boolean.cleartable_<kid2>_household_chore
mode: single
- alias: Chores - weekly
trigger:
- platform: time
at: 06:00:00
condition:
- condition: time
weekday:
- fri
action:
- service: input_boolean.turn_off
data: {}
target:
entity_id:
- input_boolean.vacuum_<kid1>_household_chore
- input_boolean.dishes_<kid2>_household_chore
mode: single
- alias: Chores - every other week
trigger:
- platform: time
at: 06:00:00
condition:
- condition: time
weekday:
- fri
- condition: template
value_template: '{{ now().isocalendar()[1] % 2 == 1 }}'
action:
- service: input_boolean.turn_off
data: {}
target:
entity_id:
- input_boolean.bedlinens_<kid1>_household_chore
- input_boolean.bedlinens_<kid2>_household_chore
mode: single
The first automation will set chores to "due" evey day at 6am. The second automation will set chores to "due" every friday at 6am. The third automation will set chores to "due" every friday at 6am, as long as the current week-number is an odd number (so every second week).
To get a list over which chores are due for a specific kid, use Thomas Lovens brilliant auto-entities card:
- type: custom:auto-entities
filter:
include:
- entity_id: input_boolean.*_<kid1>_household_chore
state: "off"
show_empty: false
card:
type: entities
title: Household chores due for <kid1>
show_header_toggle: false
show_state: false
Of course, kids nowadays are used to getting notifications for everything (I sound really old saying it like this), so you'd better create a binary sensor which will turn "on" whenever there is a new task to be done.
- unique_id: task_due_<kid1>
attributes:
friendly_name: Task due <kid1>
state: "{{ (states |selectattr('entity_id', 'search', 'input_boolean.*_<kid1>_household_chore') |selectattr('state', 'in', 'off')|list)|length > 0 }}"
When the binary sensor turns on, or maybe every afternoon at a set time, if the binary sensor is on, you just send a notification to your kid's mobile phone.
automation:
- alias: Tasks due notification
trigger:
- platform: time
at: 16:00:00
condition:
- condition: state
entity_id: binary_sensor.template_task_due_<kid1>
state: on
action:
- service: notify.mobile_app_<kid1>_mobile
continue_on_error: true
data:
message: 'Hey - complete those due tasks!'
mode: single
Now we have a way of assigning tasks, notifying your kids and a way to show them their todo-list. Now we need a mechanism to grant points whenever the task is done: simply use e.g. "(+1)" in the name field of the input booleans you defined earlier, to define how many points each task is worth, like this:
input boolean:
vacuum_<kid1>_household_chore:
name: Vacuum the house (+3)
bedlinens_<kid1>_household_chore:
name: Change your bed linens (+5)
settable_<kid1>_household_chore:
name: Set the dinner table (+1)
dishes_<kid2>_household_chore:
name: Do the dishes (+3)
bedlinens_<kid2>_household_chore:
name: Change your bed linens (+5)
cleartable_<kid2>_household_chore:
name: Clear the dinner table (+1)
Now, when seeing the todo list, the kid will know how much each task is worth before completing it. It would thus be natural to grant more points to certain weekly tasks, and less points to daily tasks. That way, it's okay to skip a daily task now and then, but not to often, or the kid won't accumulate enouth points to get a decent weekly allowance (we'll soon get to calculating the allowance).
To actually accumulate points based on the (+1) and other values, do the following:
In code, it looks like this:
input_number:
household_chores_<kid1>:
name: <kid1> - points
max: 100
min: 0
step: 1
automation:
- alias: Grant points for chores
trigger:
- platform: state
entity_id:
- input_boolean.vacuum_<kid1>_household_chore
- input_boolean.bedlinens_<kid1>_household_chore
- input_boolean.settable_<kid1>_household_chore
- input_boolean.dishes_<kid2>_household_chore
- input_boolean.bedlinens_<kid2>_household_chore
- input_boolean.cleartable_<kid2>_household_chore
condition: []
action:
- service: script.household_points
data:
triggered_id: '{{ trigger.entity_id }}'
from_state: '{{ trigger.from_state.state }}'
to_state: '{{ trigger.to_state.state }}'
mode: single
script:
household_points:
variables:
grant_to_entity_id: "{{ 'input_number.household_chores_' + triggered_id.split('input_boolean.')[1].split('household_chore')[0].split('_')[1] }}"
grant_points: "{{ state_attr(triggered_id, 'friendly_name').split('(+')[1].split(')')[0]|int }}"
sequence:
- choose:
- conditions: "{{ from_state == 'off' and to_state == 'on' }}"
sequence:
- service: input_number.set_value
target:
entity_id: "{{ grant_to_entity_id }}"
data:
value: "{{ states(grant_to_entity_id)|int + grant_points }}"
Now we are able to count upwards. But we still need a way to reset the score each week, and maybe the adults need a way to deduct points for a task not so well done.
Resetting the score each week is a simple automation every sunday night / monday morning:
automation:
- alias: Reset household chore points
description: ''
trigger:
- platform: time
at: 06:00:00
condition:
- condition: time
weekday:
- mon
action:
- service: input_number.set_value
data:
value: 0
target:
entity_id:
- input_number.household_chores_<kid1>
- input_number.household_chores_<kid2>
mode: single
Deducting points for a task not so well done, is a matter of having a parent dashboard with the kids tasks, and a way of resetting a task while at the same time deducting the points the task was worth.
Deduction of points can be done by setting a "deduct points" input_boolean to "true", before flipping a completed task from "on" to "off. Thus, we need to define an input_boolean for the deduct part first:
input_boolean:
deduct_score:
name: Chore not approved
We'll use the input_boolean in a dashboard, where the parent can flip the "Chore not approved" to true when they want to deduct a score. It can look like this:
# the dashboard part to turn on the "deduct score flag"
- type: entities
entities:
- entity: input_boolean.deduct_score
# the dashboard part where you see and change state of all completed and not completed tasks for <kid1>
- type: custom:auto-entities
filter:
include:
- entity_id: input_boolean.*_<kid1>_household_chore
show_empty: false
card:
type: entities
show_header_toggle: false
show_state: false
If "deduct_score" is "on", when a household_chore os flipped to "off", it means the task was rejected and points deducted.
To actually do this, we also need to adjust the script that is called whenever a chore changes state, so it catches up on the deduction, like this:
script:
household_points:
variables:
grant_to_entity_id: "{{ 'input_number.household_chores_' + triggered_id.split('input_boolean.')[1].split('household_chore')[0].split('_')[1] }}"
grant_points: "{{ state_attr(triggered_id, 'friendly_name').split('(+')[1].split(')')[0]|int }}"
deduct: "{{ states('input_boolean.deduct_score') }}"
sequence:
- choose:
- choose:
- conditions: "{{ from_state == 'on' and to_state == 'off' and deduct == 'on' }}"
sequence:
- service: input_number.set_value
target:
entity_id: "{{ grant_to_entity_id }}"
data:
value: "{{ states(grant_to_entity_id)|int - grant_points }}"
- service: input_boolean.turn_off
target:
entity_id: input_boolean.deduct_score
- conditions: "{{ from_state == 'off' and to_state == 'on' }}"
sequence:
- service: input_number.set_value
target:
entity_id: "{{ grant_to_entity_id }}"
data:
value: "{{ states(grant_to_entity_id)|int + grant_points }}"
The script will also reset the deduction input_boolean; so you have to flip it to true every time you want to reject a chore.
So, it's not much gamified unless the kid kan see the progress and the weekly allowance payout live. To get an idea of the progress of the current week, I built a star based progress indicator, with different levels corresponding to achieving a certain number of points. For this, I use a set of template entities and a custom button card to display the current state of progress.
For each kid, you first need to create a set of template sensors like this:
- name: Household chores <kid1> points
unique_id: household_chores_<kid1>_points
state: >
{{ states('input_number.household_chores_<kid1>')|int(default=0) }}
- name: Household chores <kid1> stars
unique_id: household_chores_<kid1>_stars
icon: mdi:star
state: >
{% set points = states('input_number.household_chores_<kid1>')|int(default=0) %}
{% if points > 14 %}
{% set stars = 5 %}
{% elif points > 9 %}
{% set stars = 4 %}
{% elif points > 6 %}
{% set stars = 3 %}
{% elif points > 3 %}
{% set stars = 2 %}
{% elif points > 0 %}
{% set stars = 1 %}
{% else %}
{% set stars = 0 %}
{% endif %}
{{ stars }}
- name: Household chores <kid1> payout
unique_id: household_chores_<kid1>_payout
icon: mdi:cash
unit_of_measurement: "NOK"
state: >
{% set stars = states('sensor.household_chores_<kid1>_stars')|int %}
{% if stars == 5 %}
{% set payout = 50 %}
{% elif stars == 4 %}
{% set payout = 40 %}
{% elif stars == 3 %}
{% set payout = 30 %}
{% elif stars == 2 %}
{% set payout = 20 %}
{% elif stars == 1 %}
{% set payout = 10 %}
{% else %}
{% set payout = 0 %}
{% endif %}
{{ payout }}
- name: Household chores <kid1> robux
unique_id: household_chores_<kid1>_robux
icon: mdi:cash
unit_of_measurement: "Robux"
state: >
{{ ((states('sensor.household_chores_<kid1>_payout')|int * 8) / 400)|int * 400 }}
- name: Household chores <kid1> payout rest after robux
unique_id: household_chores_<kid1>_payout_rest_after_robux
icon: mdi:cash
unit_of_measurement: "NOK"
state: >
{{ (((states('sensor.household_chores_<kid1>_payout')|int * 8) % 400) / 8)|int }}
(The thing with the Robux, is that one of my kids is more motivated by Robux than real money.)
Now, to use these sensors in a dashboard for the kid to display progress, you need two custom button templates that require the brilliant custom button cards by RomRider.
To create the templates, you may create a "rating-templates.yaml" in your config-directory with the following content:
button_rating:
show_name: false
show_state: false
show_icon: false
styles:
card:
- box-shadow: none
- border: 0
- background: transparent
- width: 275px
grid:
- grid-template-areas: '". title title title title title ." ". first second third fourth fifth ." ". first_points second_points third_points fourth_points fifth_points ." ". points_week points_week points_week points_week points_week ." ". money_week money_week money_week money_week money_week ." ". robux_week robux_week robux_week robux_week robux_week ." ". rest_week rest_week rest_week rest_week rest_week ."'
- grid-template-columns: auto
- grid-gap: 0px
custom_fields:
title:
- font-size: 1.5em
- padding-bottom: 15px
first_points:
- font-size: 10px
second_points:
- font-size: 10px
third_points:
- font-size: 10px
fourth_points:
- font-size: 10px
fifth_points:
- font-size: 10px
points_week:
- font-size: 1em
- text-align: center
- padding-top: 15px
- padding-bottom: 10px
money_week:
- font-size: 0.7em
- text-align: center
- padding-bottom: 5px
robux_week:
- font-size: 0.7em
- text-align: center
- padding-bottom: 5px
rest_week:
- font-size: 0.7em
- text-align: center
button_rating_star:
color_type: icon
icon: mdi:star
color: rgb(68, 115, 158)
show_name: false
show_state: false
styles:
card:
- background-color: transparent
- box-shadow: none
- border: 0
icon:
- width: 33px
- height: 33px
When you have the template in place, you can create a custom dashboard for the kid like this:
lovelace:
dashboards:
smarthome-yaml:
mode: yaml
title: Chores <kid1>
icon: mdi:home-assistant
show_in_sidebar: true
filename: chores-<kid1>.yaml
And then you create a file in the config directory with the name "chores-
button_card_templates: !include rating-templates.yaml
views:
- title: Gamified chores
type: panel
badges: []
cards:
- type: custom:mod-card
style:
.: |
ha-card {
background-color: #1c1c1c;
}
hui-grid-card$: |
#root {
justify-items: center !important;
box-shadow: none;
border: 0;
}
card:
type: grid
columns: 1
square: false
cards:
- type: custom:button-card
styles:
card:
- margin-top: 40px
- margin-left: 5px
- background-color: "#202020"
- border: solid 1px purple
template: button_rating
entity: sensor.household_chores_<kid1>_stars
custom_fields:
title: Weekly allowance
first:
card:
type: custom:button-card
template: button_rating_star
entity: sensor.household_chores_<kid1>_stars
state:
- value: 1
operator: ">="
styles:
icon:
- color: var(--paper-item-icon-active-color)
first_points: 1 point
second:
card:
type: custom:button-card
template: button_rating_star
entity: sensor.household_chores_<kid1>_stars
state:
- value: 2
operator: ">="
styles:
icon:
- color: var(--paper-item-icon-active-color)
second_points: 4 points
third:
card:
type: custom:button-card
template: button_rating_star
entity: sensor.household_chores_<kid1>_stars
state:
- value: 3
operator: ">="
styles:
icon:
- color: var(--paper-item-icon-active-color)
third_points: 7 points
fourth:
card:
type: custom:button-card
template: button_rating_star
entity: sensor.household_chores_<kid1>_stars
state:
- value: 4
operator: ">="
styles:
icon:
- color: var(--paper-item-icon-active-color)
fourth_points: 10 points
fifth:
card:
type: custom:button-card
template: button_rating_star
entity: sensor.household_chores_<kid1>_stars
state:
- value: 5
operator: ">="
styles:
icon:
- color: var(--paper-item-icon-active-color)
fifth_points: 15 points
points_week: >
[[[ return `<ha-icon icon="mdi:progress-star" style="font-size: 20px; width: 25px; height: 25px; "></ha-icon> ${states['sensor.household_chores_<kid1>_points'].state} points this week!` ]]]
money_week: |
[[[
return `Which equals ${states['sensor.household_chores_<kid1>_payout'].state} kr`
]]]
robux_week: |
[[[
if (states['sensor.household_chores_<kid1>_robux'].state > 0) {
return `or ${states['sensor.household_chores_<kid1>_robux'].state} Robux`
}
]]]
rest_week: |
[[[
if (states['sensor.household_chores_<kid1>_payout_rest_after_robux'].state > 0 && states['sensor.household_chores_<kid1>_robux'].state > 0) {
return `and ${states['sensor.household_chores_<kid1>_payout_rest_after_robux'].state} kr`
}
]]]
- type: custom:auto-entities
filter:
include:
- entity_id: input_boolean.*_<kid1>_household_chore
state: "off"
show_empty: false
card:
type: entities
card_mod:
style: |
ha-card {
background: none;
box-shadow: none;
}
title: Tasks due
show_header_toggle: false
show_state: false
The above code requires the mod-card plugin by Thomas Loven.
I would suggest removing borders from the current default theme, if you use it. You could do that by definining the following code in your configuration file to create a very simple custom theme.
frontend:
themes:
My Custom Theme:
ha-card-border-color: rgba(0,0,0,0) ## transparent
Then you need to change the theme for each device you'll use the dashboard on. The custom theme won't appear in the list of themes before you restart Home Assistant. Make sure to check the config and backup beforehand.
This is how I made a gamified score based household chore system for Home Assistant. I hope you got inspired, and maybe implement some of these ideas in your own smart home.