Skip to main content

viva_camctl/
cmd_execute.rs

1use std::net::Ipv4Addr;
2use std::time::Duration;
3
4use anyhow::{Context, Result};
5use serde::Serialize;
6use tracing::info;
7
8use viva_gige::nic::IfaceSelector;
9
10use crate::common::{self, DEFAULT_DISCOVERY_TIMEOUT_MS};
11
12#[derive(Serialize)]
13struct ExecuteResponse<'a> {
14    name: &'a str,
15    executed: bool,
16}
17
18/// Execute a GenApi `<Command>` feature.
19///
20/// Separate from `set` because a command has no value: `set --name UserSetLoad
21/// --value 1` worked, since `Camera::set` dispatches commands and discards the
22/// value, but nothing said so and the required `--value` reads like a mistake
23/// (issue #121).
24///
25/// There is deliberately no read-back. `Camera::get` on a `Command` returns a
26/// type error, and GenICam's `pIsDone` polling is not implemented — so the only
27/// honest report is that the write was acknowledged.
28pub async fn run(
29    ip: Option<Ipv4Addr>,
30    index: Option<usize>,
31    name: String,
32    iface: Option<IfaceSelector>,
33    json: bool,
34) -> Result<()> {
35    let timeout = Duration::from_millis(DEFAULT_DISCOVERY_TIMEOUT_MS);
36    let device = common::select_device(ip, index, iface.as_ref(), timeout).await?;
37    info!(ip = %device.ip, "opening camera for execute");
38    let mut camera = common::open_camera(&device)
39        .await
40        .context("open camera for execute")?;
41    camera
42        .execute_command(&name)
43        .with_context(|| format!("execute command {name}"))?;
44
45    if json {
46        common::print_json(&ExecuteResponse {
47            name: &name,
48            executed: true,
49        })?;
50    } else {
51        println!("{name} executed");
52    }
53
54    Ok(())
55}