Quick start
Get up and running with SiFi Bridge Python in just a few minutes. This guide covers the essential steps to connect to a device and start acquiring data.
Basic workflow
Working with SiFi Bridge Python follows this pattern:
- Create a
SifiBridgeinstance - Connect to a device
- Configure sensors
- Start data acquisition
- Read data packets
- Stop and disconnect
Your first connection
Here's a minimal example to connect and stream ECG data:
import time
import sifi_bridge_py as sbp
# Create bridge instance
sb = sbp.SifiBridge()
# Connect to the first available SiFi device (BioPoint or SiFi Band)
sb.connect()
# Sensors are off by default. Turn the ECG sensor on, then set its
# filter parameters (500 Hz sampling rate).
sb.configure_sensors(ecg=True)
sb.configure_ecg(fs=500)
# Start acquisition
sb.start()
# Collect for 10 seconds
start_time = time.time()
data_buffer = []
try:
while time.time() - start_time < 10:
packet = sb.get_data() # Get any packet
data_buffer.append(packet)
print(f"Received {packet['packet_type']} packet")
except KeyboardInterrupt:
print("Stopped by user")
finally:
sb.stop()
sb.disconnect()
print(f"Collected {len(data_buffer)} packets")
Understanding data packets
Sensor data has the exact same structure as SiFi Bridge's, deserialized as a dictionary:
{
'device': 'BioPoint', # Device model
'id': 'BP_EF05', # Device identifier
'name': 'BioPoint_EF05', # BLE local name
'mac': 'FA:31:9F:7E:6A:A9', # Device MAC address (UUID on macOS)
'packet_type': 'ecg', # Type of data (ecg, emg, imu, ppg, etc.)
'status': 'ok', # Packet status
'received_at': 1790040045.074, # Packet arrival time (Unix epoch seconds)
'sample_rate': 500.25, # Measured sample rate of this sensor (Hz)
'timestamps': [0.198, 0.2, ...], # Per-sample times relative to acquisition start (s)
'data': {
'ecg': [0.001, 0.002, ...] # Sensor data arrays, one entry per timestamp
}
}
sample_rate is absent from the first packetIt is measured from inter-packet timing, so the first packet of each
sensor arrives without it. Read it with packet.get("sample_rate").
Connect to a specific device
connect() accepts either the device's name or its MAC address
(Linux/Windows) / UUID (macOS):
import sifi_bridge_py as sbp
sb = sbp.SifiBridge()
# Scan. Each result carries the device's name and its id (MAC on
# Windows/Linux, UUID on macOS).
devices = sb.list_devices(sbp.ListSources.BLE)
print(f"Found devices: {devices}")
# [{'name': 'BioPoint_EF05', 'id': 'FA:31:9F:7E:6A:A9'}]
if not devices:
raise SystemExit("No SiFi device found — is it powered on and in range?")
# Connect to the first one found, by name...
sb.connect(devices[0]["name"])
# ...or by id, which is unambiguous when several devices share a name.
# sb.connect(devices[0]["id"])
connect() raises SifiBridgeError if the handle doesn't match a device
in range, so pass a name or id you got from the scan rather than a
hard-coded one.
Use sb.rename_device("MyBioPoint") once connected to give a device a
memorable name so you can target it by name later. The custom name should not have space and be 14 characters maximum
Configure multiple sensors
Enable and configure multiple sensors at once. configure_sensors() turns
sensors on/off; each sensor's own configure_<sensor>() call sets its
sampling rate and filter parameters:
# Enable ECG, EMG, and IMU
sb.configure_sensors(ecg=True, emg=True, imu=True)
# Set each sensor's sampling rate / filters
sb.configure_ecg(fs=500)
sb.configure_emg(fs=2000)
sb.configure_imu(fs=100)
# Start acquisition
sb.start()
# Read data from any sensor
ecg_packet = sb.get_ecg()
emg_packet = sb.get_emg()
imu_packet = sb.get_imu()
Simple data collection loop
Collect data continuously with a loop:
import sifi_bridge_py as sbp
import time
sb = sbp.SifiBridge()
sb.connect()
# Enable sensors
sb.configure_sensors(ecg=True, emg=True, imu=True)
sb.start()
# Collect for 10 seconds
start_time = time.time()
data_buffer = []
try:
while time.time() - start_time < 10:
packet = sb.get_data() # Get any packet
data_buffer.append(packet)
print(f"Received {packet['packet_type']} packet")
except KeyboardInterrupt:
print("Stopped by user")
finally:
sb.stop()
sb.disconnect()
print(f"Collected {len(data_buffer)} packets")
Using threading
Since get_data() blocks, use threading for responsive applications:
import time
import threading
import sifi_bridge_py as sbp
def data_collection_thread(sb):
"""Background thread for data collection"""
while running:
packet = sb.get_data(timeout=1.0)
if packet:
# Process packet
print(f"Got {packet['packet_type']}")
# Setup
sb = sbp.SifiBridge()
sb.connect()
sb.configure_sensors(ecg=True)
sb.start()
# Start background thread
running = True
thread = threading.Thread(target=data_collection_thread, args=(sb,))
thread.start()
# Do other work in main thread
time.sleep(30)
# Cleanup
running = False
thread.join()
sb.stop()
sb.disconnect()
Common patterns
Check connection status
info() raises SifiBridgeError if no device is currently connected,
rather than returning a "not connected" status:
try:
info = sb.info()
print(f"Connected to {info['device']}")
except sbp.SifiBridgeError:
print("Not connected")
Retry connection
import time
max_retries = 5
for attempt in range(max_retries):
if sb.connect():
print("Connected!")
break
print(f"Retry {attempt + 1}/{max_retries}")
time.sleep(2)
Wait for a packet with a timeout
By default the get_* methods block indefinitely. Pass timeout (seconds)
to give up and get {} back instead:
ecg_packet = sb.get_ecg(timeout=5.0)
if not ecg_packet:
print("No ECG packet received within 5 seconds")
Error handling
Always include error handling for robust applications:
import sifi_bridge_py as sbp
try:
sb = sbp.SifiBridge()
# Try to connect
if not sb.connect():
raise ConnectionError("Failed to connect to device")
sb.configure_sensors(ecg=True)
sb.configure_ecg(fs=500)
sb.start()
# Collect data
for _ in range(100):
packet = sb.get_ecg()
# Process packet...
except ConnectionError as e:
# Also raised by connect() itself if Bluetooth is off
print(f"Connection error: {e}")
except KeyboardInterrupt:
print("Interrupted by user")
finally:
# Always cleanup. stop()/disconnect() block until the device
# confirms, so no extra sleep is needed here.
try:
sb.stop()
sb.disconnect()
except Exception:
pass
Quick reference
# Import
import time
import sifi_bridge_py as sbp
# Create bridge
sb = sbp.SifiBridge()
try:
# Connection
sb.connect() # Connect to the first available device
sb.connect("MAC_OR_UUID") # Connect to a specific device by address
sb.disconnect() # Disconnect
# Configuration
sb.configure_sensors(ecg=True, emg=True) # Enable sensors (off by default)
sb.configure_ecg(fs=500, dc_notch=True, mains_notch=50, bandpass=True, flo=0, fhi=30) # Set ECG sampling rate / filters
sb.configure_emg(fs=2000, dc_notch=True, mains_notch=50, bandpass=True, flo=20, fhi=450) # Set EMG sampling rate / filters
sb.set_low_latency_mode(True) # Toggle low-latency mode (on by default, tradeoff between latency and bandwidth use)
# Control
sb.start() # Start acquisition
sb.stop() # Stop acquisition
# Data
packet = sb.get_data() # Get the next packet of any type
ecg = sb.get_ecg() # Get the next ECG packet
emg = sb.get_emg() # Get the next EMG packet
imu = sb.get_imu() # Get the next IMU packet
# Device commands
sb.set_led(1, True) # Turn LED 1 on
sb.set_motor(True) # Start the vibration motor
time.sleep(1)
sb.set_motor_intensity(10) # Set vibration motor intensity to 10
time.sleep(1)
sb.set_motor_intensity(5) # Set vibration motor intensity to 5
time.sleep(1)
sb.set_motor(False) # Stop the vibration motor
sb.set_led(1, False) # Turn LED 1 off
finally:
sb.stop()
sb.disconnect()