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)
| File | Size | Uploaded | |
|---|---|---|---|
| signalino-0.2.1.tar.gz | 38.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|