Skip to main content
Version: 1.3

API reference

Complete API reference for the SiFi Bridge Python package (sifi_bridge_py) 1.3.0, which pairs with the SiFi Bridge CLI 1.3.

You are reading the 1.3 documentation

SiFi Bridge 2.0 reworked this API substantially — sensors are enabled differently, filters take explicit cutoffs, send_command() was replaced by individual methods, and the packet field timestamp became received_at. If you are on 2.0 or later, see the current API reference.

Version pairing​

sifi_bridge_py downloads a matching CLI binary on first use: it picks the newest SiFi Bridge release whose major and minor version match the Python package. So sifi_bridge_py 1.3.0 runs the CLI 1.3 — 1.3.4 at the time of writing. No separate install is needed, but the machine needs network access the first time.

SifiBridge class​

Constructor​

SifiBridge(publishers=None, use_lsl=False)

Create a SiFi Bridge instance, launching the sifibridge CLI as a subprocess.

Parameters:

  • publishers (str | Iterable[str] | None): Additional data output destinations, passed through to the CLI's output flags.
    • "tcp://ip:port" — send packets to a TCP port (--tcp-out)
    • "udp://ip:port" — send packets to a UDP port (--udp-out)
    • "csv://dir" — write packets to CSV files in a directory (--csv-out)
  • use_lsl (bool): If True, also publish the data stream to Lab Streaming Layer (--lsl).
A csv:// directory must already exist

The CLI panics and exits if the --csv-out directory is missing, which takes the subprocess down with it — the next call then fails on a closed pipe, typically surfacing as OSError: [Errno 22] Invalid argument from inside connect(). Create the directory before constructing SifiBridge:

import os
os.makedirs("./data", exist_ok=True)
sb = sbp.SifiBridge(publishers="csv://./data/")

Example:

import sifi_bridge_py as sbp

sb = sbp.SifiBridge()
sb = sbp.SifiBridge(publishers="tcp://127.0.0.1:9001")
sb = sbp.SifiBridge(publishers=["tcp://127.0.0.1:9001", "csv://./data"])
sb = sbp.SifiBridge(use_lsl=True)

Device managers​

1.3 organises work around device managers: named slots, each handling one device. The CLI creates a default manager called default-1 at startup (its own help text says device-1, but default-1 is what it actually creates). Commands apply to the active manager only.

This model is gone in 2.0

2.0 replaced managers with real sessions keyed by the device's BLE id — connect() creates the session and create_device()/delete_device() no longer exist.

create_device()​

create_device(name, select=True)

Create a device manager, optionally selecting it.

Parameters:

  • name (str): Manager name. Must not contain spaces.
  • select (bool): Select it after creation.

Raises: ValueError if name contains spaces.

delete_device()​

delete_device(name)

Delete a device manager. If it was active, another becomes active. The last remaining manager cannot be deleted.

select_device()​

select_device(name)

Select which manager subsequent commands apply to.


Connection methods​

connect()​

connect(handle=None) -> bool

Connect to a device over BLE.

Parameters:

  • handle (DeviceType | str | None): BLE device name (e.g. "BioArmband"), MAC address (Windows/Linux), or UUID (macOS). None auto-connects to the first device found.

Returns: True on success.

Do not pass a DeviceType

The signature accepts DeviceType | str | None, but passing a DeviceType does not work: connect() matches the handle against the device's advertised BLE name, and a device type value such as "BioPoint_v1_3" is not that name — a BioPoint advertising as BioPoint_EF05 will not match. The call returns False rather than raising, so the failure is silent and the next blocking read hangs forever.

sb.connect(sbp.DeviceType.BIOPOINT_V1_3)   # -> False, never connects
sb.connect() # -> True, first device found
sb.connect("BioPoint_EF05") # -> True, by BLE name
sb.connect("FA:31:9F:7E:6A:A9") # -> True, by MAC

Always check the return value.

No timeout parameter

connect() in 1.3 takes no timeout. It was added in 2.0.

disconnect()​

disconnect()

Disconnect from the current device.

list_devices()​

list_devices(source) -> list[dict]

List devices from a given source.

Parameters:

  • source (ListSources | str): BLE, SERIAL, or DEVICES.

