autosar_data_abstraction/communication/cluster/
can.rs1use crate::communication::{AbstractCluster, CanPhysicalChannel};
2use crate::{
3 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
4};
5use autosar_data::{Element, ElementName};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct CanCluster(Element);
11abstraction_element!(CanCluster, CanCluster);
12impl IdentifiableAbstractionElement for CanCluster {}
13
14impl CanCluster {
15 pub(crate) fn new(
17 cluster_name: &str,
18 package: &ArPackage,
19 can_baudrate: Option<u32>,
20 ) -> Result<Self, AutosarAbstractionError> {
21 let elem_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
22 let elem_cluster = elem_pkg_elements.create_named_sub_element(ElementName::CanCluster, cluster_name)?;
23 if let Ok(cluster_content) = elem_cluster
24 .create_sub_element(ElementName::CanClusterVariants)
25 .and_then(|ccv| ccv.create_sub_element(ElementName::CanClusterConditional))
26 {
27 let _ = cluster_content
28 .create_sub_element(ElementName::ProtocolName)
29 .and_then(|pn| pn.set_character_data("CAN"));
30
31 let _ = cluster_content.create_sub_element(ElementName::PhysicalChannels);
32 }
33
34 let can_cluster = CanCluster(elem_cluster);
35 can_cluster.set_baudrate(can_baudrate.unwrap_or(500_000))?;
36
37 Ok(can_cluster)
38 }
39
40 pub fn set_baudrate(&self, baudrate: u32) -> Result<(), AutosarAbstractionError> {
42 self.0
43 .get_or_create_sub_element(ElementName::CanClusterVariants)
44 .and_then(|ccv| ccv.get_or_create_sub_element(ElementName::CanClusterConditional))
45 .and_then(|cc| cc.get_or_create_sub_element(ElementName::Baudrate))
46 .and_then(|br| br.set_character_data(baudrate as u64))?;
47 Ok(())
48 }
49
50 #[must_use]
52 pub fn baudrate(&self) -> Option<u32> {
53 self.0
54 .get_sub_element(ElementName::CanClusterVariants)
55 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
56 .and_then(|cc| cc.get_sub_element(ElementName::Baudrate))
57 .and_then(|br| br.character_data())
58 .and_then(|cdata| cdata.parse_integer())
59 }
60
61 pub fn set_can_fd_baudrate(&self, baudrate: Option<u32>) -> Result<(), AutosarAbstractionError> {
63 if let Some(baudrate) = baudrate {
64 self.0
65 .get_or_create_sub_element(ElementName::CanClusterVariants)
66 .and_then(|ccv| ccv.get_or_create_sub_element(ElementName::CanClusterConditional))
67 .and_then(|cc| cc.get_or_create_sub_element(ElementName::CanFdBaudrate))
68 .and_then(|br| br.set_character_data(baudrate as u64))?;
69 } else {
70 let _ = self
71 .0
72 .get_sub_element(ElementName::CanClusterVariants)
73 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
74 .and_then(|cc| cc.remove_sub_element_kind(ElementName::CanFdBaudrate).ok());
75 }
76 Ok(())
77 }
78
79 #[must_use]
81 pub fn can_fd_baudrate(&self) -> Option<u32> {
82 self.0
83 .get_sub_element(ElementName::CanClusterVariants)
84 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
85 .and_then(|cc| cc.get_sub_element(ElementName::CanFdBaudrate))
86 .and_then(|br| br.character_data())
87 .and_then(|cdata| cdata.parse_integer())
88 }
89
90 pub fn set_can_xl_baudrate(&self, baudrate: Option<u32>) -> Result<(), AutosarAbstractionError> {
92 if let Some(baudrate) = baudrate {
93 self.0
94 .get_or_create_sub_element(ElementName::CanClusterVariants)
95 .and_then(|ccv| ccv.get_or_create_sub_element(ElementName::CanClusterConditional))
96 .and_then(|cc| cc.get_or_create_sub_element(ElementName::CanXlBaudrate))
97 .and_then(|br| br.set_character_data(baudrate as u64))?;
98 } else {
99 let _ = self
100 .0
101 .get_sub_element(ElementName::CanClusterVariants)
102 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
103 .and_then(|cc| cc.remove_sub_element_kind(ElementName::CanXlBaudrate).ok());
104 }
105 Ok(())
106 }
107
108 #[must_use]
110 pub fn can_xl_baudrate(&self) -> Option<u32> {
111 self.0
112 .get_sub_element(ElementName::CanClusterVariants)
113 .and_then(|ccv| ccv.get_sub_element(ElementName::CanClusterConditional))
114 .and_then(|cc| cc.get_sub_element(ElementName::CanXlBaudrate))
115 .and_then(|br| br.character_data())
116 .and_then(|cdata| cdata.parse_integer())
117 }
118
119 pub fn create_physical_channel(&self, channel_name: &str) -> Result<CanPhysicalChannel, AutosarAbstractionError> {
143 let phys_channels = self
144 .0
145 .get_or_create_sub_element(ElementName::CanClusterVariants)?
146 .get_or_create_sub_element(ElementName::CanClusterConditional)?
147 .get_or_create_sub_element(ElementName::PhysicalChannels)?;
148
149 if phys_channels.sub_elements().count() != 0 {
150 return Err(AutosarAbstractionError::ItemAlreadyExists);
151 }
152
153 let channel = phys_channels.create_named_sub_element(ElementName::CanPhysicalChannel, channel_name)?;
154
155 CanPhysicalChannel::try_from(channel)
156 }
157
158 #[must_use]
178 pub fn physical_channel(&self) -> Option<CanPhysicalChannel> {
179 let channel = self
180 .0
181 .get_sub_element(ElementName::CanClusterVariants)?
182 .get_sub_element(ElementName::CanClusterConditional)?
183 .get_sub_element(ElementName::PhysicalChannels)?
184 .get_sub_element(ElementName::CanPhysicalChannel)?;
185 CanPhysicalChannel::try_from(channel).ok()
186 }
187}
188
189impl AbstractCluster for CanCluster {}
190
191#[cfg(test)]
194mod test {
195 use crate::{AutosarModelAbstraction, SystemCategory, communication::AbstractCluster};
196 use autosar_data::AutosarVersion;
197
198 #[test]
199 fn cluster() {
200 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00051);
201 let pkg = model.get_or_create_package("/test").unwrap();
202 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
203
204 let pkg2 = model.get_or_create_package("/can").unwrap();
205 let result = system.create_can_cluster("CanCluster", &pkg2, None);
207 assert!(result.is_ok());
208 let cluster = result.unwrap();
209 let result = system.create_can_cluster("CanCluster", &pkg2, None);
211 assert!(result.is_err());
212
213 let linked_system = cluster.system().unwrap();
215 assert_eq!(linked_system, system);
216
217 cluster.set_baudrate(250_000).unwrap();
219 assert_eq!(cluster.baudrate().unwrap(), 250_000);
220 cluster.set_can_fd_baudrate(Some(2_000_000)).unwrap();
221 assert_eq!(cluster.can_fd_baudrate().unwrap(), 2_000_000);
222 cluster.set_can_xl_baudrate(Some(10_000_000)).unwrap();
223 assert_eq!(cluster.can_xl_baudrate().unwrap(), 10_000_000);
224 cluster.set_can_fd_baudrate(None).unwrap();
226 assert!(cluster.can_fd_baudrate().is_none());
227 cluster.set_can_xl_baudrate(None).unwrap();
229 assert!(cluster.can_xl_baudrate().is_none());
230
231 let result = cluster.create_physical_channel("Channel1");
233 assert!(result.is_ok());
234 let result = cluster.create_physical_channel("Channel2");
236 assert!(result.is_err());
237
238 let pc = cluster.physical_channel();
239 assert!(pc.is_some());
240 }
241}