Skip to main content

Sensirion SEK-SensorBridge Driver (Rust & Python)

CI License

High-performance, async and sync SEK-SensorBridge hardware driver written in Rust with native PyO3 / Maturin bindings for Python.

Overview

The Sensirion SEK-SensorBridge enables connecting Sensirion sensors (such as environmental, flow, and humidity sensors) to a computer via USB/UART using the SHDLC (Sensirion High-Level Data Link Control) protocol.

This library provides:

  • Clean 4-Layer Architecture:
    • Transport Layer: Non-blocking serial, TCP, and mock transport interfaces (powered by rust-shdlc-driver).
    • Connection Layer: Async and sync SHDLC connection managers.
    • Protocol Layer: Type-safe command encoding, decoding, port/voltage/frequency definitions, and structured error hierarchies.
    • Application Layer: High-level driver (SensorBridgeDevice, AsyncSensorBridgeDevice), unified I²C proxies (SensorBridgeI2cProxy, AsyncSensorBridgeI2cProxy), and firmware update capabilities (SensorBridgeFirmwareImage).
  • Synchronous and Asynchronous APIs in both Rust and Python (native asyncio integration).
  • Zero-cost FFI bindings using PyO3 and Maturin.
  • Built-in Mock Transports for unit testing and CI without physical hardware attached.

Installation & Usage

Rust (Cargo)

Add rust-uart-sensorbridge to your project's Cargo.toml:

[dependencies]
rust-uart-sensorbridge = "0.1.0"
rust-shdlc-driver = "0.1.0"
tokio = { version = "1.0", features = ["full"] }

Or add the dependencies via the Cargo CLI:

cargo add rust-uart-sensorbridge
cargo add rust-shdlc-driver
cargo add tokio --features full

Python (pip)

It is strongly recommended to install and run Python packages inside a virtual environment to prevent dependency conflicts:

# 1. Create a virtual environment
python3 -m venv .venv

# 2. Activate the virtual environment
# On Linux / macOS:
source .venv/bin/activate
# On Windows (PowerShell):
# .\.venv\Scripts\Activate.ps1
# On Windows (cmd):
# .\.venv\Scripts\activate.bat

# 3. Install the package via pip
pip install sensirion-uart-sensorbridge

Quickstart

Rust (Sync)

use sensirion_uart_sensorbridge::device::SensorBridgeDevice;
use sensirion_uart_sensorbridge::protocol::definitions::SensorBridgePort;
use rust_shdlc_driver::connection::ShdlcConnection;
use rust_shdlc_driver::transport::serial::AsyncSerialPort;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut port = AsyncSerialPort::new("/dev/ttyUSB0", 460_800);
    port.open()?;
    let conn = ShdlcConnection::new(Box::new(port))?;
    let mut bridge = SensorBridgeDevice::new(conn, 0x00);

    // Configure Port 1 with 3.3V supply voltage and enable power
    bridge.set_supply_voltage(SensorBridgePort::One, 3.3)?;
    bridge.switch_supply_on(SensorBridgePort::One)?;
    bridge.set_i2c_frequency(SensorBridgePort::One, 400_000)?;

    // Scan for connected I2C devices on Port 1
    let devices = bridge.scan_i2c(SensorBridgePort::One, 1, 127)?;
    println!("Found devices on Port 1: {:?}", devices);

    // Turn off power before exiting
    bridge.switch_supply_off(SensorBridgePort::One)?;
    Ok(())
}

Rust (Async)

use sensirion_uart_sensorbridge::device::AsyncSensorBridgeDevice;
use sensirion_uart_sensorbridge::protocol::definitions::SensorBridgePort;
use rust_shdlc_driver::connection::AsyncShdlcConnection;
use rust_shdlc_driver::transport::serial::AsyncSerialPort;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut port = AsyncSerialPort::new("/dev/ttyUSB0", 460_800);
    port.open()?;
    let conn = AsyncShdlcConnection::new(Box::new(port));
    let mut bridge = AsyncSensorBridgeDevice::new(conn, 0x00);

    // Power Port 1
    bridge.set_supply_voltage(SensorBridgePort::One, 3.3).await?;
    bridge.switch_supply_on(SensorBridgePort::One).await?;

    // Measure analog voltage on Port 1
    let voltage = bridge.measure_voltage(SensorBridgePort::One).await?;
    println!("Measured analog voltage on Port 1: {:.3} V", voltage);

    bridge.switch_supply_off(SensorBridgePort::One).await?;
    Ok(())
}

Python (Sync)

from rust_shdlc_driver import ShdlcSerialPort, ShdlcConnection
from sensirion_uart_sensorbridge import SensorBridgeShdlcDevice, SensorBridgePort