Returns: a list of dicts with name and id keys, e.g. [{'name': 'BioPoint_EF', 'id': 'FA:31:9F:7E:6A:A9'}]. Note the package annotates this as list[str], but it returns dicts.

Example:

for dev in sb.list_devices(sbp.ListSources.BLE):
print(dev["name"], dev["id"])

show()​

show()

Return information about the current device, including its configuration.

Renamed in 2.0

This method is called info() from 2.0 onwards.


Configuration methods​

set_channels()​

set_channels(ecg=False, emg=False, eda=False, imu=False, ppg=False)

Select which biochannels are enabled. Every parameter defaults to False, so this call states the complete set: any channel you do not pass as True is disabled.

Example:

# ECG and IMU on, everything else off.
sb.set_channels(ecg=True, imu=True)
Renamed and re-specified in 2.0

2.0 calls this configure_sensors(), and there omitted parameters keep their current state instead of being disabled.

configure_ecg()​

configure_ecg(bandpass_freqs=(0, 30))

Configure the ECG bandpass filter. Also enables on-board filtering, as if set_filters(True) had been called.

Parameters:

  • bandpass_freqs (tuple): (low, high) cutoff frequencies in Hz.

Example:

sb.configure_ecg(bandpass_freqs=(0, 30))

configure_emg()​

configure_emg(bandpass_freqs=(20, 450), notch_freq=50)

Configure the EMG filters. Also enables on-board filtering.

Parameters:

  • bandpass_freqs (tuple): (low, high) cutoff frequencies in Hz.
  • notch_freq (int | None): Mains notch frequency — 50 or 60. None, or any other value, disables it.

configure_eda()​

configure_eda(bandpass_freqs=(0, 5), signal_freq=0)

Configure the EDA filters and excitation frequency. Also enables on-board filtering.

Parameters:

  • bandpass_freqs (tuple): (low, high) cutoff frequencies in Hz.
  • signal_freq (int): Excitation signal frequency in Hz. 0 for DC.

configure_ppg()​

configure_ppg(ir=9, red=9, green=9, blue=9, sens=PpgSensitivity.MEDIUM)

Configure PPG LED currents and photodiode sensitivity. Also enables on-board filtering.

Parameters:

  • ir, red, green, blue (int): LED drive current in mA (1–50).
  • sens (PpgSensitivity | str): LOW, MEDIUM, HIGH, or MAX.
There is no configure_imu() in 1.3

The IMU is enabled with set_channels(imu=True) and has no per-sensor configuration method. configure_imu() arrives in 2.0.

configure_sampling_freqs()​

configure_sampling_freqs(ecg=500, emg=2000, eda=40, imu=50, ppg=50)
This method has no effect in 1.3

The package's own docstring marks it "Currently unused". It accepts the values and returns a configuration response, but the device keeps its default sampling rates. Per-sensor sampling rates only became settable in 2.0, via the fs parameter of each configure_* method.

set_filters()​

set_filters(enable)

Enable or disable on-board filtering for all biochannels. Note the configure_ecg/emg/eda/ppg methods already enable it.

Renamed in 2.0

Called set_onboard_filtering() from 2.0 onwards.

set_memory_mode()​

set_memory_mode(memory_config)

Parameters:

  • memory_config (MemoryMode | str): STREAMING, DEVICE, or BOTH.

set_low_latency_mode()​

set_low_latency_mode(on)

set_ble_power()​

set_ble_power(power)

Parameters:

  • power (BleTxPower | str): LOW, MEDIUM, or HIGH.

Acquisition and data​

start() / stop()​

start() -> bool
stop() -> bool

Start and stop acquisition.

get_data()​

get_data() -> dict

Wait for the next packet. Blocking — 1.3 has no timeout parameter, so this call waits indefinitely if no packet arrives. The timeout parameter was added in 2.0.

get_data_with_key()​

get_data_with_key(keys) -> dict

Block until a packet containing the given key, or nested path of keys, arrives.

Parameters:

  • keys (str | Iterable[str]): A key, or a sequence describing a nested path.

Example:

packet = sb.get_data_with_key("ecg")
packet = sb.get_data_with_key(["data", "ecg"])
Removed in 2.0

