Temperature Sensor Example
A complete example showing how to publish and subscribe to sensor data.
Overview
This example demonstrates:
- Defining a sensor data type in IDL
- Publishing temperature readings at 10 Hz
- Subscribing and processing sensor data
- Using Best Effort QoS for high-frequency data
IDL Definition
SensorData.idl
module sensors {
@topic
struct SensorData {
@key uint32 sensor_id; // Unique sensor identifier
uint64 timestamp; // Nanoseconds since epoch
float temperature; // Celsius
float pressure; // Pascals
float humidity; // Percentage (0-100)
};
};
Generate the Rust types:
hdds-gen --input SensorData.idl --output src/
Publisher
src/publisher.rs
use hdds::prelude::*;
use sensors::SensorData;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create participant on domain 0
let participant = DomainParticipant::new(0)?;
// Create topic
let topic = participant.create_topic::<SensorData>("SensorTopic")?;
// Configure QoS for high-frequency sensor data
let qos = DataWriterQos::default()
.reliability(Reliability::BestEffort)
.history(History::KeepLast { depth: 1 })
.durability(Durability::Volatile);
// Create publisher and writer
let publisher = participant.create_publisher()?;
let writer = publisher.create_writer_with_qos(&topic, qos)?;
println!("Publishing sensor data at 10 Hz...");
let sensor_id = 1;
loop {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)?
.as_nanos() as u64;
let sample = SensorData {
sensor_id,
timestamp: now,
temperature: 22.5 + (rand::random::<f32>() - 0.5),
pressure: 101325.0 + (rand::random::<f32>() - 0.5) * 100.0,
humidity: 45.0 + (rand::random::<f32>() - 0.5) * 5.0,
};
writer.write(&sample)?;
std::thread::sleep(Duration::from_millis(100)); // 10 Hz
}
}
Subscriber
src/subscriber.rs
use hdds::prelude::*;
use sensors::SensorData;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let participant = DomainParticipant::new(0)?;
let topic = participant.create_topic::<SensorData>("SensorTopic")?;
let qos = DataReaderQos::default()
.reliability(Reliability::BestEffort)
.history(History::KeepLast { depth: 10 });
let subscriber = participant.create_subscriber()?;
let reader = subscriber.create_reader_with_qos(&topic, qos)?;
println!("Listening for sensor data...");
loop {
// Non-blocking read
match reader.try_take() {
Ok(samples) => {
for sample in samples {
println!(
"Sensor {}: temp={:.2}C, pressure={:.0} Pa, humidity={:.1}%",
sample.sensor_id,
sample.temperature,
sample.pressure,
sample.humidity
);
}
}
Err(HddsError::NoData) => {
// No data available, sleep briefly
std::thread::sleep(std::time::Duration::from_millis(10));
}
Err(e) => return Err(e.into()),
}
}
}
Running the Example
Terminal 1 - Start the subscriber:
cargo run --bin subscriber
Terminal 2 - Start the publisher:
cargo run --bin publisher
Expected output:
Sensor 1: temp=22.43C, pressure=101312 Pa, humidity=44.8%
Sensor 1: temp=22.51C, pressure=101340 Pa, humidity=45.2%
Sensor 1: temp=22.48C, pressure=101298 Pa, humidity=44.9%
...
Multiple Sensors
The @key annotation on sensor_id enables tracking multiple sensors:
// Publish from multiple sensors
for sensor_id in 1..=4 {
let sample = SensorData {
sensor_id,
timestamp: now,
temperature: 20.0 + sensor_id as f32,
// ...
};
writer.write(&sample)?;
}
Each sensor_id creates a separate instance with independent:
- History buffer
- Deadline tracking
- Liveliness monitoring
QoS Considerations
| Scenario | Recommended QoS |
|---|---|
| High-rate sensors (>100 Hz) | BestEffort, KeepLast(1), Volatile |
| Critical measurements | Reliable, KeepLast(10), TransientLocal |
| Logging/recording | Reliable, KeepAll, Persistent |
Performance Tips
- Batch small samples: Group multiple readings if sending faster than 1 kHz
- Use BestEffort: For high-frequency non-critical data
- Keep history small: KeepLast(1) minimizes memory for streaming data
- Pre-allocate: Reuse SensorData struct to avoid allocations
Next Steps
- Reliable Delivery - Guaranteed message delivery
- Key Instance - Multi-instance topics
- QoS Policies - Complete QoS reference