autosar_data_abstraction/communication/controller/
can.rs1use crate::{
2 AbstractionElement, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement, abstraction_element,
3 communication::{AbstractCommunicationConnector, AbstractCommunicationController, CanPhysicalChannel},
4};
5use autosar_data::{AutosarDataError, AutosarModel, Element, ElementName, ElementsIterator, WeakElement};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct CanCommunicationController(Element);
10abstraction_element!(CanCommunicationController, CanCommunicationController);
11impl IdentifiableAbstractionElement for CanCommunicationController {}
12
13impl CanCommunicationController {
14 pub(crate) fn new(name: &str, ecu: &EcuInstance) -> Result<Self, AutosarAbstractionError> {
16 let commcontrollers = ecu.element().get_or_create_sub_element(ElementName::CommControllers)?;
17 let ctrl = commcontrollers.create_named_sub_element(ElementName::CanCommunicationController, name)?;
18 let _canccc = ctrl
19 .create_sub_element(ElementName::CanCommunicationControllerVariants)?
20 .create_sub_element(ElementName::CanCommunicationControllerConditional)?;
21
22 Ok(Self(ctrl))
23 }
24
25 pub fn connected_channels(&self) -> impl Iterator<Item = CanPhysicalChannel> + Send + 'static {
52 if let Ok(ecu) = self.ecu_instance().map(|ecuinstance| ecuinstance.element().clone()) {
53 CanCtrlChannelsIterator::new(self, &ecu)
54 } else {
55 CanCtrlChannelsIterator {
56 connector_iter: None,
57 comm_controller: self.0.clone(),
58 model: None,
59 }
60 }
61 }
62
63 pub fn connect_physical_channel(
93 &self,
94 connection_name: &str,
95 can_channel: &CanPhysicalChannel,
96 ) -> Result<CanCommunicationConnector, AutosarAbstractionError> {
97 let ecu = self.0.named_parent()?.unwrap();
98 if let Some(connectors) = ecu.get_sub_element(ElementName::Connectors) {
100 for connector in connectors.sub_elements() {
101 if let Some(ccref) = connector.get_sub_element(ElementName::CommControllerRef) {
105 if let Ok(commcontroller_of_connector) = ccref.get_reference_target() {
106 if commcontroller_of_connector == self.0 {
107 return Err(AutosarAbstractionError::ItemAlreadyExists);
108 }
109 }
110 }
111 }
112 }
113 let connectors = ecu.get_or_create_sub_element(ElementName::Connectors)?;
115 let connector = CanCommunicationConnector::new(connection_name, &connectors, self)?;
116
117 let channel_connctor_refs = can_channel
118 .element()
119 .get_or_create_sub_element(ElementName::CommConnectors)?;
120 channel_connctor_refs
121 .create_sub_element(ElementName::CommunicationConnectorRefConditional)
122 .and_then(|ccrc| ccrc.create_sub_element(ElementName::CommunicationConnectorRef))
123 .and_then(|ccr| ccr.set_reference_target(connector.element()))?;
124
125 Ok(connector)
126 }
127}
128
129impl AbstractCommunicationController for CanCommunicationController {}
130
131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
135pub struct CanCommunicationConnector(Element);
136abstraction_element!(CanCommunicationConnector, CanCommunicationConnector);
137impl IdentifiableAbstractionElement for CanCommunicationConnector {}
138
139impl CanCommunicationConnector {
140 pub(crate) fn new(
141 name: &str,
142 parent: &Element,
143 controller: &CanCommunicationController,
144 ) -> Result<Self, AutosarAbstractionError> {
145 let connector = parent.create_named_sub_element(ElementName::CanCommunicationConnector, name)?;
146 connector
147 .create_sub_element(ElementName::CommControllerRef)?
148 .set_reference_target(controller.element())?;
149 Ok(Self(connector))
150 }
151}
152
153impl AbstractCommunicationConnector for CanCommunicationConnector {
154 type CommunicationControllerType = CanCommunicationController;
155
156 fn controller(&self) -> Result<Self::CommunicationControllerType, AutosarAbstractionError> {
157 let controller = self
158 .element()
159 .get_sub_element(ElementName::CommControllerRef)
160 .ok_or_else(|| {
161 AutosarAbstractionError::ModelError(AutosarDataError::ElementNotFound {
162 target: ElementName::CommControllerRef,
163 parent: self.element().element_name(),
164 })
165 })?
166 .get_reference_target()?;
167 CanCommunicationController::try_from(controller)
168 }
169}
170
171#[doc(hidden)]
174pub struct CanCtrlChannelsIterator {
175 connector_iter: Option<ElementsIterator>,
176 comm_controller: Element,
177 model: Option<AutosarModel>,
178}
179
180impl CanCtrlChannelsIterator {
181 fn new(controller: &CanCommunicationController, ecu: &Element) -> Self {
182 let iter = ecu.get_sub_element(ElementName::Connectors).map(|c| c.sub_elements());
183 let comm_controller = controller.element().clone();
184 let model = comm_controller.model().ok();
185 Self {
186 connector_iter: iter,
187 comm_controller,
188 model,
189 }
190 }
191}
192
193impl Iterator for CanCtrlChannelsIterator {
194 type Item = CanPhysicalChannel;
195
196 fn next(&mut self) -> Option<Self::Item> {
197 let model = self.model.as_ref()?;
198 let connector_iter = self.connector_iter.as_mut()?;
199 for connector in connector_iter.by_ref() {
200 if connector.element_name() == ElementName::CanCommunicationConnector {
201 if let Some(commcontroller_of_connector) = connector
202 .get_sub_element(ElementName::CommControllerRef)
203 .and_then(|ccr| ccr.get_reference_target().ok())
204 {
205 if commcontroller_of_connector == self.comm_controller {
206 for ref_origin in model
207 .get_references_to(&connector.path().ok()?)
208 .iter()
209 .filter_map(WeakElement::upgrade)
210 .filter_map(|elem| elem.named_parent().ok().flatten())
211 {
212 if ref_origin.element_name() == ElementName::CanPhysicalChannel {
215 return CanPhysicalChannel::try_from(ref_origin).ok();
216 }
217 }
218 }
219 }
220 }
221 }
222 None
223 }
224}
225
226#[cfg(test)]
229mod test {
230 use super::*;
231 use crate::{AutosarModelAbstraction, SystemCategory};
232 use autosar_data::AutosarVersion;
233
234 #[test]
235 fn controller() {
236 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
237 let pkg = model.get_or_create_package("/test").unwrap();
238 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
239 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
240
241 let result = ecu.create_can_communication_controller("Controller");
243 let controller = result.unwrap();
244
245 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
247 let channel1 = cluster.create_physical_channel("C1").unwrap();
248
249 let connector = controller
251 .connect_physical_channel("connection_name1", &channel1)
252 .unwrap();
253 assert_eq!(connector.controller().unwrap(), controller);
254 let result = controller.connect_physical_channel("connection_name2", &channel1);
256 assert!(result.is_err());
257
258 let count = controller.connected_channels().count();
259 assert_eq!(count, 1);
260
261 let ctrl_parent = controller.0.parent().unwrap().unwrap();
263 ctrl_parent.remove_sub_element(controller.0.clone()).unwrap();
264 let count = controller.connected_channels().count();
265 assert_eq!(count, 0);
266 }
267
268 #[test]
269 fn connector() {
270 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
271 let pkg = model.get_or_create_package("/test").unwrap();
272 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
273 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
274
275 let controller = ecu.create_can_communication_controller("Controller").unwrap();
277 assert_eq!(controller.ecu_instance().unwrap(), ecu);
278
279 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
281 let channel1 = cluster.create_physical_channel("C1").unwrap();
282
283 let connector = controller
285 .connect_physical_channel("connection_name1", &channel1)
286 .unwrap();
287 assert_eq!(connector.controller().unwrap(), controller);
288 assert_eq!(connector.ecu_instance().unwrap(), ecu);
289
290 connector
292 .element()
293 .remove_sub_element_kind(ElementName::CommControllerRef)
294 .unwrap();
295 let result = connector.controller();
296 assert!(result.is_err());
297 }
298}