use lnmp::prelude::*;
use std::time::{SystemTime, UNIX_EPOCH};
fn current_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64
}
struct Sensor {
id: String,
position: (f32, f32, f32), temperature: f32,
humidity: f32,
battery: u8,
alert_level: AlertLevel,
}
#[derive(Clone, Copy, PartialEq)]
enum AlertLevel {
Normal,
Warning,
Critical,
}
impl Sensor {
fn new(id: String, position: (f32, f32, f32)) -> Self {
Self {
id,
position,
temperature: 20.0,
humidity: 50.0,
battery: 100,
alert_level: AlertLevel::Normal,
}
}
fn update_readings(&mut self) {
self.temperature += (rand::random() - 0.5) * 2.0;
self.humidity += (rand::random() - 0.5) * 5.0;
self.battery = self.battery.saturating_sub(1);
self.alert_level = if self.temperature > 40.0 || self.battery < 20 {
AlertLevel::Critical
} else if self.temperature > 30.0 || self.battery < 50 {
AlertLevel::Warning
} else {
AlertLevel::Normal
};
}
fn to_lnmp_record(&self) -> LnmpRecord {
let mut record = LnmpRecord::new();
record.add_field(LnmpField {
fid: 1,
value: LnmpValue::String(self.id.clone()),
});
record.add_field(LnmpField {
fid: 10,
value: LnmpValue::Float(self.position.0 as f64),
});
record.add_field(LnmpField {
fid: 11,
value: LnmpValue::Float(self.position.1 as f64),
});
record.add_field(LnmpField {
fid: 12,
value: LnmpValue::Float(self.position.2 as f64),
});
record.add_field(LnmpField {
fid: 20,
value: LnmpValue::Float(self.temperature as f64),
});
record.add_field(LnmpField {
fid: 21,
value: LnmpValue::Float(self.humidity as f64),
});
record.add_field(LnmpField {
fid: 30,
value: LnmpValue::Int(self.battery as i64),
});
record
}
fn priority(&self) -> u8 {
match self.alert_level {
AlertLevel::Critical => 255,
AlertLevel::Warning => 180,
AlertLevel::Normal => 100,
}
}
}
mod rand {
static mut SEED: u64 = 0x123456789ABCDEF;
pub fn random() -> f32 {
unsafe {
SEED = SEED.wrapping_mul(6364136223846793005).wrapping_add(1);
((SEED >> 32) as f32) / (u32::MAX as f32)
}
}
}
fn main() {
println!("🌐 IoT Sensor Telemetry - LNMP Showcase\n");
println!("Simulating 3 sensors sending telemetry data...\n");
let mut sensors = vec![
Sensor::new("sensor-001".to_string(), (10.0, 20.0, 0.5)),
Sensor::new("sensor-002".to_string(), (15.0, 25.0, 1.2)),
Sensor::new("sensor-003".to_string(), (12.0, 18.0, 0.8)),
];
let encoder = Encoder::new();
for cycle in 1..=5 {
println!("📡 Cycle {} ---", cycle);
let now = current_timestamp();
for sensor in &mut sensors {
sensor.update_readings();
let record = sensor.to_lnmp_record();
let envelope = lnmp::envelope::EnvelopeBuilder::new(record)
.timestamp(now)
.source(&sensor.id)
.build();
let lnmp_text = encoder.encode(&envelope.record);
let _net_msg = lnmp::net::NetMessage::with_qos(
envelope,
lnmp::net::MessageKind::Event,
sensor.priority(),
5000, );
let importance = sensor.priority() as f64 / 255.0;
let route = if importance > 0.7 {
"🚨 PRIORITY QUEUE"
} else {
"📮 STANDARD QUEUE"
};
println!(
" {} | Temp: {:.1}°C | Battery: {}% | {} | Size: {} bytes",
sensor.id,
sensor.temperature,
sensor.battery,
route,
lnmp_text.len()
);
}
println!();
}
println!("✅ Demo complete!");
println!("\n💡 Key Features Demonstrated:");
println!(" • LNMP encoding for structured IoT data");
println!(" • Envelope metadata (timestamp, source)");
println!(" • Priority-based routing (QoS)");
println!(" • Compact wire format for bandwidth efficiency");
}