Zwift Sensor Component - Feedback and Testers Needed

@BambamNZ I’ve created this issue to track the request:

I’m also adding some detail on how refresh intervals currently work within the configuration below and in the issue:

Currently the integration will obey an update_interval setting in the YAML configuration, but defaults to 15 seconds. When API call detects that the user is online, this is decreased to 2 seconds to give more frequent data. If we receive a 429 response from the API for polling too frequently, the online update interval will be throttled back by 0.25s on the next retry until 429s are no longer received.

if you wish to reduce the offline polling frequency, you can add an update_interval setting in your YAML configuration for the integration. However, the disadvantage here when compared to your proposed switch is that if you happen to log on to Zwift and start cycling within 60 seconds, you are likely to miss the first bit of incoming data. Once online, data will update every 2 seconds (subject to throttling from the server)

1 Like

I’ll also add that I don’t often get free time to work on this integration these days, so I am incredibly open to contributions from anyone that wishes to help update the integration to support requested features and some of the upgrades the integration needs to support many of the newer functionalities within Home Assistant (UI configuration, reloading, multiple instances of the integration,etc)

I still use the integration myself pretty dang frequently, so I will quickly become aware of anything that breaks functionality and can help fix.

Thanks, @snicker - I’ll check that out the next time I log in and let you know what I see.

I’d also like to contribute, but I’m just now dipping my toe into all this, so I’ve probably got a lot to learn before I’m useful. I’ll do what I can, though, because I love this integration.

I did verify today that I do still have this data coming from the Zwift API on my account, so the value is still there. I am just now wondering if the value is absent if unconfigured for a user on the server side, and if absent, we should assume imperial. @gsarjeant please report back and if so, I can modify the integration to behave correctly (or offer a configuration setting to force it)

actually @gsarjeant you should be able to check the attributes on your sensor even if you aren’t online:

Thanks, @snicker . I do see the UseMetric attribute, and it’s returning false.

Is it possibly just a string/boolean issue? It looks like is_metric is directly returning the value from the API if it exists, so if that’s a string that is lowercase false, perhaps python is interpreting it as truthy?

@gsarjeant you may be right. I created this issue to track investigation. I will try to dig into it this weekend.

1 Like

@snicker FYI I think I was wrong. It looks like is_metric() only affects the units that are displayed, and that’s correct on my end. I see “miles” in the display on Home Assistant. It’s just the distance coming out of the API that’s metric. I ssh’d into my Home Assistant and modified is_metric() so it always returned False and there was no change in behavior (I restarted Home Assistant just in case that’s necessary).

Makes me wonder if Zwift is always reporting distances in metric and the conversion to imperial happens in the app for those of us who use it. That would be a simpler implementation on their end. But then I feel like someone else who’s using imperial units would have noticed this.

Or maybe nobody uses imperial and I’m about to get my Zwift card revoked. :rofl:

@snicker Just FYI, I’m working on a PR for this. I have the distance and speed working, but somehow I’ve messed up the gradient in the process. I suspect I don’t actually understand how Zwift is reporting altitude. I’m hoping to work that out this weekend and get the PR over.

Hi,

I’m new to HA and the Zwift integration and like to use Zwift Power for changing the color of a Led strip based on a ESP32-WROOM Device with WLED. Both the Zwift integration and Wled working like it should be and HA, Zwift integration and wled are on the latest software levels.

I looked at the Code from @Phillprice. I seem to do exactly what I want to do but I’m not clear where to save the code. When creating an automation based on the code and saving it, it generates an error and it won’t save.

The error code I get is Message: malformed: extra keys not allowed @ data[‘0’] , probably due to malformed syntax during copy-paste.

I’m not a programmer so I prefer the wizard in automations and looking for the possibilities I have with NodeRed, but for now it looks like I have to use scripting.

What I’d like to do is:

Changing the color of a led strip (wled) based on the Zwift Powerzones (%). Nothing more or less (at this moment)

Can someone help me with getting started and point me to some useful scripts/implementations I can use for starting?

Thx in advance
Rob Coenders

I would choose one of the more recent code blocks.

A lot has changed in the 6.5 years since I made that post!

1 Like

This should work in the HA Automations. Replace xxxxxx with your Zwift id and the wled segments as required. Once you’ve pasted it in and made the changes it should render in the visual editor.

I created a helper entity that pulls out the sport type as I run as well as cycle, so that this only comes on for cycling. That is set up as follows, and has the entity sensor.zwift_sport:

{% set last_act = state_attr('sensor.zwift_online_xxxxxx','latest_activity') %}{{ last_act['sport']}}

Then this is the automation yaml:

alias: Zwift Power
description: ""
triggers:
  - trigger: state
    entity_id:
      - sensor.zwift_power_xxxxxx
conditions:
  - condition: state
    entity_id: sensor.zwift_online_xxxxxx
    state: "True"
  - condition: state
    entity_id: sensor.zwift_sport
    state: CYCLING
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: >-
              {{ states("sensor.zwift_power_xxxxxx")|float >=
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *0.59 and
              states("sensor.zwift_power_xxxxxx")|float <
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *0.76}}
        sequence:
          - action: light.turn_on
            metadata: {}
            data:
              effect: Solid
              rgbw_color:
                - 0
                - 134
                - 255
                - 0
            target:
              entity_id:
                - light.wled_segment_3
                - light.wled_segment_4
                - light.wled_segment_5
      - conditions:
          - condition: template
            value_template: >-
              {{ states("sensor.zwift_power_xxxxxx")|float >=
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *0.76 and
              states("sensor.zwift_power_xxxxxx")|float <
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *0.90}}
        sequence:
          - action: light.turn_on
            metadata: {}
            data:
              effect: Solid
              rgbw_color:
                - 0
                - 196
                - 33
                - 0
            target:
              entity_id:
                - light.wled_segment_3
                - light.wled_segment_4
                - light.wled_segment_5
      - conditions:
          - condition: template
            value_template: >-
              {{ states("sensor.zwift_power_xxxxxx")|float >=
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *0.90 and
              states("sensor.zwift_power_xxxxxx")|float <
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *1.05}}
        sequence:
          - action: light.turn_on
            metadata: {}
            data:
              effect: Solid
              rgbw_color:
                - 252
                - 206
                - 0
                - 0
            target:
              entity_id:
                - light.wled_segment_3
                - light.wled_segment_4
                - light.wled_segment_5
      - conditions:
          - condition: template
            value_template: >-
              {{ states("sensor.zwift_power_xxxxxx")|float >=
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *1.05 and
              states("sensor.zwift_power_xxxxxx")|float <
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *1.19}}
        sequence:
          - action: light.turn_on
            metadata: {}
            data:
              effect: Solid
              rgbw_color:
                - 249
                - 104
                - 0
                - 0
            target:
              entity_id:
                - light.wled_segment_3
                - light.wled_segment_4
                - light.wled_segment_5
      - conditions:
          - condition: template
            value_template: >-
              {{ states("sensor.zwift_power_xxxxxx")|float >=
              state_attr("sensor.zwift_online_xxxxxx", "ftp") *1.19}}
        sequence:
          - action: light.turn_on
            metadata: {}
            data:
              effect: Solid
              rgbw_color:
                - 249
                - 0
                - 0
                - 0
            target:
              entity_id:
                - light.wled_segment_3
                - light.wled_segment_4
                - light.wled_segment_5
    default:
      - action: light.turn_on
        metadata: {}
        data:
          effect: Solid
          rgbw_color:
            - 0
            - 0
            - 0
            - 240
        target:
          entity_id:
            - light.wled_segment_3
            - light.wled_segment_4
            - light.wled_segment_5
mode: single
max_exceeded: silent

1 Like

Thx,

I’m going to Play with this Code. I do not use Zwift for running but that won’t be a problem I think.

First I’m going to ride my bike outside for as long as it is good weather over here but I Certainly let you know if it is working.

I know it’s is old. But I did struggle finding more code blocks I can use. May I have to learn searching a little bit better :slight_smile: