@elata-biosciences/eeg-web-ble
v0.1.23
Published
Web Bluetooth headband transport that emits normalized headband frames
Readme
@elata-biosciences/eeg-web-ble
Web Bluetooth transport package for EEG headbands in the browser. It emits
normalized HeadbandFrameV1 frames for the Elata EEG web stack.
New to the SDK? npm create @elata-biosciences/elata-demo my-app is the
recommended start. You can also run
npx @elata-biosciences/create-elata-demo my-app. Either path scaffolds a
working app with synthetic mode, correct Vite config, and WASM imports already
set up — no hardware required to get started.
Bluetooth vs built-in devices
Keep two ideas separate:
- Web Bluetooth + transport — Chromium
navigator.bluetooth, secure context, GATT connect/disconnect, and turning peripheral data intoHeadbandFrameV1viaBleTransport. That contract comes from@elata-biosciences/eeg-web(HeadbandTransport, frame types). It is not tied to a single vendor. - Device protocol — service UUIDs, characteristics, packet decode, and
channel maps for a specific headset. Today the repo ships Muse 2 /
Muse S (classic + Athena) under
src/devices/muse/. Other protocols belong in new modules (or a customdevicepassed intoBleTransport).
What This Package Is
This package owns:
BleTransport(src/transport/) — session lifecycle and frame assembly for Web Bluetooth (default device:MuseBleDevice)MuseBleDevice(src/devices/muse/) — Muse classic + Athena GATT handling- optional hooks for other headsets via
new BleTransport({ device }) - emission of normalized
HeadbandFrameV1frames
It intentionally depends on @elata-biosciences/eeg-web for shared transport
and frame contracts.
Source layout (maintainers)
| Path | Role |
|------|------|
| src/transport/bleTransport.ts | Web Bluetooth–oriented transport; merges EEG + Muse-shaped PPG/aux into frames |
| src/devices/muse/museDevice.ts | Muse 2 / Muse S classic and Athena protocol |
| src/index.ts | Public exports only — import from the package root, not deep paths |
Tests live under src/__tests__/.
When To Use It
Use @elata-biosciences/eeg-web-ble when you want:
- browser BLE discovery and session control for supported headsets (today: Muse 2, Muse S classic, Muse S Athena — see below)
- normalized headband frames in a browser app
- a transport layer that plugs into the rest of the Elata EEG web stack
For additional hardware (non-Muse BLE, or bridge-based flows), implement the
same transport contract and either pass a custom device into BleTransport or
contribute a new module — see
docs/contributing-eeg-transports.md.
If you only need EEG signal APIs without device transport, start with
@elata-biosciences/eeg-web.
Install
pnpm add @elata-biosciences/eeg-web-ble @elata-biosciences/eeg-web
npm install @elata-biosciences/eeg-web-ble @elata-biosciences/eeg-webRequirements
- Node.js
>= 20for build and tests - browser with Web Bluetooth support, typically Chrome or Edge
- secure context (
https://) for browser BLE access
Usage
import { BleTransport } from "@elata-biosciences/eeg-web-ble";
import {
AthenaWasmDecoder,
getEegChannelSamples,
} from "@elata-biosciences/eeg-web";
const transport = new BleTransport({
deviceOptions: {
athenaDecoderFactory: () => new AthenaWasmDecoder()
},
// Set eegProcessing: false if you want raw transport data in frame.eeg.
});
transport.onFrame = (frame) => {
console.log(getEegChannelSamples(frame, 0).length, frame.eegRaw?.samples.length);
};
transport.onStatus = (status) => {
console.log(status.state, status.reason);
};
await transport.connect();
await transport.start();By default, frame.eeg carries processed EEG and frame.eegRaw preserves the
original transport samples. Pass eegProcessing: false if you want
frame.eeg to remain raw.
EEG Signal Contract
BleTransport now applies the SDK EEG preprocessing pipeline automatically by
default. That keeps the transport aligned with the same Rust/WASM DSP used by
the rest of the repo instead of forcing each app or demo to maintain its own
notch, detrend, and rereference logic.
Default transport behavior:
frame.eegcontains processed EEGframe.eegRawpreserves the original decoded transport rowsframe.eegProcessingdescribes what was applied
Default processing stages:
- notch filtering at
60 Hzand120 Hz - detrending via
0.5 Hzhigh-pass cleanup - common-average rereferencing
If you want raw transport samples as the primary signal, disable processing:
const transport = new BleTransport({
eegProcessing: false,
});If you want processing but need to tune it, pass options through to the
underlying @elata-biosciences/eeg-web preprocessor:
const transport = new BleTransport({
eegProcessing: {
notch: { mainsHz: 50 },
detrend: { mode: "linear" },
reference: { mode: "custom-average", channels: ["TP9", "TP10"] },
},
});Signal-selection helpers such as getEegChannelSamples(frame, 0, "raw") come
from @elata-biosciences/eeg-web.
Key Exports
BleTransportBleDeviceLike(adapter contract for custom headset integrations)MuseBleDevice(reference implementation and default device)HeadbandTransporttypes (re-exported usage flows align with@elata-biosciences/eeg-web)
Built-In Device Support
These device classes are implemented in this package today:
- Muse 2 and Muse S classic BLE (documented UUIDs and framing)
- Muse S Athena protocol v2 (requires
athenaDecoderFactoryfromeeg-web) - the synthetic Muse-compatible BLE bridge used for testing
Other headsets can be integrated by contributors; see docs/contributing-eeg-transports.md.
Platform Caveats
- Safari and iOS do not provide usable Web Bluetooth support for this workflow
- Muse firmware variants may differ in command behavior
For Safari and iOS, prefer a native BLE shell, a companion bridge, or a hybrid
WebView strategy with @elata-biosciences/eeg-web frame contracts as the
boundary.
Build And Dev Notes
From the repo root:
pnpm --dir packages/eeg-web-ble test
pnpm --dir packages/eeg-web-ble buildIf you are working across repo workflows, prefer starting with:
./run.sh testTroubleshooting
- If
navigator.bluetoothis missing, use a supported Chromium-based browser and a secure context. - If device selection never appears, confirm the site is running on
https://orlocalhostand that Bluetooth is enabled on the machine. - If you are targeting Safari or iOS, this package is not the right browser-side transport; use a native or bridge strategy instead.
- If Athena startup fails, verify that you passed an
athenaDecoderFactorybacked by@elata-biosciences/eeg-web. - If your analysis expects raw EEG, explicitly set
eegProcessing: falseor read fromframe.eegRaw.
Release Notes
@elata-biosciences/eeg-web-ble depends on @elata-biosciences/eeg-web and
should be released after it when compatibility changes. Full release flow:
docs/releasing.md.
Roadmap
- Safari and iOS BLE bridge plan: docs/implementation-plan-ios-safari-ble-bridge.md
