use std::time::Duration;
use mqtt_typed_client::prelude::*;
use tokio::select;
use super::topics::TemperatureReading;
use super::topics::temperature_topic::*;
use crate::shared;
pub async fn run_example() -> Result<()> {
println!("Initializing multi-sensor monitoring system...\n");
let connection_url = shared::config::build_url("modular_sensor_system");
println!("Connecting to MQTT broker: {connection_url}");
let (client, connection) =
MqttClient::<BincodeSerializer>::connect(&connection_url)
.await
.inspect_err(|e| {
shared::config::print_connection_error(&connection_url, e);
})?;
println!("- Connected to MQTT broker\n");
let temp_client = client.temperature_topic();
let temp_reading = TemperatureReading {
device_id: 42,
temperature: 23.5,
humidity: Some(45.0),
battery_level: Some(80),
};
println!("Sample sensor data: {temp_reading:?}\n");
let publisher = temp_client.get_publisher("Home", "floor", 37)?;
let publisher_handle = {
let temp_data = temp_reading.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis(500)).await;
println!("Publishing sensor data to: sensors/Home/floor/37/data");
if let Err(e) = publisher.publish(&temp_data).await {
eprintln!("Publish error: {e}");
return Err(e);
}
println!("- Data published successfully\n");
Ok(())
})
};
println!("Setting up wildcard subscriber for all sensors...");
let mut subscriber_all = temp_client.subscribe().await?;
println!("- Subscribed to: sensors/+/+/+/data\n");
println!("Setting up filtered subscriber for device 370...");
let mut subscriber_specific = temp_client
.subscription()
.for_device_id(370)
.with_cache(100)
.subscribe()
.await?;
println!(
"- Subscribed to: sensors/+/+/370/data (with 100-message cache)\n"
);
println!("Listening for temperature messages...\n");
let timeout_duration = Duration::from_secs(10);
let mut message_count = 0;
let max_messages = 5;
let monitoring_result = tokio::time::timeout(timeout_duration, async {
loop {
select! {
msg_result = subscriber_all.receive() => {
match msg_result {
Some(ReceiveEvent::Message(temp_msg)) => {
message_count += 1;
println!("[ALL-SENSORS] Received from: {}", temp_msg.topic.topic_path());
println!(" Location: {} | Sensor: {} | Device: {}",
temp_msg.location, temp_msg.sensor_type, temp_msg.device_id);
println!(" Data: temp={}°C, humidity={:?}%, battery={:?}%\n",
temp_msg.payload.temperature,
temp_msg.payload.humidity,
temp_msg.payload.battery_level);
if message_count >= max_messages {
break;
}
},
Some(ReceiveEvent::DecodeFailed(e)) => {
eprintln!("Wildcard subscription decode error: {e}");
},
Some(ReceiveEvent::Lagged { missed }) => {
eprintln!("[ALL-SENSORS] lagged: {missed} messages dropped");
},
Some(_) => {},
None => {
println!("Wildcard subscription ended");
break;
}
}
},
msg_result = subscriber_specific.receive() => {
match msg_result {
Some(ReceiveEvent::Message(temp_msg)) => {
println!("[DEVICE-370] Specific device message: {}", temp_msg.topic.topic_path());
println!(" This would only trigger for device_id=370\n");
},
Some(ReceiveEvent::DecodeFailed(e)) => {
eprintln!("Specific subscription decode error: {e}");
},
Some(ReceiveEvent::Lagged { missed }) => {
eprintln!("[DEVICE-370] lagged: {missed} messages dropped");
},
Some(_) => {},
None => {
println!("Specific subscription ended");
break;
}
}
}
}
}
}).await;
if let Err(e) = publisher_handle.await.unwrap_or(Ok(())) {
eprintln!("Publisher task error: {e}");
}
match monitoring_result {
| Ok(_) => println!("Processed {message_count} messages successfully"),
| Err(_) => println!("Demo timeout reached ({timeout_duration:?})"),
}
println!("\nShutting down connection...");
connection.shutdown().await?;
println!("- Connection closed gracefully");
Ok(())
}