autosar_data_abstraction/communication/controller/
mod.rs

1use crate::{AbstractionElement, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement};
2use autosar_data::{AutosarDataError, Element, ElementName};
3
4mod can;
5mod ethernet;
6mod flexray;
7mod lin;
8
9pub use can::*;
10pub use ethernet::*;
11pub use flexray::*;
12pub use lin::*;
13
14//##################################################################
15
16/// wraps all different kinds of communication controller
17#[derive(Debug, Clone, PartialEq, Eq)]
18#[non_exhaustive]
19pub enum CommunicationController {
20    /// The `CommunicationController` is a [`CanCommunicationController`]
21    Can(CanCommunicationController),
22    /// The `CommunicationController` is an [`EthernetCommunicationController`]
23    Ethernet(EthernetCommunicationController),
24    /// The `CommunicationController` is a [`FlexrayCommunicationController`]
25    Flexray(FlexrayCommunicationController),
26    /// The `CommunicationController` is a [`LinMaster`] CommunicationController
27    LinMaster(LinMaster),
28    /// The `CommunicationController` is a [`LinSlave`] CommunicationController
29    LinSlave(LinSlave),
30}
31
32impl AbstractionElement for CommunicationController {
33    fn element(&self) -> &autosar_data::Element {
34        match self {
35            CommunicationController::Can(ccc) => ccc.element(),
36            CommunicationController::Ethernet(ecc) => ecc.element(),
37            CommunicationController::Flexray(fcc) => fcc.element(),
38            CommunicationController::LinMaster(lcc) => lcc.element(),
39            CommunicationController::LinSlave(lcc) => lcc.element(),
40        }
41    }
42}
43
44impl TryFrom<Element> for CommunicationController {
45    type Error = AutosarAbstractionError;
46
47    fn try_from(element: Element) -> Result<Self, Self::Error> {
48        match element.element_name() {
49            ElementName::CanCommunicationController => Ok(Self::Can(CanCommunicationController::try_from(element)?)),
50            ElementName::EthernetCommunicationController => {
51                Ok(Self::Ethernet(EthernetCommunicationController::try_from(element)?))
52            }
53            ElementName::FlexrayCommunicationController => {
54                Ok(Self::Flexray(FlexrayCommunicationController::try_from(element)?))
55            }
56            ElementName::LinMaster => Ok(Self::LinMaster(LinMaster::try_from(element)?)),
57            ElementName::LinSlave => Ok(Self::LinSlave(LinSlave::try_from(element)?)),
58            _ => Err(AutosarAbstractionError::ConversionError {
59                element,
60                dest: "CommunicationController".to_string(),
61            }),
62        }
63    }
64}
65
66impl IdentifiableAbstractionElement for CommunicationController {}
67impl AbstractCommunicationController for CommunicationController {}
68
69impl From<CanCommunicationController> for CommunicationController {
70    fn from(value: CanCommunicationController) -> Self {
71        CommunicationController::Can(value)
72    }
73}
74
75impl From<EthernetCommunicationController> for CommunicationController {
76    fn from(value: EthernetCommunicationController) -> Self {
77        CommunicationController::Ethernet(value)
78    }
79}
80
81impl From<FlexrayCommunicationController> for CommunicationController {
82    fn from(value: FlexrayCommunicationController) -> Self {
83        CommunicationController::Flexray(value)
84    }
85}
86
87impl From<LinMaster> for CommunicationController {
88    fn from(value: LinMaster) -> Self {
89        CommunicationController::LinMaster(value)
90    }
91}
92
93impl From<LinSlave> for CommunicationController {
94    fn from(value: LinSlave) -> Self {
95        CommunicationController::LinSlave(value)
96    }
97}
98
99impl CommunicationController {
100    /// remove this `CommunicationController` from the model
101    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
102        match self {
103            CommunicationController::Can(can_ctrl) => can_ctrl.remove(deep),
104            CommunicationController::Ethernet(eth_ctrl) => eth_ctrl.remove(deep),
105            CommunicationController::Flexray(flx_ctrl) => flx_ctrl.remove(deep),
106            CommunicationController::LinMaster(lin_master) => lin_master.remove(deep),
107            CommunicationController::LinSlave(lin_slave) => lin_slave.remove(deep),
108        }
109    }
110}
111
112//##################################################################
113
114/// A trait for all communication controllers
115pub trait AbstractCommunicationController: AbstractionElement {
116    /// Get the `EcuInstance` that contains this `CommunicationController`
117    ///
118    /// # Example
119    ///
120    /// ```
121    /// # use autosar_data::*;
122    /// # use autosar_data_abstraction::{*, communication::*};
123    /// # fn main() -> Result<(), AutosarAbstractionError> {
124    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
125    /// # let package = model.get_or_create_package("/pkg1")?;
126    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
127    /// # let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
128    /// let can_controller = ecu_instance.create_can_communication_controller("CanCtrl")?;
129    /// assert_eq!(can_controller.ecu_instance()?, ecu_instance);
130    /// # Ok(()) }
131    /// ```
132    ///
133    /// # Errors
134    ///
135    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to get the ECU-INSTANCE
136    fn ecu_instance(&self) -> Result<EcuInstance, AutosarAbstractionError> {
137        // Note: it is always OK to unwrap the result of named_parent() because
138        // the parent of a CommunicationController is always an EcuInstance
139        // named_parent() can only return Ok(None) for an ArPackage
140        self.element().named_parent()?.unwrap().try_into()
141    }
142}
143
144//##################################################################
145
146/// A trait for all communication connectors
147pub trait AbstractCommunicationConnector: AbstractionElement {
148    /// The controller type of the `CommunicationConnector`
149    type CommunicationControllerType: AbstractCommunicationController;
150
151    /// Get the `EcuInstance` that contains this `CommunicationConnector`
152    fn ecu_instance(&self) -> Result<EcuInstance, AutosarAbstractionError> {
153        // Note: it is always OK to unwrap the result of named_parent() because
154        // the parent of a CommunicationConnector is always an EcuInstance
155        // named_parent() can only return Ok(None) for an ArPackage
156        self.element().named_parent()?.unwrap().try_into()
157    }
158
159    /// Get the controller of the `CommunicationConnector`
160    fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError>;
161}
162
163//##################################################################
164
165/// wraps all different kinds of communication connector
166#[derive(Debug, Clone, PartialEq, Eq)]
167pub enum CommunicationConnector {
168    /// The `CommunicationConnector` is a [`CanCommunicationConnector`]
169    Can(CanCommunicationConnector),
170    /// The `CommunicationConnector` is an [`EthernetCommunicationConnector`]
171    Ethernet(EthernetCommunicationConnector),
172    /// The `CommunicationConnector` is a [`FlexrayCommunicationConnector`]
173    Flexray(FlexrayCommunicationConnector),
174    /// The `CommunicationConnector` is a [`LinCommunicationConnector`]
175    Lin(LinCommunicationConnector),
176}
177
178impl AbstractionElement for CommunicationConnector {
179    fn element(&self) -> &autosar_data::Element {
180        match self {
181            CommunicationConnector::Can(cc) => cc.element(),
182            CommunicationConnector::Ethernet(ec) => ec.element(),
183            CommunicationConnector::Flexray(fc) => fc.element(),
184            CommunicationConnector::Lin(lc) => lc.element(),
185        }
186    }
187}
188
189impl TryFrom<Element> for CommunicationConnector {
190    type Error = AutosarAbstractionError;
191
192    fn try_from(element: Element) -> Result<Self, Self::Error> {
193        match element.element_name() {
194            ElementName::CanCommunicationConnector => Ok(Self::Can(CanCommunicationConnector::try_from(element)?)),
195            ElementName::EthernetCommunicationConnector => {
196                Ok(Self::Ethernet(EthernetCommunicationConnector::try_from(element)?))
197            }
198            ElementName::FlexrayCommunicationConnector => {
199                Ok(Self::Flexray(FlexrayCommunicationConnector::try_from(element)?))
200            }
201            ElementName::LinCommunicationConnector => Ok(Self::Lin(LinCommunicationConnector::try_from(element)?)),
202            _ => Err(AutosarAbstractionError::ConversionError {
203                element,
204                dest: "CommunicationConnector".to_string(),
205            }),
206        }
207    }
208}
209
210impl IdentifiableAbstractionElement for CommunicationConnector {}
211
212impl AbstractCommunicationConnector for CommunicationConnector {
213    type CommunicationControllerType = CommunicationController;
214
215    fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
216        let Some(controller_ref) = self.element().get_sub_element(ElementName::CommControllerRef) else {
217            return Err(AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
218                target: ElementName::CommControllerRef,
219                parent: self.element().element_name(),
220            }));
221        };
222        let controller = controller_ref.get_reference_target()?;
223        Self::CommunicationControllerType::try_from(controller)
224    }
225}
226
227//##################################################################
228
229#[cfg(test)]
230mod tests {
231    use super::*;
232    use crate::{
233        AutosarModelAbstraction, SystemCategory,
234        communication::{FlexrayChannelName, FlexrayClusterSettings},
235    };
236    use autosar_data::AutosarVersion;
237
238    #[test]
239    fn test_communication_controller() {
240        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
241        let package = model.get_or_create_package("/test").unwrap();
242        let system = package.create_system("System", SystemCategory::SystemExtract).unwrap();
243
244        let ecu = system.create_ecu_instance("ecu", &package).unwrap();
245        let can_ctrl = ecu.create_can_communication_controller("can").unwrap();
246        let ethernet_ctrl = ecu.create_ethernet_communication_controller("ethernet", None).unwrap();
247        let flexray_ctrl = ecu.create_flexray_communication_controller("flexray").unwrap();
248        let lin_master_ctrl = ecu.create_lin_master_communication_controller("lin_master").unwrap();
249        let lin_slave_ctrl = ecu.create_lin_slave_communication_controller("lin_slave").unwrap();
250
251        let can_cc: CommunicationController = can_ctrl.clone().into();
252        let ethernet_cc: CommunicationController = ethernet_ctrl.clone().into();
253        let flexray_cc: CommunicationController = flexray_ctrl.clone().into();
254        let lin_master_cc: CommunicationController = lin_master_ctrl.clone().into();
255        let lin_slave_cc: CommunicationController = lin_slave_ctrl.clone().into();
256
257        let can_cluster = system.create_can_cluster("can_cluster", &package, None).unwrap();
258        let ethernet_cluster = system.create_ethernet_cluster("ethernet_cluster", &package).unwrap();
259        let flexray_cluster = system
260            .create_flexray_cluster("flexray_cluster", &package, &FlexrayClusterSettings::default())
261            .unwrap();
262        let lin_cluster = system.create_lin_cluster("lin_cluster", &package).unwrap();
263
264        let can_channel = can_cluster.create_physical_channel("can_channel").unwrap();
265        let ethernet_channel = ethernet_cluster
266            .create_physical_channel("ethernet_channel", None)
267            .unwrap();
268        let flexray_channel = flexray_cluster
269            .create_physical_channel("flexray_channel", FlexrayChannelName::A)
270            .unwrap();
271        let lin_channel = lin_cluster.create_physical_channel("lin_channel").unwrap();
272
273        let can_connector = can_ctrl
274            .connect_physical_channel("can_connector", &can_channel)
275            .unwrap();
276        let ethernet_connector = ethernet_ctrl
277            .connect_physical_channel("ethernet_connector", &ethernet_channel)
278            .unwrap();
279        let flexray_connector = flexray_ctrl
280            .connect_physical_channel("flexray_connector", &flexray_channel)
281            .unwrap();
282        let lin_connector = lin_master_ctrl
283            .connect_physical_channel("lin_connector", &lin_channel)
284            .unwrap();
285        let lin_slave_connector = lin_slave_ctrl
286            .connect_physical_channel("lin_slave_connector", &lin_channel)
287            .unwrap();
288
289        let connector: CommunicationConnector = CommunicationConnector::Can(can_connector.clone());
290        assert_eq!(connector.controller().unwrap(), can_cc);
291        let connector = CommunicationConnector::Ethernet(ethernet_connector.clone());
292        assert_eq!(connector.controller().unwrap(), ethernet_cc);
293        let connector = CommunicationConnector::Flexray(flexray_connector.clone());
294        assert_eq!(connector.controller().unwrap(), flexray_cc);
295        let connector = CommunicationConnector::Lin(lin_connector.clone());
296        assert_eq!(connector.controller().unwrap(), lin_master_cc);
297        let connector = CommunicationConnector::Lin(lin_slave_connector.clone());
298        assert_eq!(connector.controller().unwrap(), lin_slave_cc);
299
300        assert_eq!(can_cc.element().item_name().unwrap(), "can");
301        assert_eq!(ethernet_cc.element().item_name().unwrap(), "ethernet");
302        assert_eq!(flexray_cc.element().item_name().unwrap(), "flexray");
303        assert_eq!(lin_master_cc.element().item_name().unwrap(), "lin_master");
304        assert_eq!(lin_slave_cc.element().item_name().unwrap(), "lin_slave");
305
306        assert_eq!(ecu.communication_controllers().count(), 5);
307        can_cc.remove(true).unwrap();
308        ethernet_cc.remove(true).unwrap();
309        flexray_cc.remove(true).unwrap();
310        lin_master_cc.remove(true).unwrap();
311        lin_slave_cc.remove(true).unwrap();
312        assert_eq!(ecu.communication_controllers().count(), 0);
313    }
314}