Baby tracker script with todo list for sleep duration, baby feed, bath and poop tracking

I’ve made this simple script for tracking baby routine. I’m sure the data could be stored and displayed in a better way but I’ve worked enough on it and it has been fine. I like the todo list because it is easy to edit the data. It uses string variable so it can easily be translated.

This works with 3 todo list (2 more for testing in dev):

  • babysleep (track sleep time)
  • baby (track other stuff)
  • longbaby (data go there after x days, 3 by default, change variable keep_log_time for else)

and it uses :

  • one toggle helper baby_sleep_toggle
  • 3 buttons helper baby_feed, baby_bath, baby_poop
  • 1 text helper (for daily sleep total time) baby_sleep_txt

Here’s the script:

alias: baby-script
variables:
  is_test: "{{ 'test' in t_button }}"
  sleep_toggle: >-
    {% if is_test == true %} input_boolean.test_toggle {% else %}
    input_boolean.baby_sleep_toggle {% endif %}
  feed_button: >-
    {% if is_test == true %} input_button.test_button {% else %}
    input_button.baby_feed {% endif %}
  sleep_txt: >-
    {% if is_test == true %} input_text.test_txt {% else %}
    input_text.baby_sleep_txt {% endif %}
  bath_button: input_button.baby_bath
  poop_button: input_button.baby_poop
  i_sleep: 0
  short_list: "{% if is_test == true %} todo.test {% else %} todo.baby {% endif %}"
  sleep_list: "{%if is_test == true%} todo.testsleep {%else%} todo.babysleep {% endif%}"
  long_list: "{% if is_test == true %} todo.longtest {% else %} todo.longbaby {% endif %}"
  str_sleep_start: Start sleep
  str_sleep_stop: End sleep
  str_feed: Feed
  str_poop: Poop
  str_bath: Bath
  str_datetime: "{{now().strftime(\"%Y-%m-%d %H:%M\")}}"
  str_separator: "|"
  ts_day: "{{60*60*24}}"
  ts_week: "{{ts_day * 7}}"
  ts_7d_ago: "{{as_timestamp(str_datetime) - ts_week}}"
  ts_3d_ago: "{{as_timestamp(str_datetime) - (3 * ts_day)}}"
  keep_log_time: "{{ts_3d_ago}}"
sequence:
  - service: input_boolean.toggle
    metadata: {}
    data: {}
    target:
      entity_id: "{{ t_button }}"
  - service: todo.get_items
    data:
      status: needs_action
    target:
      entity_id: " {{ short_list }} "
    response_variable: short_list_obj
  - service: todo.get_items
    data:
      status: needs_action
    target:
      entity_id: " {{ sleep_list }} "
    response_variable: sleep_list_obj
  - variables:
      short_list_items: >-
        {{ short_list_obj[short_list]['items'] | sort(attribute='summary',
        reverse=true) }}
      sleep_list_items: >-
        {{ sleep_list_obj[sleep_list]['items'] | sort(attribute='summary',
        reverse=true) }}
      str_0: "{{str_datetime}}"
      str_1: >-
        {%if sleep_toggle == t_button and states(t_button) == "on" %}{{
        str_sleep_start }}{% elif sleep_toggle == t_button and states(t_button)
        == "off" %}{{ str_sleep_stop }}{% elif t_button == feed_button %}{{
        str_feed }}{% elif t_button == bath_button %}{{str_bath}}{% elif
        t_button == poop_button %}{{str_poop}}{% else %}unknown{% endif %}
      is_sleep: "{{str_1 == str_sleep_stop or str_1 == str_sleep_start}}"
      minute: >-
        {% if sleep_toggle == t_button and states(t_button) == "off" %} {%set
        str_dt = (sleep_list_items[0]['summary'].split(str_separator)[0] |
        trim)%}{{ ((as_timestamp(str_datetime) - as_timestamp(str_dt)) / 60) |
        int}}{% else %}{{int(0)}}{%endif%}
      str_2: >-
        {% if (minute | int(0)) > 0 %}{{str_separator}}{{((minute | int) / 60) |
        int}}h{{((minute | int) % 60) | int}}{%endif%}
      str_item: "{{str_0}}{{str_separator}}{{str_1}}{{str_2}}"
  - service: todo.add_item
    metadata: {}
    data:
      item: "{{str_item}}"
    target:
      entity_id: "{%if is_sleep %}{{sleep_list}}{%else%}{{ short_list }}{%endif%}"
  - service: input_text.set_value
    metadata: {}
    data:
      value: "{{minute}}"
    target:
      entity_id: "{{ sleep_txt }}"
  - repeat:
      sequence:
        - variables:
            str_dt: "{{ repeat.item['summary'].split(str_separator)[0] | trim\_}}"
            str_content: "{{ repeat.item['summary'].split(str_separator)[1] | trim\_}}"
            str_data: "{{ repeat.item['summary'].split(str_separator)[2]| trim }}"
        - if:
            - condition: template
              value_template: >-
                {{  str_data != '' and as_timestamp(today_at()) <=
                as_timestamp(str_dt) and str_content == str_sleep_stop}}
          then:
            - variables:
                str_h: "{{ str_data.split('h')[0] | int(0) }}"
                str_m: "{{ str_data.split('h')[1] | int(0) }}"
            - service: input_text.set_value
              metadata: {}
              data:
                value: "{{ (str_h * 60) + str_m  + (states( sleep_txt)|int) }}"
              target:
                entity_id: "{{ sleep_txt }}"
        - service: todo.add_item
          metadata: {}
          data:
            item: "{{ repeat.item['summary'] }}"
          target:
            entity_id: >-
              {% if as_timestamp(str_dt) > keep_log_time %}{{sleep_list}}{% else
              %}{{long_list}}{%endif%}
        - service: todo.remove_item
          data:
            item: "{{ repeat.item['summary'] }}"
          target:
            entity_id: "{{ sleep_list }}"
      for_each: "{{sleep_list_items}}"
  - repeat:
      sequence:
        - variables:
            str_dt: "{{ repeat.item['summary'].split(str_separator)[0] | trim\_}}"
            str_content: "{{ repeat.item['summary'].split(str_separator)[1] | trim\_}}"
            str_data: "{{ repeat.item['summary'].split(str_separator)[2]| trim }}"
        - service: todo.add_item
          metadata: {}
          data:
            item: "{{ repeat.item['summary'] }}"
          target:
            entity_id: >-
              {% if as_timestamp(str_dt) > keep_log_time %}{{short_list}}{% else
              %}{{long_list}}{%endif%}
        - service: todo.remove_item
          data:
            item: "{{ repeat.item['summary'] }}"
          target:
            entity_id: "{{ short_list }}"
      for_each: "{{short_list_items}}"
  - service: input_text.set_value
    metadata: {}
    data:
      value: >-
        {% set minute = (states(sleep_txt) | int) %}{{(minute / 60) |
        int}}h{{(minute % 60) | int}}
    target:
      entity_id: "{{ sleep_txt }}"
mode: single
icon: mdi:baby-face
fields:
  t_button:
    selector:
      entity: {}
    name: Button
    required: false

Common error

  • After editing a sleep time, make sure single digit hours starts with 0 and uses 24 hour format.
  • The todo entry follows a stict string pattern which is: Date( YY-MM-DD HH:mm)|String of activity|Sleep duration(h<Minutes without 0 in front>

Hope this is useful!