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 + use<> {
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 && 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 Ok(connector)
179 }
180}
181
182impl AbstractCommunicationController for EthernetCommunicationController {}
183
184#[derive(Debug, Clone, PartialEq, Eq, Hash)]
188pub struct EthernetCommunicationConnector(Element);
189abstraction_element!(EthernetCommunicationConnector, EthernetCommunicationConnector);
190impl IdentifiableAbstractionElement for EthernetCommunicationConnector {}
191
192impl EthernetCommunicationConnector {
193 pub(crate) fn new(
194 name: &str,
195 parent: &Element,
196 controller: &EthernetCommunicationController,
197 ) -> Result<Self, AutosarAbstractionError> {
198 let connector = parent.create_named_sub_element(ElementName::EthernetCommunicationConnector, name)?;
199 connector
200 .create_sub_element(ElementName::CommControllerRef)
201 .and_then(|refelem| refelem.set_reference_target(&controller.0))?;
202 Ok(Self(connector))
203 }
204}
205
206impl AbstractCommunicationConnector for EthernetCommunicationConnector {
207 type CommunicationControllerType = EthernetCommunicationController;
208
209 fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
210 let controller = self
211 .element()
212 .get_sub_element(ElementName::CommControllerRef)
213 .ok_or_else(|| {
214 AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
215 target: ElementName::CommControllerRef,
216 parent: self.element().element_name(),
217 })
218 })?
219 .get_reference_target()?;
220 EthernetCommunicationController::try_from(controller)
221 }
222}
223
224#[doc(hidden)]
227pub struct EthernetCtrlChannelsIterator {
228 connector_iter: Option<ElementsIterator>,
229 comm_controller: Element,
230 model: Option<AutosarModel>,
231}
232
233impl EthernetCtrlChannelsIterator {
234 fn new(controller: &EthernetCommunicationController, ecu: &Element) -> Self {
235 let iter = ecu.get_sub_element(ElementName::Connectors).map(|c| c.sub_elements());
236 let comm_controller = controller.element().clone();
237 let model = comm_controller.model().ok();
238 Self {
239 connector_iter: iter,
240 comm_controller,
241 model,
242 }
243 }
244}
245
246impl Iterator for EthernetCtrlChannelsIterator {
247 type Item = EthernetPhysicalChannel;
248
249 fn next(&mut self) -> Option<Self::Item> {
250 let model = self.model.as_ref()?;
251 let connector_iter = self.connector_iter.as_mut()?;
252 for connector in connector_iter.by_ref() {
253 if connector.element_name() == ElementName::EthernetCommunicationConnector
254 && let Some(commcontroller_of_connector) = connector
255 .get_sub_element(ElementName::CommControllerRef)
256 .and_then(|ccr| ccr.get_reference_target().ok())
257 && commcontroller_of_connector == self.comm_controller
258 {
259 for ref_origin in model
260 .get_references_to(&connector.path().ok()?)
261 .iter()
262 .filter_map(WeakElement::upgrade)
263 .filter_map(|elem| elem.named_parent().ok().flatten())
264 {
265 if ref_origin.element_name() == ElementName::EthernetPhysicalChannel {
268 return EthernetPhysicalChannel::try_from(ref_origin).ok();
269 }
270 }
271 }
272 }
273 None
274 }
275}
276
277#[cfg(test)]
280mod test {
281 use super::*;
282 use crate::{AutosarModelAbstraction, SystemCategory, communication::EthernetVlanInfo};
283 use autosar_data::AutosarVersion;
284
285 #[test]
286 fn controller() {
287 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
288 let pkg = model.get_or_create_package("/test").unwrap();
289 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
290 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
291
292 let result = ecu.create_ethernet_communication_controller("Controller", Some("abcdef".to_string()));
294 assert!(result.is_err());
295
296 let result = ecu.create_ethernet_communication_controller("Controller", Some("01:02:03:04:05:06".to_string()));
298 let controller = result.unwrap();
299
300 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
302 let channel1 = cluster.create_physical_channel("C1", None).unwrap();
303 let vlan_info = EthernetVlanInfo {
304 vlan_name: "VLAN_1".to_string(),
305 vlan_id: 1,
306 };
307 let channel2 = cluster.create_physical_channel("C2", Some(&vlan_info)).unwrap();
308
309 let connector = controller
311 .connect_physical_channel("connection_name1", &channel1)
312 .unwrap();
313 assert_eq!(connector.controller().unwrap(), controller);
314 let result = controller.connect_physical_channel("connection_name2", &channel1);
316 assert!(result.is_err());
317 let result = controller.connect_physical_channel("connection_name2", &channel2);
319 assert!(result.is_ok());
320
321 let cluster2 = system.create_ethernet_cluster("EthCluster2", &pkg).unwrap();
323 let channel3 = cluster2.create_physical_channel("C3", None).unwrap();
324 let result = controller.connect_physical_channel("connection_name3", &channel3);
325 assert!(result.is_err());
327
328 let count = controller.connected_channels().count();
329 assert_eq!(count, 2);
330
331 let ctrl_parent = controller.element().parent().unwrap().unwrap();
333 ctrl_parent.remove_sub_element(controller.element().clone()).unwrap();
334 let count = controller.connected_channels().count();
335 assert_eq!(count, 0);
336 }
337
338 #[test]
339 fn connector() {
340 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
341 let pkg = model.get_or_create_package("/test").unwrap();
342 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
343 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
344
345 let controller = ecu
346 .create_ethernet_communication_controller("Controller", None)
347 .unwrap();
348 assert_eq!(controller.ecu_instance().unwrap(), ecu);
349
350 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
351 let channel = cluster.create_physical_channel("C1", None).unwrap();
352
353 let connector = controller
355 .connect_physical_channel("connection_name", &channel)
356 .unwrap();
357 assert_eq!(connector.controller().unwrap(), controller);
358 assert_eq!(connector.ecu_instance().unwrap(), ecu);
359
360 let conn_parent = connector.element().parent().unwrap().unwrap();
362 conn_parent.remove_sub_element(connector.element().clone()).unwrap();
363 let result = connector.controller();
364 assert!(result.is_err());
365 }
366}