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}