Skip to main content

Transports

SiFi Bridge communicates over two independent channels, and each can run over a different transport:

  • The control channel carries commands in and responses out — the request/response model you use in the REPL. This is a pull interface: you send a command, you get one JSON response back.
  • The data channel carries the asynchronous DataPacket stream out — the live samples as they arrive from the device.

Choosing transports lets you, for example, drive SiFi Bridge programmatically from another machine while fanning the data stream out to a separate processing host.

Two channels, two directions

The control channel is bidirectional and synchronous (command → response). The data channel is outbound and asynchronous (a continuous stream). buffer pull rides the control channel — it is a command with a response — even though it returns sample data. The live stream rides the data channel.

Control channel (commands & responses)​

Every command — connect, start, buffer pull, … — is sent on the control channel and answered with a single JSON response on the same channel. This is the REPL model.

stdin / stdout (default)​

By default SiFi Bridge reads commands from stdin (one command per line) and writes responses to stdout. This is what you get when you launch sifibridge and type at the > prompt, and it is also the simplest way to drive it from a parent process via pipes.

TCP (--tcp-in)​

sifibridge --tcp-in 127.0.0.1:5000

Binds a TCP listener so commands are sent over a socket — useful for remote control or driving SiFi Bridge from another process/host without managing a child process's stdin. When --tcp-in is set it replaces stdin: commands are no longer read from stdin, and each command's response is sent back on the same socket.

You must provide the host:port to bind — there is no default.

Data channel (the DataPacket stream)​

The live stream can be sent to several outputs at once — e.g. --tcp-out and --lsl together — so you can deliver data to multiple consumers simultaneously. The --tcp-out and --udp-out transports each require an explicit host:port (there are no default ports); --lsl takes no address, since LSL handles discovery itself.

stdout (default)​

DataPackets are emitted to stdout (i.e., terminal output) as JSON. In the default stdin/stdout REPL they are interleaved with command responses on the same stream; with --tcp-in responses go to the socket instead, so stdout then carries only data packets.

Disable the stdout data stream with --no-stdout-data. This is useful when you route the stream elsewhere (--tcp-out/--udp-out/--lsl) and want stdout kept clean, or when you work exclusively through the buffering service — making SiFi Bridge effectively a pure REPL:

sifibridge --no-stdout-data
Clean REPL + separate data stream

Combine --no-stdout-data with a data transport to get the best of both: a clean stdin/stdout REPL for commands and responses, with the DataPacket stream routed somewhere else. For example, keep typing commands at the prompt while a separate consumer reads the stream over TCP:

sifibridge --no-stdout-data --tcp-out 0.0.0.0:12345

TCP (--tcp-out)​

sifibridge --tcp-out 0.0.0.0:12345

SiFi Bridge acts as a TCP server: it binds the provided address and waits for subscribers to connect. The address is therefore a local bind address (e.g. 0.0.0.0:8080 for all interfaces, or a specific LAN IP), not a remote host. TCP is reliable and ordered — prefer it when you cannot tolerate dropped packets and a little extra latency/buffering is acceptable.

UDP (--udp-out)​

sifibridge --udp-out 192.168.1.100:12345

Sends DataPackets to a UDP endpoint. Unlike --tcp-out, the address here is the remote destination to send to (the subscriber's host:port), not a local bind address. UDP is fire-and-forget — lowest latency and overhead, but packets may be dropped or reordered. Prefer it for real-time visualization or feedback where the freshest sample matters more than completeness.

Lab Streaming Layer (--lsl)​

sifibridge --lsl

Publishes the data stream over Lab Streaming Layer (LSL) for integration with LSL-aware acquisition and synchronization tooling. Unlike the network transports, --lsl takes no address — LSL handles its own discovery, so consumers find the streams by name or type rather than connecting to a host:port.

Optional build feature

LSL support is a compile-time feature. If the binary was built without it, --lsl logs LSL feature not enabled and does nothing.

Stream layout​

SiFi Bridge publishes one LSL outlet per channel group, per device — not a single combined stream. A device with every sensor enabled surfaces as the following outlets:

SensorOutletsLSL stream typeChannels per outlet
ECG<device>:ecgECG1
EMG<device>:emgEMG1 (BioPoint) / 8 (SiFiBand armband)
EDA<device>:edaEDA1
IMU<device>:ax, :ay, :az, :qw, :qx, :qy, :qzIMU1 each (7 outlets)
PPG<device>:ir, :r, :g, :bPPG1 each (4 outlets)
Temperature<device>:temperatureTemperature1

So a fully-enabled device yields 15 outlets (IMU and PPG are split into one single-channel outlet per axis/wavelength; the 8-channel SiFiBand armband is the one exception, carried as a single 8-channel emg outlet).

  • Stream name follows <device id>:<channel>, where <device id> is the id field reported by info — not the BLE local name. A BioPoint whose local name is BioPoint_EF05 has id BP_EF05, so its outlets are BP_EF05:ecg, BP_EF05:ax, BP_EF05:ir.
  • source_id is the device's BLE MAC address, which lets LSL consumers recognise and automatically reconnect to the same physical device across restarts.
  • Channel format is float32. Note this is narrower than the f64 used by the buffers and the JSON DataPacket — samples are downcast to 32-bit floats on the LSL path.
  • Nominal sample rate is taken from the device configuration (the sensor's fs; for PPG, the effective --sps ÷ --avg rate).

Dynamic reconfiguration​

Outlets are created lazily on the first packet of each type and rebuilt automatically when the device configuration changes. Changing a sampling rate updates the affected stream's nominal rate; disabling a sensor drops its outlet; enabling one adds it — without restarting SiFi Bridge.

Multiple devices​

Each connected device gets its own independent set of outlets, distinguished by the <device name>: prefix and its unique source_id. Streaming several devices at once therefore produces several parallel stream sets.

Timestamps are assigned at push time

SiFi Bridge pushes samples to LSL without forwarding the device-side timestamps, so each sample is stamped by LSL using the host clock at the moment it is pushed. Because BLE delivers samples in bursts, expect push-time jitter on the LSL timestamps. For exact device timing, use the DataPacket timestamps (over another transport) or a buffered export instead.

Choosing a data transport​

TransportReliabilityLatencyUse when
stdoutReliable (local pipe)LowLocal processing in a parent process; quick inspection.
TCP (--tcp-out)Reliable, orderedLow–moderateNetworked consumers that must not drop samples.
UDP (--udp-out)Best-effortLowestReal-time feedback/visualization tolerant of loss.
LSL (--lsl)Per LSLPer LSLMulti-device sync and the LSL ecosystem.

See the Invocation options reference for the full flag list, and Data output for the packet format carried over every data transport.