Live Training Telemetry
Use Cortex to monitor live VOLTRA training events as NDJSON for dashboards, recording, and replay.
Overview
Cortex uses voltra stream to monitor a connected VOLTRA device in real time.
The command writes newline-delimited JSON (NDJSON) to stdout: each line is one
complete event that can be processed as soon as it arrives.
Use the stream for workout dashboards, recording, replay, and custom analysis. It is a telemetry subscription. It does not control resistance or create, upload, or reconcile workout History records.
Quick start
1. Configure access
Cortex needs a persisted VOLTRA API key for device commands, including
stream. Configure it once if it is not already available:
voltra config set-api-key <VOLTRA_API_KEY>Keep the key out of shell history, logs, and analysis output.
2. Connect the device
The Cortex daemon owns the device connection. Scan and connect before starting the stream:
voltra scan --json
voltra connect <DEVICE_ID> --jsonvoltra stream does not scan or connect by itself.
3. Start the stream
voltra streamThe stream writes NDJSON records to stdout. Diagnostic messages go to stderr,
so a consumer can read stdout without mixing diagnostics into the data. Do not
add --json; the stream is already JSON, one event per line.
To save the events for replay:
voltra stream --output ./training.ndjsonThe command replaces an existing output file. Check the path first if the previous recording must be preserved. Each record is flushed as it is written; a slow disk or downstream consumer can contribute to dropped data.
When the stream closes, the realtime subscription stops and the daemon keeps
the device connected. voltra disconnect ends the device session and the
active stream. Only one stream subscriber can be active at a time.
Choose the event you need
| If you want to… | Read these events |
|---|---|
| Identify the stream and its units | streamStart |
| Show the current training state | workoutState |
| Count completed repetitions | rep where direction is pull and valid is true |
| Show progress during a set | progress |
| Show the result of one set | setSummary |
| Show workout totals | workoutSummary |
| Detect missing or interrupted data | dataQuality, connectionLost, reconnected |
| Finish a recording and inspect final counters | streamEnd |
Supported training modes
The public stream currently provides mode-specific training events for:
weightTraining, including chains, eccentric, assist, and burnout settings;resistanceBand;damper;isokinetic(constant-velocity training).
Isometric, Professional/Custom Curve, Rowing, Ski, Sled Pull, and Twin/coworker
telemetry are not part of the public event contract yet. If the device starts
in one of those modes, Cortex keeps the subscription active but waits to emit
streamStart until a supported mode is observed. A normally stopped stream
still emits streamEnd, which may be the only public event in that case.
If the user changes to an unsupported mode while streaming, mode-specific
training events are suppressed. When a supported mode is observed again,
workoutState resumes training output with the same streamId and sequence.
Example output
The stream is not a JSON array. Each physical line below is a separate event; the values are illustrative:
{"event":"streamStart","schema":"voltra.training.v7","timestamp":"2026-09-07T10:00:00.000Z","sequence":1,"streamId":"550e8400-e29b-41d4-a716-446655440000","deviceId":"AA:BB:CC:DD:EE:FF","connectionId":1,"trainingMode":"weightTraining","units":{"weight":"lbs","distance":"mm","velocity":"mm/s","power":"W"}}
{"event":"workoutState","schema":"voltra.training.v7","timestamp":"2026-09-07T10:00:00.120Z","sequence":2,"streamId":"550e8400-e29b-41d4-a716-446655440000","deviceId":"AA:BB:CC:DD:EE:FF","connectionId":1,"trainingMode":"weightTraining","workoutState":"workout","powerEnabled":true,"baseWeight":40}
{"event":"rep","schema":"voltra.training.v7","timestamp":"2026-09-07T10:00:01.100Z","sequence":2,"streamId":"550e8400-e29b-41d4-a716-446655440000","deviceId":"AA:BB:CC:DD:EE:FF","connectionId":1,"setIndex":0,"repIndex":1,"direction":"pull","valid":true,"distanceMm":480,"peakVelocityMmPerSecond":1230,"peakPowerWatt":612,"volume":40,"durationMs":900}
{"event":"progress","schema":"voltra.training.v7","timestamp":"2026-09-07T10:00:01.200Z","sequence":3,"streamId":"550e8400-e29b-41d4-a716-446655440000","deviceId":"AA:BB:CC:DD:EE:FF","connectionId":1,"setIndex":0,"repIndex":1,"volume":40,"pullDistanceMm":480,"elapsedMs":1200}
{"event":"streamEnd","schema":"voltra.training.v7","timestamp":"2026-09-07T10:05:00.000Z","sequence":4,"streamId":"550e8400-e29b-41d4-a716-446655440000","deviceId":"AA:BB:CC:DD:EE:FF","connectionId":1,"reason":"stopped","complete":true,"droppedEvents":0,"decodeErrors":0}Optional fields are omitted when the device does not provide them. A real stream can contain more events between the lines shown here, and an event can arrive before or after a related event from the other direction.
Event lifecycle
Starting
streamStart declares the first supported trainingMode and the units for the
stream. The units.weight value is lbs or kg; distance is mm, velocity is
mm/s, and power is W. The declared weight unit remains fixed for the life
of the stream, including after reconnects or device preference changes.
If the device begins in an unsupported mode, streamStart is delayed as
described above.
During training
rep, progress, setSummary, and workoutSummary are emitted when the
device reports the corresponding completed measurement or update. They are not
sampled as a uniform high-frequency stream. pullDistanceMm is cumulative pull
distance in progress and summary events.
Reconnecting
When the device connection is interrupted, Cortex emits connectionLost and,
if recovery succeeds, reconnected. A reconnect changes connectionId but
keeps the same streamId; use connectionId as a continuity boundary when
joining or analyzing records.
sequence describes output order within the stream. It is not a timestamp and
should not be used as a substitute for timestamp when measuring elapsed time.
Ending
streamEnd includes the termination reason and final quality counters.
complete: true means the subscriber stopped normally; it does not mean that
the workout was completed. complete: false means the subscription ended
abnormally and the recorded data should be treated as incomplete.
A process or machine failure can end the file without streamEnd. Treat EOF
without streamEnd as an abnormal termination.
Event fields
Common fields
Every public event contains these fields:
| Field | Meaning |
|---|---|
event | Event name, such as rep or progress. |
schema | Public schema identifier: voltra.training.v7. |
timestamp | Event time in UTC RFC 3339 format. |
sequence | Monotonic output order for this stream. |
streamId | Identifier for the subscription. |
deviceId | Identifier of the VOLTRA device. |
connectionId | Connection generation; it changes after reconnect. |
streamStart
trainingMode
units.weight lbs or kg
units.distance mm
units.velocity mm/s
units.power WworkoutState
| Field | Applies to | Meaning |
|---|---|---|
trainingMode | All supported modes | Current training mode. |
workoutState | All supported modes | Current device workout state. |
powerEnabled | All supported modes | Whether power output is enabled. |
baseWeight | weightTraining | Base load. |
chainsWeight | weightTraining | Chains load. |
eccentricWeight | weightTraining | Eccentric load. |
resistanceBandWeight | resistanceBand | Resistance-band load. |
level | damper | Damper level from 1 to 10. |
targetVelocityMmPerSecond | isokinetic | Target cable velocity. |
Mode-specific fields are omitted when they do not apply.
rep
Each physical repetition can produce two directional events with the same
setIndex and repIndex:
direction: "pull"— the pull phase;direction: "recovery"— the recovery phase.
Recovery is not a second repetition. Count only events where
direction: "pull" and valid: true. The two directions can arrive in either
order, so pair them by setIndex and repIndex when both are needed.
setIndex
repIndex one-based physical rep number
direction pull or recovery
valid
distanceMm directional distance
peakVelocityMmPerSecond
peakPowerWatt
meanPowerWatt? optional device-reported mean power
totalWorkJ? optional device-reported work
volume
durationMs
startPosMm?
finishPosMm?meanPowerWatt, when present, is the device-reported mean power for that
direction. totalWorkJ is device-reported work in joules and may be omitted
when unavailable. Do not reconstruct mean power from another field, and do not
use mechanical work alone to estimate calorie expenditure.
progress
setIndex
repIndex completed reps in the current set
volume
pullVolume? pull-direction volume when provided
pullDistanceMm cumulative pull distance
elapsedMsprogress reports cumulative workout distance rather than a continuous movement
sample.
setSummary and workoutSummary
These events contain user-facing counts, distance, volume, duration, rest time,
and nested pull and recovery metrics:
maxForce
meanForce
maxVelocityMmPerSecond
meanVelocityMmPerSecond
maxPowerWatt
meanPowerWattpullVolume is pull-direction volume. It may be omitted from setSummary when
the device does not provide it, but workoutSummary always includes it.
dataQuality, connection, and end events
dataQuality reports transport drops or decode errors. Connection events mark
recovery boundaries. streamEnd reports the termination reason, whether the
subscription stopped normally, and final droppedEvents and decodeErrors
counters.
Reliability rules
- Count only
repevents withdirection: "pull"andvalid: true. Arecoveryevent is not a second repetition, and raw high-frequency samples are not part of this stream. - Do not treat an omitted optional value as zero. Missing values are omitted from the event.
- Treat every
dataQuality,connectionLost, andreconnectedevent as a data boundary. Partition records byconnectionId; do not pair pull and recovery events across different connection IDs, and do not synthesize missing repetitions. - Use
dataQualityand the finalstreamEndcounters to report data quality. They describe the telemetry stream, not whether the workout itself was successful. - Treat
complete: false, or EOF withoutstreamEnd, as incomplete data. - This stream is device telemetry only. It does not create or upload History records.
Machine-readable schema
For integrations, use the machine-readable contract:
The schema is the source of truth for required fields, optional fields, data types, and enum values. This page explains how to consume the stream; it does not expose raw device notifications or internal protocol fields.