use std::io;
use std::path::PathBuf;
use core_types::{Timestamp, TransportDomain};
use data_model::{ControlEnvelope, Packet, PacketHeader, SchemaId, SchemaVersion};
use introspection_core::{
ActionStatus, GraphEdge, HealthStatusItem, MissionStatus, NodeStatus, PluginStatus,
ResourceCatalogReport, ServiceStatus, StatusSnapshot, TopicStatus, collect_middleware_load,
write_middleware_load_report, write_resource_catalog_report, write_status_snapshot,
};
use middleware_core::MiddlewareStack;
pub fn capture_demo_report(path: &PathBuf) -> io::Result<()> {
let mut stack = MiddlewareStack::default();
stack.register_topic("demo/camera/raw");
stack.register_topic("demo/camera/processed");
stack.register_service("demo/echo");
let raw_slot = stack.topic_slot("demo/camera/raw", 8);
let processed_slot = stack.topic_slot("demo/camera/processed", 16);
for idx in 0..5u32 {
raw_slot.push(Box::new(idx));
}
for idx in 0..3u32 {
processed_slot.push(Box::new(idx));
}
let echo = stack.service_channel("demo/echo");
echo.push_request(1, Box::new(String::from("hello")));
echo.push_request(2, Box::new(String::from("world")));
echo.push_response(1, Box::new(String::from("ok")));
let closed_id = stack.open_session(TransportDomain::Local, "demo/local");
stack.close_session(closed_id);
let reconnecting_id = stack.open_session(TransportDomain::Network, "demo/network");
stack.mission_disconnect(reconnecting_id, "demo reconnecting");
let report = collect_middleware_load(&stack);
write_middleware_load_report(path, &report)
}
pub fn capture_demo_resource_report(path: &PathBuf) -> io::Result<()> {
let report = ResourceCatalogReport::from_lists(
vec!["demo_node".to_string()],
vec![
"/demo/camera/raw".to_string(),
"/demo/camera/processed".to_string(),
],
vec!["/demo/echo".to_string()],
vec!["/demo/calibrate".to_string()],
vec!["demo_mission".to_string()],
);
write_resource_catalog_report(path, &report)
}
pub fn capture_demo_status_report(path: &PathBuf) -> io::Result<()> {
let snapshot = demo_status_snapshot();
write_status_snapshot(path, &snapshot)
}
pub fn demo_status_snapshot() -> StatusSnapshot {
StatusSnapshot::new(
vec![NodeStatus {
name: "demo_node".to_string(),
namespace: "/demo".to_string(),
capabilities: vec![
"pubsub".to_string(),
"service".to_string(),
"mission".to_string(),
],
}],
vec![TopicStatus {
name: "/demo/camera/raw".to_string(),
schema: "sample.image".to_string(),
reliable: true,
depth: 16,
pending: 3,
max_depth: 16,
publishers: 1,
subscribers: 1,
}],
vec![ServiceStatus {
name: "/demo/echo".to_string(),
pending_requests: 1,
pending_responses: 0,
clients: 1,
servers: 1,
}],
vec![ActionStatus {
name: "/demo/calibrate".to_string(),
clients: 1,
servers: 1,
current_state: Some("executing".to_string()),
active_goals: Some(1),
health_state: Some("active".to_string()),
heartbeat_timeout_ms: Some(5000),
last_heartbeat_at_unix_nanos: Some(Timestamp::now().0),
last_feedback_at_unix_nanos: Some(Timestamp::now().0),
last_result_at_unix_nanos: None,
}],
vec![MissionStatus {
name: "demo_mission".to_string(),
state: "running".to_string(),
last_checkpoint: Some("cp-demo-1".to_string()),
}],
vec![
HealthStatusItem {
component: "runtime".to_string(),
status: "healthy".to_string(),
reason: None,
},
HealthStatusItem {
component: "device".to_string(),
status: "healthy".to_string(),
reason: None,
},
HealthStatusItem {
component: "pipeline".to_string(),
status: "healthy".to_string(),
reason: None,
},
HealthStatusItem {
component: "plugin".to_string(),
status: "healthy".to_string(),
reason: None,
},
],
vec![
PluginStatus {
name: "sample-device-plugin".to_string(),
kind: "device".to_string(),
loaded: true,
},
PluginStatus {
name: "sample-obs-plugin".to_string(),
kind: "observability".to_string(),
loaded: false,
},
],
vec![
GraphEdge {
from: "demo_node".to_string(),
to: "/demo/camera/raw".to_string(),
relation: "publishes".to_string(),
},
GraphEdge {
from: "demo_node".to_string(),
to: "/demo/echo".to_string(),
relation: "provides".to_string(),
},
],
)
}
pub fn make_demo_packet(sequence: u64, domain: TransportDomain) -> Packet {
Packet::Control(ControlEnvelope {
header: PacketHeader {
version: 1,
domain,
session_id: None,
stream_id: None,
sequence,
ack: None,
timestamp: Timestamp::now(),
schema_id: SchemaId::new("robotrt.bag.demo"),
schema_version: SchemaVersion(1),
},
label: format!("bag.demo.{sequence}"),
payload: format!("payload-{sequence}").into_bytes(),
})
}