use crate::constants::DEFAULT_STATUS_REPORT_PATH;
use crate::demo::demo_status_snapshot;
use crate::helpers::{has_flag, option_value, parse_report_path};
use crate::status_api::{
STATUS_SERVICE_API_VERSION, STATUS_SERVICE_NAME, make_udp_service_server, recv_status_request,
validate_request,
};
use super::DEFAULT_STATUS_BIND_ADDR;
pub(super) fn status_serve(args: &[String]) -> Result<(), String> {
let bind = option_value(args, "--bind").unwrap_or_else(|| DEFAULT_STATUS_BIND_ADDR.to_string());
let source = option_value(args, "--source").unwrap_or_else(|| "demo".to_string());
let report_path = parse_report_path(args, DEFAULT_STATUS_REPORT_PATH)?;
let once = has_flag(args, "--once");
let json = has_flag(args, "--json");
if source != "demo" && source != "file" {
return Err(format!(
"unsupported --source value: {source} (expected demo|file)"
));
}
let server = make_udp_service_server(&bind)?;
if json {
let boot = serde_json::json!({
"api_version": STATUS_SERVICE_API_VERSION,
"mode": "status_serve",
"service": STATUS_SERVICE_NAME,
"bind": bind,
"source": source,
"once": once,
});
println!(
"{}",
serde_json::to_string_pretty(&boot)
.map_err(|err| format!("serialize status server bootstrap failed: {err}"))?
);
} else {
println!("RobotRT Status Serve");
println!("bind: {}", bind);
println!("source: {}", source);
println!("once: {}", once);
}
loop {
let incoming = recv_status_request(&server)?;
let req = incoming.request;
let request_id = incoming.request_id;
let peer = incoming.peer;
let service_name = incoming.service;
if let Err(reason) = validate_request(&req) {
server
.reply_error(&service_name, request_id, peer, reason)
.map_err(|err| format!("status server send error response failed: {err}"))?;
if once {
return Ok(());
}
continue;
}
let snapshot = if source == "demo" {
Ok(demo_status_snapshot())
} else {
introspection_core::read_status_snapshot(&report_path).map_err(|err| {
format!(
"read status snapshot from {} failed: {err}",
report_path.display()
)
})
};
match snapshot {
Ok(snapshot) => {
let payload = crate::status_api::success_response(request_id, snapshot);
server
.reply_json(&service_name, request_id, peer, &payload)
.map_err(|err| format!("status server send response failed: {err}"))?;
}
Err(err) => {
server
.reply_error(&service_name, request_id, peer, err)
.map_err(|err| format!("status server send error response failed: {err}"))?;
}
}
if once {
return Ok(());
}
}
}