惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Privacy International News Feed
I
Intezer
T
Tenable Blog
S
Schneier on Security
Project Zero
Project Zero
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
Know Your Adversary
Know Your Adversary
博客园 - 司徒正美
The Cloudflare Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
News and Events Feed by Topic
博客园 - 叶小钗
宝玉的分享
宝玉的分享
L
LINUX DO - 热门话题
aimingoo的专栏
aimingoo的专栏
S
Secure Thoughts
Forbes - Security
Forbes - Security
T
The Exploit Database - CXSecurity.com
D
Darknet – Hacking Tools, Hacker News & Cyber Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
罗磊的独立博客
IT之家
IT之家
H
Hacker News: Front Page
I
InfoQ
云风的 BLOG
云风的 BLOG
S
Security Affairs
M
MIT News - Artificial intelligence
GbyAI
GbyAI
Jina AI
Jina AI
Help Net Security
Help Net Security
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
Webroot Blog
Webroot Blog
L
Lohrmann on Cybersecurity
A
About on SuperTechFans
Attack and Defense Labs
Attack and Defense Labs
The Register - Security
The Register - Security
V
V2EX
G
Google Developers Blog
D
DataBreaches.Net
Apple Machine Learning Research
Apple Machine Learning Research
C
Cybersecurity and Infrastructure Security Agency CISA
J
Java Code Geeks
W
WeLiveSecurity
Cloudbric
Cloudbric
T
Tor Project blog

herrkaefer

"Vibe planning \u003e vibe coding" "Anything to Markdown" "Built anocus: anonymous commenting for static sites" "日记与小说 -- AI 续写小说欣赏" "Any-podcast: from newsletters to a podcast" "Made MicPipe: a simple voice input tool using ChatGPT dictation" "关于 Tools 和 Skills 的一点感想" "Realtime monitoring of ComEd hourly price" "Introducing SwiftEdgeTTS" "Thoughts on the philosophy of building AI-native apps" "jelly鼻屎" "等饭的人" "Migrated Blog to Hugo and Cloudflare Pages" "Easy Aspen monitoring for Chicago parents" "Introducing HabitBuilder: A simple Telegram bot for habit tracking" "鼓捣" "Open folder or file with Sublime Text from Finder toolbar" "Python dev workflow on macOS" "Create new text file from Finder toolbar" "Uno reinvented for 3-year-old kids" "Uno变身儿童数字游戏" "自动转发Twitter到微博" "Handle annoying operations of objects in Realm DB" "Move Jekyll blog to Ubuntu VPS" "Introducing Mole" "Note taking without note taking app" "Deploy Python web application on Ubuntu server" "Setup Shadowsocks / VPN on Ubuntu Server" "Linode Notes - Basic Setup" "CLASS Style Adapted for Embedded Systems" "psycopgr Tutorial" "pgRouting Notes" "PostgreSQL Notes" "阿城三王" "这一年,这一把日子" "另一面的发现——读《坟》" "定理" "封面与腰封" "Google book下载" "lulu最新写真出炉" "The Big Bang Theory第三季" "自拍婚纱照1" "日全食" "期待动画片" "《麦兜响当当》动画电影主题曲" "转:饶毅--“杂志拜物教”:何时发Cell Nature Science 论文害你" "转:饶毅--提醒年轻人:何时SCI害你?" "西安" "3d打印机" "Dropbox" "刷牙" "贴几张照片" "6156167" "永久和凤凰" "老板的想法" "春" "原来奥巴马也是个朗读者" "应邀发Freeware List 2.0" "史上最能睡的淘宝老板" "至少出名的效果是达到了" "错怪了msn" "独立游戏节2009" "114" "馒头" "Crayon Physics Deluxe" "2008,2009" "盖章记" "小虎队附身许巍" "怎么给word文档加索引:排序问题" "怎么给word文档加索引Q\u0026amp;A" "怎么给Word文档加索引" "教我如何不疯掉" "二则" "P" "哦!报告" "蓝天" "萧翰" "lm" "故宫印象" "转:美国历任总统像" "time can kill itself" "嗯" "建议,只是建议哦" "奥地利行记3" "奥地利行记2" "奥地利行记1" "叶子" "GayBoy" "天使教你扔frisbie" "门徒因何面容愁?" "手机教堂" "丝竹管弦之盛" "残奥" "争座位" "秋意浅" "总理府" "流觞曲水" "映带左右引以为" "咚咚咚 续" "茂林修竹又有"
"Use home assistant to motivate my kid to brush teeth"
"herrkaefer" · 2025-10-22 · via herrkaefer

