Dashboard / Card to show yearly cycling progress

Hello, I would like to make a card on a dashboard that will show my progress for cycling for the year. Can you tell me if I am on the right path, or if I should be doing this differently?

So, I have the sensor entities: - sensor.strava_stats_summary_ytd_ride_distance

And if I want my yearly goal to be 6000 miles, it should be something like this

  • Total Distance = 6000
  • Miles So Far this year: sensor.strava_stats_summary_ytd_ride_distance
  • Percent Complete = YTD_Ride_Distance / 6000

And as I understand it, to get this to show on a gauge, I would need to do a Template

type: gauge
entity: Yearly Cycling
template:
  - sensor:
      - name: "Yearly Cycling"
        {% set Percent= states('sensor.strava_stats_summary_ytd_ride_distance') /6000}

I am sure the code above is not “right”, but I am hoping I am am on the right path.

Am I going about this the correct way, or should I be looking at doing this a different way?

Hi,
A progress gauge is an interesting idea, particularly as “Progress” stats are one of the Strava features reserved for premium subscribers.

I’ve not tried this yet, but here’s a sketch before trying it myself:

  • Define a helper or Text entity to hold the annual distance target
  • Define another to hold the current distance (looks like you have a sensor already)
  • Define a template entity which is calculated once per day, to give the % year time complete
  • Define another template which calculates the % distance goal complete (calc once a day, or when the distance sensor changes)
  • Create a gauge to display:
    • % year time complete
    • % year distance goal complete
    • Actual distance

How do you get the actual stats out of Strava? Is there something in HACS, a web scraper, or just enter a value (text entity).

To get a template entity to run once a day, I have a templates.yaml included in configuration.yaml, so here’s a quick hack to get % year complete. I need to look for the Python “day of year” object as this may be simpler than needing to compare with a hard-coded year start.

# templates.yaml
# no "template:" here as in configuration.yaml

- trigger:
    - event: start
      platform: homeassistant
    - platform: event
      event_type: event_template_reloaded
    - platform: time_pattern
      # only needs to change once a day
      hours:   05
      minutes: 05
  unique_id: 111111111
  sensor:
    - name: Percentage of year elapsed
      state: >
          {{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * 100)|round(1,'ceil') }}
      icon: "mdi:CalendarRange"

James

Thanks,

I am not currently paying for Strava, but I’d be happy to. But, I would like to have my progress on my dashboard in HA, similar to how others display weather or energy usage.

Here is the Strava integration for Home Assistant

I am going to re-read what you posted about 3 times and try to figure out how to do this. Thanks !

Thanks for the Strava integration pointer!

The block of YAML is distilled from several years of posts, so there is some magic in there (e.g. to re-calculate on a reboot/ restart), but to tinker, simply copy the template function into Dev Tools to take it apart and test:

{{ ((as_timestamp(now().date()) }}
{{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * 100)|round(1,'ceil') }}

To install it, I prefer a separate file for templates, so add template: !include templates.yaml to configuration.yaml, and create templates.yaml with the contents above. Having a place for once a day calculations can be really useful (e.g. bin reminders, text to speech formatted dates, etc).

More tinkering is to come… :slight_smile:

Thanks for looking at this , and having interest. This is all one or 2 levels above my current skill set, but I am going to see if I can make the magic happen

FYI - just installed the Strava integration, and it worked first time! :slight_smile:
I’ll look at defining targets and the gauges tomorrow, but straight away it looks like only Total / Year / “Recent” totals are available, suggesting weekly targets night not be possible.

For me, the year to date distance verses time are enough. One gauge with two bars (distance, time), and a progress (% distance / % time) might be enough (possibly with red / amber / green / amber / red zones for show).

Making progress:

  • Create input_number.year_ride_target
  • Create input_number.year_run_target

Try the following in the Developer Tools Template

This Year
Ride {{ states('sensor.strava_stats_summary_ytd_ride_distance')|round(0,'ceil') }}km of {{ states('input_number.year_ride_target')|round(0,'ceil') }}km ({{ (states('sensor.strava_stats_summary_ytd_ride_distance')|float - ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * states('input_number.year_ride_target')|round(0,'ceil')))|round(0,'ceil') }}km ahead)
Run   {{ states('sensor.strava_stats_summary_ytd_run_distance')|round(0,'ceil') }}km of  {{ states('input_number.year_run_target')|round(0,'ceil') }}km ({{ (states('sensor.strava_stats_summary_ytd_run_distance')|float - ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * states('input_number.year_run_target')|round(0,'ceil')))|round(0,'ceil') }}km ahead)

