Zwift Sensor Component - Feedback and Testers Needed

Can you post your dashboard code? Looks great!

Hi, my name is Armin and i am a total noob on this. I would love to get your input on the below questions , possible or not?

i want to have a pi which controlls:

fan according the zwift zones
led according to zwift zones
reading the gradient and my control a electric motor with that (lifter)
would this be possible to install on a pi standalone? or would i always need the pc running simultaniously?
sorry for the noob questions.
thanks in advance, armin

This project connects to home assistant so home assistant needs to be running.

Depending on the fan and lights they could also integrate with home assistant.

You can do all of this on a Pi running homeassistant. You may need to have additional items controlling the fan and LED lights, and the motor as well, but you should not need a PC as well.

thanks for your reply. so i would need a pi, the ha software and ant+ sensors for getting heart rate? Major issue is getting the ant+ signals read out

This project uses Zwift’s API so Zwift does all the communications with the sensors and this uses home assistant to pull the data out.

Does anyone know if this integration will be compatabile with HA core-2021.3.1? Particularly this requirement “Custom integrations now require a version key in their manifest file, this also means that all custom integrations now require a manifest file.”

Hi I’m trying to implement this code but do matter what the power is set to it always shows Neuromuscular Power. Where am I going wrong please? I’ve copied and pasted the code and changed the ID to my ID. Thanks

will look into this today and make necessary updates, I am upgrading to 2021.3.2 now.

1 Like

No issues with the current version of this integration and 2021.3.2!

I’m getting the following error message in the log after updating to 2021.3.2
"No ‘version’ key in the manifest file for custom integration ‘zwift’. This will not be allowed in a future version of Home Assistant. Please report this to the maintainer of ‘zwift’ "

Like it says, it’s a warning for now, but will block it in a later version. I raised https://github.com/snicker/zwift_hass/issues/20 for this.

Thanks @badguy, I honestly had missed that issue entirely- I’ll get an update out within the week.

No worries, life happens :slight_smile:

Updated to v3.2.1!

  • implements rounding for sensor values
  • removes several superfluous and unnecessary profile values from attributes
  • add names for new world values (thanks to @mountainsandcode for this and the 2 changes above!)
  • implements automated checks using hassfest (thanks to @badguy!)

I guess important to note is that it also addresses the version requirement in manifest.json :slight_smile:

1 Like

After the v3.2.1 update I am now seeing a red box with the error:

Config is not an object

break

Does anyone have any ideas please?

If i remove the - break line in the config the error box goes away however the data is not formatted correctly

Take a look at https://github.com/thomasloven/lovelace-layout-card - this is going to be due to breaking changes with that card - I don’t think it uses the break keyword any more.

Im running this integration for 6 months , i have a 3 speed fan controlled by zwift hr. I have rgb lights controlled by zwift power zones. However i have a we bug. Sorry if its been covered already, but a few times i have started my zwift workout and homeassistant has not recognised my status online in zwift, after i restart HA everything works?

I suddenly started getting this error in my logs this evening, any ideas anyone?

2021-04-11 22:14:44 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: 'None' has no attribute 'distanceInMeters' when rendering '{% set last_act = state_attr("sensor.zwift_online_XXXXXX", 'latest_activity') %} {% set t = last_act['movingTimeInMs'] %} {% set d = last_act['distanceInMeters'] %} {% set pace_in_seconds = 0 %} {% if d and t %} 
{% set pace_in_seconds = t/d %}
{% endif %} Last session: {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.name }} 
![Activity Image]( {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.primaryImageUrl }} )
The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run {%- endif %} started on {{ as_timestamp(states.sensor.zwift_online_XXXXXX.attributes.latest_activity.startDate) | timestamp_custom(' %d %B %Y at %H:%M ') | replace(" 0", "") }}
The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run {%- endif %} took {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.duration }} Minutes
The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run {%- endif %} ended on {{ as_timestamp(states.sensor.zwift_online_XXXXXX.attributes.latest_activity.endDate) | timestamp_custom(' %d %B %Y at %H:%M ') | replace(" 0", "") }}
{% if last_act['sport'] == "CYCLING" -%} Ride {%- else -%} Run {%- endif %} stats:
Distance: {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.distanceInMeters|round/1000 }} Km
{% if last_act['sport'] == "CYCLING" -%} Climbing: {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.totalElevation }}m {%- else -%} Pace: {{pace_in_seconds|round//60}}:{{pace_in_seconds|round%60}}/Km {%- endif %}
Power: {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.avgWatts }}W (Average)
Calories: {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.calories }}
Ride On Count: {{ states.sensor.zwift_online_XXXXXX.attributes.latest_activity.activityRideOnCount }}'

I guess it has something to do with this card, but the card itself is working perfectly, no idea what’s happening…

cards:
  - entities:
      - entity: sensor.zwift_online_XXXXXX
        name: Online
      - entity: sensor.zwift_level_XXXXXX
        name: Cycling Level
      - 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'
      - entity: sensor.zwift_run_level_XXXXXX
        name: Run Level
      - color: deeppink
        entity: sensor.zwift_run_progress_XXXXXX
        entity_row: true
        height: 20px
        name: Run 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'
    show_header_toggle: false
    title: Zwift Profile
    type: entities
  - card:
      content: >-
        {% set last_act = state_attr("sensor.zwift_online_XXXXXX",
        'latest_activity') %} {% set t = last_act['movingTimeInMs'] %} {% set d
        = last_act['distanceInMeters'] %} {% set pace_in_seconds = 0 %} {% if d
        and t %}
           {% set pace_in_seconds = t/d %}
        {% endif %} Last session: {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.name }}

        ![Activity Image]( {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.primaryImageUrl
        }} )

        The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run {%-
        endif %} started on {{
        as_timestamp(states.sensor.zwift_online_XXXXXX.attributes.latest_activity.startDate)
        | timestamp_custom(' %d %B %Y at  %H:%M ') | replace(" 0", "") }}

        The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run {%-
        endif %} took {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.duration }}
        Minutes

        The {% if last_act['sport'] == "CYCLING" -%} ride {%- else -%} run {%-
        endif %} ended on {{
        as_timestamp(states.sensor.zwift_online_XXXXXX.attributes.latest_activity.endDate)
        | timestamp_custom(' %d %B %Y at  %H:%M ') | replace(" 0", "") }}


        {% if last_act['sport'] == "CYCLING" -%} Ride {%- else -%} Run {%- endif
        %} stats:

        Distance: {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.distanceInMeters|round/1000
        }} Km 

        {% if last_act['sport'] == "CYCLING" -%} Climbing: {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.totalElevation
        }}m  {%- else -%} Pace:
        {{pace_in_seconds|round//60}}:{{pace_in_seconds|round%60}}/Km {%- endif
        %}

        Power: {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.avgWatts
        }}W (Average)

        Calories: {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.calories }}

        Ride On Count: {{
        states.sensor.zwift_online_XXXXXX.attributes.latest_activity.activityRideOnCount
        }}
      title: Last Zwift Session
      type: markdown
    conditions:
      - entity: sensor.zwift_online_XXXXXX
        state: 'False'
    type: conditional
  - card:
      entities:
        - entity: sensor.zwift_distance_XXXXXX
          name: Distance
        - entity: sensor.zwift_altitude_XXXXXX
          name: Altitude
        - entity: sensor.zwift_gradient_XXXXXX
          name: Gradient
        - entity: sensor.zwift_power_XXXXXX
          name: Power
        - entity: sensor.zwift_cadence_XXXXXX
          name: Cadence
        - entity: sensor.zwift_speed_XXXXXX
          name: Speed
        - entity: sensor.zwift_heart_rate_XXXXXX
          name: Heart Rate
      show_header_toggle: false
      title: Zwift Live Session
      type: entities
    conditions:
      - entity: sensor.zwift_online_XXXXXX
        state: 'True'
    type: conditional
layout: vertical
type: 'custom:layout-card'
layout_type: masonry
view_layout: vertical