1use crate::communication::{
2 AbstractFrame, AbstractFrameTriggering, AbstractPdu, CanPhysicalChannel, CommunicationDirection, Frame, FramePort,
3 FrameTriggering, 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, EnumItem};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct CanFrame(Element);
16abstraction_element!(CanFrame, CanFrame);
17impl IdentifiableAbstractionElement for CanFrame {}
18
19impl CanFrame {
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 can_frame = pkg_elements.create_named_sub_element(ElementName::CanFrame, name)?;
23
24 can_frame
25 .create_sub_element(ElementName::FrameLength)?
26 .set_character_data(byte_length.to_string())?;
27
28 Ok(Self(can_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 CanFrame {
53 type FrameTriggeringType = CanFrameTriggering;
54
55 fn frame_triggerings(&self) -> Vec<CanFrameTriggering> {
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| CanFrameTriggering::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::Can(self.clone()).map_pdu(gen_pdu, start_position, byte_order, update_bit)
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Hash)]
90pub struct CanFrameTriggering(Element);
91abstraction_element!(CanFrameTriggering, CanFrameTriggering);
92impl IdentifiableAbstractionElement for CanFrameTriggering {}
93
94impl CanFrameTriggering {
95 pub(crate) fn new(
96 channel: &CanPhysicalChannel,
97 frame: &CanFrame,
98 identifier: u32,
99 addressing_mode: CanAddressingMode,
100 frame_type: CanFrameType,
101 ) -> Result<Self, AutosarAbstractionError> {
102 let model = channel.element().model()?;
103 let base_path = channel.element().path()?;
104 let frame_name = frame
105 .name()
106 .ok_or(AutosarAbstractionError::InvalidParameter("invalid frame".to_string()))?;
107 let ft_name = format!("FT_{frame_name}");
108 let ft_name = make_unique_name(&model, &base_path, &ft_name);
109
110 let frame_triggerings = channel
111 .element()
112 .get_or_create_sub_element(ElementName::FrameTriggerings)?;
113 let can_triggering = frame_triggerings.create_named_sub_element(ElementName::CanFrameTriggering, &ft_name)?;
114
115 can_triggering
116 .create_sub_element(ElementName::FrameRef)?
117 .set_reference_target(frame.element())?;
118
119 let ft = Self(can_triggering);
120 ft.set_addressing_mode(addressing_mode)?;
121 ft.set_frame_type(frame_type)?;
122 if let Err(error) = ft.set_identifier(identifier) {
123 let _ = frame_triggerings.remove_sub_element(ft.0);
124 return Err(error);
125 }
126
127 for pdu_mapping in frame.mapped_pdus() {
128 if let Some(pdu) = pdu_mapping.pdu() {
129 ft.add_pdu_triggering(&pdu)?;
130 }
131 }
132
133 Ok(ft)
134 }
135
136 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
138 let opt_frame = self.frame();
139
140 for pt in self.pdu_triggerings() {
142 pt.remove(deep)?;
143 }
144 for frame_port in self.frame_ports() {
145 frame_port.remove(deep)?;
146 }
147
148 AbstractionElement::remove(self, deep)?;
149
150 if deep && let Some(frame) = opt_frame {
153 if !is_used_system_element(frame.element()) {
156 frame.remove(deep)?;
157 }
158 }
159
160 Ok(())
161 }
162
163 pub fn set_identifier(&self, identifier: u32) -> Result<(), AutosarAbstractionError> {
165 let amode = self.addressing_mode().unwrap_or(CanAddressingMode::Standard);
166 if amode == CanAddressingMode::Standard && identifier > 0x7ff {
167 return Err(AutosarAbstractionError::InvalidParameter(format!(
168 "CAN-ID {identifier} is outside the 11-bit range allowed by standard addressing"
169 )));
170 } else if identifier > 0x1fff_ffff {
171 return Err(AutosarAbstractionError::InvalidParameter(format!(
172 "CAN-ID {identifier} is outside the 29-bit range allowed by extended addressing"
173 )));
174 }
175 self.element()
176 .get_or_create_sub_element(ElementName::Identifier)?
177 .set_character_data(identifier.to_string())?;
178
179 Ok(())
180 }
181
182 #[must_use]
184 pub fn identifier(&self) -> Option<u32> {
185 self.element()
186 .get_sub_element(ElementName::Identifier)?
187 .character_data()?
188 .parse_integer()
189 }
190
191 pub fn set_addressing_mode(&self, addressing_mode: CanAddressingMode) -> Result<(), AutosarAbstractionError> {
193 self.element()
194 .get_or_create_sub_element(ElementName::CanAddressingMode)?
195 .set_character_data::<EnumItem>(addressing_mode.into())?;
196
197 Ok(())
198 }
199
200 #[must_use]
202 pub fn addressing_mode(&self) -> Option<CanAddressingMode> {
203 self.element()
204 .get_sub_element(ElementName::CanAddressingMode)?
205 .character_data()?
206 .enum_value()?
207 .try_into()
208 .ok()
209 }
210
211 pub fn set_frame_type(&self, frame_type: CanFrameType) -> Result<(), AutosarAbstractionError> {
213 self.element()
214 .get_or_create_sub_element(ElementName::CanFrameRxBehavior)?
215 .set_character_data::<EnumItem>(frame_type.into())?;
216 self.element()
217 .get_or_create_sub_element(ElementName::CanFrameTxBehavior)?
218 .set_character_data::<EnumItem>(frame_type.into())?;
219
220 Ok(())
221 }
222
223 #[must_use]
225 pub fn frame_type(&self) -> Option<CanFrameType> {
226 self.element()
227 .get_sub_element(ElementName::CanFrameTxBehavior)?
228 .character_data()?
229 .enum_value()?
230 .try_into()
231 .ok()
232 }
233
234 pub(crate) fn add_pdu_triggering(&self, pdu: &Pdu) -> Result<PduTriggering, AutosarAbstractionError> {
235 FrameTriggering::Can(self.clone()).add_pdu_triggering(pdu)
236 }
237
238 pub fn physical_channel(&self) -> Result<CanPhysicalChannel, AutosarAbstractionError> {
240 let channel_elem = self.element().named_parent()?.unwrap();
241 CanPhysicalChannel::try_from(channel_elem)
242 }
243
244 pub fn connect_to_ecu(
248 &self,
249 ecu: &EcuInstance,
250 direction: CommunicationDirection,
251 ) -> Result<FramePort, AutosarAbstractionError> {
252 FrameTriggering::Can(self.clone()).connect_to_ecu(ecu, direction)
253 }
254}
255
256impl AbstractFrameTriggering for CanFrameTriggering {
257 type FrameType = CanFrame;
258}
259
260impl From<CanFrameTriggering> for FrameTriggering {
261 fn from(cft: CanFrameTriggering) -> Self {
262 FrameTriggering::Can(cft)
263 }
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq)]
270pub enum CanAddressingMode {
271 Standard,
273 Extended,
275}
276
277impl TryFrom<EnumItem> for CanAddressingMode {
278 type Error = AutosarAbstractionError;
279
280 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
281 match value {
282 EnumItem::Standard => Ok(CanAddressingMode::Standard),
283 EnumItem::Extended => Ok(CanAddressingMode::Extended),
284 _ => Err(AutosarAbstractionError::ValueConversionError {
285 value: value.to_string(),
286 dest: "CanAddressingMode".to_string(),
287 }),
288 }
289 }
290}
291
292impl From<CanAddressingMode> for EnumItem {
293 fn from(value: CanAddressingMode) -> Self {
294 match value {
295 CanAddressingMode::Standard => EnumItem::Standard,
296 CanAddressingMode::Extended => EnumItem::Extended,
297 }
298 }
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
305pub enum CanFrameType {
306 Can20,
308 CanFd,
310 Any,
312}
313
314impl TryFrom<EnumItem> for CanFrameType {
315 type Error = AutosarAbstractionError;
316
317 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
318 match value {
319 EnumItem::Can20 => Ok(CanFrameType::Can20),
320 EnumItem::CanFd => Ok(CanFrameType::CanFd),
321 EnumItem::Any => Ok(CanFrameType::Any),
322 _ => Err(AutosarAbstractionError::ValueConversionError {
323 value: value.to_string(),
324 dest: "CanFrameType".to_string(),
325 }),
326 }
327 }
328}
329
330impl From<CanFrameType> for EnumItem {
331 fn from(value: CanFrameType) -> Self {
332 match value {
333 CanFrameType::Can20 => EnumItem::Can20,
334 CanFrameType::CanFd => EnumItem::CanFd,
335 CanFrameType::Any => EnumItem::Any,
336 }
337 }
338}
339
340#[cfg(test)]
343mod test {
344 use super::*;
345 use crate::{AutosarModelAbstraction, ByteOrder, SystemCategory, communication::AbstractPhysicalChannel};
346 use autosar_data::AutosarVersion;
347
348 #[test]
349 fn can_frame() {
350 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
351 let package = model.get_or_create_package("/package").unwrap();
352 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
353 let can_cluster = system.create_can_cluster("Cluster", &package, None).unwrap();
354 let channel = can_cluster.create_physical_channel("Channel").unwrap();
355
356 let ecu_instance = system.create_ecu_instance("ECU", &package).unwrap();
357 let can_controller = ecu_instance.create_can_communication_controller("Controller").unwrap();
358 can_controller.connect_physical_channel("connection", &channel).unwrap();
359 assert_eq!(channel.connectors().count(), 1);
360 assert_eq!(channel.connectors().next().unwrap().name().unwrap(), "connection");
361
362 let pdu1 = system.create_isignal_ipdu("pdu1", &package, 8).unwrap();
363 let pdu2 = system.create_isignal_ipdu("pdu2", &package, 8).unwrap();
364
365 let frame1 = system.create_can_frame("frame1", &package, 8).unwrap();
367 let frame2 = system.create_can_frame("frame2", &package, 8).unwrap();
368
369 assert_eq!(frame1.length().unwrap(), 8);
370 frame1.set_length(6).unwrap();
371 assert_eq!(frame1.length().unwrap(), 6);
372
373 let mapping1 = frame1
375 .map_pdu(&pdu1, 7, ByteOrder::MostSignificantByteFirst, None)
376 .unwrap();
377 assert!(frame1.mapped_pdus().count() == 1);
378 assert_eq!(frame1.mapped_pdus().next().unwrap(), mapping1);
379
380 let frame_triggering1 = channel
382 .trigger_frame(&frame1, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
383 .unwrap();
384 assert_eq!(frame1.frame_triggerings().len(), 1);
385 let frame_triggering2 = channel
386 .trigger_frame(&frame2, 0x456, CanAddressingMode::Standard, CanFrameType::Can20)
387 .unwrap();
388 assert_eq!(frame2.frame_triggerings().len(), 1);
389 assert_eq!(channel.frame_triggerings().count(), 2);
390
391 let result = frame_triggering1.set_identifier(0xffff_ffff);
393 assert!(result.is_err());
394
395 assert_eq!(frame_triggering1.pdu_triggerings().count(), 1);
397 assert_eq!(frame_triggering2.pdu_triggerings().count(), 0);
399
400 let mapping2 = frame2
402 .map_pdu(&pdu2, 7, ByteOrder::MostSignificantByteFirst, None)
403 .unwrap();
404 assert!(frame2.mapped_pdus().count() == 1);
405 assert_eq!(frame2.mapped_pdus().next().unwrap(), mapping2);
406
407 assert_eq!(frame_triggering2.pdu_triggerings().count(), 1);
409
410 let port1 = frame_triggering1
412 .connect_to_ecu(&ecu_instance, CommunicationDirection::Out)
413 .unwrap();
414 let port2 = frame_triggering2
415 .connect_to_ecu(&ecu_instance, CommunicationDirection::In)
416 .unwrap();
417
418 assert_eq!(frame_triggering1.identifier().unwrap(), 0x123);
419 assert_eq!(
420 frame_triggering1.addressing_mode().unwrap(),
421 CanAddressingMode::Standard
422 );
423 assert_eq!(frame_triggering1.frame_type().unwrap(), CanFrameType::Can20);
424 assert_eq!(frame_triggering1.frame().unwrap(), frame1);
425 assert_eq!(frame_triggering1.physical_channel().unwrap(), channel);
426
427 assert_eq!(mapping1.pdu().unwrap(), pdu1.into());
428 assert_eq!(mapping1.byte_order().unwrap(), ByteOrder::MostSignificantByteFirst);
429 assert_eq!(mapping1.start_position().unwrap(), 7);
430 assert_eq!(mapping1.update_bit(), None);
431
432 assert_eq!(port1.ecu().unwrap(), ecu_instance);
433 assert_eq!(port1.communication_direction().unwrap(), CommunicationDirection::Out);
434 assert_eq!(port2.ecu().unwrap(), ecu_instance);
435 assert_eq!(port2.communication_direction().unwrap(), CommunicationDirection::In);
436 port2.set_communication_direction(CommunicationDirection::Out).unwrap();
437 assert_eq!(port2.communication_direction().unwrap(), CommunicationDirection::Out);
438 }
439
440 #[test]
441 fn remove_frame_triggering() {
442 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
443 let package = model.get_or_create_package("/package").unwrap();
444 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
445 let can_cluster = system.create_can_cluster("Cluster", &package, None).unwrap();
446 let channel = can_cluster.create_physical_channel("Channel").unwrap();
447
448 let frame = system.create_can_frame("frame", &package, 8).unwrap();
449 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
450
451 let frame_triggering = channel
452 .trigger_frame(&frame, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
453 .unwrap();
454
455 let _mapping = frame
456 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
457 .unwrap();
458
459 assert_eq!(frame.mapped_pdus().count(), 1);
460 assert_eq!(frame.frame_triggerings().len(), 1);
461 assert_eq!(channel.frame_triggerings().count(), 1);
462
463 frame_triggering.remove(false).unwrap();
465 assert_eq!(system.frames().count(), 1);
467
468 let frame_triggering = channel
470 .trigger_frame(&frame, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
471 .unwrap();
472 frame_triggering.remove(true).unwrap();
474
475 assert_eq!(channel.frame_triggerings().count(), 0);
477 assert_eq!(system.frames().count(), 0);
479 assert_eq!(frame.mapped_pdus().count(), 0);
481 assert_eq!(system.pdus().count(), 0);
483
484 assert_eq!(channel.frame_triggerings().count(), 0);
485 assert_eq!(channel.pdu_triggerings().count(), 0);
486 }
487
488 #[test]
489 fn remove_frame() {
490 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
491 let package = model.get_or_create_package("/package").unwrap();
492 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
493 let can_cluster = system.create_can_cluster("Cluster", &package, None).unwrap();
494 let channel = can_cluster.create_physical_channel("Channel").unwrap();
495 let frame = system.create_can_frame("frame", &package, 8).unwrap();
496 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
497 let frame_triggering = channel
498 .trigger_frame(&frame, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
499 .unwrap();
500 let mapping = frame
501 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
502 .unwrap();
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 frame.remove(false).unwrap();
508 assert_eq!(system.frames().count(), 0);
510 assert!(mapping.element().path().is_err());
512 assert_eq!(system.pdus().count(), 1);
514 assert!(frame_triggering.element().path().is_err());
516 assert_eq!(channel.frame_triggerings().count(), 0);
517 assert_eq!(channel.pdu_triggerings().count(), 0);
518 }
519}