DeviceSession
One connected device. Owns a supervised CoroutineScope cancelled on disconnect; the handshake awaits suspend acks from the GattConnection instead of polling a shared event log with magic delays (the legacy design). Fallible ops return Result.
Created by BrainAccessClient; not constructed directly.
Properties
Per-active-channel electrode contact from the latest chunk; false = not connected.
Hardware generation, resolved during initialize from the Device Information Service Model Number (the C core's ba_device_model); until then, and whenever the string is missing or names a different montage than the advertised name, the V2 board of model. Decides which IMU blocks the stream footer carries and how EegChunk.accel is scaled — a HALO V3 has an accelerometer and gyroscope, a HALO V2 has neither.
Device Information Service strings; populated once during initialize.
Cumulative device-side samples lost over the air (gap-filled), this session.
Whether this device exposes the vendor firmware-update service (see updateFirmware).
Whether this device can stream OutputMode.TEST_SIGNAL: firmware 3.7.0+ exposes the output-mode characteristic, older firmware does not (see stream).
Functions
Apply a new configuration (writes the config blob and restarts sample indexing). Fails with BrainAccessError.ConfigRejected when the device refuses the blob; the previous config then stays current.
The config currently applied to the device.
Stop streaming, unsubscribe, disconnect, and cancel this session's scope.
Bring the device to DeviceState.Ready: discover, raise MTU, read+subscribe battery, subscribe stream data, and write the stored (or default) config.
Cold stream of decoded chunks. On collection it starts the device stream (control 0x01) and decodes each notification into one EegChunk; on completion it stops the stream (control 0x00, best-effort). Notifications are buffered UNBOUNDED between the BLE callback and the decoder: the transport's callback bridge (Nordic callbackFlow) would otherwise silently discard packets once its default 64-slot buffer fills behind a transiently slow collector — a drop the decoder then gap-fills and misattributes to missedSamples as device-side loss. A backlog here costs memory (~500 B/packet), never data; only a consumer that is sustainedly slower than real time can grow it. Each chunk also carries per-active-channel EegChunk.contact; device-side losses (gap-filled samples) accumulate into missedSamples.
Flash firmware onto the device (vendor OTA service; see OtaControl for the wire contract). Cold flow: collection performs the update and reports OtaProgress; the terminal emission is OtaProgress.Done, after which the device applies the image and typically reboots — expect the session to go DeviceState.Disconnected. On any failure (NAK, timeout, link drop) the device keeps its previous firmware.