Zwift Sensor Component - Feedback and Testers Needed

That’s not a problem at all @snicker, I like learning new stuff, so it wasn’t too difficult to figure out. But I can see a lot of guys find your great integration without necessary experience and it may be bit of a steep curve :wink: I know I’ve spent quite some time digging around.

I’ll write something down from my notes when I have a minute and if you want, feel free to add it under installation instructions.

Need a bit of advice here, I am trying to code up LEDs which change colour the higher my heart rate goes on Zwift.

Firstly thanks for all the posts, helped me along thus far, and apologies if in wrong thread. Admin please feel free to move this post if required.

The Sensors I am using I got from the git on this page.

Hardware I am using is:

D1 Mini

WS2812B LEDs

Connected with jumpers (5v, G, D4 data)

Used ESPhome to connect.

In automations, below I will place the code, So far I have only input the thresholds of the different heart rate, will get to the colour change once I get it to trigger.

When I execute the automation through the UI in Home Assistant it works, but when I am on Zwift it does not work. The data is going into home assistant as I have built a Grafana Dashboard which shows the heart rate data live, and it works.
I have set up the LED as a entity also

What am I missing here? Any help greatly appreciated.

Here is the Automation code:

- id: '1605030778837'
  alias: hEART_1_Automation
  description: ''
  trigger:
  - platform: numeric_state
    entity_id: sensor.zwift_heart_rate_[my_zwift_id]
    above: '70'
    below: '121'
    attribute: unit_of_measurement
  - platform: numeric_state
    entity_id: sensor.zwift_heart_rate_[my_zwift_id]
    attribute: unit_of_measurement
    above: '121'
    below: '130'
  - platform: numeric_state
    entity_id: sensor.zwift_heart_rate_[my_zwift_id]
    attribute: unit_of_measurement
    above: '130'
    below: '140'
  - platform: numeric_state
    entity_id: sensor.zwift_heart_rate_[my_zwift_id]
    attribute: unit_of_measurement
    above: '140'
    below: '155'
  - platform: numeric_state
    entity_id: sensor.zwift_heart_rate_[my_zwift_id]
    attribute: unit_of_measurement
    above: '155'
  - platform: state
    entity_id: light.heartrate_led_2_4
    attribute: rgb_color
    from: '230'
    to: '23'
    for: '23'
  condition: []
  action:
  - type: turn_on
    device_id: 86975048523eea93a18e0908b3eb9e2e
    entity_id: light.heartrate_led_2_4
    domain: light
    brightness_pct: 90
  mode: single

HI, @noisufnoc could you share your flow file for node-red for changing the LEDs? I am trying to do this and have hit wall.

@phillprice I am missing sensor.zwift_ftp from the repo. Is this a sensor you have? I have sensor.zwift_power from the repo.

@ronan25 It is a template sensor found a bit further up in here by @phillprice:

- platform: template
  sensors:
    zwift_ftp:
      friendly_name: "Zwift FTP"
      entity_id: sensor.zwift_online_XXXXXX
      unit_of_measurement: 'watts'
      value_template: "{{states.sensor.zwift_online_XXXXXX.attributes.ftp}}"

Thank you, Thank you, Have scrolled through this page many times and did not see this. Thank you again.

badguy,

Love your Lovelace card.
I did notice that the Zwift sensor doesn’t give a nice duration. If you rode 1 hour and 24 minutes, you don’t want it to say 1:24 Minutes. It also doesn’t look like the data coming in is formatted so well, either. So, if you were to ride 1 hr and 4 min, the duration comes back from Zwift as 1:4. This code fixes it to be in the format 1h:04m.

{% set value =
states.sensor.zwift_online_XXXXXX.attributes.latest_activity.duration%}
{% set parts = value.split(":") %}
{{ parts[0]}}h:{{'{:02}'.format(parts[1]| int)}}m
1 Like

Thanks for this! It had bugged me, just not enough to look in to sorting it, so this is great!

This doesn’t seem to work if the duration is less than an hour - it breaks my card?

Try this:

{% set value = states.sensor.zwift_online_xxxxxx.attributes.latest_activity.duration|string %}
{% if ':' is in value -%}
{% set parts = value.split(":") %}
{{ parts[0]}}h:{{'{:02}'.format(parts[1]| int)}}m
{%- else -%}
{{ value}}m
{%- endif %}

