ConnectionState
ConnectionState = {
cause:"never-connected"|"user"|"link-lost"|"bluetooth-off"|"timeout"|"failed";error:ConsoleSdkError|null;status:"disconnected"; } | {startedAt:number;status:"connecting";step:"link"|"negotiating"|"identifying"|"clock-sync";via:ConnectVia; } | {link:"healthy"|"unresponsive";since:number;status:"ready";via:ConnectVia; } | {progress:number;since:number;status:"updating"; } | {attempt:number;lastError:ConsoleSdkError|null;nextAttemptAt:number;since:number;status:"reconnecting"; }
Defined in: console-sdk/src/device/deviceModel.ts:50
The per-device connection state machine (SDK_PLAN.md §3.4.1). Consumers
never subscribe to connection events; they read device.connection and
branch on status. Every transition — including the degraded
link: 'unresponsive' and the updating OTA hold — is data on this union.
Union Members
Section titled “Union Members”Type Literal
Section titled “Type Literal”{ cause: "never-connected" | "user" | "link-lost" | "bluetooth-off" | "timeout" | "failed"; error: ConsoleSdkError | null; status: "disconnected"; }
No live link. The single cause-carrying terminal state: cause
distinguishes a fresh device ('never-connected'), a deliberate
disconnect() ('user', which also suppresses auto-reconnect for the
session), a dropped link with exhausted reconnect attempts ('link-lost'),
a radio-off drop ('bluetooth-off'), a setup 'timeout', or a setup
'failed'. error carries the typed failure when one applies.
Type Literal
Section titled “Type Literal”{ startedAt: number; status: "connecting"; step: "link" | "negotiating" | "identifying" | "clock-sync"; via: ConnectVia; }
A connect() is in flight. step reports the setup phase (BLE link →
MTU/priority negotiation → DIS/serial identification → console clock sync);
startedAt is the establishment attempt’s start time and via its
provenance. connect() resolves only once the device reaches ready.
Type Literal
Section titled “Type Literal”{ link: "healthy" | "unresponsive"; since: number; status: "ready"; via: ConnectVia; }
Protocol session up, realtime stream available, 2 s health check running.
since is when the connection was established and via its provenance.
link: 'unresponsive' is a degraded health-check reading surfaced as
data (not a separate phase): commands remain callable and may recover the
link; UI can badge it.
Type Literal
Section titled “Type Literal”{ progress: number; since: number; status: "updating"; }
An OTA firmware transfer holds the link (fleet-visible so every screen
renders the device consistently). since is when the update began;
progress is 0–1. Workout arming rejects with command/busy while a
device is here.
Type Literal
Section titled “Type Literal”{ attempt: number; lastError: ConsoleSdkError | null; nextAttemptAt: number; since: number; status: "reconnecting"; }
The link dropped while the device was still wanted (auto-reconnect policy,
or a drop mid-workout). Treated as degraded, not gone: bounded attempts
with visible attempt/nextAttemptAt, and lastError from the previous
failed attempt. since is when reconnection began.