viva_camctl/
cmd_events.rs1use std::net::Ipv4Addr;
2use std::time::Duration;
3
4use anyhow::{Context, Result, anyhow};
5use serde::Serialize;
6use tracing::{info, warn};
7
8use viva_gige::nic::IfaceSelector;
9
10use crate::common::{self, DEFAULT_DISCOVERY_TIMEOUT_MS};
11
12#[derive(Serialize)]
13struct EventRecord {
14 index: usize,
15 id: u16,
16 ts_dev: u64,
17 ts_host: String,
18 payload_len: usize,
19}
20
21fn parse_events(csv: &str) -> Vec<String> {
22 csv.split(',')
23 .map(|entry| entry.trim())
24 .filter(|entry| !entry.is_empty())
25 .map(|entry| entry.to_string())
26 .collect()
27}
28
29pub async fn run(
30 ip: Option<Ipv4Addr>,
31 index: Option<usize>,
32 iface: Option<IfaceSelector>,
33 port: u16,
34 enable: String,
35 count: u32,
36 json: bool,
37) -> Result<()> {
38 let timeout = Duration::from_millis(DEFAULT_DISCOVERY_TIMEOUT_MS);
39 let device = common::select_device(ip, index, iface.as_ref(), timeout).await?;
40
41 let local_ip = common::resolve_receive_iface(iface.as_ref(), device.ip)?
47 .ipv4()
48 .ok_or_else(|| anyhow!("interface routing to {} has no IPv4 address", device.ip))?;
49 info!(ip = %device.ip, %local_ip, port, "configuring events");
50 let mut camera = common::open_camera(&device)
51 .await
52 .context("open camera for events")?;
53
54 let enable_list = parse_events(&enable);
55 let enable_refs: Vec<&str> = enable_list.iter().map(|s| s.as_str()).collect();
56 camera
57 .configure_events(local_ip, port, &enable_refs)
58 .await
59 .context("configure event channel")?;
60 let stream = camera
61 .open_event_stream(local_ip, port)
62 .await
63 .context("open event stream")?;
64 if let Ok(addr) = stream.local_addr() {
65 info!(local = %addr, "listening for events");
66 }
67
68 let mut records = Vec::new();
69 for idx in 0..usize::try_from(count).unwrap_or(0) {
70 match stream.next().await {
71 Ok(event) => {
72 let ts_host = common::format_system_time(event.ts_host)
73 .unwrap_or_else(|_| "unknown".to_string());
74 if json {
75 records.push(EventRecord {
76 index: idx + 1,
77 id: event.id,
78 ts_dev: event.ts_dev,
79 ts_host,
80 payload_len: event.data.len(),
81 });
82 } else {
83 println!(
84 "#{:02} host={} id=0x{:04X} ticks={} payload={} bytes",
85 idx + 1,
86 ts_host,
87 event.id,
88 event.ts_dev,
89 event.data.len()
90 );
91 }
92 }
93 Err(err) => {
94 warn!(error = %err, "failed to receive event");
95 break;
96 }
97 }
98 }
99
100 if json {
101 common::print_json(&records)?;
102 }
103
104 Ok(())
105}