This should load the duration into ‘value’ then check if it includes a ‘:’ split it into parts, and display as 12h:34m if it does, or just display 56m if it doesn’t include a ‘:’ and not try and do the split.

1 Like

Perfect - thanks!!

Badguy,
You beat me to the punch. My less elegant fix was this:

The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run
{%- endif %} duration was
{% set value = states.sensor.zwift_online_XXXXXX.attributes.latest_activity.duration %}
{% set parts = value.split(":") %} 
{% set duration_length = parts | length %} 
{% if duration_length == 2 -%}
{{parts[0]}}h:{{'{:02}'.format(parts[1]| int)}}m
{%- else -%}
{{parts[0]}}m
{%- endif %}

@badguy @vk2him
And, like a fool, I didn’t edit my Zwift ID out of my post. So, if you wouldn’t mind, could you, please, edit it out of your reply posts?

Thanks,
Kevin

No problem - done - thanks again!

1 Like

Hi all!

Awesome work! I new to Home assistant (been using it for a month now) and I finnaly got this Zwift implementation to work. I’ve used @badguy his example to create my own dashboard. Learned a lot!

I use the heart rate sensor to control my two fans. Really awesome. Nextup is pain cave lightning that changes when going deep or taking it easy…

One small issue… My bar-card does not allign properly with the entity icon. Did you change something?

This is what I have for the bar entity:

      - color: darkorange
        entity: sensor.zwift_cycle_progress_xxxxxx
        entity_row: true
        height: 20px
        name: Cycle Progress
        positions:
          indicator: 'off'
          name: inside
          value: 'off'
        style: |-
          bar-card-currentbar, bar-card-contentbar, bar-card-backgroundbar {
          margin-top: 10px;
          }
        type: 'custom:bar-card'

I guess the margin-top bit is the thing that pushing the bar down.

Nevermind! I was missing a plugin…
In order to get your dashboard to work. I had to add layout-card, bar-card and card-mod. The last one did the trick with the allignment.
z

To get it a little bit more alligned with the other entities, I’ve added a few allignment options

              - color: darkorange
                entity: sensor.zwift_cycle_progress_XXXXXX
                entity_row: true
                height: 20px
                name: Cycle Progress
                positions:
                  indicator: 'off'
                  name: inside
                  value: 'off'
                style: >-
                  bar-card-currentbar, bar-card-contentbar,
                  bar-card-backgroundbar {  margin-left: 15px;  margin-top:
                  10px; margin-right: auto; width: 97%; }
                type: 'custom:bar-card'

Ok strange… I Have exactly the same.

</s> <s> - color: darkorange</s> <s> entity: sensor.zwift_cycle_progress_XXXXXX</s> <s> entity_row: true</s> <s> height: 20px</s> <s> name: Cycle Progress</s> <s> positions:</s> <s> indicator: 'off'</s> <s> name: inside</s> <s> value: 'off'</s> <s> style: >-</s> <s> bar-card-currentbar, bar-card-contentbar,</s> <s> bar-card-backgroundbar { margin-top: 10px; }</s> <s> type: 'custom:bar-card'</s> <s>

For the Ride On Sensor… I’ve found a Powershell script online that reads the log file and counts the ride ons, ride ons given and reads the name of the player that gave the ride on.


It works only on Windows (since it is powershell) and Zwift must run from that Windows computer.
The script outputs these number to a file.

Now I made some changes so that it only outputs a number (ride ons received) and writes this to a file in the config folder.
Then I use a File sensor to read the number in the file, and tadaah… I have A Ride On Entity.
z
Setting the update interval to 1 second makes it pretty fast. I see the thumb in game, and the number on my dashboard changes at the same time. This will depend on your network…
I know it is pretty dirty, but this works for now…
Now I need to create a script that checks if the number goes +1 and create an activity. Also change the update interval with a script when online, so it doesn’t check every second when not online.
This should also work when riding through an arch, go up one level, since this is all in the log file.

I know there will be other ways to do this, so if someone has a suggestion, let me know…

2 Likes

Hi , everything works pretty well , it updates regularly and without issues.
Really pleased with this integration.
thanks @snicker

1 Like

thanks @Umbe! your dashboard looks EXCELLENT!!

1 Like