Skip to main content

When To Use This Package

Use @elata-biosciences/eeg-web-ble when your app needs:
  • browser-side discovery of Muse-compatible devices
  • live EEG streaming over Web Bluetooth
  • normalized headband frames for app logic or downstream analysis
Install it alongside @elata-biosciences/eeg-web.

Installation

pnpm add @elata-biosciences/eeg-web-ble @elata-biosciences/eeg-web
eeg-web-ble depends on eeg-web for shared frame types and the WASM module.

Requirements

  • Browser with Web Bluetooth support (Chrome/Edge on desktop or Android)
  • Served from a secure context (https:// or localhost)
  • Safari/iOS does not support Web Bluetooth. See platform notes for alternatives

Basic Usage

startStreaming() is the recommended default. It wraps connect() and start() together and avoids the common mistake of connecting successfully but never beginning to stream.
import { initEegWasm, AthenaWasmDecoder } from "@elata-biosciences/eeg-web";
import { BleTransport } from "@elata-biosciences/eeg-web-ble";

// Initialize WASM first
await initEegWasm();

// Create transport
const transport = new BleTransport({
  deviceOptions: {
    athenaDecoderFactory: () => new AthenaWasmDecoder(),
  },
});

// Handle incoming EEG frames
transport.onFrame = (frame) => {
  console.log(`EEG samples: ${frame.eeg.samples.length} rows`);
  console.log(`Channels: ${frame.eeg.channelNames.join(", ")}`);
};

// Handle connection status changes
transport.onStatus = (status) => {
  console.log(`Transport: ${status.state}`, status.reason || "");
};

// Connect and start streaming (triggers Bluetooth device picker)
await transport.startStreaming();

// ... later
await transport.stop();

BleTransport Lifecycle

MethodWhat it does
startStreaming()Recommended: connects and starts the stream in one call
connect()Opens Bluetooth device picker, pairs, and prepares session
start()Begins EEG data stream; onFrame callbacks fire
stop()Stops the data stream; connection stays open
disconnect()Releases the Bluetooth session

BleTransportOptions

const transport = new BleTransport({
  sourceName: "my-app-ble",           // name tag in frame.source
  deviceOptions: {
    athenaDecoderFactory: () => new AthenaWasmDecoder(),  // for Athena headbands
    logger: (msg) => console.debug(msg),
    onDisconnected: () => console.warn("Device disconnected"),
  },
});
OptionTypeDescription
sourceNamestringIdentifier included in HeadbandFrameV1.source
deviceOptionsMuseDeviceOptionsPassed to underlying MuseBleDevice
deviceBleDeviceLikeInject a custom device implementation

Athena Support

Muse S headbands with Athena firmware require an Athena decoder factory. Include it up front to keep both classic and Athena flows covered:
import { AthenaWasmDecoder } from "@elata-biosciences/eeg-web";
import { BleTransport } from "@elata-biosciences/eeg-web-ble";

const transport = new BleTransport({
  deviceOptions: {
    athenaDecoderFactory: () => new AthenaWasmDecoder(),
  },
});
Athena headbands provide 8 EEG channels, optics, accelerometer/gyroscope, and battery data in each frame.

Device Info

After connecting, you can query device metadata:
await transport.connect();

const isAthena = transport.getIsAthena();
const boardInfo = transport.getBoardInfo();
const channelNames = transport.getEegNames();

Platform Caveats

  • Safari and iOS do not provide usable Web Bluetooth support for this workflow.
  • For Safari and iOS, use a native BLE shell, companion bridge, or hybrid WebView strategy with @elata-biosciences/eeg-web frame contracts as the boundary.
  • Firmware variants may differ in command behavior.

Next

Live Stream Tutorial

Step-by-step BLE streaming guide

Muse Device Details

Protocol details, characteristics, and compatibility

EEG + BLE Integration

End-to-end streaming and processing guide