zencan_client/
nmt_master.rs1use std::time::Instant;
3
4use zencan_common::{
5 messages::{CanMessage, NmtCommand, NmtCommandSpecifier, ZencanMessage},
6 nmt::NmtState,
7 traits::{AsyncCanReceiver, AsyncCanSender},
8};
9
10type Result<T> = std::result::Result<T, ()>;
11
12#[derive(Copy, Clone, Debug)]
14pub struct Node {
15 pub id: u8,
17 pub state: NmtState,
19 pub last_status: Instant,
21 last_toggle: bool,
22}
23
24impl Default for Node {
25 fn default() -> Self {
26 Self {
27 id: 0,
28 state: NmtState::Bootup,
29 last_status: Instant::now(),
30 last_toggle: true,
31 }
32 }
33}
34
35const MAX_NODES: usize = 127;
36
37#[derive(Debug)]
38pub struct NmtMaster<S, R> {
40 sender: S,
41 receiver: R,
42 nodes: [Node; MAX_NODES],
43}
44
45impl<S: AsyncCanSender, R: AsyncCanReceiver> NmtMaster<S, R> {
46 pub fn new(sender: S, receiver: R) -> Self {
56 let nodes = [Node::default(); MAX_NODES];
57 Self {
58 sender,
59 receiver,
60 nodes,
61 }
62 }
63
64 pub fn process_rx(&mut self) {
66 while let Some(msg) = self.receiver.try_recv() {
67 self.handle_message(msg);
68 }
69 }
70
71 fn handle_message(&mut self, msg: CanMessage) {
72 let open_msg: ZencanMessage = match msg.try_into() {
75 Ok(m) => m,
76 Err(_) => return,
77 };
78
79 if let ZencanMessage::Heartbeat(heartbeat) = open_msg {
80 self.handle_heartbeat(heartbeat.node, heartbeat.state, heartbeat.toggle)
81 }
82 }
83
84 pub fn get_nodes(&mut self) -> &[Node] {
86 self.process_rx();
87
88 let n = self
90 .nodes
91 .iter()
92 .position(|n| n.id == 0)
93 .unwrap_or(MAX_NODES);
94 &self.nodes[0..n]
95 }
96
97 fn handle_heartbeat(&mut self, node: u8, state: NmtState, toggle: bool) {
98 for i in 0..self.nodes.len() {
100 let list_node = &mut self.nodes[i];
101 if list_node.id == node {
102 list_node.last_status = Instant::now();
104 list_node.last_toggle = toggle;
105 list_node.state = state;
106 break;
107 } else if list_node.id == 0 || list_node.id > node {
108 for j in self.nodes.len() - 1..i {
111 self.nodes[j] = self.nodes[j - 1];
112 }
113 self.nodes[i] = Node {
114 id: node,
115 state,
116 last_status: Instant::now(),
117 last_toggle: toggle,
118 };
119 break;
120 }
121 }
122 }
123
124 pub async fn nmt_reset_app(&mut self, node: u8) -> Result<()> {
130 self.send_nmt_cmd(NmtCommandSpecifier::ResetApp, node).await
131 }
132
133 pub async fn nmt_reset_comms(&mut self, node: u8) -> Result<()> {
139 self.send_nmt_cmd(NmtCommandSpecifier::ResetComm, node)
140 .await
141 }
142
143 pub async fn nmt_start(&mut self, node: u8) -> Result<()> {
149 self.send_nmt_cmd(NmtCommandSpecifier::Start, node).await
150 }
151
152 pub async fn nmt_stop(&mut self, node: u8) -> Result<()> {
158 self.send_nmt_cmd(NmtCommandSpecifier::Stop, node).await
159 }
160
161 async fn send_nmt_cmd(&mut self, cmd: NmtCommandSpecifier, node: u8) -> Result<()> {
162 let message = NmtCommand { cs: cmd, node };
163 self.sender.send(message.into()).await.map_err(|_| ())?;
164 Ok(())
165 }
166}