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