I hope you’re not in the same boat, but getting my kids to brush their teeth consistently can be a daily struggle. After an unpleasant incident this morning, I decided to add some fun to the routine using Home Assistant, hoping my daughter would stay motivated (at least for a while😆).

With this setup, I wanted the teeth brushing events to be automatically detected, announced by the Google speaker, accompanied by a two-minute song playing, and recorded in Home Assistant.

Plan

As she is using a plain electric tooth brush without bluetooth or app connection, there’s no direct way to get the teeth brushing data. I was thinking to put a NFC stick on the brush or somewhere, but it doesn’t sound good because it relies on a phone touch to trigger.

So I removed a Zigbee button from the frontdoor (which was set to press before leaving home but rearly used) and stick it on the mirror in the bathroom. The kid can press it to start the brushing automation.

Here’s a random link of the button on AliExpress.

Components that are needed for this flow:

  • A working Home Assistant
  • A Aqara Zigbee Button
  • Google Speaker (or any speaker that can be controled by home assistant) for voice & music
  • Spotify and Spotcast integrations for 2-minute brushing songs

Helpers

Create a few helper entities in Home Assistant:

  • input_datetime.teeth_brushing_start and end (single brushing recording)
  • counter.teeth_brushing_counter (daily count)
  • counter.teeth_brush_streak (streak days)

Automations

1. Brushing Routine

The kid is expected to press the button and then start the brushing. The button triggers an automation:

  1. Records brushing start time
  2. Let the speaker announces start
  3. Plays a song from a predefined Spotify playlist for 2 minutes
  4. Announces completion and records the end time
  5. Increments the daily brushing counter
alias: Brush teeth
description: ""
triggers:
  - device_id: 24c653c21ef64657d22831f1194c63e1
    domain: zha
    type: remote_button_short_press
    subtype: remote_button_short_press
    trigger: device
conditions:
  - condition: time
    after: "06:00:00"
    before: "23:59:00"
actions:
  - action: input_datetime.set_datetime
    metadata: {}
    data:
      datetime: "{{now()}}"
    target:
      entity_id: input_datetime.teeth_brushing_start
  - action: media_player.volume_set
    metadata: {}
    data:
      volume_level: "{{ volume_level }}"
    target:
      entity_id: "{{ speaker }}"
  - action: tts.google_translate_say
    metadata: {}
    data:
      cache: true
      entity_id: "{{ speaker }}"
      message: Let's brush our teeth for two minutes!
  - delay: "00:00:05"
  - action: script.play_spotify_list
    metadata: {}
    data:
      entity: "{{ speaker }}"
      uri: "{{ playlist_uri }}"
      volume: "{{ (volume_level * 100) | int }}"
  - delay:
      hours: 0
      minutes: 1
      seconds: 50
      milliseconds: 0
  - action: input_datetime.set_datetime
    metadata: {}
    data:
      datetime: "{{now()}}"
    target:
      entity_id: input_datetime.teeth_brushing_end
  - action: counter.increment
    metadata: {}
    data: {}
    target:
      entity_id: counter.teeth_brushing_counter
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ states('counter.teeth_brushing_counter') | int == 1 }}"
        sequence:
          - data:
              cache: false
              entity_id: "{{ speaker }}"
              message: >
                Great job starting your day with brushing! You’re on a {{
                states('counter.teeth_brushing_streak') | int }}-day streak.
                Keep it up, and you’ll make it even longer tonight!
            action: tts.google_translate_say
      - conditions:
          - condition: template
            value_template: "{{ states('counter.teeth_brushing_counter') | int == 2 }}"
        sequence:
          - target:
              entity_id: counter.teeth_brushing_streak
            action: counter.increment
          - data:
              cache: false
              entity_id: "{{ speaker }}"
              message: >
                Fantastic! You’ve brushed twice today and kept your streak
                going! That’s now {{ states('counter.teeth_brushing_streak') |
                int }} days in a row! Awesome job, keep shining!
            action: tts.google_translate_say
      - conditions:
          - condition: template
            value_template: "{{ states('counter.teeth_brushing_counter') | int > 2 }}"
        sequence:
          - data:
              cache: true
              entity_id: "{{ speaker }}"
              message: >
                Wow, you’re really into brushing today! Keep those teeth
                sparkling clean!
            action: tts.google_translate_say
