Simple habit tracking - X days since... with WearOS support!

Simple habit tracking - X days since…

Screenshot_20240403_232002 Screenshot_20240403_232055

Do you also want to reduce the amount of sweets or stay away from some other bad habit…? Here’s my take on how I use (or at how I’m trying to use) Home Assistant for simple habit tracking along with my Pixel Watch :smiley:

The idea is simple:

  • Every time you eat that chocolate cake you press a button to reset a counter
  • For every day that passes without the button being pressed the counter goes up
  • You will either see if you’re on a winning streak or what record to beat

This way you don’t have to remember to click a button every day, only when you actually did that bad habit :crossed_fingers:

Setup

The habit tracker consists of four parts:

  • input button.habit_sweets - when this is clicked the counter is reset
  • sensor.time_since_last_habit_sweets - template sensor that shows the current number of days since button was last pressed, increases every midnight
  • sensor.longest_time_since_habit_sweets - template sensor that shows the longest streak
  • Template for WearOS template tiles

Put this in your configuration.yaml, or in a package:

input_button:
  habit_sweets:
    name: Sweets habit
    icon: mdi:candy

template: 
  - trigger: 
    - platform: time_pattern
      hours: 0
      minutes: 0
    - platform: state
      entity_id: input_button.habit_sweets
    sensor: 
    - name: Time since last habit sweets
      state: >-
        {{ ((now() - as_datetime(states('input_button.habit_sweets'))).total_seconds() / (60*60*24)) | round(3) | round(0, 'ceil') }}
      unit_of_measurement: days
      attributes:
        is_record: >-
          {{ int(this.state, 0) > state_attr('sensor.longest_time_since_habit_sweets', 'total_days')  }}
        best_streak: >-
          {% set nrOfDays = state_attr('sensor.longest_time_since_habit_sweets', 'total_days') %}
          {{ "%d %s" % (nrOfDays, 'day' if nrOfDays == 1 else 'days') }}
          
  - trigger:
    - platform: state
      entity_id: input_button.habit_sweets
    sensor:
      # Can it be done without this sensor...? 
      - name: Longest time since habit sweets
        state: >-
          {{ [this.state, (now() - as_datetime(trigger.from_state.state)).total_seconds()] | map('int', 0) | max }}
        unit_of_measurement: seconds
        attributes:
          total_days: >
            {{ (( this.state | int(0)) / (60*60*24)) | round(3) | round(0, 'ceil') }}

And then for Wear OS, add this template in the settings for template tiles in your Home Assistant companion app:

{% set nrOfDays = states('sensor.time_since_last_habit_sweets') | int -%}
{% set heading = "%d %s" % (nrOfDays, 'day' if nrOfDays == 1 else 'days') -%}
<h1>🚫🍫</h1><h1>{{ heading }}</h1>
{%- set record = state_attr('sensor.longest_time_since_habit_sweets', 'total_days') | int -%}
{%- if state_attr('sensor.time_since_last_habit_sweets', 'is_record') -%}
  <b><font color=#81C784>NEW RECORD!</font></b>
{%- else -%}
  {{ "Record: %d %s" % (record, 'day' if record == 1 else 'days') }}
{% endif %}

Easiest is probably to send this template to your phone with some note or messaging app, then paste it in.

I also added a shortcut tile on my Pixel Watch to easily click the reset button:
Screenshot_20240403_232107

You could of course click the button in the Home Assistant app, set up some automations that would click it or even connect a real physical button if you would like to.

And then the hardest part - try to keep up staying away from that bad habit :smile:

I would love to get some input on if it’s possible to generalize this somehow, or if it’s even possible to solve this with only one template sensor… :thinking: