Pregnancy Tracking Privately with Tempalate Sensors

My wife and I are expecting our first kid in a few months and suffice to say, we’re pretty excited to keep tabs on the whole process. Right off the bat a couple of friends suggested a variety of pregnancy apps.

Here’s the thing, after a bit of research we were totally scared off. One of them even got written up in WP because it was sharing data with employers. As a home assistant user, I obviously like to keep things “In house” so to speak. I realized all these apps are doing is some basic math based on a due date and thought, “Why can’t I just do this in home assistant?” Anyway, turns out it wasn’t too hard.

It’s not perfect. For information I link to a couple of websites (VeryWell Family and What to Expect when You’re Expecting). So they still get to track me a bit when I visit their sites, but at the very least it should be less than the spooky apps.

Also, sorry about the references to “Download” we joked about the kid being a download and it sort of stuck, so some stuff says that.


(Image credit: https://whattoexpect.com/)

Input Datetime:

I used an input datetime to record the due date.

input_datetime:
  due_date:
    name: Pregnancy Due Date
    has_date: true
    has_time: false

Sensors:

sensor:
  - platform: template
    sensors:
      pregnancy_days:
        friendly_name: "Days until due"
        unit_of_measurement: 'days'
        value_template: "{{ (strptime(states.input_datetime.due_date.state, '%Y-%m-%d') - now().replace(tzinfo=None)).days }}"
      pregnancy_weeks:
        friendly_name: "Pregnancy Week"
        unit_of_measurement: 'weeks'
        value_template: "{{ ((40 - ((states.sensor.pregnancy_days.state | int) / 7)) | round(0, 'floor')) }}"
      pregnancy_percent:
        friendly_name: "Pregnancy Percent"
        unit_of_measurement: '%'
        value_template: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 2.8) | round(0, 'floor')}}"

      pregnancy:
        friendly_name: "Pregnancy"
        unit_of_measurement: 'Trimester'
        value_template: |
          {% set x = ((280 - (states.sensor.pregnancy_days.state | int)) / 93.3) | round(0, 'ceil') %}
          {{ 'First' if x == 1 else 'Second' if x == 2 else 'Third' }}
        attribute_templates:
          days: "{{ states.sensor.pregnancy_days.state }}"
          weeks: "{{ states.sensor.pregnancy_weeks.state }}"
          trimester: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 93.3) | round(0, 'ceil') }}"
          months: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 30.5) | round(1, 'half') }}"
          percent: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 2.8) | round(0, 'floor')}}"
          what_to_expect_url: "https://www.whattoexpect.com/pregnancy/week-by-week/week-{{ states.sensor.pregnancy_weeks.state }}.aspx"
          fetus_size_image: "https://images.agoramedia.com/wte3.0/gcms/wbw_squares_baby_wk_{{ states.sensor.pregnancy_weeks.state }}.jpg"
          fetus_size_fruit_image: "https://images.agoramedia.com/wte3.0/gcms/wbw-{{ states.sensor.pregnancy_weeks.state }}-fruit.png"
          fetus_size_fruit: |
            {% set sizes = { 4: 'Strawberry Seed', 5: 'Orange Seed', 6: 'Sweet Pea', 7: 'Blueberry', 8: 'Raspberry',
                             9: 'Green Olive', 10: 'Prune', 11: 'Large Strawberry', 12: 'Lime', 13: 'Lemon',
                            14: 'Navel Orange', 15: 'Pear', 16: 'Avocado', 17: 'Large Onion', 18: 'Cucumber',
                            19: 'Mango', 20: 'Sweet Potato', 21: 'Large Banana', 22: 'Red Bell Pepper',
                            23: 'Grapefruit', 24: 'Pomegranate', 25: 'Eggplant', 26: 'Acorn Squash', 27: 'Cabbage',
                            28: 'Head of Lettuce', 29: 'Head of Cauliflower', 30: 'Bunch of Broccoli', 31: 'Coconut',
                            32: 'Cantaloupe', 33: 'Butternut Squash', 34: 'Pineapple', 35: 'Spaghetti Squash',
                            36: 'Bunch of Kale', 37: 'Canary Melon', 38: 'Mini Watermelon', 39: 'Honeydew Melon',
                            40: 'Small Pumpkin', 41: 'Pumpkin', 42: 'Watermelon' } %}
            {{ sizes[([4, states('sensor.pregnancy_weeks')|int, 42]|sort)[1]] }}
          verywellfamily_link: |
            {% set pages =  { 1: '4158813', 2: '4158819', 3: '4158839', 4: '4158847', 5: '4158868',
                              6: '4158911', 7: '4158916', 8: '4158920', 9: '4158922', 10: '4158926',
                             11: '4158930', 12: '4158934', 13: '4158941', 14: '4158944', 15: '4158988',
                             16: '4158998', 17: '4159005', 14: '4158944', 15: '4158988', 16: '4158998',
                             17: '4159005', 18: '4159009', 19: '4159012', 20: '4159017', 21: '4159022',
                             22: '4159032', 23: '4159036', 24: '4159040', 25: '4159047', 26: '4159097',
                             27: '4159102', 28: '4159110', 29: '4159140', 30: '4159146', 31: '4159202',
                             32: '4159205', 33: '4159211', 34: '4159227', 35: '4159237', 36: '4159243',
                             37: '4159250', 38: '4159251', 39: '4159263', 40: '4159264' } %}
            {% set x = ([1, states('sensor.pregnancy_weeks')|int, 40]|sort)[1] %}
            https://www.verywellfamily.com/{{x|string}}-weeks-pregnant-{{pages[x]}}

Input Numbers:

input_number:
  pregnancy_week:
    name: Pregnancy week persistent number
    max: 42
    min: 4
    step: 1
    mode: box

Automations:

# Use an input number to record the week updating so that it doesn't
# trigger on restart. This updates that (and notifies your phone with a link
# to the lovelace when it does!)
automation:
  - id: pregnancy_week_updated
    alias: 'Baby: Week Updated'
    description: Triggered when the baby week changes
    trigger:
      - platform: template
        value_template: >-
          {{ (states('sensor.pregnancy_weeks') | int) >
          (states('input_number.pregnancy_week') | int ) }}
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.pregnancy_week
          value: "{{ states('sensor.pregnancy_weeks') | int }}"
      - service: notify.mobile_app_courtney_phone
        data:
          title: "It's Pregnancy week {{ states('sensor.pregnancy_weeks') }}!"
          message: "Tap here to read all about what's up this week!"
          data:
            clickAction: /lovelace-pregnancy/baby

Lovelace:

Note: For the lovelace view I ended up using custom:text-element and custom:card-templater in order to get the image of “Fruit size” from “What to expect” to update.

title: Baby
path: baby
panel: false
badges: []
cards:
  - type: 'custom:card-templater'
    card:
      type: picture-elements
      image_template: '{{ states.sensor.pregnancy.attributes.fetus_size_fruit_image }}'
      elements:
        - type: state-label
          entity: sensor.pregnancy
          style:
            font-size: 30px
            top: 10%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: 'It''s Week '
          attribute: weeks
          suffix: '!'
          style:
            font-size: 40px
            top: 20%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: '(That''s '
          suffix: ' Months)'
          attribute: months
          style:
            font-size: 20px
            top: 29%
            left: 50%
        - type: 'custom:text-element'
          text: The fetus is about
          style:
            font-size: 20px
            top: 75%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: 'the size of a '
          attribute: fetus_size_fruit
          suffix: '!'
          style:
            font-size: 20px
            top: 82%
            left: 50%
    entities:
      - sensor.pregnancy
  - type: markdown
    content: |
      ## [Read up from verywell Family]({{ states.sensor.pregnancy.attributes.verywellfamily_link }})
  - type: markdown
    content: |
      ## [Read up from "What to Expect"]({{ states.sensor.pregnancy.attributes.what_to_expect_url }})
  - type: gauge
    name: Download Status
    entity: sensor.pregnancy_percent
    min: 0
    max: 100
    severity:
      green: 33
      yellow: 67
      red: 100

Edit: Thanks to @123 for the suggestion. Much neater!

11 Likes

Wow :roll_eyes: I’d just cross my fingers and hope the baby comes out healthy , and leaves hospital for a very long time :wink:

1 Like

All the best and congratulations.

You better get as much home assisting done as you can, you won’t have time after the birth!

2 Likes

Congrats! as a father of two myself (3.5 and 1) I can attest to the need to get your home assisting done now. Hope everything goes well for you and your wife.

1 Like

First, congratulations to you both!

Second, thanks for your contribution of code.

Third, I offer you a few suggestions to reduce the size of some of the templates:

The value_template can be reduced to this:

        value_template: |
          {% set x = ((280 - (states.sensor.pregnancy_days.state | int)) / 93.3) | round(0, 'ceil') %}
          {{ 'First' if x == 1 else 'Second' if x == 2 else 'Third' }}

The lengthy attribute templates for fetus_size_fruit and verywellfamily_link can be shrunken to this:

          fetus_size_fruit: |
            {% set sizes = { 4: 'Strawberry Seed', 5: 'Orange Seed', 6: 'Sweet Pea', 7: 'Blueberry', 8: 'Raspberry',
                             9: 'Green Olive', 10: 'Prune', 11: 'Large Strawberry', 12: 'Lime', 13: 'Lemon',
                            14: 'Navel Orange', 15: 'Pear', 16: 'Avocado', 17: 'Large Onion', 18: 'Cucumber',
                            19: 'Mango', 20: 'Sweet Potato', 21: 'Large Banana', 22: 'Red Bell Pepper',
                            23: 'Grapefruit', 24: 'Pomegranate', 25: 'Eggplant', 26: 'Acorn Squash', 27: 'Cabbage',
                            28: 'Head of Lettuce', 29: 'Head of Cauliflower', 30: 'Bunch of Broccoli', 31: 'Coconut',
                            32: 'Cantaloupe', 33: 'Butternut Squash', 34: 'Pineapple', 35: 'Spaghetti Squash',
                            36: 'Bunch of Kale', 37: 'Canary Melon', 38: 'Mini Watermelon', 39: 'Honeydew Melon',
                            40: 'Small Pumpkin', 41: 'Pumpkin', 42: 'Watermelon' } %}
            {{ sizes[([4, states('sensor.pregnancy_weeks')|int, 42]|sort)[1]] }}
          verywellfamily_link: |
            {% set pages =  { 1: '4158813', 2: '4158819', 3: '4158839', 4: '4158847', 5: '4158868',
                              6: '4158911', 7: '4158916', 8: '4158920', 9: '4158922', 10: '4158926',
                             11: '4158930', 12: '4158934', 13: '4158941', 14: '4158944', 15: '4158988',
                             16: '4158998', 17: '4159005', 14: '4158944', 15: '4158988', 16: '4158998',
                             17: '4159005', 18: '4159009', 19: '4159012', 20: '4159017', 21: '4159022',
                             22: '4159032', 23: '4159036', 24: '4159040', 25: '4159047', 26: '4159097',
                             27: '4159102', 28: '4159110', 29: '4159140', 30: '4159146', 31: '4159202',
                             32: '4159205', 33: '4159211', 34: '4159227', 35: '4159237', 36: '4159243',
                             37: '4159250', 38: '4159251', 39: '4159263', 40: '4159264' } %}
            {% set x = ([1, states('sensor.pregnancy_weeks')|int, 40]|sort)[1] %}
            https://www.verywellfamily.com/{{x|string}}-weeks-pregnant-{{pages[x]}}
1 Like

he’s just showing off now :joy::joy:

1 Like

Awesomeeee work man! We’re expecting our first also so will definitely use this!
Want to play around a bit so that the image overlay works a bit better, but you put in all the hard work!

P.S. you also require custom:text-element with your code for it to work.

@ninjaef Thanks!!! Me too!
@nickrout and @squirtbrnr - Yeah… I have a list of things that I don’t want to have to worry about once kid shows up. Home assistant definitely has to be in a good place by then.
@123 Oh good call! I’ll give that a try!
@Hass10 Good luck! Hope this works for you!

1 Like

Super small detail, but I noticed my wife’s What to Expect app updates her weeks on a Wednesday and Home Assistant will update on a Tuesday with the same Due Date.

I might update the code to add an additional day so that they align.

Just FYI :slight_smile:

Thanks again for all your work on this.

1 Like

Yeah, I also noticed that! I probably should do the same thing.

1 Like

This is great! I love it and added it to my home assistant. Good work man :+1:

I’ve added months left:

pregnancy_month: friendly_name: "Pregnancy Month" 
unit_of_measurement: 'months' 
value_template: "{{ ((9 - ((states.sensor.pregnancy_weeks.state | int) / 4)) | round(0, 'floor')) }}

hi all,

very new to HA…
could someone please be so kind as to let me know where to add the code to? :slight_smile:

thanks

Input_number, sensor and input_datetime in configuration.yaml. keep in mind to you should only have one line with sensor: and input_datetime: and so on so add the config below your current header or create a new if you don’t have one.

Automation should be in automations.yaml

And Lovelace is card configurations to the dashboard.
Add a new card and use the manual card and just paste the config there.

Thanks

I get the following though when I paste the card code into the manual card setup:

**configuration.yaml**:
# Pregnancy Tracker
input_datetime:
  due_date:
    name: Pregnancy Due Date
    has_date: true
    has_time: false
    
sensor:
  - platform: template
    sensors:
      pregnancy_days:
        friendly_name: "Days until due"
        unit_of_measurement: 'days'
        value_template: "{{ (strptime(states.input_datetime.due_date.state, '%Y-%m-%d') - now().replace(tzinfo=None)).days }}"
      pregnancy_weeks:
        friendly_name: "Pregnancy Week"
        unit_of_measurement: 'weeks'
        value_template: "{{ ((40 - ((states.sensor.pregnancy_days.state | int) / 7)) | round(0, 'floor')) }}"
      pregnancy_percent:
        friendly_name: "Pregnancy Percent"
        unit_of_measurement: '%'
        value_template: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 2.8) | round(0, 'floor')}}"

      pregnancy:
        friendly_name: "Pregnancy"
        unit_of_measurement: 'Trimester'
        value_template: |
          {% set x = ((280 - (states.sensor.pregnancy_days.state | int)) / 93.3) | round(0, 'ceil') %}
          {{ 'First' if x == 1 else 'Second' if x == 2 else 'Third' }}
        attribute_templates:
          days: "{{ states.sensor.pregnancy_days.state }}"
          weeks: "{{ states.sensor.pregnancy_weeks.state }}"
          trimester: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 93.3) | round(0, 'ceil') }}"
          months: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 30.5) | round(1, 'half') }}"
          percent: "{{ ((280 - (states.sensor.pregnancy_days.state | int)) / 2.8) | round(0, 'floor')}}"
          what_to_expect_url: "https://www.whattoexpect.com/pregnancy/week-by-week/week-{{ states.sensor.pregnancy_weeks.state }}.aspx"
          fetus_size_image: "https://images.agoramedia.com/wte3.0/gcms/wbw_squares_baby_wk_{{ states.sensor.pregnancy_weeks.state }}.jpg"
          fetus_size_fruit_image: "https://images.agoramedia.com/wte3.0/gcms/wbw-{{ states.sensor.pregnancy_weeks.state }}-fruit.png"
          fetus_size_fruit: |
            {% set sizes = { 4: 'Strawberry Seed', 5: 'Orange Seed', 6: 'Sweet Pea', 7: 'Blueberry', 8: 'Raspberry',
                             9: 'Green Olive', 10: 'Prune', 11: 'Large Strawberry', 12: 'Lime', 13: 'Lemon',
                            14: 'Navel Orange', 15: 'Pear', 16: 'Avocado', 17: 'Large Onion', 18: 'Cucumber',
                            19: 'Mango', 20: 'Sweet Potato', 21: 'Large Banana', 22: 'Red Bell Pepper',
                            23: 'Grapefruit', 24: 'Pomegranate', 25: 'Eggplant', 26: 'Acorn Squash', 27: 'Cabbage',
                            28: 'Head of Lettuce', 29: 'Head of Cauliflower', 30: 'Bunch of Broccoli', 31: 'Coconut',
                            32: 'Cantaloupe', 33: 'Butternut Squash', 34: 'Pineapple', 35: 'Spaghetti Squash',
                            36: 'Bunch of Kale', 37: 'Canary Melon', 38: 'Mini Watermelon', 39: 'Honeydew Melon',
                            40: 'Small Pumpkin', 41: 'Pumpkin', 42: 'Watermelon' } %}
            {{ sizes[([4, states('sensor.pregnancy_weeks')|int, 42]|sort)[1]] }}
          verywellfamily_link: |
            {% set pages =  { 1: '4158813', 2: '4158819', 3: '4158839', 4: '4158847', 5: '4158868',
                              6: '4158911', 7: '4158916', 8: '4158920', 9: '4158922', 10: '4158926',
                             11: '4158930', 12: '4158934', 13: '4158941', 14: '4158944', 15: '4158988',
                             16: '4158998', 17: '4159005', 14: '4158944', 15: '4158988', 16: '4158998',
                             17: '4159005', 18: '4159009', 19: '4159012', 20: '4159017', 21: '4159022',
                             22: '4159032', 23: '4159036', 24: '4159040', 25: '4159047', 26: '4159097',
                             27: '4159102', 28: '4159110', 29: '4159140', 30: '4159146', 31: '4159202',
                             32: '4159205', 33: '4159211', 34: '4159227', 35: '4159237', 36: '4159243',
                             37: '4159250', 38: '4159251', 39: '4159263', 40: '4159264' } %}
            {% set x = ([1, states('sensor.pregnancy_weeks')|int, 40]|sort)[1] %}
            https://www.verywellfamily.com/{{x|string}}-weeks-pregnant-{{pages[x]}}

