Skip to main content

signalino

Native Python API for Signalino EEG devices. It connects directly over USB, Bluetooth Classic or Bluetooth LE and decodes the Signalino S4CP control protocol and stable 33-byte OpenBCI-compatible EEG frames.

This package does not depend on BrainFlow. Applications that specifically need the BrainFlow API can install the separate brainflow-signalino integration.

Signalino is research software. It is not a medical device and must not be used for diagnosis or patient monitoring.

New in 0.2.1

Linux can now discover paired HC-06/Signalino devices and connect directly over Bluetooth Classic, without creating /dev/rfcomm0 or running Signalino Suite. This also works with Conda Python builds that lack Bluetooth socket address support, using the system Python for connection setup. Existing macOS, USB and BLE paths are preserved. Pair the HC-06 first and close other clients.

Upgrade with python -m pip install --upgrade signalino. See CHANGELOG.md for release details.

Installation

python -m pip install signalino

Python 3.10 or newer is supported on macOS, Linux and Windows. Optional integrations are installed separately:

python -m pip install "signalino[lsl]"
python -m pip install "signalino[mne]"
python -m pip install "signalino[viewer]"

USB

import time

from signalino import Signalino

with Signalino.usb() as device:
    print(device.info.name, device.info.hardware)
    device.start_streaming()
    time.sleep(2)
    eeg_uv = device.get_data()

print(eeg_uv.shape)  # (8, approximately 500)

Signalino.usb() chooses the most probable port. Select it explicitly when several boards are connected:

device = Signalino.usb("/dev/cu.usbmodem1101")  # macOS
device = Signalino.usb("/dev/ttyACM0")  # Linux
device = Signalino.usb("COM3")  # Windows

Bluetooth Classic

Pair the HC-06 (or equivalent serial Bluetooth module) with the computer first:

with Signalino.bluetooth_classic() as device:
    device.start_streaming()

The package finds likely paired serial ports automatically. An explicit port can also be passed to Signalino.bluetooth_classic(port).

On macOS, Classic Bluetooth uses the native RFCOMM helper installed with Signalino Suite. Its location can instead be supplied through the SIGNALINO_CLASSIC_CONNECT environment variable. Linux normally exposes /dev/rfcomm0; Windows exposes a paired COM port.

Bluetooth LE

with Signalino.ble("Signalino-852960") as device:
    device.start_streaming()

Use Signalino.ble() when only one Signalino is advertising. With several units in the room, select one by advertised name or address:

Signalino.ble(name="Signalino-852960")
Signalino.ble(address="AA:BB:CC:12:34:56")

Data and losses

get_data() returns microvolts as a NumPy array shaped (channels, samples). It consumes the oldest samples by default. Use clear=False to inspect without consuming:

latest = device.get_data(250, clear=False)
batch = device.get_data_batch()
print(batch.samples_uv, batch.timestamps)

print(device.stats.received_samples)
print(device.stats.lost_samples)
print(device.stats.loss_percent)

The package validates frame headers and footers, recovers alignment after corrupt input, and uses the 8-bit sample counter to detect losses and duplicates. Buffers are bounded and LSL does not consume data requested by get_data().

Battery, impedance and sensors

battery = device.battery()
print(battery.volts, battery.percent, battery.charging)

impedance = device.impedance()
print(impedance.kiloohms)

auxiliary = device.get_auxiliary_data()
print(auxiliary.raw_values, auxiliary.packet_types)

Normal EEG acquisition pauses while impedances are measured and resumes automatically afterward. USB and Bluetooth Classic share control and binary data on one serial channel, so battery queries on those transports also require streaming to be stopped. BLE has separate control and EEG characteristics.

Hardware, firmware, available sensors and capabilities are reported by the physical unit through device.info; they are not inferred from a board number.

S4CP control

High-level operations use S4CP internally. Documented low-level commands remain available for diagnostics:

print(device.command("STS;"))
device.command("SRC1;SMP250;GAN24;")

Control replies are compact strings such as STS SRC=1 REC=0 SMP=250 ...;. The EEG data plane remains the 33-byte OpenBCI-compatible frame.

LSL

device.start_streaming()
stream = device.start_lsl()
print(stream.name, stream.source_id)

The LSL outlet contains eight float32 EEG channels in microvolts and closes automatically when acquisition stops.

MNE

raw = device.to_mne(clear=False)
print(raw.info["sfreq"])

MNE stores EEG in volts; conversion from Signalino microvolts is automatic.

Examples

The examples/ directory contains minimal USB, BLE and Bluetooth Classic programs, an LSL publisher, impedance acquisition, MNE conversion, a rolling viewer, and a Classic Bluetooth loss measurement.

For local development:

python -m pip install -e ".[dev,all]"
ruff check .
ruff format --check .
pytest --cov=signalino
python -m build
twine check dist/*

License

MIT. Copyright Scignals 2026.

Linux Bluetooth Classic without a serial port

On Linux, Signalino.bluetooth_classic() now falls back to paired BlueZ devices when no serial port exists. It opens RFCOMM channel 1 directly; /dev/rfcomm0, root privileges and a running Suite are not required. Pair the HC-06 in Linux Bluetooth settings first and close other clients before connecting.

with Signalino.bluetooth_classic(address="98:D3:91:FD:3D:CE") as device:
    device.start_streaming()

Omit address for automatic selection, or pass a serial port as before. Multiple candidates require an explicit address. Linux needs bluetoothctl; Conda builds without Bluetooth socket address support also use /usr/bin/python3 briefly to open the socket and pass its descriptor. Acquisition remains in the calling Python process. Other platforms keep their existing serial/bridge behavior.

Release files for signalino 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for signalino 0.2.1
File Size Uploaded
signalino-0.2.1.tar.gz 38.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for signalino 0.2.1
File Interpreter ABI Platform
signalino-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size:65.7 kB

Release files / signalino-0.2.1.tar.gz

Download URL signalino-0.2.1.tar.gz
Size 38.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9e0a5370ae67ff374c340ff133f066881541425ec088a72444f1221d2cb67631
BLAKE2b-256 checksum
How to use checksums
db95c358cbe014a96b03f722d576d5b7b4e90ed89583d27c4878af3595384d56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.8

Release files / signalino-0.2.1-py3-none-any.whl

Download URL signalino-0.2.1-py3-none-any.whl
Size 27.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
035a4ff05c567560a7ae4e32ad3b280d69b750b421883a6f1f70aef82a69f874
BLAKE2b-256 checksum
How to use checksums
59774de5a949c0d638103325865862134cb71d315d86d446e1581415f82f34a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.8

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page