1use crate::communication::{
2 AbstractFrame, AbstractFrameTriggering, AbstractPdu, CommunicationDirection, Frame, FramePort, FrameTriggering,
3 LinPhysicalChannel, Pdu, PduToFrameMapping, PduTriggering,
4};
5use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, EcuInstance, IdentifiableAbstractionElement,
7 abstraction_element, is_used_system_element, make_unique_name,
8};
9use autosar_data::{Element, ElementName};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct LinEventTriggeredFrame(Element);
16abstraction_element!(LinEventTriggeredFrame, LinEventTriggeredFrame);
17impl IdentifiableAbstractionElement for LinEventTriggeredFrame {}
18
19impl LinEventTriggeredFrame {
20 pub(crate) fn new(name: &str, package: &ArPackage, byte_length: u64) -> Result<Self, AutosarAbstractionError> {
21 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
22 let lin_frame = pkg_elements.create_named_sub_element(ElementName::LinEventTriggeredFrame, name)?;
23
24 lin_frame
25 .create_sub_element(ElementName::FrameLength)?
26 .set_character_data(byte_length.to_string())?;
27
28 Ok(Self(lin_frame))
29 }
30
31 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
33 for pdu_mapping in self.mapped_pdus() {
34 pdu_mapping.remove(deep)?;
35 }
36
37 let frame_triggerings = self.frame_triggerings();
39
40 AbstractionElement::remove(self, deep)?;
42
43 for ft in frame_triggerings {
45 ft.remove(deep)?;
46 }
47
48 Ok(())
49 }
50}
51
52impl AbstractFrame for LinEventTriggeredFrame {
53 type FrameTriggeringType = LinFrameTriggering;
54
55 fn frame_triggerings(&self) -> Vec<LinFrameTriggering> {
57 let model_result = self.element().model();
58 let path_result = self.element().path();
59 if let (Ok(model), Ok(path)) = (model_result, path_result) {
60 model
61 .get_references_to(&path)
62 .iter()
63 .filter_map(|e| {
64 e.upgrade()
65 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
66 .and_then(|elem| LinFrameTriggering::try_from(elem).ok())
67 })
68 .collect()
69 } else {
70 vec![]
71 }
72 }
73
74 fn map_pdu<T: AbstractPdu>(
76 &self,
77 gen_pdu: &T,
78 start_position: u32,
79 byte_order: ByteOrder,
80 update_bit: Option<u32>,
81 ) -> Result<PduToFrameMapping, AutosarAbstractionError> {
82 Frame::Lin(LinFrame::EventTriggered(self.clone())).map_pdu(gen_pdu, start_position, byte_order, update_bit)
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Hash)]
90pub struct LinSporadicFrame(Element);
91abstraction_element!(LinSporadicFrame, LinSporadicFrame);
92impl IdentifiableAbstractionElement for LinSporadicFrame {}
93
94impl LinSporadicFrame {
95 pub(crate) fn new(name: &str, package: &ArPackage, byte_length: u64) -> Result<Self, AutosarAbstractionError> {
96 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
97 let lin_frame = pkg_elements.create_named_sub_element(ElementName::LinSporadicFrame, name)?;
98
99 lin_frame
100 .create_sub_element(ElementName::FrameLength)?
101 .set_character_data(byte_length.to_string())?;
102
103 Ok(Self(lin_frame))
104 }
105
106 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
108 for pdu_mapping in self.mapped_pdus() {
109 pdu_mapping.remove(deep)?;
110 }
111
112 let frame_triggerings = self.frame_triggerings();
114
115 AbstractionElement::remove(self, deep)?;
117
118 for ft in frame_triggerings {
120 ft.remove(deep)?;
121 }
122
123 Ok(())
124 }
125}
126
127impl AbstractFrame for LinSporadicFrame {
128 type FrameTriggeringType = LinFrameTriggering;
129
130 fn frame_triggerings(&self) -> Vec<LinFrameTriggering> {
132 let model_result = self.element().model();
133 let path_result = self.element().path();
134 if let (Ok(model), Ok(path)) = (model_result, path_result) {
135 model
136 .get_references_to(&path)
137 .iter()
138 .filter_map(|e| {
139 e.upgrade()
140 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
141 .and_then(|elem| LinFrameTriggering::try_from(elem).ok())
142 })
143 .collect()
144 } else {
145 vec![]
146 }
147 }
148
149 fn map_pdu<T: AbstractPdu>(
151 &self,
152 gen_pdu: &T,
153 start_position: u32,
154 byte_order: ByteOrder,
155 update_bit: Option<u32>,
156 ) -> Result<PduToFrameMapping, AutosarAbstractionError> {
157 Frame::Lin(LinFrame::Sporadic(self.clone())).map_pdu(gen_pdu, start_position, byte_order, update_bit)
158 }
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Hash)]
165pub struct LinUnconditionalFrame(Element);
166abstraction_element!(LinUnconditionalFrame, LinUnconditionalFrame);
167impl IdentifiableAbstractionElement for LinUnconditionalFrame {}
168
169impl LinUnconditionalFrame {
170 pub(crate) fn new(name: &str, package: &ArPackage, byte_length: u64) -> Result<Self, AutosarAbstractionError> {
171 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
172 let lin_frame = pkg_elements.create_named_sub_element(ElementName::LinUnconditionalFrame, name)?;
173
174 lin_frame
175 .create_sub_element(ElementName::FrameLength)?
176 .set_character_data(byte_length.to_string())?;
177
178 Ok(Self(lin_frame))
179 }
180
181 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
183 for pdu_mapping in self.mapped_pdus() {
184 pdu_mapping.remove(deep)?;
185 }
186
187 let frame_triggerings = self.frame_triggerings();
189
190 AbstractionElement::remove(self, deep)?;
192
193 for ft in frame_triggerings {
195 ft.remove(deep)?;
196 }
197
198 Ok(())
199 }
200}
201
202impl AbstractFrame for LinUnconditionalFrame {
203 type FrameTriggeringType = LinFrameTriggering;
204
205 fn frame_triggerings(&self) -> Vec<LinFrameTriggering> {
207 let model_result = self.element().model();
208 let path_result = self.element().path();
209 if let (Ok(model), Ok(path)) = (model_result, path_result) {
210 model
211 .get_references_to(&path)
212 .iter()
213 .filter_map(|e| {
214 e.upgrade()
215 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
216 .and_then(|elem| LinFrameTriggering::try_from(elem).ok())
217 })
218 .collect()
219 } else {
220 vec![]
221 }
222 }
223
224 fn map_pdu<T: AbstractPdu>(
226 &self,
227 gen_pdu: &T,
228 start_position: u32,
229 byte_order: ByteOrder,
230 update_bit: Option<u32>,
231 ) -> Result<PduToFrameMapping, AutosarAbstractionError> {
232 Frame::Lin(LinFrame::Unconditional(self.clone())).map_pdu(gen_pdu, start_position, byte_order, update_bit)
233 }
234}
235
236#[derive(Debug, Clone, PartialEq, Eq, Hash)]
240pub enum LinFrame {
241 EventTriggered(LinEventTriggeredFrame),
243 Sporadic(LinSporadicFrame),
245 Unconditional(LinUnconditionalFrame),
247}
248
249impl AbstractionElement for LinFrame {
250 fn element(&self) -> &autosar_data::Element {
251 match self {
252 LinFrame::EventTriggered(ftf) => ftf.element(),
253 LinFrame::Sporadic(fs) => fs.element(),
254 LinFrame::Unconditional(fu) => fu.element(),
255 }
256 }
257}
258impl IdentifiableAbstractionElement for LinFrame {}
259
260impl TryFrom<Element> for LinFrame {
261 type Error = AutosarAbstractionError;
262
263 fn try_from(element: Element) -> Result<Self, Self::Error> {
264 match element.element_name() {
265 ElementName::LinEventTriggeredFrame => {
266 Ok(LinFrame::EventTriggered(LinEventTriggeredFrame::try_from(element)?))
267 }
268 ElementName::LinSporadicFrame => Ok(LinFrame::Sporadic(LinSporadicFrame::try_from(element)?)),
269 ElementName::LinUnconditionalFrame => {
270 Ok(LinFrame::Unconditional(LinUnconditionalFrame::try_from(element)?))
271 }
272 _ => Err(AutosarAbstractionError::ConversionError {
273 element,
274 dest: "LinFrame".to_string(),
275 }),
276 }
277 }
278}
279
280impl From<LinEventTriggeredFrame> for LinFrame {
281 fn from(frame: LinEventTriggeredFrame) -> Self {
282 LinFrame::EventTriggered(frame)
283 }
284}
285
286impl From<LinSporadicFrame> for LinFrame {
287 fn from(frame: LinSporadicFrame) -> Self {
288 LinFrame::Sporadic(frame)
289 }
290}
291
292impl From<LinUnconditionalFrame> for LinFrame {
293 fn from(frame: LinUnconditionalFrame) -> Self {
294 LinFrame::Unconditional(frame)
295 }
296}
297
298impl AbstractFrame for LinFrame {
299 type FrameTriggeringType = LinFrameTriggering;
300
301 fn frame_triggerings(&self) -> Vec<LinFrameTriggering> {
303 match self {
304 LinFrame::EventTriggered(ftf) => ftf.frame_triggerings(),
305 LinFrame::Sporadic(fs) => fs.frame_triggerings(),
306 LinFrame::Unconditional(fu) => fu.frame_triggerings(),
307 }
308 }
309
310 fn map_pdu<T: AbstractPdu>(
312 &self,
313 gen_pdu: &T,
314 start_position: u32,
315 byte_order: ByteOrder,
316 update_bit: Option<u32>,
317 ) -> Result<PduToFrameMapping, AutosarAbstractionError> {
318 match self {
319 LinFrame::EventTriggered(ftf) => ftf.map_pdu(gen_pdu, start_position, byte_order, update_bit),
320 LinFrame::Sporadic(fs) => fs.map_pdu(gen_pdu, start_position, byte_order, update_bit),
321 LinFrame::Unconditional(fu) => fu.map_pdu(gen_pdu, start_position, byte_order, update_bit),
322 }
323 }
324}
325
326impl LinFrame {
327 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
329 match self {
330 LinFrame::EventTriggered(ftf) => ftf.remove(deep),
331 LinFrame::Sporadic(fs) => fs.remove(deep),
332 LinFrame::Unconditional(fu) => fu.remove(deep),
333 }
334 }
335}
336
337#[derive(Debug, Clone, PartialEq, Eq, Hash)]
341pub struct LinFrameTriggering(Element);
342abstraction_element!(LinFrameTriggering, LinFrameTriggering);
343impl IdentifiableAbstractionElement for LinFrameTriggering {}
344
345impl LinFrameTriggering {
346 pub(crate) fn new(
347 channel: &LinPhysicalChannel,
348 frame: &LinFrame,
349 identifier: u32,
350 ) -> Result<Self, AutosarAbstractionError> {
351 let model = channel.element().model()?;
352 let base_path = channel.element().path()?;
353 let frame_name = frame
354 .name()
355 .ok_or(AutosarAbstractionError::InvalidParameter("invalid frame".to_string()))?;
356 let ft_name = format!("FT_{frame_name}");
357 let ft_name = make_unique_name(&model, &base_path, &ft_name);
358
359 let frame_triggerings = channel
360 .element()
361 .get_or_create_sub_element(ElementName::FrameTriggerings)?;
362 let lin_triggering = frame_triggerings.create_named_sub_element(ElementName::LinFrameTriggering, &ft_name)?;
363
364 lin_triggering
365 .create_sub_element(ElementName::FrameRef)?
366 .set_reference_target(frame.element())?;
367
368 let ft = Self(lin_triggering);
369 ft.set_identifier(identifier)?;
370
371 for pdu_mapping in frame.mapped_pdus() {
372 if let Some(pdu) = pdu_mapping.pdu() {
373 ft.add_pdu_triggering(&pdu)?;
374 }
375 }
376
377 Ok(ft)
378 }
379
380 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
382 let opt_frame = self.frame();
383
384 for pt in self.pdu_triggerings() {
386 pt.remove(deep)?;
387 }
388 for frame_port in self.frame_ports() {
389 frame_port.remove(deep)?;
390 }
391
392 AbstractionElement::remove(self, deep)?;
393
394 if deep && let Some(frame) = opt_frame {
397 if !is_used_system_element(frame.element()) {
400 frame.remove(deep)?;
401 }
402 }
403
404 Ok(())
405 }
406
407 pub fn set_identifier(&self, identifier: u32) -> Result<(), AutosarAbstractionError> {
409 self.element()
410 .get_or_create_sub_element(ElementName::Identifier)?
411 .set_character_data(identifier.to_string())?;
412
413 Ok(())
414 }
415
416 #[must_use]
418 pub fn identifier(&self) -> Option<u32> {
419 self.element()
420 .get_sub_element(ElementName::Identifier)?
421 .character_data()?
422 .parse_integer()
423 }
424
425 pub(crate) fn add_pdu_triggering(&self, pdu: &Pdu) -> Result<PduTriggering, AutosarAbstractionError> {
426 FrameTriggering::Lin(self.clone()).add_pdu_triggering(pdu)
427 }
428
429 pub fn physical_channel(&self) -> Result<LinPhysicalChannel, AutosarAbstractionError> {
431 let channel_elem = self.element().named_parent()?.unwrap();
432 LinPhysicalChannel::try_from(channel_elem)
433 }
434
435 pub fn connect_to_ecu(
439 &self,
440 ecu: &EcuInstance,
441 direction: CommunicationDirection,
442 ) -> Result<FramePort, AutosarAbstractionError> {
443 FrameTriggering::Lin(self.clone()).connect_to_ecu(ecu, direction)
444 }
445}
446
447impl AbstractFrameTriggering for LinFrameTriggering {
448 type FrameType = LinFrame;
449}
450
451impl From<LinFrameTriggering> for FrameTriggering {
452 fn from(cft: LinFrameTriggering) -> Self {
453 FrameTriggering::Lin(cft)
454 }
455}
456
457#[cfg(test)]
460mod test {
461 use super::*;
462 use crate::{AutosarModelAbstraction, SystemCategory, communication::AbstractPhysicalChannel};
463 use autosar_data::AutosarVersion;
464
465 #[test]
466 fn create_frames() {
467 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
468 let package = model.get_or_create_package("/package").unwrap();
469
470 let event_triggered_frame = LinEventTriggeredFrame::new("EventTriggeredFrame", &package, 8).unwrap();
471 assert_eq!(
472 event_triggered_frame.element().element_name(),
473 ElementName::LinEventTriggeredFrame
474 );
475
476 let sporadic_frame = LinSporadicFrame::new("SporadicFrame", &package, 8).unwrap();
477 assert_eq!(sporadic_frame.element().element_name(), ElementName::LinSporadicFrame);
478
479 let unconditional_frame = LinUnconditionalFrame::new("UnconditionalFrame", &package, 8).unwrap();
480 assert_eq!(
481 unconditional_frame.element().element_name(),
482 ElementName::LinUnconditionalFrame
483 );
484 }
485
486 #[test]
487 fn remove_frame_triggering() {
488 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
489 let package = model.get_or_create_package("/package").unwrap();
490 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
491 let lin_cluster = system.create_lin_cluster("Cluster", &package).unwrap();
492 let channel = lin_cluster.create_physical_channel("Channel").unwrap();
493
494 let frame = system.create_lin_unconditional_frame("frame", &package, 8).unwrap();
495 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
496
497 let frame_triggering = channel.trigger_frame(&frame, 1).unwrap();
498
499 let _mapping = frame
500 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
501 .unwrap();
502
503 assert_eq!(frame.mapped_pdus().count(), 1);
504 assert_eq!(frame.frame_triggerings().len(), 1);
505 assert_eq!(channel.frame_triggerings().count(), 1);
506
507 frame_triggering.remove(false).unwrap();
509 assert_eq!(system.frames().count(), 1);
511
512 let frame_triggering = channel.trigger_frame(&frame, 2).unwrap();
514 frame_triggering.remove(true).unwrap();
516
517 assert_eq!(channel.frame_triggerings().count(), 0);
519 assert_eq!(system.frames().count(), 0);
521 assert_eq!(frame.mapped_pdus().count(), 0);
523 assert_eq!(system.pdus().count(), 0);
525
526 assert_eq!(channel.frame_triggerings().count(), 0);
527 assert_eq!(channel.pdu_triggerings().count(), 0);
528 }
529
530 #[test]
531 fn remove_frame() {
532 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
533 let package = model.get_or_create_package("/package").unwrap();
534 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
535 let lin_cluster = system.create_lin_cluster("Cluster", &package).unwrap();
536 let channel = lin_cluster.create_physical_channel("Channel").unwrap();
537 let frame = system.create_lin_unconditional_frame("frame", &package, 8).unwrap();
538 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
539 let frame_triggering = channel.trigger_frame(&frame, 1).unwrap();
540 let mapping = frame
541 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
542 .unwrap();
543 assert_eq!(frame.mapped_pdus().count(), 1);
544 assert_eq!(frame.frame_triggerings().len(), 1);
545 assert_eq!(channel.frame_triggerings().count(), 1);
546 frame.remove(false).unwrap();
548 assert_eq!(system.frames().count(), 0);
550 assert!(mapping.element().path().is_err());
552 assert_eq!(system.pdus().count(), 1);
554 assert!(frame_triggering.element().path().is_err());
556 assert_eq!(channel.frame_triggerings().count(), 0);
557 assert_eq!(channel.pdu_triggerings().count(), 0);
558 }
559}