autosar_data_abstraction/
ecuinstance.rs

1use crate::communication::{
2    CanCommunicationController, CanTpEcu, CommunicationController, EthernetCommunicationController,
3    FlexrayCommunicationController, FlexrayTpEcu, ISignalIPduGroup, LinMaster, LinSlave, NmEcu,
4};
5use crate::{
6    AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
7    get_reference_parents,
8};
9use autosar_data::{Element, ElementName};
10
11/// The `EcuInstance` represents one ECU in a `System`
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct EcuInstance(Element);
14abstraction_element!(EcuInstance, EcuInstance);
15impl IdentifiableAbstractionElement for EcuInstance {}
16
17impl EcuInstance {
18    // Create a new EcuInstance
19    //
20    // This new EcuInstance will not be connected to a System.
21    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<EcuInstance, AutosarAbstractionError> {
22        let elem_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
23        let elem_ecu_instance = elem_pkg_elements.create_named_sub_element(ElementName::EcuInstance, name)?;
24
25        Ok(EcuInstance(elem_ecu_instance))
26    }
27
28    /// remove this `EcuInstance` from the model
29    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
30        // remove all communication controllers of this ECU
31        for controller in self.communication_controllers() {
32            controller.remove(deep)?;
33        }
34
35        let ref_parents = get_reference_parents(&self.0)?;
36
37        AbstractionElement::remove(self, deep)?;
38
39        for (_named_parent, parent) in ref_parents {
40            match parent.element_name() {
41                ElementName::NmEcu => {
42                    if let Ok(nm_ecu) = NmEcu::try_from(parent) {
43                        nm_ecu.remove(deep)?;
44                    };
45                }
46                ElementName::CanTpEcu => {
47                    if let Ok(can_tp_ecu) = CanTpEcu::try_from(parent) {
48                        can_tp_ecu.remove(deep)?;
49                    };
50                }
51                ElementName::FlexrayTpEcu => {
52                    if let Ok(frtp_ecu) = FlexrayTpEcu::try_from(parent) {
53                        frtp_ecu.remove(deep)?;
54                    };
55                }
56                _ => {}
57            }
58        }
59
60        Ok(())
61    }
62
63    /// Create a CAN-COMMUNICATION-CONTROLLER for this ECU-INSTANCE
64    ///
65    /// The ECU must have one controller per bus it communicates on.
66    /// For example, if it communicates on two CAN buses, then two CAN-COMMUNICATION-CONTROLLERs are needed.
67    ///
68    /// # Example
69    ///
70    /// ```
71    /// # use autosar_data::*;
72    /// # use autosar_data_abstraction::*;
73    /// # fn main() -> Result<(), AutosarAbstractionError> {
74    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
75    /// # let package = model.get_or_create_package("/pkg1")?;
76    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
77    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
78    /// let can_controller = ecu_instance.create_can_communication_controller("CanCtrl")?;
79    /// # Ok(())}
80    /// ```
81    ///
82    /// # Errors
83    ///
84    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to create the ECU-INSTANCE
85    pub fn create_can_communication_controller(
86        &self,
87        name: &str,
88    ) -> Result<CanCommunicationController, AutosarAbstractionError> {
89        CanCommunicationController::new(name, self)
90    }
91
92    /// Create an ETHERNET-COMMUNICATION-CONTROLLER for this ECU-INSTANCE
93    ///
94    /// The ECU must have one controller per bus it communicates on.
95    /// For example, if it communicates on two CAN buses, then two CAN-COMMUNICATION-CONTROLLERs are needed.
96    ///
97    /// # Example
98    ///
99    /// ```
100    /// # use autosar_data::*;
101    /// # use autosar_data_abstraction::*;
102    /// # fn main() -> Result<(), AutosarAbstractionError> {
103    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
104    /// # let package = model.get_or_create_package("/pkg1")?;
105    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
106    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
107    /// let ethernet_controller = ecu_instance
108    ///     .create_ethernet_communication_controller("EthCtrl", Some("ab:cd:ef:01:02:03".to_string()))?;
109    /// # Ok(())}
110    /// ```
111    ///
112    /// # Errors
113    ///
114    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to create the ECU-INSTANCE
115    pub fn create_ethernet_communication_controller(
116        &self,
117        name: &str,
118        mac_address: Option<String>,
119    ) -> Result<EthernetCommunicationController, AutosarAbstractionError> {
120        EthernetCommunicationController::new(name, self, mac_address)
121    }
122
123    /// Create a FLEXRAY-COMMUNICATION-CONTROLLER for this ECU-INSTANCE
124    ///
125    /// The ECU must have one controller per bus it communicates on.
126    /// For example, if it communicates on two CAN buses, then two CAN-COMMUNICATION-CONTROLLERs are needed.
127    ///
128    /// # Example
129    ///
130    /// ```
131    /// # use autosar_data::*;
132    /// # use autosar_data_abstraction::*;
133    /// # fn main() -> Result<(), AutosarAbstractionError> {
134    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
135    /// # let package = model.get_or_create_package("/pkg1")?;
136    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
137    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
138    /// let flexray_controller = ecu_instance
139    ///     .create_flexray_communication_controller("FlexrayCtrl")?;
140    /// # Ok(())}
141    /// ```
142    ///
143    /// # Errors
144    ///
145    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to
146    ///   create the FLEXRAY-COMMUNICATION-CONTROLLER
147    pub fn create_flexray_communication_controller(
148        &self,
149        name: &str,
150    ) -> Result<FlexrayCommunicationController, AutosarAbstractionError> {
151        FlexrayCommunicationController::new(name, self)
152    }
153
154    /// Create a LIN-MASTER communication controller for this ECU-INSTANCE
155    ///
156    /// The ECU must have one controller per bus it communicates on.
157    /// For example, if it communicates on two LIN buses, then two LIN-MASTER or
158    /// LIN-SLAVE communication controllers are needed.
159    ///
160    /// # Example
161    ///
162    /// ```
163    /// # use autosar_data::*;
164    /// # use autosar_data_abstraction::*;
165    /// # fn main() -> Result<(), AutosarAbstractionError> {
166    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
167    /// # let package = model.get_or_create_package("/pkg1")?;
168    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
169    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
170    /// let can_controller = ecu_instance.create_lin_master_communication_controller("LinMasterCtrl")?;
171    /// # Ok(())}
172    /// ```
173    ///
174    /// # Errors
175    ///
176    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to create the LIN-MASTER
177    pub fn create_lin_master_communication_controller(&self, name: &str) -> Result<LinMaster, AutosarAbstractionError> {
178        LinMaster::new(name, self)
179    }
180
181    /// Create a LIN-SLAVE communication controller for this ECU-INSTANCE
182    ///
183    /// The ECU must have one controller per bus it communicates on.
184    /// For example, if it communicates on two LIN buses, then two LIN-MASTER or
185    /// LIN-SLAVE communication controllers are needed.
186    ///
187    /// # Example
188    ///
189    /// ```
190    /// # use autosar_data::*;
191    /// # use autosar_data_abstraction::*;
192    /// # fn main() -> Result<(), AutosarAbstractionError> {
193    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
194    /// # let package = model.get_or_create_package("/pkg1")?;
195    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
196    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
197    /// let can_controller = ecu_instance.create_lin_slave_communication_controller("LinSlaveCtrl")?;
198    /// # Ok(())}
199    /// ```
200    ///
201    /// # Errors
202    ///
203    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model while trying to create the LIN-MASTER
204    pub fn create_lin_slave_communication_controller(&self, name: &str) -> Result<LinSlave, AutosarAbstractionError> {
205        LinSlave::new(name, self)
206    }
207
208    /// return an interator over all communication controllers in this `EcuInstance`
209    ///
210    /// # Example
211    ///
212    /// ```
213    /// # use autosar_data::*;
214    /// # use autosar_data_abstraction::*;
215    /// # fn main() -> Result<(), AutosarAbstractionError> {
216    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
217    /// # let package = model.get_or_create_package("/pkg1")?;
218    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
219    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
220    /// ecu_instance.create_flexray_communication_controller("FlexrayCtrl")?;
221    /// ecu_instance.create_can_communication_controller("CanCtrl")?;
222    /// for ctrl in ecu_instance.communication_controllers() {
223    ///     // ...
224    /// }
225    /// # assert_eq!(ecu_instance.communication_controllers().count(), 2);
226    /// # Ok(())}
227    /// ```
228    pub fn communication_controllers(&self) -> impl Iterator<Item = CommunicationController> + Send + use<> {
229        self.0
230            .get_sub_element(ElementName::CommControllers)
231            .into_iter()
232            .flat_map(|cc| cc.sub_elements())
233            .filter_map(|ccelem| CommunicationController::try_from(ccelem).ok())
234    }
235
236    /// Add a reference to an associated COM IPdu group
237    ///
238    /// # Example
239    ///
240    /// ```
241    /// # use autosar_data::*;
242    /// # use autosar_data_abstraction::{*, communication::*};
243    /// # fn main() -> Result<(), AutosarAbstractionError> {
244    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
245    /// # let package = model.get_or_create_package("/pkg1")?;
246    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
247    /// # let group = system.create_isignal_ipdu_group("PduGroup", &package, CommunicationDirection::In)?;
248    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
249    /// ecu_instance.add_associated_com_ipdu_group(&group)?;
250    /// for group in ecu_instance.associated_com_ipdu_groups() {
251    ///     // ...
252    /// }
253    /// # assert_eq!(ecu_instance.associated_com_ipdu_groups().count(), 1);
254    /// # Ok(())}
255    /// ```
256    pub fn add_associated_com_ipdu_group(&self, group: &ISignalIPduGroup) -> Result<(), AutosarAbstractionError> {
257        self.0
258            .get_or_create_sub_element(ElementName::AssociatedComIPduGroupRefs)?
259            .create_sub_element(ElementName::AssociatedComIPduGroupRef)?
260            .set_reference_target(group.element())?;
261        Ok(())
262    }
263
264    /// Return an iterator over all associated COM IPdu groups
265    ///
266    /// # Example
267    ///
268    /// ```
269    /// # use autosar_data::*;
270    /// # use autosar_data_abstraction::{*, communication::*};
271    /// # fn main() -> Result<(), AutosarAbstractionError> {
272    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
273    /// # let package = model.get_or_create_package("/pkg1")?;
274    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
275    /// # let group = system.create_isignal_ipdu_group("PduGroup", &package, CommunicationDirection::In)?;
276    /// let ecu_instance = system.create_ecu_instance("ecu_name", &package)?;
277    /// # ecu_instance.add_associated_com_ipdu_group(&group)?;
278    /// for group in ecu_instance.associated_com_ipdu_groups() {
279    ///     // ...
280    /// }
281    /// # assert_eq!(ecu_instance.associated_com_ipdu_groups().count(), 1);
282    /// # Ok(())}
283    /// ```
284    pub fn associated_com_ipdu_groups(&self) -> impl Iterator<Item = ISignalIPduGroup> + Send + use<> {
285        self.0
286            .get_sub_element(ElementName::AssociatedComIPduGroupRefs)
287            .into_iter()
288            .flat_map(|acigr| acigr.sub_elements())
289            .filter_map(|acigrf| {
290                acigrf
291                    .get_reference_target()
292                    .ok()
293                    .and_then(|elem| ISignalIPduGroup::try_from(elem).ok())
294            })
295    }
296}
297
298//##################################################################
299
300#[cfg(test)]
301mod test {
302    use crate::*;
303    use autosar_data::AutosarVersion;
304
305    #[test]
306    fn ecu() {
307        let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
308        let package = model.get_or_create_package("/pkg1").unwrap();
309        let system = package.create_system("System", SystemCategory::SystemExtract).unwrap();
310        let ecu_instance = system.create_ecu_instance("ecu_name", &package).unwrap();
311        ecu_instance
312            .create_flexray_communication_controller("FlexrayCtrl")
313            .unwrap();
314        ecu_instance.create_can_communication_controller("CanCtrl").unwrap();
315        ecu_instance
316            .create_ethernet_communication_controller("EthCtrl", None)
317            .unwrap();
318        assert_eq!(ecu_instance.communication_controllers().count(), 3);
319    }
320}