robonix_executor/
rtdl_wire.rs1use crate::pb::executor::rtdl_event::RtdlEventEnum;
5use crate::pb::executor::{RtdlEvent, RtdlPlanComplete, RtdlPlanStarted};
6use crate::pb::pilot::rtdl_node_state::RtdlNodeStateEnum;
7use crate::pb::pilot::{CapabilityCallResult, RtdlNodeState};
8
9#[derive(Clone)]
10pub struct NodeEventContext {
11 pub plan_id: String,
12 pub node_index: u32,
13 pub node_kind: u32,
14 pub op_id: String,
15 pub description: String,
16}
17
18pub fn is_terminal_state(state: u32) -> bool {
19 matches!(
20 RtdlNodeStateEnum::try_from(state as i32),
21 Ok(RtdlNodeStateEnum::Succeeded
22 | RtdlNodeStateEnum::Failed
23 | RtdlNodeStateEnum::Canceled
24 | RtdlNodeStateEnum::Timeout)
25 )
26}
27
28pub fn plan_started(plan_id: String) -> RtdlEvent {
29 RtdlEvent {
30 event_kind: RtdlEventEnum::PlanStarted as u32,
31 plan_started: Some(RtdlPlanStarted { plan_id }),
32 ..Default::default()
33 }
34}
35
36pub fn node_state(
37 node: &NodeEventContext,
38 state: u32,
39 operator_detail: String,
40 leaf_result: Option<CapabilityCallResult>,
41) -> RtdlEvent {
42 RtdlEvent {
43 event_kind: RtdlEventEnum::NodeState as u32,
44 node_state: Some(RtdlNodeState {
45 plan_id: node.plan_id.clone(),
46 node_index: node.node_index,
47 node_kind: node.node_kind,
48 state,
49 operator_detail,
50 leaf_result,
51 op_id: node.op_id.clone(),
52 description: node.description.clone(),
53 }),
54 ..Default::default()
55 }
56}
57
58pub fn node_state_from_result(
59 node: &NodeEventContext,
60 result: CapabilityCallResult,
61 state: u32,
62) -> RtdlEvent {
63 node_state(node, state, String::new(), Some(result))
64}
65
66pub fn operator_node_state(node: &NodeEventContext, state: u32, detail: String) -> RtdlEvent {
67 node_state(node, state, detail, None)
68}
69
70pub fn plan_complete(plan_id: String, any_failed: bool) -> RtdlEvent {
71 RtdlEvent {
72 event_kind: RtdlEventEnum::PlanComplete as u32,
73 plan_complete: Some(RtdlPlanComplete {
74 plan_id,
75 any_failed,
76 }),
77 ..Default::default()
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn node_state_uses_plan_and_node_fields() {
87 let event = node_state(
88 &NodeEventContext {
89 plan_id: "p".into(),
90 node_index: 7,
91 node_kind: 2,
92 op_id: "op_1".into(),
93 description: "take a camera snapshot".into(),
94 },
95 RtdlNodeStateEnum::Running as u32,
96 "operator detail".into(),
97 None,
98 );
99 let ns = event.node_state.unwrap();
100
101 assert_eq!(event.event_kind, RtdlEventEnum::NodeState as u32);
102 assert_eq!(ns.plan_id, "p");
103 assert_eq!(ns.node_index, 7);
104 assert_eq!(ns.node_kind, 2);
105 assert_eq!(ns.state, RtdlNodeStateEnum::Running as u32);
106 assert_eq!(ns.operator_detail, "operator detail");
107 assert!(ns.leaf_result.is_none());
108 assert_eq!(ns.op_id, "op_1");
109 assert_eq!(ns.description, "take a camera snapshot");
110 }
111}