variables:
  speaker: media_player.mira_room_speaker
  volume_level: |
    {% set now_time = now().strftime('%H:%M') %} {% if now_time < '21:15' %}
      0.47
    {% else %}
      0.12
    {% endif %}
  playlist_uri: spotify:playlist:3lacrdXRalnL5FJrzb4UcS
mode: single

2. Midnight Helpers Update

At midnight, another automation checks whether (>= 2) brushing happened that day, and update the counter and streak.

alias: Update Teeth Brush Helpers at Midnight
description: Reset daily counter and streak
triggers:
  - at: "23:59:00"
    trigger: time
conditions: []
actions:
  - variables:
      brushed_today: "{{ states(daily_counter) | int > 1 }}"
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ not brushed_today }}"
        sequence:
          - target:
              entity_id: "{{ streak_counter }}"
            action: counter.reset
  - target:
      entity_id: "{{ daily_counter }}"
    action: counter.reset
mode: single
variables:
  daily_counter: counter.teeth_brushing_counter
  streak_counter: counter.teeth_brushing_streak

Stream emoji evolution on dashboard!

🥚 → 🐣 → 🐥 → 🐓 → 🦅 → 🐦‍🔥 → 🐉

Make it a bit more fun by adding some emoji evolution on home assistant dashboard. Each emoji evolves every 7 days to another level. This little trick has been working very well for my daughter to keep her motivated. Actually this idea was suggested by my daughter herself, and she always wants to take a look at the dashboard to see how the emojis are evolving after brushing.

A single Mushroom Template Chip shows both today’s brushing and the running streak. The number of 🪥 icons corresponds to the daily brushing count, and the streak is visualized with fire emojis.

type: custom:mushroom-chips-card
chips:
  - type: template
    entity: counter.teeth_brushing_counter
    icon: mdi:toothbrush-electric
    icon_color: blue
    content: >
      {% set count = states('counter.teeth_brushing_counter') | int %} {% set
      streak = states('counter.teeth_brushing_streak') | int %} {% set brushes =
      '🪥' * count if count > 0 else '0' %}

      {% set stage = streak // 7 %} {% set rem = streak % 7 %}

      {% set evolutions = ['🐣', '🐥', '🐓', '🦅', '🐦‍🔥'] %}

      {% if stage == 0 %}
        {% set evo = '' %}
      {% elif stage <= evolutions | length %}
        {% set evo = evolutions[:stage] | reverse | join('') %}
      {% else %}
        {% set dragons = '🐉' * (stage - (evolutions | length)) %}
        {% set evo = dragons + (evolutions | reverse | join('')) %}
      {% endif %}

      {% set eggs = '🥚' * rem %} {% set final = evo + eggs if streak > 0 else
      '0' %}

      Today:{{ brushes }} Streak:{{ final }}
    tap_action:
      action: more-info

What are good to add later

  • Let brushing ends by manually pressing the button again, if cheating is noticed. – So far not needed.
  • Add a small battery-powered display near the sink to show streaks. Physical visialization would be more powerful feedback for the kid.