Ride {{ (((states('sensor.strava_stats_summary_ytd_ride_distance')|float / states('input_number.year_ride_target')|float) *100) |round(1,'ceil')) }} %
Run  {{ (((states('sensor.strava_stats_summary_ytd_run_distance')|float / states('input_number.year_run_target')|float) *100) |round(1,'ceil')) }} %
Year {{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * 100)|round(1,'ceil') }} %

Ride target {{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * states('input_number.year_ride_target')|round(0,'ceil'))|round(1,'ceil') }}km
Run  target  {{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * states('input_number.year_run_target')|round(0,'ceil'))|round(1,'ceil') }}km

Which gives:

This Year
Ride 1086km of 2000km (-31km ahead)
Run   193km of  250km (53km ahead)

Ride 54.3 %
Run  77.1 %
Year 55.9 %

Ride target 1116.9km
Run  target  139.7km

The percentages are best moved to a template function, generating entities for a gaugue.

The main issue is the Strava integration seems to exclude virtual distances - e.g. Zwift, putting me behind! :slight_smile:

Almost a dashboard…

I’ve tidied the calculations up into template functions to give more usable entities:

# templates.yaml
# no "template:" here as in configuration.yaml

- trigger:
    - event: start
      platform: homeassistant
    - platform: event
      event_type: event_template_reloaded
    - platform: time_pattern
      # only needs to change once a day
      hours:   05
      minutes: 05
  unique_id: 100000000001
  sensor:
    - name: YTD Percent
      state: "{{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * 100)|round(1,'ceil') }}"
      #state_class: "measurement"
      icon: "mdi:percent"
      unique_id: 10000001

    - name: YTD Ride Percent
      state: "{{ (((states('sensor.strava_stats_summary_ytd_ride_distance')|float / states('input_number.year_ride_target')|float) *100) |round(1,'ceil')) }}"
      #state_class: "measurement"
      icon: "mdi:bicycle"
      unique_id: 10000002

    - name: YTD Ride Target
      state: "{{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * states('input_number.year_ride_target')|round(0,'ceil'))|round(1,'ceil') }}"
      #state_class: "measurement"
      icon: "mdi:bicycle"
      unique_id: 10000003

    - name: YTD Run Percent
      state: "{{ (((states('sensor.strava_stats_summary_ytd_run_distance')|float / states('input_number.year_run_target')|float) *100) |round(1,'ceil')) }}"
      #state_class: "measurement"
      icon: "mdi:shoe-sneaker"
      unique_id: 10000004

    - name: YTD Run Target
      state: "{{ ((as_timestamp(now().date()) - as_timestamp('2023-01-01')) / 86400 / 365.25 * states('input_number.year_run_target')|round(0,'ceil'))|round(1,'ceil') }}"
      #state_class: "measurement"
      icon: "mdi:shoe-sneaker"
      unique_id: 10000005

This gives a simpler text dashboard:

This Year
Ride {{ states('sensor.strava_stats_summary_ytd_ride_distance')|round(0,'ceil') }}km of {{ states('input_number.year_ride_target')|round(0,'ceil') }}km ({{ (states('sensor.strava_stats_summary_ytd_ride_distance')|float - states('sensor.ytd_ride_target')|float)|round(0,'ceil') }}km ahead @ {{states('sensor.ytd_ride_target')}}km)
Run  {{ states('sensor.strava_stats_summary_ytd_run_distance')|round(0,'ceil') }}km of {{ states('input_number.year_run_target')|round(0,'ceil') }}km ({{ (states('sensor.strava_stats_summary_ytd_run_distance')|float - states('sensor.ytd_run_target')|float)|round(0,'ceil') }}km ahead @ {{states('sensor.ytd_run_target')}}km)

Ride {{ states('sensor.ytd_ride_percent') }}%
Run  {{ states('sensor.ytd_run_percent') }}%
Year {{ states('sensor.ytd_percent') }}%

The problem now is it appears the Gauge card only supports fixed constant segments, which means I can’t define colours based on the dynamic sensor.ytd_percent - effectively plotting YTD progress against YTD time.

This suggests a fully custom component might be needed to give a time bar graph with target progress - effectively just 3x percentages plotted on the same 0-100 axis.

Unless someone else has an idea… :slight_smile: