From Performance Tracking to Anomaly Detection: Building a “Safety Layer” for Zwift in Home Assistant

Most Home Assistant setups that integrate Zwift or cycling platforms tend to focus on performance: heart rate zones, power curves, calories burned, progress over time, and colorful lighting effects that respond to effort. These are fun, motivating, and visually engaging.

Advertisements

But there is another direction that is far less explored—and arguably more interesting from a systems perspective: using the same data as a lightweight safety and anomaly detection layer.

Instead of asking “How hard am I training?”, we ask:

“Does this look like normal physiological behavior under load—or something unusual enough that I should pay attention?”

This is not about medical diagnosis. It is about detecting patterns that deviate from expected behavior during exercise, similar in spirit to how modern wearables provide alerts for unusual heart rate or potential crash detection.


A Shift in Thinking: From Visualization to Detection

Traditional Zwift + Home Assistant setups are event-driven and aesthetic:

  • Change light color when heart rate enters zones
  • Display wattage on dashboards
  • Trigger music playlists based on intensity

These are reactive and expressive systems.

An anomaly detection layer is different. It is:

  • Continuous rather than event-based
  • Comparative rather than absolute
  • Context-aware rather than single-signal driven

Instead of focusing on “high performance = red lights”, we focus on:

  • “Is the relationship between effort and physiological response consistent with normal training behavior?”

This introduces a more “system-level” perspective similar to how modern wearable ecosystems behave: they do not rely on one signal, but on patterns across multiple signals over time.


Core Signals in a Zwift Safety Model

To build a meaningful anomaly detection system, we need multiple inputs. A single metric like heart rate or power is never enough.

1. Heart Rate (Physiological Response)

Heart rate reflects cardiovascular effort, but it is noisy:

  • Sensor dropouts are common
  • Sudden spikes or dips can occur due to contact issues
  • Delayed response relative to power changes is normal

We are less interested in raw values and more in:

  • Trends over 30–60 seconds
  • Stability under constant load

2. Power Output (Mechanical Load)

Power (watts) is the most reliable indicator of effort in cycling:

  • Stable and immediate
  • Direct representation of workload
  • Useful baseline for comparison with heart rate

However, power alone cannot describe physiological state.


3. Context Awareness (Is Zwift actually active?)

Context prevents false alarms:

Advertisements
  • Is a workout session running?
  • Is power consistently above zero?
  • Is cadence stable (not coasting)?

Without context, normal pauses would be misinterpreted as anomalies.


4. Trend Analysis (Not single values)

Instead of reacting to instantaneous values:

  • Heart rate slope over time
  • Power stability window (e.g., 20–60 seconds)
  • Divergence between heart rate and power

This is where meaningful detection begins.


5. Sensor Quality and Stability

One of the most important but overlooked components:

  • Heart rate dropouts (e.g., 0 bpm spikes)
  • Bluetooth reconnection events
  • Sudden unrealistic jumps

Many “false alarms” in health-like systems are actually just bad data, not real physiological events.


Building an “Anomaly Score” Instead of a Binary Trigger

A more robust approach is to assign weighted scores instead of relying on a single condition.

Example logic:

  • High load (power > 200W): +2
  • High load + falling heart rate: +2
  • Heart rate instability: +1–3
  • Prolonged inconsistency (>15 seconds): +2

Only when the score exceeds a threshold do we trigger an alert.

This approach reduces false positives and creates a more flexible system that can evolve over time.


Home Assistant Architecture

A practical implementation in Home Assistant typically includes:

  1. Raw Sensors
    • Zwift power sensor
    • Zwift heart rate sensor
    • Optional cadence sensor
  2. Template Sensors
    • Moving average heart rate
    • Heart rate delta (change over time)
    • Basic anomaly scoring sensor
  3. Automation Layer
    • Triggers based on anomaly score threshold
    • Notifications via mobile app or dashboard alert
  4. Optional Enhancements
    • Historical statistics integration
    • Energy usage tracking (e.g., smart trainer consumption in kWh)
    • Environmental context (indoor temperature around 20–22°C in training room)

Example Automation in Home Assistant

Below is a simplified but functional example of an anomaly detection automation using a scoring model.

template:
- sensor:
- name: zwift_anomaly_score
state: >
{% set watt = states('sensor.zwift_power')|float(0) %}
{% set hr = states('sensor.zwift_heart_rate')|float(0) %}
{% set hr_prev = states('sensor.zwift_heart_rate_prev')|float(hr) %}

{% set score = 0 %}

{# High workload #}
{% if watt > 200 %}
{% set score = score + 2 %}
{% endif %}

{# Unexpected HR drop under load #}
{% if watt > 200 and (hr_prev - hr) > 10 %}
{% set score = score + 2 %}
{% endif %}

{# Sensor instability #}
{% if hr == 0 %}
{% set score = score + 3 %}
{% endif %}

{{ score }}

Automation

automation:
- alias: Zwift Anomaly Detection Alert
trigger:
- platform: numeric_state
entity_id: sensor.zwift_anomaly_score
above: 4
for: "00:00:15"

action:
- service: notify.mobile_app
data:
title: "Zwift Safety Alert"
message: >
Unusual training pattern detected:
High power combined with irregular heart rate response.

This may indicate sensor issues or abnormal physiological response.
Please verify your sensors and consider pausing the session.

Practical Example Scenario

Imagine a rider doing interval training:

  • Power increases to 250W and stays stable
  • Heart rate unexpectedly drops from 150 bpm to 135 bpm
  • Power remains high for 20 seconds

In a normal situation, heart rate would either:

  • Continue rising
  • Plateau
  • Or slightly lag behind power increases

A sudden drop under sustained load is unusual. In most cases it is:

  • A chest strap losing contact
  • Bluetooth interference
  • Moisture or positioning issues

The system does not assume danger. Instead, it raises awareness:

“Something in this data pattern is inconsistent with normal cycling behavior.”


Limitations and Important Disclaimer

This type of system is not a medical device and should never be treated as one.

It is important to clearly state:

  • It cannot diagnose health conditions
  • It cannot determine whether a person is in danger
  • It can produce false positives due to sensor limitations
  • It may miss real issues due to data latency or missing signals

The purpose is strictly:

To provide informational context and highlight unusual patterns in training data.

Not:

To act as a crisis, emergency, or health alert system.

If anything ever feels physically wrong during exercise, the correct action is always to stop and seek appropriate attention—not rely on automation systems.


Conclusion

By combining heart rate, power data, context awareness, and trend analysis, Home Assistant can move beyond simple dashboards and into a more intelligent role: a lightweight anomaly detection layer for training data.

This does not replace wearables or health monitoring systems. Instead, it complements them by adding:

  • Local awareness
  • Custom logic
  • Flexible thresholds
  • User-defined sensitivity

In many ways, it is closer to building a “training sanity check system” than a traditional automation.

And that is where Home Assistant becomes particularly powerful: not just reacting to data, but interpreting it.


Some of the links in this article are "affiliate links", a link with a special tracking code. This means if you click on an affiliate link and purchase the item, we will receive an affiliate commission. The price of the item is the same whether it is an affiliate link or not. Regardless, we only recommend products or services we believe will add value to our readers. By using the affiliate links, you are helping support our Website, and we genuinely appreciate your support.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.