Getting Started with the SDK
Connect your first device to Tetrapus in under 5 minutes.
1. Add the Crate
Bash
cargo add nerve-sdk
# With compression support:
cargo add nerve-sdk --features full 2. Configure the Client
Rust
use nerve_sdk::{NerveClient, NerveConfig, SchemaId};
use std::time::Duration;
let config = NerveConfig::new("127.0.0.1:4433")
.with_queue_capacity(10_000) // in-memory buffer
.with_batch_size(1_400) // MTU-sized batches
.with_flush_interval(Duration::from_millis(10)); // 100 Hz max flush See Client API for the full NerveConfig reference.
3. Connect
Rust
let client = NerveClient::connect(config).await?;
// Connection probe: full TLS 1.3 handshake + teardown
// Background SendWorker spawned automatically 4. Define a Schema
Schema IDs are content-addressed: first 4 bytes of SHA-256, as a 32-bit big-endian integer.
Rust
// From a FlatBuffers schema file:
let schema = SchemaId::from_file("schemas/fleet_gps_v2.fbs")?;
// Or from raw bytes:
let schema = SchemaId::from_bytes(b"my_sensor_schema_v1");
// Or a known constant:
let schema = SchemaId::new(0x00000002); 5. Send Data
Rust
loop {
let payload = read_sensor_data();
// Non-blocking: ~50 ns, pushes to in-memory queue
client.send_raw(schema, &payload)?;
// Or with explicit priority:
// client.send_priority(schema, &payload, Priority::Critical)?;
tokio::time::sleep(Duration::from_millis(100)).await; // 10 Hz
} That's it. The background worker handles batching, compression, reconnection, and spill-to-disk automatically. Your application thread never blocks.
6. Monitor Health
Rust
// Check queue pressure
println!("Queue: {}", client.queue_depth());
println!("Spilled: {}", client.spill_depth());
// Access atomic counters
let m = client.metrics();
println!("Sent: {}, Bytes: {}", m.messages_sent(), m.bytes_sent());
// All counters as (name, value) pairs — for Prometheus/StatsD
for (name, value) in m.snapshot() {
println!("{}: {}", name, value);
} 7. Graceful Shutdown
Rust
// Drain remaining messages with a 5-second timeout
let unflushed = client.shutdown(Duration::from_secs(5)).await?;
if unflushed > 0 {
eprintln!("{} messages were not flushed", unflushed);
} Complete Example
Rust
use nerve_sdk::{NerveClient, NerveConfig, SchemaId};
use std::time::Duration;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = NerveConfig::new("127.0.0.1:4433")
.with_queue_capacity(50_000)
.with_batch_size(1_400)
.with_flush_interval(Duration::from_millis(10));
let client = NerveClient::connect(config).await?;
let schema = SchemaId::from_bytes(b"temperature_v1");
for i in 0..1000 {
let temp: f32 = 20.0 + (i as f32 * 0.01).sin() * 5.0;
client.send_raw(schema, &temp.to_le_bytes())?;
tokio::time::sleep(Duration::from_millis(10)).await;
}
let unflushed = client.shutdown(Duration::from_secs(5)).await?;
println!("Done. Unflushed: {}", unflushed);
Ok(())
} Next Steps
- Client API Reference — full NerveConfig options, TLS, authentication
- Reliability — spill buffers, circuit breaker, adaptive bandwidth
- Command Channel — receive commands from the server
- YAML Schema Reference — define data_schema.yaml for your telemetry
Questions?
Reach out for help with integration, deployment, or custom domain codecs.