input_number:
  pregnancy_week:
    name: Pregnancy week persistent number
    max: 42
    min: 4
    step: 1
    mode: box
**automations.yaml**
#automation:
  - id: pregnancy_week_updated
    alias: 'Baby: Week Updated'
    description: Triggered when the baby week changes
    trigger:
      - platform: template
        value_template: >-
          {{ (states('sensor.pregnancy_weeks') | int) >
          (states('input_number.pregnancy_week') | int ) }}
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.pregnancy_week
          value: "{{ states('sensor.pregnancy_weeks') | int }}"
      - service: notify.mobile_app_courtney_phone
        data:
          title: "It's Pregnancy week {{ states('sensor.pregnancy_weeks') }}!"
          message: "Tap here to read all about what's up this week!"
          data:
            clickAction: /lovelace-pregnancy/baby

Lovelace
Configuration errors detected:

  • No type provided.

Top of code: - not all config
type: ‘’
title: Baby
path: baby
panel: false
badges: []
cards:

Also tried:
title: Baby
path: baby
panel: false
badges: []
cards:

Also installed lovelace-card-templater from HACS

I’m sure I’m missing something really simple. any help is greatly appreciated

Tried the following this morning as well…

Invalid configuration

type: custom:card-templater
title: Baby
path: baby
panel: false
badges: []
cards:
  - type: custom:card-templater
    card:
      type: picture-elements
      image_template: '{{ states.sensor.pregnancy.attributes.fetus_size_fruit_image }}'
      elements:
        - type: state-label
          entity: sensor.pregnancy
          style:
            font-size: 30px
            top: 10%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: 'It''s Week '
          attribute: weeks
          suffix: '!'
          style:
            font-size: 40px
            top: 20%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: '(That''s '
          suffix: ' Months)'
          attribute: months
          style:
            font-size: 20px
            top: 29%
            left: 50%
        - type: custom:text-element
          text: The fetus is about
          style:
            font-size: 20px
            top: 75%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: 'the size of a '
          attribute: fetus_size_fruit
          suffix: '!'
          style:
            font-size: 20px
            top: 82%
            left: 50%
    entities:
      - sensor.pregnancy
  - type: markdown
    content: >
      ## [Read up from verywell Family]({{
      states.sensor.pregnancy.attributes.verywellfamily_link }})
  - type: markdown
    content: >
      ## [Read up from "What to Expect"]({{
      states.sensor.pregnancy.attributes.what_to_expect_url }})
  - type: gauge
    name: Download Status
    entity: sensor.pregnancy_percent
    min: 0
    max: 100
    severity:
      green: 33
      yellow: 67
      red: 100