Use get_data() or the per-sensor getters instead.

get_ecg() / get_emg() / get_eda() / get_imu() / get_ppg() / get_temperature()​

get_ecg()

Return the next packet for one specific sensor. None of these take a timeout in 1.3.


Device commands​

send_command()​

send_command(command) -> bool

Send a command to the active device. This one method covers everything that 2.0 splits into individual methods (set_led(), set_motor(), power_off(), and so on).

Parameters:

  • command (DeviceCommand | str): The command to send.

Example:

sb.send_command(sbp.DeviceCommand.OPEN_LED_1)
sb.send_command(sbp.DeviceCommand.START_MOTOR)
sb.send_command(sbp.DeviceCommand.POWER_OFF)

start_memory_download()​

start_memory_download() -> int

Begin downloading the device's on-board memory.

Returns: the number of kilobytes to download.

Raises: ConnectionError if not connected; TypeError if the device does not support memory download.

Depending on the output transport you either keep calling get_data() (stdout, the default) or wait for a memory packet whose status is MemoryDownloadCompleted.

Example:

kb = sb.start_memory_download()
print(f"Downloading {kb} kB...")
while True:
packet = sb.get_data()
if packet.get("packet_type") == "memory" and \
packet.get("status") == "MemoryDownloadCompleted":
break
Replaced in 2.0

2.0 provides download_memory_ble() / download_memory_serial(), which block until the download finishes and export the data for you.


Enumerations​

DeviceCommand​

Commands accepted by send_command().

class DeviceCommand(Enum):
START_ACQUISITION = "start-acquisition"
STOP_ACQUISITION = "stop-acquisition"
SET_BLE_POWER = "set-ble-power"
SET_ONBOARD_FILTERING = "set-filtering"
ERASE_ONBOARD_MEMORY = "erase-memory"
DOWNLOAD_ONBOARD_MEMORY = "download-memory"
START_STATUS_UPDATE = "start-status-update"
STOP_STATUS_UPDATE = "stop-status-update"
OPEN_LED_1 = "open-led1"
OPEN_LED_2 = "open-led2"
CLOSE_LED_1 = "close-led1"
CLOSE_LED_2 = "close-led2"
START_MOTOR = "start-motor"
STOP_MOTOR = "stop-motor"
POWER_OFF = "power-off"
POWER_DEEP_SLEEP = "deep-sleep"
SET_PPG_CURRENTS = "set-ppg-currents"
SET_PPG_SENSITIVITY = "set-ppg-sensitivity"
SET_EMG_MAINS_NOTCH = "set-emg-mains-notch"
SET_EDA_FREQUENCY = "set-eda-freq"
SET_EDA_GAIN = "set-eda-gain"
DOWNLOAD_MEMORY_SERIAL = "download-memory-serial"

The CLI additionally accepts test-memory and invalid, which this enum does not model. Some commands are firmware-gated: set-eda-freq and set-eda-gain need firmware 1.1+, stop-status-update needs 1.3+, and download-memory-serial is firmware 1.2 only and unused.

DeviceType​

class DeviceType(Enum):
BIOPOINT_V1_1 = "BioPoint_v1_1"
BIOPOINT_V1_2 = "BioPoint_v1_2"
BIOPOINT_V1_3 = "BioPoint_v1_3"
BIOARMBAND = "BioArmband"
SIFIBAND = "SiFiBand"

BleTxPower​

class BleTxPower(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"

MemoryMode​

class MemoryMode(Enum):
STREAMING = "streaming" # Stream via BLE only
DEVICE = "device" # Save to device memory only
BOTH = "both" # Stream and save

PpgSensitivity​

class PpgSensitivity(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
MAX = "max"

ListSources​

class ListSources(Enum):
BLE = "ble" # Bluetooth devices
SERIAL = "serial" # Serial / USB devices
DEVICES = "devices" # Device managers
Enums that do not exist in 1.3

sifi_bridge_py 1.3.0 exports only the six enums above. PacketType, PacketStatus, SensorChannel, BioChannel and DataPacket were all introduced in 2.0 — in 1.3, packet fields are plain strings.