autosar_data_abstraction/communication/controller/
ethernet.rs1use crate::communication::{
2 AbstractCommunicationConnector, AbstractCommunicationController, EthernetPhysicalChannel, EthernetVlanInfo,
3};
4use crate::{
5 AbstractionElement, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement, abstraction_element,
6};
7use autosar_data::{AutosarDataError, AutosarModel, Element, ElementName, ElementsIterator, WeakElement};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct EthernetCommunicationController(Element);
12abstraction_element!(EthernetCommunicationController, EthernetCommunicationController);
13impl IdentifiableAbstractionElement for EthernetCommunicationController {}
14
15impl EthernetCommunicationController {
16 pub(crate) fn new(
18 name: &str,
19 ecu: &EcuInstance,
20 mac_address: Option<String>,
21 ) -> Result<Self, AutosarAbstractionError> {
22 let commcontrollers = ecu.element().get_or_create_sub_element(ElementName::CommControllers)?;
23 let ctrl = commcontrollers.create_named_sub_element(ElementName::EthernetCommunicationController, name)?;
24 let ethccc = ctrl
25 .create_sub_element(ElementName::EthernetCommunicationControllerVariants)?
26 .create_sub_element(ElementName::EthernetCommunicationControllerConditional)?;
27 if let Some(mac_address) = mac_address {
28 let result = ethccc
30 .create_sub_element(ElementName::MacUnicastAddress)
31 .and_then(|mua| mua.set_character_data(mac_address));
32 if let Err(mac_address_error) = result {
33 let _ = commcontrollers.remove_sub_element(ctrl);
34 return Err(mac_address_error.into());
35 }
36 }
37 let coupling_port_name = format!("{name}_CouplingPort");
38 let _ = ethccc
39 .create_sub_element(ElementName::CouplingPorts)
40 .and_then(|cps| cps.create_named_sub_element(ElementName::CouplingPort, &coupling_port_name));
41
42 Ok(Self(ctrl))
43 }
44
45 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
47 let ecu_instance = self.ecu_instance()?;
49 for connector in ecu_instance
50 .element()
51 .get_sub_element(ElementName::Connectors)
52 .iter()
53 .flat_map(|connectors| connectors.sub_elements())
54 .filter_map(|conn| EthernetCommunicationConnector::try_from(conn).ok())
55 {
56 if let Ok(controller_of_connector) = connector.controller()
57 && controller_of_connector == self
58 {
59 connector.remove(deep)?;
60 }
61 }
62
63 AbstractionElement::remove(self, deep)
64 }
65
66 pub fn connected_channels(&self) -> impl Iterator<Item = EthernetPhysicalChannel> + Send + use<> {
92 if let Ok(ecu) = self.ecu_instance().map(|ecuinstance| ecuinstance.element().clone()) {
93 EthernetCtrlChannelsIterator::new(self, &ecu)
94 } else {
95 EthernetCtrlChannelsIterator {
96 connector_iter: None,
97 comm_controller: self.0.clone(),
98 model: None,
99 }
100 }
101 }
102
103 pub fn connect_physical_channel(
132 &self,
133 connection_name: &str,
134 eth_channel: &EthernetPhysicalChannel,
135 ) -> Result<EthernetCommunicationConnector, AutosarAbstractionError> {
136 let ecu: Element = self.0.named_parent()?.unwrap();
137 let cluster_of_channel = eth_channel.cluster()?;
138
139 for phys_channel in self.connected_channels() {
143 if phys_channel == *eth_channel {
144 return Err(AutosarAbstractionError::ItemAlreadyExists);
145 }
146
147 if phys_channel.cluster()? != cluster_of_channel {
148 return Err(AutosarAbstractionError::InvalidParameter(
149 "The EthernetCommunicationController may only refer to different channels within the same cluster"
150 .to_string(),
151 ));
152 }
153 }
154
155 let connectors = ecu.get_or_create_sub_element(ElementName::Connectors)?;
157 let connector = EthernetCommunicationConnector::new(connection_name, &connectors, self)?;
158
159 if let Some(category) = eth_channel
162 .element()
163 .get_sub_element(ElementName::Category)
164 .and_then(|cat| cat.character_data())
165 .and_then(|cdata| cdata.string_value())
166 {
167 let _ = connector
168 .element()
169 .create_sub_element(ElementName::Category)
170 .and_then(|cat| cat.set_character_data(category));
171 }
172
173 let channel_connctor_refs = eth_channel
175 .element()
176 .get_or_create_sub_element(ElementName::CommConnectors)?;
177 channel_connctor_refs
178 .create_sub_element(ElementName::CommunicationConnectorRefConditional)
179 .and_then(|ccrc| ccrc.create_sub_element(ElementName::CommunicationConnectorRef))
180 .and_then(|ccr| ccr.set_reference_target(connector.element()))?;
181
182 if let Some(EthernetVlanInfo { .. }) = eth_channel.vlan_info()
185 && let Some(coupling_port) = self
186 .0
187 .get_sub_element(ElementName::EthernetCommunicationControllerVariants)
188 .and_then(|eccv| eccv.get_sub_element(ElementName::EthernetCommunicationControllerConditional))
189 .and_then(|eccc| eccc.get_sub_element(ElementName::CouplingPorts))
190 .and_then(|cps| cps.get_sub_element(ElementName::CouplingPort))
191 {
192 coupling_port
193 .get_or_create_sub_element(ElementName::VlanMemberships)
194 .and_then(|vms| vms.create_sub_element(ElementName::VlanMembership))
195 .and_then(|vm| vm.create_sub_element(ElementName::VlanRef))
196 .and_then(|vr| vr.set_reference_target(eth_channel.element()))?;
197 }
198
199 Ok(connector)
200 }
201}
202
203impl AbstractCommunicationController for EthernetCommunicationController {}
204
205#[derive(Debug, Clone, PartialEq, Eq, Hash)]
209pub struct EthernetCommunicationConnector(Element);
210abstraction_element!(EthernetCommunicationConnector, EthernetCommunicationConnector);
211impl IdentifiableAbstractionElement for EthernetCommunicationConnector {}
212
213impl EthernetCommunicationConnector {
214 pub(crate) fn new(
215 name: &str,
216 parent: &Element,
217 controller: &EthernetCommunicationController,
218 ) -> Result<Self, AutosarAbstractionError> {
219 let connector = parent.create_named_sub_element(ElementName::EthernetCommunicationConnector, name)?;
220 connector
221 .create_sub_element(ElementName::CommControllerRef)
222 .and_then(|refelem| refelem.set_reference_target(&controller.0))?;
223 Ok(Self(connector))
224 }
225}
226
227impl AbstractCommunicationConnector for EthernetCommunicationConnector {
228 type CommunicationControllerType = EthernetCommunicationController;
229
230 fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
231 let controller = self
232 .element()
233 .get_sub_element(ElementName::CommControllerRef)
234 .ok_or_else(|| {
235 AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
236 target: ElementName::CommControllerRef,
237 parent: self.element().element_name(),
238 })
239 })?
240 .get_reference_target()?;
241 EthernetCommunicationController::try_from(controller)
242 }
243}
244
245#[doc(hidden)]
248pub struct EthernetCtrlChannelsIterator {
249 connector_iter: Option<ElementsIterator>,
250 comm_controller: Element,
251 model: Option<AutosarModel>,
252}
253
254impl EthernetCtrlChannelsIterator {
255 fn new(controller: &EthernetCommunicationController, ecu: &Element) -> Self {
256 let iter = ecu.get_sub_element(ElementName::Connectors).map(|c| c.sub_elements());
257 let comm_controller = controller.element().clone();
258 let model = comm_controller.model().ok();
259 Self {
260 connector_iter: iter,
261 comm_controller,
262 model,
263 }
264 }
265}
266
267impl Iterator for EthernetCtrlChannelsIterator {
268 type Item = EthernetPhysicalChannel;
269
270 fn next(&mut self) -> Option<Self::Item> {
271 let model = self.model.as_ref()?;
272 let connector_iter = self.connector_iter.as_mut()?;
273 for connector in connector_iter.by_ref() {
274 if connector.element_name() == ElementName::EthernetCommunicationConnector
275 && let Some(commcontroller_of_connector) = connector
276 .get_sub_element(ElementName::CommControllerRef)
277 .and_then(|ccr| ccr.get_reference_target().ok())
278 && commcontroller_of_connector == self.comm_controller
279 {
280 for ref_origin in model
281 .get_references_to(&connector.path().ok()?)
282 .iter()
283 .filter_map(WeakElement::upgrade)
284 .filter_map(|elem| elem.named_parent().ok().flatten())
285 {
286 if ref_origin.element_name() == ElementName::EthernetPhysicalChannel {
289 return EthernetPhysicalChannel::try_from(ref_origin).ok();
290 }
291 }
292 }
293 }
294 None
295 }
296}
297
298#[cfg(test)]
301mod test {
302 use super::*;
303 use crate::{AutosarModelAbstraction, SystemCategory, communication::EthernetVlanInfo};
304 use autosar_data::AutosarVersion;
305
306 #[test]
307 fn controller() {
308 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
309 let pkg = model.get_or_create_package("/test").unwrap();
310 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
311 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
312
313 let result = ecu.create_ethernet_communication_controller("Controller", Some("abcdef".to_string()));
315 assert!(result.is_err());
316
317 let result = ecu.create_ethernet_communication_controller("Controller", Some("01:02:03:04:05:06".to_string()));
319 let controller = result.unwrap();
320
321 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
323 let channel1 = cluster.create_physical_channel("C1", None).unwrap();
324 let vlan_info = EthernetVlanInfo {
325 vlan_name: "VLAN_1".to_string(),
326 vlan_id: 1,
327 };
328 let channel2 = cluster.create_physical_channel("C2", Some(&vlan_info)).unwrap();
329
330 let connector = controller
332 .connect_physical_channel("connection_name1", &channel1)
333 .unwrap();
334 assert_eq!(connector.controller().unwrap(), controller);
335 let result = controller.connect_physical_channel("connection_name2", &channel1);
337 assert!(result.is_err());
338 let result = controller.connect_physical_channel("connection_name2", &channel2);
340 assert!(result.is_ok());
341
342 let cluster2 = system.create_ethernet_cluster("EthCluster2", &pkg).unwrap();
344 let channel3 = cluster2.create_physical_channel("C3", None).unwrap();
345 let result = controller.connect_physical_channel("connection_name3", &channel3);
346 assert!(result.is_err());
348
349 let count = controller.connected_channels().count();
350 assert_eq!(count, 2);
351
352 let ctrl_parent = controller.element().parent().unwrap().unwrap();
354 ctrl_parent.remove_sub_element(controller.element().clone()).unwrap();
355 let count = controller.connected_channels().count();
356 assert_eq!(count, 0);
357 }
358
359 #[test]
360 fn connector() {
361 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
362 let pkg = model.get_or_create_package("/test").unwrap();
363 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
364 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
365
366 let controller = ecu
367 .create_ethernet_communication_controller("Controller", None)
368 .unwrap();
369 assert_eq!(controller.ecu_instance().unwrap(), ecu);
370
371 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
372 let channel = cluster.create_physical_channel("C1", None).unwrap();
373
374 let connector = controller
376 .connect_physical_channel("connection_name", &channel)
377 .unwrap();
378 assert_eq!(connector.controller().unwrap(), controller);
379 assert_eq!(connector.ecu_instance().unwrap(), ecu);
380
381 let conn_parent = connector.element().parent().unwrap().unwrap();
383 conn_parent.remove_sub_element(connector.element().clone()).unwrap();
384 let result = connector.controller();
385 assert!(result.is_err());
386 }
387
388 #[test]
389 fn remove_controller() {
390 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
391 let pkg = model.get_or_create_package("/test").unwrap();
392 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
393 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
394 let controller = ecu
395 .create_ethernet_communication_controller("Controller", None)
396 .unwrap();
397 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
398 let channel = cluster.create_physical_channel("C1", None).unwrap();
399 let connector = controller
400 .connect_physical_channel("connection_name", &channel)
401 .unwrap();
402
403 controller.remove(true).unwrap();
405
406 assert_eq!(ecu.communication_controllers().count(), 0);
407 assert!(connector.element().path().is_err());
408 }
409}