Skip to content

Transport Layer ​

ferrite-sdk is transport-agnostic. All telemetry flows through the ChunkTransport trait (or its async counterpart AsyncChunkTransport), and the SDK ships with implementations for UART, USB CDC, BLE, HTTP, and LoRa.

Transport traits ​

rust
pub trait ChunkTransport {
    type Error: core::fmt::Debug;
    fn send_chunk(&mut self, chunk: &[u8]) -> Result<(), Self::Error>;
    fn is_available(&self) -> bool;
    fn begin_session(&mut self) -> Result<(), Self::Error>;
    fn end_session(&mut self) -> Result<(), Self::Error>;
}

pub trait AsyncChunkTransport {
    type Error: core::fmt::Debug;
    async fn send_chunk(&mut self, chunk: &[u8]) -> Result<(), Self::Error>;
    async fn is_available(&self) -> bool;
    async fn begin_session(&mut self) -> Result<(), Self::Error>;
    async fn end_session(&mut self) -> Result<(), Self::Error>;
}

Built-in transports ​

UART (always available) ​

The default transport. Works with any embedded_io::Write UART peripheral.

rust
use ferrite_sdk::transport::UartTransport;

let transport = UartTransport::new(uart_peripheral);

USB CDC (usb-cdc feature) ​

Uses embassy-usb CdcAcmClass for USB serial communication. Waits for a host connection before sending.

toml
[dependencies]
ferrite-sdk = { version = "0.1", features = ["usb-cdc"] }

HTTP (http feature) ​

WiFi/HTTP transport using reqwless (no_std HTTP client). Posts chunks to /ingest/chunks with optional API key authentication.

toml
[dependencies]
ferrite-sdk = { version = "0.1", features = ["http"] }
rust
use ferrite_sdk::transport::http::HttpTransport;

let transport = HttpTransport::new(
    tcp_connection,
    "http://ferrite.local:4000",
    Some("my-api-key"),
);

LoRa (lora feature) ​

SX1262/SX1276 radio transport via embedded-hal SPI. Sends each chunk as a single LoRa packet.

toml
[dependencies]
ferrite-sdk = { version = "0.1", features = ["lora"] }
rust
use ferrite_sdk::transport::lora::{LoraTransport, LoraConfig};

let config = LoraConfig {
    frequency: 915_000_000,  // US ISM band
    spreading_factor: 7,
    tx_power: 14,
    ..Default::default()
};
let transport = LoraTransport::new(spi_device, config);

Maximum payload by spreading factor:

SFMax Payload
7-8222 bytes
9115 bytes
10-1251 bytes

BLE (separate crate) ​

BLE transport is in the ferrite-ble-nrf crate (excluded from workspace, requires nRF SoftDevice). Defines a custom GATT service:

  • Service UUID: FE771E00-0001-4000-8000-00805F9B34FB
  • Chunk characteristic: FE771E00-0002-4000-8000-00805F9B34FB
  • Max BLE payload: 244 bytes (BLE 5.0 MTU)

Compression wrapper ​

The CompressedTransport<T> wraps any transport to apply RLE compression before sending. Useful for bandwidth-constrained links (LoRa, BLE).

rust
use ferrite_sdk::compression::CompressedTransport;

let compressed = CompressedTransport::new(lora_transport);
// Chunks are RLE-compressed transparently

Compressed chunks set the FLAG_COMPRESSED (0x08) flag in the header. The server decompresses them automatically.

Edge gateway ​

For devices that can't reach the server directly, the ferrite-gateway daemon bridges BLE, USB, and LoRa devices to the server over HTTP. It runs on a Raspberry Pi or similar edge device and provides offline buffering with automatic retry.