Invalid configuration

type: 'custom:card-templater'
title: Baby
path: baby
panel: false
badges: []
cards:
  - type: custom:card-templater
    card:
      type: picture-elements
      image_template: '{{ states.sensor.pregnancy.attributes.fetus_size_fruit_image }}'
      elements:
        - type: state-label
          entity: sensor.pregnancy
          style:
            font-size: 30px
            top: 10%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: 'It''s Week '
          attribute: weeks
          suffix: '!'
          style:
            font-size: 40px
            top: 20%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: '(That''s '
          suffix: ' Months)'
          attribute: months
          style:
            font-size: 20px
            top: 29%
            left: 50%
        - type: custom:text-element
          text: The fetus is about
          style:
            font-size: 20px
            top: 75%
            left: 50%
        - type: state-label
          entity: sensor.pregnancy
          prefix: 'the size of a '
          attribute: fetus_size_fruit
          suffix: '!'
          style:
            font-size: 20px
            top: 82%
            left: 50%
    entities:
      - sensor.pregnancy
  - type: markdown
    content: >
      ## [Read up from verywell Family]({{
      states.sensor.pregnancy.attributes.verywellfamily_link }})
  - type: markdown
    content: >
      ## [Read up from "What to Expect"]({{
      states.sensor.pregnancy.attributes.what_to_expect_url }})
  - type: gauge
    name: Download Status
    entity: sensor.pregnancy_percent
    min: 0
    max: 100
    severity:
      green: 33
      yellow: 67
      red: 100

Have you installed the custom cards?
The first post says it uses two custom cards, they need to be installed for this to work.

I installed the ones I could find :slight_smile:


I think the code is from the raw config, so what you see is four cards.
If you paste it all in one then it won’t work.

I believe what you should do is either paste it in the raw config or delete the first six lines and split each type: xxxx as a new card.
Mind that you probably need to fix indenting if you choose the latter.

Thanks for pointing out that I had to create individual cards
I believe I have mode some progress… I am stuck on the first bit to show the fruit size etc :slight_smile:

I can however get to the image if I copy the URL and update the week number e.g.
https://images.agoramedia.com/wte3.0/gcms/wbw-12-fruit.png

image

Amazing job by the way… I am very new to HA and can use all the help out there :slight_smile:

Ah, yeah, that’s because you need the whole custom:card-templater card:

type: 'custom:card-templater'
card:
  type: picture-elements
  image_template: '{{ states.sensor.pregnancy.attributes.fetus_size_fruit_image }}'
  elements:
    - type: state-label
      entity: sensor.pregnancy
      style:
        font-size: 30px
        top: 10%
        left: 50%
    - type: state-label
      entity: sensor.pregnancy
      prefix: 'It''s Week '
      attribute: weeks
      suffix: '!'
      style:
        font-size: 40px
        top: 20%
        left: 50%
    - type: state-label
      entity: sensor.pregnancy
      prefix: '(That''s '
      suffix: ' Months)'
      attribute: months
      style:
        font-size: 20px
        top: 29%
        left: 50%
    - type: 'custom:text-element'
      text: The fetus is about
      style:
        font-size: 20px
        top: 75%
        left: 50%
    - type: state-label
      entity: sensor.pregnancy
      prefix: 'the size of a '
      attribute: fetus_size_fruit
      suffix: '!'
      style:
        font-size: 20px
        top: 82%
        left: 50%
entities:
  - sensor.pregnancy