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
99//##################################################################
100
101/// A trait for all communication controllers
102pub trait AbstractCommunicationController: AbstractionElement {
103    /// Get the `EcuInstance` that contains this `CommunicationController`
104    ///
105    /// # Example
106    ///
107    /// ```
108    /// # use autosar_data::*;
109    /// # use autosar_data_abstraction::{*, communication::*};
110    /// # fn main() -> Result<(), AutosarAbstractionError> {
111    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
112    /// # let package = model.get_or_create_package("/pkg1")?;
113    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
114    /// # let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
115    /// let can_controller = ecu_instance.create_can_communication_controller("CanCtrl")?;
116    /// assert_eq!(can_controller.ecu_instance()?, ecu_instance);
117    /// # Ok(()) }
118    /// ```
119    ///
120    /// # Errors
121    ///
122    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to get the ECU-INSTANCE
123    fn ecu_instance(&self) -> Result<EcuInstance, AutosarAbstractionError> {
124        // Note: it is always OK to unwrap the result of named_parent() because
125        // the parent of a CommunicationController is always an EcuInstance
126        // named_parent() can only return Ok(None) for an ArPackage
127        self.element().named_parent()?.unwrap().try_into()
128    }
129}
130
131//##################################################################
132
133/// A trait for all communication connectors
134pub trait AbstractCommunicationConnector: AbstractionElement {
135    /// The controller type of the `CommunicationConnector`
136    type CommunicationControllerType: AbstractCommunicationController;
137
138    /// Get the `EcuInstance` that contains this `CommunicationConnector`
139    fn ecu_instance(&self) -> Result<EcuInstance, AutosarAbstractionError> {
140        // Note: it is always OK to unwrap the result of named_parent() because
141        // the parent of a CommunicationConnector is always an EcuInstance
142        // named_parent() can only return Ok(None) for an ArPackage
143        self.element().named_parent()?.unwrap().try_into()
144    }
145
146    /// Get the controller of the `CommunicationConnector`
147    fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError>;
148}
149
150//##################################################################
151
152/// wraps all different kinds of communication connector
153#[derive(Debug, Clone, PartialEq, Eq)]
154pub enum CommunicationConnector {
155    /// The `CommunicationConnector` is a [`CanCommunicationConnector`]
156    Can(CanCommunicationConnector),
157    /// The `CommunicationConnector` is an [`EthernetCommunicationConnector`]
158    Ethernet(EthernetCommunicationConnector),
159    /// The `CommunicationConnector` is a [`FlexrayCommunicationConnector`]
160    Flexray(FlexrayCommunicationConnector),
161    /// The `CommunicationConnector` is a [`LinCommunicationConnector`]
162    Lin(LinCommunicationConnector),
163}
164
165impl AbstractionElement for CommunicationConnector {
166    fn element(&self) -> &autosar_data::Element {
167        match self {
168            CommunicationConnector::Can(cc) => cc.element(),
169            CommunicationConnector::Ethernet(ec) => ec.element(),
170            CommunicationConnector::Flexray(fc) => fc.element(),
171            CommunicationConnector::Lin(lc) => lc.element(),
172        }
173    }
174}
175
176impl TryFrom<Element> for CommunicationConnector {
177    type Error = AutosarAbstractionError;
178
179    fn try_from(element: Element) -> Result<Self, Self::Error> {
180        match element.element_name() {
181            ElementName::CanCommunicationConnector => Ok(Self::Can(CanCommunicationConnector::try_from(element)?)),
182            ElementName::EthernetCommunicationConnector => {
183                Ok(Self::Ethernet(EthernetCommunicationConnector::try_from(element)?))
184            }
185            ElementName::FlexrayCommunicationConnector => {
186                Ok(Self::Flexray(FlexrayCommunicationConnector::try_from(element)?))
187            }
188            ElementName::LinCommunicationConnector => Ok(Self::Lin(LinCommunicationConnector::try_from(element)?)),
189            _ => Err(AutosarAbstractionError::ConversionError {
190                element,
191                dest: "CommunicationConnector".to_string(),
192            }),
193        }
194    }
195}
196
197impl IdentifiableAbstractionElement for CommunicationConnector {}
198
199impl AbstractCommunicationConnector for CommunicationConnector {
200    type CommunicationControllerType = CommunicationController;
201
202    fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
203        let Some(controller_ref) = self.element().get_sub_element(ElementName::CommControllerRef) else {
204            return Err(AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
205                target: ElementName::CommControllerRef,
206                parent: self.element().element_name(),
207            }));
208        };
209        let controller = controller_ref.get_reference_target()?;
210        Self::CommunicationControllerType::try_from(controller)
211    }
212}
213
214//##################################################################
215
216#[cfg(test)]
217mod tests {
218    use super::*;
219    use crate::{
220        AutosarModelAbstraction, SystemCategory,
221        communication::{FlexrayChannelName, FlexrayClusterSettings},
222    };
223    use autosar_data::AutosarVersion;
224
225    #[test]
226    fn test_communication_controller() {
227        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
228        let package = model.get_or_create_package("/test").unwrap();
229        let system = package.create_system("System", SystemCategory::SystemExtract).unwrap();
230
231        let ecu = system.create_ecu_instance("ecu", &package).unwrap();
232        let can_ctrl = ecu.create_can_communication_controller("can").unwrap();
233        let ethernet_ctrl = ecu.create_ethernet_communication_controller("ethernet", None).unwrap();
234        let flexray_ctrl = ecu.create_flexray_communication_controller("flexray").unwrap();
235
236        let can_cc: CommunicationController = can_ctrl.clone().into();
237        let ethernet_cc: CommunicationController = ethernet_ctrl.clone().into();
238        let flexray_cc: CommunicationController = flexray_ctrl.clone().into();
239
240        let can_cluster = system.create_can_cluster("can_cluster", &package, None).unwrap();
241        let ethernet_cluster = system.create_ethernet_cluster("ethernet_cluster", &package).unwrap();
242        let flexray_cluster = system
243            .create_flexray_cluster("flexray_cluster", &package, &FlexrayClusterSettings::default())
244            .unwrap();
245
246        let can_channel = can_cluster.create_physical_channel("can_channel").unwrap();
247        let ethernet_channel = ethernet_cluster
248            .create_physical_channel("ethernet_channel", None)
249            .unwrap();
250        let flexray_channel = flexray_cluster
251            .create_physical_channel("flexray_channel", FlexrayChannelName::A)
252            .unwrap();
253
254        let can_connector = can_ctrl
255            .connect_physical_channel("can_connector", &can_channel)
256            .unwrap();
257        let ethernet_connector = ethernet_ctrl
258            .connect_physical_channel("ethernet_connector", &ethernet_channel)
259            .unwrap();
260        let flexray_connector = flexray_ctrl
261            .connect_physical_channel("flexray_connector", &flexray_channel)
262            .unwrap();
263
264        let connector: CommunicationConnector = CommunicationConnector::Can(can_connector.clone());
265        assert_eq!(connector.controller().unwrap(), can_cc);
266        let connector = CommunicationConnector::Ethernet(ethernet_connector.clone());
267        assert_eq!(connector.controller().unwrap(), ethernet_cc);
268        let connector = CommunicationConnector::Flexray(flexray_connector.clone());
269        assert_eq!(connector.controller().unwrap(), flexray_cc);
270
271        assert_eq!(can_cc.element().item_name().unwrap(), "can");
272        assert_eq!(ethernet_cc.element().item_name().unwrap(), "ethernet");
273        assert_eq!(flexray_cc.element().item_name().unwrap(), "flexray");
274    }
275}