autosar_data_abstraction/communication/controller/
can.rs1use crate::{
2 AbstractionElement, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement, abstraction_element,
3 communication::{AbstractCommunicationConnector, AbstractCommunicationController, CanPhysicalChannel},
4};
5use autosar_data::{AutosarDataError, AutosarModel, Element, ElementName, ElementsIterator, WeakElement};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct CanCommunicationController(Element);
10abstraction_element!(CanCommunicationController, CanCommunicationController);
11impl IdentifiableAbstractionElement for CanCommunicationController {}
12
13impl CanCommunicationController {
14 pub(crate) fn new(name: &str, ecu: &EcuInstance) -> Result<Self, AutosarAbstractionError> {
16 let commcontrollers = ecu.element().get_or_create_sub_element(ElementName::CommControllers)?;
17 let ctrl = commcontrollers.create_named_sub_element(ElementName::CanCommunicationController, name)?;
18 let _canccc = ctrl
19 .create_sub_element(ElementName::CanCommunicationControllerVariants)?
20 .create_sub_element(ElementName::CanCommunicationControllerConditional)?;
21
22 Ok(Self(ctrl))
23 }
24
25 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
27 let ecu_instance = self.ecu_instance()?;
29 for connector in ecu_instance
30 .element()
31 .get_sub_element(ElementName::Connectors)
32 .iter()
33 .flat_map(|connectors| connectors.sub_elements())
34 .filter_map(|conn| CanCommunicationConnector::try_from(conn).ok())
35 {
36 if let Ok(controller_of_connector) = connector.controller()
37 && controller_of_connector == self
38 {
39 connector.remove(deep)?;
40 }
41 }
42
43 AbstractionElement::remove(self, deep)
44 }
45
46 pub fn connected_channels(&self) -> impl Iterator<Item = CanPhysicalChannel> + Send + use<> {
73 if let Ok(ecu) = self.ecu_instance().map(|ecuinstance| ecuinstance.element().clone()) {
74 CanCtrlChannelsIterator::new(self, &ecu)
75 } else {
76 CanCtrlChannelsIterator {
77 connector_iter: None,
78 comm_controller: self.0.clone(),
79 model: None,
80 }
81 }
82 }
83
84 pub fn connect_physical_channel(
114 &self,
115 connection_name: &str,
116 can_channel: &CanPhysicalChannel,
117 ) -> Result<CanCommunicationConnector, AutosarAbstractionError> {
118 let ecu = self.0.named_parent()?.unwrap();
119 if let Some(connectors) = ecu.get_sub_element(ElementName::Connectors) {
121 for connector in connectors.sub_elements() {
122 if let Some(ccref) = connector.get_sub_element(ElementName::CommControllerRef)
126 && let Ok(commcontroller_of_connector) = ccref.get_reference_target()
127 && commcontroller_of_connector == self.0
128 {
129 return Err(AutosarAbstractionError::ItemAlreadyExists);
130 }
131 }
132 }
133 let connectors = ecu.get_or_create_sub_element(ElementName::Connectors)?;
135 let connector = CanCommunicationConnector::new(connection_name, &connectors, self)?;
136
137 let channel_connector_refs = can_channel
138 .element()
139 .get_or_create_sub_element(ElementName::CommConnectors)?;
140 channel_connector_refs
141 .create_sub_element(ElementName::CommunicationConnectorRefConditional)
142 .and_then(|ccrc| ccrc.create_sub_element(ElementName::CommunicationConnectorRef))
143 .and_then(|ccr| ccr.set_reference_target(connector.element()))?;
144
145 Ok(connector)
146 }
147}
148
149impl AbstractCommunicationController for CanCommunicationController {}
150
151#[derive(Debug, Clone, PartialEq, Eq, Hash)]
155pub struct CanCommunicationConnector(Element);
156abstraction_element!(CanCommunicationConnector, CanCommunicationConnector);
157impl IdentifiableAbstractionElement for CanCommunicationConnector {}
158
159impl CanCommunicationConnector {
160 pub(crate) fn new(
161 name: &str,
162 parent: &Element,
163 controller: &CanCommunicationController,
164 ) -> Result<Self, AutosarAbstractionError> {
165 let connector = parent.create_named_sub_element(ElementName::CanCommunicationConnector, name)?;
166 connector
167 .create_sub_element(ElementName::CommControllerRef)?
168 .set_reference_target(controller.element())?;
169 Ok(Self(connector))
170 }
171}
172
173impl AbstractCommunicationConnector for CanCommunicationConnector {
174 type CommunicationControllerType = CanCommunicationController;
175
176 fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
177 let controller = self
178 .element()
179 .get_sub_element(ElementName::CommControllerRef)
180 .ok_or_else(|| {
181 AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
182 target: ElementName::CommControllerRef,
183 parent: self.element().element_name(),
184 })
185 })?
186 .get_reference_target()?;
187 CanCommunicationController::try_from(controller)
188 }
189}
190
191#[doc(hidden)]
194pub struct CanCtrlChannelsIterator {
195 connector_iter: Option<ElementsIterator>,
196 comm_controller: Element,
197 model: Option<AutosarModel>,
198}
199
200impl CanCtrlChannelsIterator {
201 fn new(controller: &CanCommunicationController, ecu: &Element) -> Self {
202 let iter = ecu.get_sub_element(ElementName::Connectors).map(|c| c.sub_elements());
203 let comm_controller = controller.element().clone();
204 let model = comm_controller.model().ok();
205 Self {
206 connector_iter: iter,
207 comm_controller,
208 model,
209 }
210 }
211}
212
213impl Iterator for CanCtrlChannelsIterator {
214 type Item = CanPhysicalChannel;
215
216 fn next(&mut self) -> Option<Self::Item> {
217 let model = self.model.as_ref()?;
218 let connector_iter = self.connector_iter.as_mut()?;
219 for connector in connector_iter.by_ref() {
220 if connector.element_name() == ElementName::CanCommunicationConnector
221 && let Some(commcontroller_of_connector) = connector
222 .get_sub_element(ElementName::CommControllerRef)
223 .and_then(|ccr| ccr.get_reference_target().ok())
224 && commcontroller_of_connector == self.comm_controller
225 {
226 for ref_origin in model
227 .get_references_to(&connector.path().ok()?)
228 .iter()
229 .filter_map(WeakElement::upgrade)
230 .filter_map(|elem| elem.named_parent().ok().flatten())
231 {
232 if ref_origin.element_name() == ElementName::CanPhysicalChannel {
235 return CanPhysicalChannel::try_from(ref_origin).ok();
236 }
237 }
238 }
239 }
240 None
241 }
242}
243
244#[cfg(test)]
247mod test {
248 use super::*;
249 use crate::{AutosarModelAbstraction, SystemCategory};
250 use autosar_data::AutosarVersion;
251
252 #[test]
253 fn controller() {
254 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
255 let pkg = model.get_or_create_package("/test").unwrap();
256 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
257 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
258
259 let result = ecu.create_can_communication_controller("Controller");
261 let controller = result.unwrap();
262
263 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
265 let channel1 = cluster.create_physical_channel("C1").unwrap();
266
267 let connector = controller
269 .connect_physical_channel("connection_name1", &channel1)
270 .unwrap();
271 assert_eq!(connector.controller().unwrap(), controller);
272 let result = controller.connect_physical_channel("connection_name2", &channel1);
274 assert!(result.is_err());
275
276 let count = controller.connected_channels().count();
277 assert_eq!(count, 1);
278
279 let ctrl_parent = controller.0.parent().unwrap().unwrap();
281 ctrl_parent.remove_sub_element(controller.0.clone()).unwrap();
282 let count = controller.connected_channels().count();
283 assert_eq!(count, 0);
284 }
285
286 #[test]
287 fn connector() {
288 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
289 let pkg = model.get_or_create_package("/test").unwrap();
290 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
291 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
292
293 let controller = ecu.create_can_communication_controller("Controller").unwrap();
295 assert_eq!(controller.ecu_instance().unwrap(), ecu);
296
297 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
299 let channel1 = cluster.create_physical_channel("C1").unwrap();
300
301 let connector = controller
303 .connect_physical_channel("connection_name1", &channel1)
304 .unwrap();
305 assert_eq!(connector.controller().unwrap(), controller);
306 assert_eq!(connector.ecu_instance().unwrap(), ecu);
307
308 connector
310 .element()
311 .remove_sub_element_kind(ElementName::CommControllerRef)
312 .unwrap();
313 let result = connector.controller();
314 assert!(result.is_err());
315 }
316
317 #[test]
318 fn remove_controller() {
319 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
320 let pkg = model.get_or_create_package("/test").unwrap();
321 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
322 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
323 let controller = ecu.create_can_communication_controller("Controller").unwrap();
325 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
327 let channel = cluster.create_physical_channel("C1").unwrap();
328 let connector = controller
330 .connect_physical_channel("connection_name1", &channel)
331 .unwrap();
332
333 controller.remove(true).unwrap();
335
336 assert_eq!(ecu.communication_controllers().count(), 0);
337 assert!(connector.element().path().is_err());
338 }
339}