use crate::helpers::{
first_positional, has_flag, option_value, parse_u64_option, resolve_runtime_endpoint,
};
use crate::gateway::{
STATUS_OP_ACTION_CANCEL, STATUS_OP_ACTION_SEND, STATUS_SERVICE_NAME, StatusServiceResponse,
build_op_payload_request, make_udp_service_client, next_request_id, validate_response,
};
const DEFAULT_DAEMON_ENDPOINT: &str = "127.0.0.1:7588";
pub fn action_send(args: &[String]) -> Result<(), String> {
let action = first_positional(args).ok_or_else(|| String::from("missing action name"))?;
let goal = option_value(args, "--goal").ok_or_else(|| String::from("missing --goal payload"))?;
let timeout_ms = parse_u64_option(args, "--timeout-ms", 1000)?;
let endpoint = resolve_runtime_endpoint(
args,
DEFAULT_DAEMON_ENDPOINT,
"action control requires --endpoint in embedded mode",
)?;
let json = has_flag(args, "--json");
let client = make_udp_service_client(endpoint.clone(), timeout_ms)?;
let request_id = next_request_id();
let request = build_op_payload_request(
STATUS_OP_ACTION_SEND,
serde_json::json!({
"action": action,
"goal": goal,
"timeout_ms": timeout_ms,
}),
);
let response: StatusServiceResponse = client
.call_json(STATUS_SERVICE_NAME, request_id, &request)
.map_err(|err| format!("action send to {endpoint} failed: {err}"))?;
validate_response(&response, request_id, STATUS_OP_ACTION_SEND)?;
let result = response
.op_result
.ok_or_else(|| format!("action send response from {endpoint} missing op_result"))?;
if json {
let payload = serde_json::json!({
"api_version": "robotrt.action.send.v1",
"source": {
"mode": "remote_service",
"service": STATUS_SERVICE_NAME,
"endpoint": endpoint,
"timeout_ms": timeout_ms,
},
"result": result,
});
println!(
"{}",
serde_json::to_string_pretty(&payload)
.map_err(|err| format!("serialize action send json failed: {err}"))?
);
return Ok(());
}
println!("RobotRT Action Send");
println!("endpoint: {endpoint}");
println!("action: {}", result.get("action").and_then(serde_json::Value::as_str).unwrap_or("-"));
println!("goal_id: {}", result.get("goal_id").and_then(serde_json::Value::as_str).unwrap_or("-"));
println!("accepted: {}", result.get("accepted").and_then(serde_json::Value::as_bool).unwrap_or(false));
println!("state: {}", result.get("state").and_then(serde_json::Value::as_str).unwrap_or("-"));
Ok(())
}
pub fn action_cancel(args: &[String]) -> Result<(), String> {
let action = first_positional(args).ok_or_else(|| String::from("missing action name"))?;
let goal_id = option_value(args, "--goal-id").ok_or_else(|| String::from("missing --goal-id"))?;
let timeout_ms = parse_u64_option(args, "--timeout-ms", 1000)?;
let endpoint = resolve_runtime_endpoint(
args,
DEFAULT_DAEMON_ENDPOINT,
"action control requires --endpoint in embedded mode",
)?;
let json = has_flag(args, "--json");
let client = make_udp_service_client(endpoint.clone(), timeout_ms)?;
let request_id = next_request_id();
let request = build_op_payload_request(
STATUS_OP_ACTION_CANCEL,
serde_json::json!({
"action": action,
"goal_id": goal_id,
}),
);
let response: StatusServiceResponse = client
.call_json(STATUS_SERVICE_NAME, request_id, &request)
.map_err(|err| format!("action cancel to {endpoint} failed: {err}"))?;
validate_response(&response, request_id, STATUS_OP_ACTION_CANCEL)?;
let result = response
.op_result
.ok_or_else(|| format!("action cancel response from {endpoint} missing op_result"))?;
if json {
let payload = serde_json::json!({
"api_version": "robotrt.action.cancel.v1",
"source": {
"mode": "remote_service",
"service": STATUS_SERVICE_NAME,
"endpoint": endpoint,
"timeout_ms": timeout_ms,
},
"result": result,
});
println!(
"{}",
serde_json::to_string_pretty(&payload)
.map_err(|err| format!("serialize action cancel json failed: {err}"))?
);
return Ok(());
}
println!("RobotRT Action Cancel");
println!("endpoint: {endpoint}");
println!("action: {}", result.get("action").and_then(serde_json::Value::as_str).unwrap_or("-"));
println!("goal_id: {}", result.get("goal_id").and_then(serde_json::Value::as_str).unwrap_or("-"));
println!("canceled: {}", result.get("canceled").and_then(serde_json::Value::as_bool).unwrap_or(false));
println!("state: {}", result.get("state").and_then(serde_json::Value::as_str).unwrap_or("-"));
println!("error: {}", result.get("error").and_then(serde_json::Value::as_str).unwrap_or("-"));
Ok(())
}