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 connected_channels(&self) -> impl Iterator<Item = EthernetPhysicalChannel> + Send + 'static {
71 if let Ok(ecu) = self.ecu_instance().map(|ecuinstance| ecuinstance.element().clone()) {
72 EthernetCtrlChannelsIterator::new(self, &ecu)
73 } else {
74 EthernetCtrlChannelsIterator {
75 connector_iter: None,
76 comm_controller: self.0.clone(),
77 model: None,
78 }
79 }
80 }
81
82 pub fn connect_physical_channel(
111 &self,
112 connection_name: &str,
113 eth_channel: &EthernetPhysicalChannel,
114 ) -> Result<EthernetCommunicationConnector, AutosarAbstractionError> {
115 let ecu: Element = self.0.named_parent()?.unwrap();
116 let cluster_of_channel = eth_channel.cluster()?;
117
118 for phys_channel in self.connected_channels() {
122 if phys_channel == *eth_channel {
123 return Err(AutosarAbstractionError::ItemAlreadyExists);
124 }
125
126 if phys_channel.cluster()? != cluster_of_channel {
127 return Err(AutosarAbstractionError::InvalidParameter(
128 "The EthernetCommunicationController may only refer to different channels within the same cluster"
129 .to_string(),
130 ));
131 }
132 }
133
134 let connectors = ecu.get_or_create_sub_element(ElementName::Connectors)?;
136 let connector = EthernetCommunicationConnector::new(connection_name, &connectors, self)?;
137
138 if let Some(category) = eth_channel
141 .element()
142 .get_sub_element(ElementName::Category)
143 .and_then(|cat| cat.character_data())
144 .and_then(|cdata| cdata.string_value())
145 {
146 let _ = connector
147 .element()
148 .create_sub_element(ElementName::Category)
149 .and_then(|cat| cat.set_character_data(category));
150 }
151
152 let channel_connctor_refs = eth_channel
154 .element()
155 .get_or_create_sub_element(ElementName::CommConnectors)?;
156 channel_connctor_refs
157 .create_sub_element(ElementName::CommunicationConnectorRefConditional)
158 .and_then(|ccrc| ccrc.create_sub_element(ElementName::CommunicationConnectorRef))
159 .and_then(|ccr| ccr.set_reference_target(connector.element()))?;
160
161 if let Some(EthernetVlanInfo { .. }) = eth_channel.vlan_info() {
164 if let Some(coupling_port) = self
165 .0
166 .get_sub_element(ElementName::EthernetCommunicationControllerVariants)
167 .and_then(|eccv| eccv.get_sub_element(ElementName::EthernetCommunicationControllerConditional))
168 .and_then(|eccc| eccc.get_sub_element(ElementName::CouplingPorts))
169 .and_then(|cps| cps.get_sub_element(ElementName::CouplingPort))
170 {
171 coupling_port
172 .get_or_create_sub_element(ElementName::VlanMemberships)
173 .and_then(|vms| vms.create_sub_element(ElementName::VlanMembership))
174 .and_then(|vm| vm.create_sub_element(ElementName::VlanRef))
175 .and_then(|vr| vr.set_reference_target(eth_channel.element()))?;
176 }
177 }
178
179 Ok(connector)
180 }
181}
182
183impl AbstractCommunicationController for EthernetCommunicationController {}
184
185#[derive(Debug, Clone, PartialEq, Eq, Hash)]
189pub struct EthernetCommunicationConnector(Element);
190abstraction_element!(EthernetCommunicationConnector, EthernetCommunicationConnector);
191impl IdentifiableAbstractionElement for EthernetCommunicationConnector {}
192
193impl EthernetCommunicationConnector {
194 pub(crate) fn new(
195 name: &str,
196 parent: &Element,
197 controller: &EthernetCommunicationController,
198 ) -> Result<Self, AutosarAbstractionError> {
199 let connector = parent.create_named_sub_element(ElementName::EthernetCommunicationConnector, name)?;
200 connector
201 .create_sub_element(ElementName::CommControllerRef)
202 .and_then(|refelem| refelem.set_reference_target(&controller.0))?;
203 Ok(Self(connector))
204 }
205}
206
207impl AbstractCommunicationConnector for EthernetCommunicationConnector {
208 type CommunicationControllerType = EthernetCommunicationController;
209
210 fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
211 let controller = self
212 .element()
213 .get_sub_element(ElementName::CommControllerRef)
214 .ok_or_else(|| {
215 AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
216 target: ElementName::CommControllerRef,
217 parent: self.element().element_name(),
218 })
219 })?
220 .get_reference_target()?;
221 EthernetCommunicationController::try_from(controller)
222 }
223}
224
225#[doc(hidden)]
228pub struct EthernetCtrlChannelsIterator {
229 connector_iter: Option<ElementsIterator>,
230 comm_controller: Element,
231 model: Option<AutosarModel>,
232}
233
234impl EthernetCtrlChannelsIterator {
235 fn new(controller: &EthernetCommunicationController, ecu: &Element) -> Self {
236 let iter = ecu.get_sub_element(ElementName::Connectors).map(|c| c.sub_elements());
237 let comm_controller = controller.element().clone();
238 let model = comm_controller.model().ok();
239 Self {
240 connector_iter: iter,
241 comm_controller,
242 model,
243 }
244 }
245}
246
247impl Iterator for EthernetCtrlChannelsIterator {
248 type Item = EthernetPhysicalChannel;
249
250 fn next(&mut self) -> Option<Self::Item> {
251 let model = self.model.as_ref()?;
252 let connector_iter = self.connector_iter.as_mut()?;
253 for connector in connector_iter.by_ref() {
254 if connector.element_name() == ElementName::EthernetCommunicationConnector {
255 if let Some(commcontroller_of_connector) = connector
256 .get_sub_element(ElementName::CommControllerRef)
257 .and_then(|ccr| ccr.get_reference_target().ok())
258 {
259 if commcontroller_of_connector == self.comm_controller {
260 for ref_origin in model
261 .get_references_to(&connector.path().ok()?)
262 .iter()
263 .filter_map(WeakElement::upgrade)
264 .filter_map(|elem| elem.named_parent().ok().flatten())
265 {
266 if ref_origin.element_name() == ElementName::EthernetPhysicalChannel {
269 return EthernetPhysicalChannel::try_from(ref_origin).ok();
270 }
271 }
272 }
273 }
274 }
275 }
276 None
277 }
278}
279
280#[cfg(test)]
283mod test {
284 use super::*;
285 use crate::{AutosarModelAbstraction, SystemCategory, communication::EthernetVlanInfo};
286 use autosar_data::AutosarVersion;
287
288 #[test]
289 fn controller() {
290 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
291 let pkg = model.get_or_create_package("/test").unwrap();
292 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
293 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
294
295 let result = ecu.create_ethernet_communication_controller("Controller", Some("abcdef".to_string()));
297 assert!(result.is_err());
298
299 let result = ecu.create_ethernet_communication_controller("Controller", Some("01:02:03:04:05:06".to_string()));
301 let controller = result.unwrap();
302
303 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
305 let channel1 = cluster.create_physical_channel("C1", None).unwrap();
306 let vlan_info = EthernetVlanInfo {
307 vlan_name: "VLAN_1".to_string(),
308 vlan_id: 1,
309 };
310 let channel2 = cluster.create_physical_channel("C2", Some(&vlan_info)).unwrap();
311
312 let connector = controller
314 .connect_physical_channel("connection_name1", &channel1)
315 .unwrap();
316 assert_eq!(connector.controller().unwrap(), controller);
317 let result = controller.connect_physical_channel("connection_name2", &channel1);
319 assert!(result.is_err());
320 let result = controller.connect_physical_channel("connection_name2", &channel2);
322 assert!(result.is_ok());
323
324 let cluster2 = system.create_ethernet_cluster("EthCluster2", &pkg).unwrap();
326 let channel3 = cluster2.create_physical_channel("C3", None).unwrap();
327 let result = controller.connect_physical_channel("connection_name3", &channel3);
328 assert!(result.is_err());
330
331 let count = controller.connected_channels().count();
332 assert_eq!(count, 2);
333
334 let ctrl_parent = controller.element().parent().unwrap().unwrap();
336 ctrl_parent.remove_sub_element(controller.element().clone()).unwrap();
337 let count = controller.connected_channels().count();
338 assert_eq!(count, 0);
339 }
340
341 #[test]
342 fn connector() {
343 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
344 let pkg = model.get_or_create_package("/test").unwrap();
345 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
346 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
347
348 let controller = ecu
349 .create_ethernet_communication_controller("Controller", None)
350 .unwrap();
351 assert_eq!(controller.ecu_instance().unwrap(), ecu);
352
353 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
354 let channel = cluster.create_physical_channel("C1", None).unwrap();
355
356 let connector = controller
358 .connect_physical_channel("connection_name", &channel)
359 .unwrap();
360 assert_eq!(connector.controller().unwrap(), controller);
361 assert_eq!(connector.ecu_instance().unwrap(), ecu);
362
363 let conn_parent = connector.element().parent().unwrap().unwrap();
365 conn_parent.remove_sub_element(connector.element().clone()).unwrap();
366 let result = connector.controller();
367 assert!(result.is_err());
368 }
369}