# Open serial port and establish connection
port = ShdlcSerialPort.open("/dev/ttyUSB0", 460800)
conn = ShdlcConnection(port)
bridge = SensorBridgeShdlcDevice(conn, slave_address=0)

# Configure Port 1 with 3.3V power supply and 400kHz I2C frequency
bridge.set_supply_voltage(SensorBridgePort.ONE, 3.3)
bridge.switch_supply_on(SensorBridgePort.ONE)
bridge.set_i2c_frequency(SensorBridgePort.ONE, 400000)

# Scan for connected I2C devices
devices = bridge.scan_i2c(SensorBridgePort.ONE)
print(f"Found I2C devices on Port 1: {[hex(d) for d in devices]}")

# Blink Port 1 LED
bridge.blink_led(SensorBridgePort.ONE)

# Power down
bridge.switch_supply_off(SensorBridgePort.ONE)

Python (Async)

import asyncio
from rust_shdlc_driver import ShdlcSerialPort, AsyncShdlcConnection
from sensirion_uart_sensorbridge import AsyncSensorBridgeShdlcDevice, SensorBridgePort


async def main():
    port = ShdlcSerialPort.open("/dev/ttyUSB0", 460800)
    conn = AsyncShdlcConnection(port)
    bridge = AsyncSensorBridgeShdlcDevice(conn, slave_address=0)

    # Power Port 1
    await bridge.set_supply_voltage(SensorBridgePort.ONE, 3.3)
    await bridge.switch_supply_on(SensorBridgePort.ONE)

    # Start repeated I2C transceive measurement at 100ms interval
    handle = await bridge.start_repeated_i2c_transceive(
        port=SensorBridgePort.ONE,
        interval_us=100000,
        address=0x70,
        tx_data=b"\x78\x66",
        rx_length=6,
        timeout_us=10000,
    )

    await asyncio.sleep(0.5)

    # Read buffered measurements
    response = await bridge.read_buffer(handle, max_reads=50)
    for sample in response.values:
        print("Sample:", sample.data.hex())

    await bridge.stop_repeated_i2c_transceive(handle)
    await bridge.switch_supply_off(SensorBridgePort.ONE)


asyncio.run(main())

Testing & Quality Assurance

# Run Rust tests (unit, mock integration, protocol tests)
cargo test

# Run Rust formatting and linter
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings

# Build Python bindings in local virtual environment
maturin develop

# Run Python test suite
pytest python_tests

# Run Python linting and formatting
ruff check .
ruff format --check .

Documentation & Developer Build Instructions

Detailed documentation, architecture overviews, API references, and comprehensive build instructions for developers are available in the Sphinx documentation under docs/.

For step-by-step developer build instructions (including prerequisites, setting up virtual environments, building with Maturin, and compiling Sphinx docs), refer to the Developer Build Guide.

To build the HTML documentation locally:

# Install doc dependencies inside your virtual environment
pip install -r docs/requirements.txt

# Build Sphinx documentation
cd docs
make html

The output will be generated in docs/_build/html/index.html.


License

See LICENSE. Distributed under the BSD 3-Clause License.

Metadata

Release files for sensirion-uart-sensorbridge 0.1.0

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

Source distribution (sdist)

Source distribution for sensirion-uart-sensorbridge 0.1.0
File Size Uploaded Provenance Actions
sensirion_uart_sensorbridge-0.1.0.tar.gz 105.5 kB Without provenance Details for sensirion_uart_sensorbridge-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sensirion-uart-sensorbridge 0.1.0
File Interpreter ABI Platform Actions
sensirion_uart_sensorbridge-0.1.0-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details for sensirion_uart_sensorbridge-0.1.0-cp311-abi3-win_amd64.whl

Total release size: 1.3 MB

Release files / sensirion_uart_sensorbridge-0.1.0.tar.gz

Download URL sensirion_uart_sensorbridge-0.1.0.tar.gz
Size 105.5 kB
Tags Source
SHA-256 checksum
How to use checksums
5ceb669e03eedf2e1df074489e9f108402d5a8a78eed649198ea42ea58edb579
BLAKE2b-256 checksum
How to use checksums
73bf5b9c73ec6b89d96e5f09247306a3fac93f1ca371f00150cf4b63c7718468
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / sensirion_uart_sensorbridge-0.1.0-cp311-abi3-win_amd64.whl

Download URL sensirion_uart_sensorbridge-0.1.0-cp311-abi3-win_amd64.whl
Size 1.2 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
938e1a0c8510da9727d0bab03fc1b6209f5a266220f833597d7041dadf5b37ef
BLAKE2b-256 checksum
How to use checksums
8aef57cc10c8b7b2ac696f14fdae51dff31ab496f9bf150f535811d6c23f0a23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for sensirion-uart-sensorbridge 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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