iso14229_1/request/
communication_ctrl.rs1use crate::{CommunicationCtrlType, CommunicationType, Configuration, Error, RequestData, utils};
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7pub struct NodeId(u16);
8
9impl TryFrom<u16> for NodeId {
10 type Error = Error;
11 fn try_from(value: u16) -> Result<Self, Self::Error> {
12 match value {
13 0x0001..=0xFFFF => Ok(Self(value)),
14 v => Err(Error::InvalidParam(utils::err_msg(v))),
15 }
16 }
17}
18
19impl Into<u16> for NodeId {
20 fn into(self) -> u16 {
21 self.0
22 }
23}
24
25#[derive(Debug, Clone)]
26pub struct CommunicationCtrl {
27 pub comm_type: CommunicationType,
28 pub node_id: Option<NodeId>,
29}
30
31impl CommunicationCtrl {
32 pub fn new(
33 ctrl_type: CommunicationCtrlType,
34 comm_type: CommunicationType,
35 node_id: Option<NodeId>,
36 ) -> Result<Self, Error> {
37 match ctrl_type {
38 CommunicationCtrlType::EnableRxAndDisableTxWithEnhancedAddressInformation |
39 CommunicationCtrlType::EnableRxAndTxWithEnhancedAddressInformation => {
40 match node_id {
41 Some(v) => Ok(Self { comm_type, node_id: Some(v), }),
42 None => Err(Error::InvalidParam("`nodeIdentificationNumber` is required".to_string())),
43 }
44 },
45 _ => Ok(Self { comm_type, node_id: None, })
46 }
47 }
48}
49
50impl RequestData for CommunicationCtrl {
51 type SubFunc = CommunicationCtrlType;
52 fn try_parse(data: &[u8], sub_func: Option<Self::SubFunc>, _: &Configuration) -> Result<Self, Error> {
53 match sub_func {
54 Some(v) => {
55 let data_len = data.len();
56 utils::data_length_check(data_len, 1, false)?;
57
58 let mut offset = 0;
59 let comm_type = data[offset];
60 offset += 1;
61
62 let node_id = match v {
63 CommunicationCtrlType::EnableRxAndDisableTxWithEnhancedAddressInformation |
64 CommunicationCtrlType::EnableRxAndTxWithEnhancedAddressInformation => {
65
66 utils::data_length_check(data_len, offset + 2, true)?;
67
68 Some(NodeId::try_from(
69 u16::from_be_bytes([data[offset], data[offset + 1]])
70 )?)
71 },
72 _ => None,
73 };
74
75 Ok(Self {
76 comm_type: CommunicationType(comm_type),
77 node_id,
78 })
79 },
80 None => panic!("Sub-function required"),
81 }
82 }
83 #[inline]
84 fn to_vec(self, _: &Configuration) -> Vec<u8> {
85 self.into()
86 }
87}
88
89impl Into<Vec<u8>> for CommunicationCtrl {
90 fn into(self) -> Vec<u8> {
91 let mut result = vec![self.comm_type.0];
92 if let Some(v) = self.node_id {
93 let v: u16 = v.into();
94 result.extend(v.to_be_bytes());
95 }
96
97 result
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use crate::{CommunicationCtrlType, CommunicationType, Configuration, RequestData};
104 use super::CommunicationCtrl;
105
106 #[test]
107 fn new() -> anyhow::Result<()> {
108 let source = hex::decode("280203")?;
109
110 let request = CommunicationCtrl::new(
111 CommunicationCtrlType::DisableRxAndEnableTx,
112 CommunicationType::NormalCommunicationMessages |
113 CommunicationType::NetworkManagementCommunicationMessages,
114 None,
115 )?;
116 let result: Vec<_> = request.into();
117 assert_eq!(result, source[2..].to_vec());
118
119 let cfg = Configuration::default();
120 let request = CommunicationCtrl::try_parse(
121 &source[2..],
122 Some(CommunicationCtrlType::DisableRxAndEnableTx),
123 &cfg,
124 )?;
125
126 assert_eq!(request.comm_type, CommunicationType(0x03));
127 assert_eq!(request.node_id, None);
128
129 Ok(())
130 }
131}