autosar_data_abstraction/communication/cluster/
can.rs1use crate::communication::{AbstractCluster, CanNmCluster, CanPhysicalChannel};
2use crate::{
3 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
4 get_reference_parents,
5};
6use autosar_data::{Element, ElementName};
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct CanCluster(Element);
12abstraction_element!(CanCluster, CanCluster);
13impl IdentifiableAbstractionElement for CanCluster {}
14
15impl CanCluster {
16 pub(crate) fn new(
18 cluster_name: &str,
19 package: &ArPackage,
20 can_baudrate: Option<u32>,
21 ) -> Result<Self, AutosarAbstractionError> {
22 let elem_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
23 let elem_cluster = elem_pkg_elements.create_named_sub_element(ElementName::CanCluster, cluster_name)?;
24 if let Ok(cluster_content) = elem_cluster
25 .create_sub_element(ElementName::CanClusterVariants)
26 .and_then(|ccv| ccv.create_sub_element(ElementName::CanClusterConditional))
27 {
28 let _ = cluster_content
29 .create_sub_element(ElementName::ProtocolName)
30 .and_then(|pn| pn.set_character_data("CAN"));
31
32 let _ = cluster_content.create_sub_element(ElementName::PhysicalChannels);
33 }
34
35 let can_cluster = CanCluster(elem_cluster);
36 can_cluster.set_baudrate(can_baudrate.unwrap_or(500_000))?;
37
38 Ok(can_cluster)
39 }
40
41 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
43 if let Some(channel) = self.physical_channel() {
45 channel.remove(deep)?;
46 }
47 let ref_parents = get_reference_parents(&self.0)?;
48
49 AbstractionElement::remove(self, deep)?;
51
52 for (named_parent, _parent) in ref_parents {
55 match named_parent.element_name() {
56 ElementName::CanTpConfig => {
57 if let Ok(can_tp_config) = crate::communication::CanTpConfig::try_from(named_parent) {
58 can_tp_config.remove(deep)?;
59 }
60 }
61 ElementName::CanNmCluster => {
62 if let Ok(can_nm_cluster) = CanNmCluster::try_from(named_parent) {
63 can_nm_cluster.remove(deep)?;
64 }
65 }
66 _ => {}
67 }
68 }
69
70 Ok(())
71 }
72
73 pub fn set_baudrate(&self, baudrate: u32) -> Result<(), AutosarAbstractionError> {
75 self.0
76 .get_or_create_sub_element(ElementName::CanClusterVariants)
77 .and_then(|ccv| ccv.get_or_create_sub_element(ElementName::CanClusterConditional))
78 .and_then(|cc| cc.get_or_create_sub_element(ElementName::Baudrate))
79 .and_then(|br| br.set_character_data(baudrate as u64))?;
80 Ok(())
81 }
82
83 #[must_use]
85 pub fn baudrate(&self) -> Option<u32> {
86 self.0
87 .get_sub_element(ElementName::CanClusterVariants)
88 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
89 .and_then(|cc| cc.get_sub_element(ElementName::Baudrate))
90 .and_then(|br| br.character_data())
91 .and_then(|cdata| cdata.parse_integer())
92 }
93
94 pub fn set_can_fd_baudrate(&self, baudrate: Option<u32>) -> Result<(), AutosarAbstractionError> {
96 if let Some(baudrate) = baudrate {
97 self.0
98 .get_or_create_sub_element(ElementName::CanClusterVariants)
99 .and_then(|ccv| ccv.get_or_create_sub_element(ElementName::CanClusterConditional))
100 .and_then(|cc| cc.get_or_create_sub_element(ElementName::CanFdBaudrate))
101 .and_then(|br| br.set_character_data(baudrate as u64))?;
102 } else {
103 let _ = self
104 .0
105 .get_sub_element(ElementName::CanClusterVariants)
106 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
107 .and_then(|cc| cc.remove_sub_element_kind(ElementName::CanFdBaudrate).ok());
108 }
109 Ok(())
110 }
111
112 #[must_use]
114 pub fn can_fd_baudrate(&self) -> Option<u32> {
115 self.0
116 .get_sub_element(ElementName::CanClusterVariants)
117 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
118 .and_then(|cc| cc.get_sub_element(ElementName::CanFdBaudrate))
119 .and_then(|br| br.character_data())
120 .and_then(|cdata| cdata.parse_integer())
121 }
122
123 pub fn set_can_xl_baudrate(&self, baudrate: Option<u32>) -> Result<(), AutosarAbstractionError> {
125 if let Some(baudrate) = baudrate {
126 self.0
127 .get_or_create_sub_element(ElementName::CanClusterVariants)
128 .and_then(|ccv| ccv.get_or_create_sub_element(ElementName::CanClusterConditional))
129 .and_then(|cc| cc.get_or_create_sub_element(ElementName::CanXlBaudrate))
130 .and_then(|br| br.set_character_data(baudrate as u64))?;
131 } else {
132 let _ = self
133 .0
134 .get_sub_element(ElementName::CanClusterVariants)
135 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
136 .and_then(|cc| cc.remove_sub_element_kind(ElementName::CanXlBaudrate).ok());
137 }
138 Ok(())
139 }
140
141 #[must_use]
143 pub fn can_xl_baudrate(&self) -> Option<u32> {
144 self.0
145 .get_sub_element(ElementName::CanClusterVariants)
146 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
147 .and_then(|cc| cc.get_sub_element(ElementName::CanXlBaudrate))
148 .and_then(|br| br.character_data())
149 .and_then(|cdata| cdata.parse_integer())
150 }
151
152 pub fn create_physical_channel(&self, channel_name: &str) -> Result<CanPhysicalChannel, AutosarAbstractionError> {
176 let phys_channels = self
177 .0
178 .get_or_create_sub_element(ElementName::CanClusterVariants)?
179 .get_or_create_sub_element(ElementName::CanClusterConditional)?
180 .get_or_create_sub_element(ElementName::PhysicalChannels)?;
181
182 if phys_channels.sub_elements().count() != 0 {
183 return Err(AutosarAbstractionError::ItemAlreadyExists);
184 }
185
186 let channel = phys_channels.create_named_sub_element(ElementName::CanPhysicalChannel, channel_name)?;
187
188 CanPhysicalChannel::try_from(channel)
189 }
190
191 #[must_use]
211 pub fn physical_channel(&self) -> Option<CanPhysicalChannel> {
212 let channel = self
213 .0
214 .get_sub_element(ElementName::CanClusterVariants)?
215 .get_sub_element(ElementName::CanClusterConditional)?
216 .get_sub_element(ElementName::PhysicalChannels)?
217 .get_sub_element(ElementName::CanPhysicalChannel)?;
218 CanPhysicalChannel::try_from(channel).ok()
219 }
220}
221
222impl AbstractCluster for CanCluster {}
223
224#[cfg(test)]
227mod test {
228 use crate::{
229 AbstractionElement, AutosarModelAbstraction, SystemCategory,
230 communication::{AbstractCluster, CanNmClusterSettings},
231 };
232 use autosar_data::AutosarVersion;
233
234 #[test]
235 fn cluster() {
236 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00051);
237 let pkg = model.get_or_create_package("/test").unwrap();
238 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
239
240 let pkg2 = model.get_or_create_package("/can").unwrap();
241 let result = system.create_can_cluster("CanCluster", &pkg2, None);
243 assert!(result.is_ok());
244 let cluster = result.unwrap();
245 let result = system.create_can_cluster("CanCluster", &pkg2, None);
247 assert!(result.is_err());
248
249 let linked_system = cluster.system().unwrap();
251 assert_eq!(linked_system, system);
252
253 cluster.set_baudrate(250_000).unwrap();
255 assert_eq!(cluster.baudrate().unwrap(), 250_000);
256 cluster.set_can_fd_baudrate(Some(2_000_000)).unwrap();
257 assert_eq!(cluster.can_fd_baudrate().unwrap(), 2_000_000);
258 cluster.set_can_xl_baudrate(Some(10_000_000)).unwrap();
259 assert_eq!(cluster.can_xl_baudrate().unwrap(), 10_000_000);
260 cluster.set_can_fd_baudrate(None).unwrap();
262 assert!(cluster.can_fd_baudrate().is_none());
263 cluster.set_can_xl_baudrate(None).unwrap();
265 assert!(cluster.can_xl_baudrate().is_none());
266
267 let result = cluster.create_physical_channel("Channel1");
269 assert!(result.is_ok());
270 let result = cluster.create_physical_channel("Channel2");
272 assert!(result.is_err());
273
274 let pc = cluster.physical_channel();
275 assert!(pc.is_some());
276 }
277
278 #[test]
279 fn remove_cluster() {
280 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00051);
281 let pkg = model.get_or_create_package("/test").unwrap();
282 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
283
284 let pkg2 = model.get_or_create_package("/can").unwrap();
285 let cluster = system.create_can_cluster("CanCluster", &pkg2, None).unwrap();
286 let channel = cluster.create_physical_channel("Channel1").unwrap();
287
288 let nm_config = system.create_nm_config("NmConfig", &pkg2).unwrap();
289 let can_nm_cluster_settings = CanNmClusterSettings {
290 nm_busload_reduction_active: false,
291 nm_immediate_nm_transmissions: 5,
292 nm_message_timeout_time: 5.0,
293 nm_msg_cycle_time: 5.0,
294 nm_network_timeout: 8.0,
295 nm_remote_sleep_indication_time: 3.0,
296 nm_repeat_message_time: 1.0,
297 nm_wait_bus_sleep_time: 1.0,
298 };
299 let can_nm_cluster = nm_config
300 .create_can_nm_cluster("CanNmCluster", &can_nm_cluster_settings, &cluster)
301 .unwrap();
302 let can_tp_config = system.create_can_tp_config("CanTpConfig", &pkg2, &cluster).unwrap();
303
304 let result = cluster.remove(true);
306 assert!(result.is_ok());
307
308 assert!(channel.element().path().is_err());
310 assert!(can_nm_cluster.element().path().is_err());
311 assert!(can_tp_config.element().path().is_err());
312 }
313}