autosar_data_abstraction/communication/controller/
lin.rs1use crate::{
2 AbstractionElement, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement, abstraction_element,
3 communication::{AbstractCommunicationConnector, AbstractCommunicationController, LinPhysicalChannel},
4};
5use autosar_data::{AutosarDataError, AutosarModel, Element, ElementName, ElementsIterator, WeakElement};
6
7pub trait AbstractLinCommunicationController:
11 AbstractCommunicationController + Into<LinCommunicationController>
12{
13 fn connected_channels(&self) -> impl Iterator<Item = LinPhysicalChannel> + Send + use<Self> {
40 if let Ok(ecu) = self.ecu_instance().map(|ecuinstance| ecuinstance.element().clone()) {
41 LinCtrlChannelsIterator::new(&self.clone().into(), &ecu)
42 } else {
43 LinCtrlChannelsIterator {
44 connector_iter: None,
45 comm_controller: self.element().clone(),
46 model: None,
47 }
48 }
49 }
50
51 fn connect_physical_channel(
81 &self,
82 connection_name: &str,
83 lin_channel: &LinPhysicalChannel,
84 ) -> Result<LinCommunicationConnector, AutosarAbstractionError> {
85 let ecu = self.element().named_parent()?.unwrap();
86 if let Some(connectors) = ecu.get_sub_element(ElementName::Connectors) {
88 for connector in connectors.sub_elements() {
89 if let Some(ccref) = connector.get_sub_element(ElementName::CommControllerRef)
93 && let Ok(commcontroller_of_connector) = ccref.get_reference_target()
94 && &commcontroller_of_connector == self.element()
95 {
96 return Err(AutosarAbstractionError::ItemAlreadyExists);
97 }
98 }
99 }
100 let connectors = ecu.get_or_create_sub_element(ElementName::Connectors)?;
102 let connector = LinCommunicationConnector::new(connection_name, &connectors, &self.clone().into())?;
103
104 let channel_connector_refs = lin_channel
105 .element()
106 .get_or_create_sub_element(ElementName::CommConnectors)?;
107 channel_connector_refs
108 .create_sub_element(ElementName::CommunicationConnectorRefConditional)
109 .and_then(|ccrc| ccrc.create_sub_element(ElementName::CommunicationConnectorRef))
110 .and_then(|ccr| ccr.set_reference_target(connector.element()))?;
111
112 Ok(connector)
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq, Hash)]
120pub struct LinMaster(Element);
121abstraction_element!(LinMaster, LinMaster);
122impl IdentifiableAbstractionElement for LinMaster {}
123
124impl LinMaster {
125 pub(crate) fn new(name: &str, ecu: &EcuInstance) -> Result<Self, AutosarAbstractionError> {
127 let commcontrollers = ecu.element().get_or_create_sub_element(ElementName::CommControllers)?;
128 let ctrl = commcontrollers.create_named_sub_element(ElementName::LinMaster, name)?;
129 let _lincc = ctrl
130 .create_sub_element(ElementName::LinMasterVariants)?
131 .create_sub_element(ElementName::LinMasterConditional)?;
132
133 Ok(Self(ctrl))
134 }
135
136 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
138 let ecu_instance = self.ecu_instance()?;
140 for connector in ecu_instance
141 .element()
142 .get_sub_element(ElementName::Connectors)
143 .iter()
144 .flat_map(|connectors| connectors.sub_elements())
145 .filter_map(|conn| LinCommunicationConnector::try_from(conn).ok())
146 {
147 if let Ok(controller_of_connector) = connector.controller()
148 && controller_of_connector.element() == self.element()
149 {
150 connector.remove(deep)?;
151 }
152 }
153
154 AbstractionElement::remove(self, deep)
155 }
156}
157
158impl AbstractCommunicationController for LinMaster {}
159impl AbstractLinCommunicationController for LinMaster {}
160
161#[derive(Debug, Clone, PartialEq, Eq, Hash)]
165pub struct LinSlave(Element);
166abstraction_element!(LinSlave, LinSlave);
167impl IdentifiableAbstractionElement for LinSlave {}
168
169impl LinSlave {
170 pub(crate) fn new(name: &str, ecu: &EcuInstance) -> Result<Self, AutosarAbstractionError> {
172 let commcontrollers = ecu.element().get_or_create_sub_element(ElementName::CommControllers)?;
173 let ctrl = commcontrollers.create_named_sub_element(ElementName::LinSlave, name)?;
174 let _linsc = ctrl
175 .create_sub_element(ElementName::LinSlaveVariants)?
176 .create_sub_element(ElementName::LinSlaveConditional)?;
177
178 Ok(Self(ctrl))
179 }
180
181 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
183 let ecu_instance = self.ecu_instance()?;
185 for connector in ecu_instance
186 .element()
187 .get_sub_element(ElementName::Connectors)
188 .iter()
189 .flat_map(|connectors| connectors.sub_elements())
190 .filter_map(|conn| LinCommunicationConnector::try_from(conn).ok())
191 {
192 if let Ok(controller_of_connector) = connector.controller()
193 && controller_of_connector.element() == self.element()
194 {
195 connector.remove(deep)?;
196 }
197 }
198
199 AbstractionElement::remove(self, deep)
200 }
201}
202
203impl AbstractCommunicationController for LinSlave {}
204impl AbstractLinCommunicationController for LinSlave {}
205
206#[derive(Debug, Clone, PartialEq, Eq, Hash)]
210pub struct LinCommunicationConnector(Element);
211abstraction_element!(LinCommunicationConnector, LinCommunicationConnector);
212impl IdentifiableAbstractionElement for LinCommunicationConnector {}
213
214impl LinCommunicationConnector {
215 pub(crate) fn new(
216 name: &str,
217 parent: &Element,
218 controller: &LinCommunicationController,
219 ) -> Result<Self, AutosarAbstractionError> {
220 let connector = parent.create_named_sub_element(ElementName::LinCommunicationConnector, name)?;
221 connector
222 .create_sub_element(ElementName::CommControllerRef)?
223 .set_reference_target(controller.element())?;
224 Ok(Self(connector))
225 }
226}
227
228impl AbstractCommunicationConnector for LinCommunicationConnector {
229 type CommunicationControllerType = LinCommunicationController;
230
231 fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
232 let controller = self
233 .element()
234 .get_sub_element(ElementName::CommControllerRef)
235 .ok_or_else(|| {
236 AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
237 target: ElementName::CommControllerRef,
238 parent: self.element().element_name(),
239 })
240 })?
241 .get_reference_target()?;
242 LinCommunicationController::try_from(controller)
243 }
244}
245
246#[derive(Debug, Clone, PartialEq, Eq, Hash)]
250pub enum LinCommunicationController {
251 Master(LinMaster),
253 Slave(LinSlave),
255}
256impl AbstractionElement for LinCommunicationController {
257 fn element(&self) -> &autosar_data::Element {
258 match self {
259 LinCommunicationController::Master(master) => master.element(),
260 LinCommunicationController::Slave(slave) => slave.element(),
261 }
262 }
263}
264impl AbstractCommunicationController for LinCommunicationController {}
265
266impl TryFrom<Element> for LinCommunicationController {
267 type Error = AutosarAbstractionError;
268
269 fn try_from(element: Element) -> Result<Self, Self::Error> {
270 match element.element_name() {
271 ElementName::LinMaster => Ok(Self::Master(LinMaster::try_from(element)?)),
272 ElementName::LinSlave => Ok(Self::Slave(LinSlave::try_from(element)?)),
273 _ => Err(AutosarAbstractionError::ConversionError {
274 element,
275 dest: "LinCommunicationController".to_string(),
276 }),
277 }
278 }
279}
280
281impl From<LinMaster> for LinCommunicationController {
282 fn from(value: LinMaster) -> Self {
283 LinCommunicationController::Master(value)
284 }
285}
286
287impl From<LinSlave> for LinCommunicationController {
288 fn from(value: LinSlave) -> Self {
289 LinCommunicationController::Slave(value)
290 }
291}
292
293#[doc(hidden)]
296pub struct LinCtrlChannelsIterator {
297 connector_iter: Option<ElementsIterator>,
298 comm_controller: Element,
299 model: Option<AutosarModel>,
300}
301
302impl LinCtrlChannelsIterator {
303 fn new(controller: &LinCommunicationController, ecu: &Element) -> Self {
304 let iter = ecu.get_sub_element(ElementName::Connectors).map(|c| c.sub_elements());
305 let comm_controller = controller.element().clone();
306 let model = comm_controller.model().ok();
307 Self {
308 connector_iter: iter,
309 comm_controller,
310 model,
311 }
312 }
313}
314
315impl Iterator for LinCtrlChannelsIterator {
316 type Item = LinPhysicalChannel;
317
318 fn next(&mut self) -> Option<Self::Item> {
319 let model = self.model.as_ref()?;
320 let connector_iter = self.connector_iter.as_mut()?;
321 for connector in connector_iter.by_ref() {
322 if connector.element_name() == ElementName::LinCommunicationConnector
323 && let Some(commcontroller_of_connector) = connector
324 .get_sub_element(ElementName::CommControllerRef)
325 .and_then(|ccr| ccr.get_reference_target().ok())
326 && commcontroller_of_connector == self.comm_controller
327 {
328 for ref_origin in model
329 .get_references_to(&connector.path().ok()?)
330 .iter()
331 .filter_map(WeakElement::upgrade)
332 .filter_map(|elem| elem.named_parent().ok().flatten())
333 {
334 if ref_origin.element_name() == ElementName::LinPhysicalChannel {
337 return LinPhysicalChannel::try_from(ref_origin).ok();
338 }
339 }
340 }
341 }
342 None
343 }
344}
345
346#[cfg(test)]
349mod test {
350 use autosar_data::AutosarVersion;
351
352 use crate::{AutosarModelAbstraction, SystemCategory};
353
354 use super::*;
355
356 #[test]
357 fn controller() {
358 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
359 let pkg = model.get_or_create_package("/test").unwrap();
360 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
361 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
362
363 let result = ecu.create_lin_master_communication_controller("LinMaster");
365 let lin_master = result.unwrap();
366 let result = ecu.create_lin_slave_communication_controller("LinSlave");
367 let lin_slave = result.unwrap();
368
369 let cluster = system.create_lin_cluster("LinCluster", &pkg).unwrap();
371 let channel = cluster.create_physical_channel("C1").unwrap();
372
373 let connector_m = lin_master
375 .connect_physical_channel("master_connection", &channel)
376 .unwrap();
377 assert_eq!(connector_m.controller().unwrap(), lin_master.clone().into());
378 let connector_s = lin_slave
379 .connect_physical_channel("slave_connection", &channel)
380 .unwrap();
381 assert_eq!(connector_s.controller().unwrap(), lin_slave.clone().into());
382 let result = lin_master.connect_physical_channel("connection_name2", &channel);
384 assert!(result.is_err());
385
386 let count = lin_master.connected_channels().count();
387 assert_eq!(count, 1);
388
389 let ctrl_parent = lin_master.0.parent().unwrap().unwrap();
391 ctrl_parent.remove_sub_element(lin_master.0.clone()).unwrap();
392 let count = lin_master.connected_channels().count();
393 assert_eq!(count, 0);
394 }
395
396 #[test]
397 fn connector() {
398 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
399 let pkg = model.get_or_create_package("/test").unwrap();
400 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
401 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
402
403 let lin_master = ecu.create_lin_master_communication_controller("Controller").unwrap();
405 assert_eq!(lin_master.ecu_instance().unwrap(), ecu);
406
407 let cluster = system.create_lin_cluster("LinCluster", &pkg).unwrap();
409 let channel = cluster.create_physical_channel("C1").unwrap();
410
411 let connector = lin_master
413 .connect_physical_channel("connection_name1", &channel)
414 .unwrap();
415 assert_eq!(connector.controller().unwrap(), lin_master.clone().into());
416 assert_eq!(connector.ecu_instance().unwrap(), ecu);
417
418 connector
420 .element()
421 .remove_sub_element_kind(ElementName::CommControllerRef)
422 .unwrap();
423 let result = connector.controller();
424 assert!(result.is_err());
425 }
426
427 #[test]
428 fn remove_controller() {
429 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
430 let pkg = model.get_or_create_package("/test").unwrap();
431 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
432 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
433 let lin_master = ecu.create_lin_master_communication_controller("Controller").unwrap();
435 let cluster = system.create_lin_cluster("LinCluster", &pkg).unwrap();
437 let channel = cluster.create_physical_channel("C1").unwrap();
438 let connector = lin_master
440 .connect_physical_channel("connection_name1", &channel)
441 .unwrap();
442
443 lin_master.remove(true).unwrap();
445
446 assert_eq!(ecu.communication_controllers().count(), 0);
447 assert!(connector.element().path().is_err());
448 }
449}