use std::sync::{Arc, Mutex};
use std::time::Duration;
use ghpascon_rust::device_manager::{DeviceManager, SharedEventHandler};
use ghpascon_rust::utils::tag_list::{TagList, make_tag};
use serde_json::Value;
fn build_handler(tags: Arc<TagList>) -> SharedEventHandler {
Arc::new(Mutex::new(Box::new(
move |name: &str, event_type: &str, data: Option<Value>| match event_type {
"tag" => {
let Some(obj) = data.as_ref().and_then(|v| v.as_object()) else {
return;
};
let epc = obj.get("epc").and_then(|v| v.as_str()).unwrap_or_default();
let tid = obj.get("tid").and_then(|v| v.as_str());
let rssi = obj.get("rssi").and_then(|v| v.as_i64()).unwrap_or(0);
let ant = obj.get("ant").and_then(|v| v.as_u64()).unwrap_or(0);
let record = make_tag(epc, tid, rssi, ant);
let (is_new, _) = tags.add(record, name);
let marker = if is_new { "β NEW" } else { "β»οΈ UPD" };
println!(
"[{}] π· {} epc={} tid={} ant={} rssi={}",
name,
marker,
epc,
tid.unwrap_or("-"),
ant,
rssi
);
}
"connection" => {
let ok = data.and_then(|v| v.as_bool()).unwrap_or(false);
if ok {
println!("[{}] β
Conectado", name);
} else {
println!("[{}] π Desconectado", name);
}
}
"reading" => {
let on = data.and_then(|v| v.as_bool()).unwrap_or(false);
println!("[{}] π‘ Reading: {}", name, if on { "ON" } else { "OFF" });
}
"serial_number" => {
let sn = data
.and_then(|v| v.as_str().map(str::to_string))
.unwrap_or_default();
println!("[{}] π’ Serial: {}", name, sn);
}
other => {
println!("[{}] βΉ {} β {:?}", name, other, data);
}
},
)))
}
#[tokio::main]
async fn main() {
let tags = Arc::new(TagList::builder().build());
let mut manager = DeviceManager::new("examples/devices/configs")
.with_event_handler(build_handler(Arc::clone(&tags)));
manager.connect_devices(false).await;
println!(
"\nπ¦ {} device(s) carregado(s): {:?}",
manager.len(),
manager.get_device_names()
);
println!("Ctrl+C para parar\n");
let tags_timer = Arc::clone(&tags);
let dump_task = tokio::spawn(async move {
let mut interval = tokio::time::interval(Duration::from_secs(10));
interval.tick().await; loop {
interval.tick().await;
let all = tags_timer.get_all_sorted();
println!("\nβββ Tag collection ({} tags) βββ", all.len());
for tag in &all {
println!(
" epc={} tid={} ant={} rssi={} count={} device={}",
tag.get("epc").and_then(|v| v.as_str()).unwrap_or("-"),
tag.get("tid").and_then(|v| v.as_str()).unwrap_or("-"),
tag.get("ant").and_then(|v| v.as_i64()).unwrap_or(0),
tag.get("rssi").and_then(|v| v.as_i64()).unwrap_or(0),
tag.get("count").and_then(|v| v.as_i64()).unwrap_or(1),
tag.get("device").and_then(|v| v.as_str()).unwrap_or("-"),
);
}
println!("ββββββββββββββββββββββββββββββββ\n");
}
});
let status_task = tokio::spawn({
let device_clones: Vec<_> = manager.devices.iter().map(|d| d.clone()).collect();
async move {
let mut interval = tokio::time::interval(Duration::from_secs(30));
interval.tick().await;
loop {
interval.tick().await;
println!("\nβββ Status dos devices βββ");
for d in &device_clones {
println!(
" {} [{}] conectado={} lendo={} serial={:?}",
d.name(),
d.device_type(),
d.is_connected(),
d.is_reading(),
d.serial_number(),
);
}
println!("βββββββββββββββββββββββββ\n");
}
}
});
tokio::signal::ctrl_c().await.ok();
println!("\nπ Parandoβ¦");
manager.cancel_connect_tasks().await;
manager.disconnect_devices().await;
dump_task.abort();
status_task.abort();
println!("β
Encerrado.");
}