1use crate::IdentifiableAbstractionElement;
2use crate::communication::{
3 AbstractPhysicalChannel, CommunicationDirection, DataTransformation, EndToEndTransformationISignalProps,
4 PhysicalChannel, SomeIpTransformationISignalProps, TransformationTechnology,
5};
6use crate::datatype::{CompuMethod, DataConstr, SwBaseType, Unit, ValueSpecification};
7use crate::{
8 AbstractionElement, ArPackage, AutosarAbstractionError, EcuInstance, abstraction_element,
9 communication::ISignalToIPduMapping, make_unique_name,
10};
11use autosar_data::{AutosarDataError, Element, ElementName, EnumItem, WeakElement};
12
13use super::TransformationISignalProps;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct ISignal(Element);
18abstraction_element!(ISignal, ISignal);
19impl IdentifiableAbstractionElement for ISignal {}
20
21impl ISignal {
22 pub(crate) fn new(
23 name: &str,
24 package: &ArPackage,
25 bit_length: u64,
26 syssignal: &SystemSignal,
27 datatype: Option<&SwBaseType>,
28 ) -> Result<Self, AutosarAbstractionError> {
29 if bit_length > u64::from(u32::MAX) * 8 {
30 return Err(AutosarAbstractionError::InvalidParameter(format!(
32 "isignal {name}: bit length {bit_length} is too big"
33 )));
34 }
35
36 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
37 let elem_isignal = pkg_elements.create_named_sub_element(ElementName::ISignal, name)?;
38
39 elem_isignal
40 .create_sub_element(ElementName::DataTypePolicy)?
41 .set_character_data(EnumItem::Override)?;
42
43 let isignal = Self(elem_isignal);
44 isignal.set_length(bit_length)?;
45 isignal.set_system_signal(syssignal)?;
46
47 if let Some(datatype) = datatype {
48 isignal.set_datatype(datatype)?;
49 }
50
51 Ok(isignal)
52 }
53
54 pub fn set_datatype(&self, datatype: &SwBaseType) -> Result<(), AutosarAbstractionError> {
56 self.element()
57 .get_or_create_sub_element(ElementName::NetworkRepresentationProps)?
58 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
59 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
60 .get_or_create_sub_element(ElementName::BaseTypeRef)?
61 .set_reference_target(datatype.element())?;
62 Ok(())
63 }
64
65 #[must_use]
67 pub fn datatype(&self) -> Option<SwBaseType> {
68 self.element()
69 .get_sub_element(ElementName::NetworkRepresentationProps)?
70 .get_sub_element(ElementName::SwDataDefPropsVariants)?
71 .get_sub_element(ElementName::SwDataDefPropsConditional)?
72 .get_sub_element(ElementName::BaseTypeRef)?
73 .get_reference_target()
74 .ok()?
75 .try_into()
76 .ok()
77 }
78
79 pub fn set_length(&self, bit_length: u64) -> Result<(), AutosarAbstractionError> {
81 self.element()
82 .get_or_create_sub_element(ElementName::Length)?
83 .set_character_data(bit_length)?;
84 Ok(())
85 }
86
87 #[must_use]
89 pub fn length(&self) -> Option<u64> {
90 self.element()
91 .get_sub_element(ElementName::Length)?
92 .character_data()?
93 .parse_integer()
94 }
95
96 pub fn set_init_value<T: Into<ValueSpecification>>(
100 &self,
101 value_spec: Option<T>,
102 ) -> Result<(), AutosarAbstractionError> {
103 if let Some(value_spec) = value_spec {
104 let value_spec: ValueSpecification = value_spec.into();
105 if !matches!(
106 value_spec,
107 ValueSpecification::Numerical(_) | ValueSpecification::Text(_) | ValueSpecification::Array(_)
108 ) {
109 return Err(AutosarAbstractionError::InvalidParameter(
110 "The init value must be a NumericalValueSpecification, TextValueSpecification or ArrayValueSpecification".to_string(),
111 ));
112 }
113 let init_value_elem = self.element().get_or_create_sub_element(ElementName::InitValue)?;
114 value_spec.store(&init_value_elem)?;
115 } else {
116 let _ = self.element().remove_sub_element_kind(ElementName::InitValue);
118 }
119 Ok(())
120 }
121
122 #[must_use]
124 pub fn init_value(&self) -> Option<ValueSpecification> {
125 let init_value_elem = self
126 .element()
127 .get_sub_element(ElementName::InitValue)?
128 .get_sub_element_at(0)?;
129 ValueSpecification::load(&init_value_elem)
130 }
131
132 pub fn set_system_signal(&self, syssignal: &SystemSignal) -> Result<(), AutosarAbstractionError> {
134 self.element()
135 .get_or_create_sub_element(ElementName::SystemSignalRef)?
136 .set_reference_target(syssignal.element())?;
137 Ok(())
138 }
139
140 #[must_use]
142 pub fn system_signal(&self) -> Option<SystemSignal> {
143 self.element()
144 .get_sub_element(ElementName::SystemSignalRef)?
145 .get_reference_target()
146 .ok()?
147 .try_into()
148 .ok()
149 }
150
151 #[must_use]
156 pub fn mappings(&self) -> Vec<ISignalToIPduMapping> {
157 let model_result = self.element().model();
158 let path_result = self.element().path();
159 if let (Ok(model), Ok(path)) = (model_result, path_result) {
160 model
161 .get_references_to(&path)
162 .iter()
163 .filter_map(|e| {
164 e.upgrade()
165 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
166 .and_then(|elem| ISignalToIPduMapping::try_from(elem).ok())
167 })
168 .collect()
169 } else {
170 vec![]
171 }
172 }
173
174 #[must_use]
176 pub fn signal_group(&self) -> Option<ISignalGroup> {
177 let path = self.element().path().ok()?;
178 let referrers = self.element().model().ok()?.get_references_to(&path);
179
180 for elem in referrers
181 .iter()
182 .filter_map(|weak| weak.upgrade().and_then(|elem| elem.named_parent().ok().flatten()))
183 {
184 if let Ok(grp) = ISignalGroup::try_from(elem) {
185 return Some(grp);
186 }
187 }
188 None
189 }
190
191 #[must_use]
193 pub fn signal_triggerings(&self) -> Vec<ISignalTriggering> {
194 let model_result = self.element().model();
195 let path_result = self.element().path();
196 if let (Ok(model), Ok(path)) = (model_result, path_result) {
197 model
198 .get_references_to(&path)
199 .iter()
200 .filter_map(|e| {
201 e.upgrade()
202 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
203 .and_then(|elem| ISignalTriggering::try_from(elem).ok())
204 })
205 .collect()
206 } else {
207 vec![]
208 }
209 }
210
211 pub fn add_data_transformation(
213 &self,
214 data_transformation: &DataTransformation,
215 ) -> Result<(), AutosarAbstractionError> {
216 let transformations = self
217 .element()
218 .get_or_create_sub_element(ElementName::DataTransformations)?;
219 transformations
220 .create_sub_element(ElementName::DataTransformationRefConditional)?
221 .create_sub_element(ElementName::DataTransformationRef)?
222 .set_reference_target(data_transformation.element())?;
223
224 Ok(())
225 }
226
227 pub fn data_transformations(&self) -> impl Iterator<Item = DataTransformation> + Send + 'static {
229 self.element()
230 .get_sub_element(ElementName::DataTransformations)
231 .into_iter()
232 .flat_map(|elem| elem.sub_elements())
233 .filter_map(|elem| elem.get_sub_element(ElementName::DataTransformationRef))
234 .filter_map(|elem| elem.get_reference_target().ok())
235 .filter_map(|elem| elem.try_into().ok())
236 }
237
238 pub fn create_e2e_transformation_isignal_props(
240 &self,
241 transformer: &TransformationTechnology,
242 ) -> Result<EndToEndTransformationISignalProps, AutosarAbstractionError> {
243 let tsp = self
244 .element()
245 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
246 EndToEndTransformationISignalProps::new(tsp, transformer)
247 }
248
249 pub fn create_someip_transformation_isignal_props(
251 &self,
252 transformer: &TransformationTechnology,
253 ) -> Result<SomeIpTransformationISignalProps, AutosarAbstractionError> {
254 let tsp = self
255 .element()
256 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
257 SomeIpTransformationISignalProps::new(tsp, transformer)
258 }
259
260 pub fn transformation_isignal_props(&self) -> impl Iterator<Item = TransformationISignalProps> + Send + 'static {
262 self.element()
263 .get_sub_element(ElementName::TransformationISignalPropss)
264 .into_iter()
265 .flat_map(|elem| elem.sub_elements())
266 .filter_map(|elem| TransformationISignalProps::try_from(elem).ok())
267 }
268}
269
270#[derive(Debug, Clone, PartialEq, Eq, Hash)]
276pub struct SystemSignal(Element);
277abstraction_element!(SystemSignal, SystemSignal);
278impl IdentifiableAbstractionElement for SystemSignal {}
279
280impl SystemSignal {
281 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
283 let package_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
284 let elem_syssignal = package_elements.create_named_sub_element(ElementName::SystemSignal, name)?;
285
286 Ok(Self(elem_syssignal))
287 }
288
289 pub fn signal_group(&self) -> Option<SystemSignalGroup> {
291 let path = self.element().path().ok()?;
292 let referrers = self.element().model().ok()?.get_references_to(&path);
293 for elem in referrers
294 .iter()
295 .filter_map(WeakElement::upgrade)
296 .filter_map(|refelem| refelem.named_parent().ok().flatten())
297 {
298 if let Ok(grp) = SystemSignalGroup::try_from(elem) {
299 return Some(grp);
300 }
301 }
302 None
303 }
304
305 pub fn set_unit(&self, unit: &Unit) -> Result<(), AutosarAbstractionError> {
307 self.element()
308 .get_or_create_sub_element(ElementName::PhysicalProps)?
309 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
310 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
311 .get_or_create_sub_element(ElementName::UnitRef)?
312 .set_reference_target(unit.element())?;
313 Ok(())
314 }
315
316 #[must_use]
318 pub fn unit(&self) -> Option<Unit> {
319 self.element()
320 .get_sub_element(ElementName::PhysicalProps)?
321 .get_sub_element(ElementName::SwDataDefPropsVariants)?
322 .get_sub_element(ElementName::SwDataDefPropsConditional)?
323 .get_sub_element(ElementName::UnitRef)?
324 .get_reference_target()
325 .ok()?
326 .try_into()
327 .ok()
328 }
329
330 pub fn set_compu_method(&self, compu_method: &CompuMethod) -> Result<(), AutosarAbstractionError> {
332 self.element()
333 .get_or_create_sub_element(ElementName::PhysicalProps)?
334 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
335 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
336 .get_or_create_sub_element(ElementName::CompuMethodRef)?
337 .set_reference_target(compu_method.element())?;
338 Ok(())
339 }
340
341 #[must_use]
343 pub fn compu_method(&self) -> Option<CompuMethod> {
344 self.element()
345 .get_sub_element(ElementName::PhysicalProps)?
346 .get_sub_element(ElementName::SwDataDefPropsVariants)?
347 .get_sub_element(ElementName::SwDataDefPropsConditional)?
348 .get_sub_element(ElementName::CompuMethodRef)?
349 .get_reference_target()
350 .ok()?
351 .try_into()
352 .ok()
353 }
354
355 pub fn set_data_constr(&self, data_constr: &DataConstr) -> Result<(), AutosarAbstractionError> {
357 self.element()
358 .get_or_create_sub_element(ElementName::PhysicalProps)?
359 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
360 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
361 .get_or_create_sub_element(ElementName::DataConstrRef)?
362 .set_reference_target(data_constr.element())?;
363 Ok(())
364 }
365
366 #[must_use]
368 pub fn data_constr(&self) -> Option<DataConstr> {
369 self.element()
370 .get_sub_element(ElementName::PhysicalProps)?
371 .get_sub_element(ElementName::SwDataDefPropsVariants)?
372 .get_sub_element(ElementName::SwDataDefPropsConditional)?
373 .get_sub_element(ElementName::DataConstrRef)?
374 .get_reference_target()
375 .ok()?
376 .try_into()
377 .ok()
378 }
379}
380
381#[derive(Debug, Clone, PartialEq, Eq, Hash)]
385pub struct ISignalGroup(Element);
386abstraction_element!(ISignalGroup, ISignalGroup);
387impl IdentifiableAbstractionElement for ISignalGroup {}
388
389impl ISignalGroup {
390 pub(crate) fn new(
391 name: &str,
392 package: &ArPackage,
393 system_signal_group: &SystemSignalGroup,
394 ) -> Result<Self, AutosarAbstractionError> {
395 let sig_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
396 let elem_isiggrp = sig_pkg_elements.create_named_sub_element(ElementName::ISignalGroup, name)?;
397
398 elem_isiggrp
399 .create_sub_element(ElementName::SystemSignalGroupRef)?
400 .set_reference_target(system_signal_group.element())?;
401
402 Ok(Self(elem_isiggrp))
403 }
404
405 pub fn add_signal(&self, signal: &ISignal) -> Result<(), AutosarAbstractionError> {
407 let syssig_grp_of_signal = signal.system_signal().and_then(|ss| ss.signal_group());
409 let syssig_grp = self.system_signal_group();
410 if syssig_grp != syssig_grp_of_signal {
411 return Err(AutosarAbstractionError::InvalidParameter(
412 "The isignal and the system signal must both be part of corresponding signal groups".to_string(),
413 ));
414 }
415
416 let isrefs = self.element().get_or_create_sub_element(ElementName::ISignalRefs)?;
417
418 isrefs
421 .create_sub_element(ElementName::ISignalRef)?
422 .set_reference_target(signal.element())?;
423
424 Ok(())
425 }
426
427 #[must_use]
429 pub fn system_signal_group(&self) -> Option<SystemSignalGroup> {
430 self.element()
431 .get_sub_element(ElementName::SystemSignalGroupRef)?
432 .get_reference_target()
433 .ok()?
434 .try_into()
435 .ok()
436 }
437
438 pub fn signals(&self) -> impl Iterator<Item = ISignal> + Send + 'static {
442 self.element()
443 .get_sub_element(ElementName::ISignalRefs)
444 .into_iter()
445 .flat_map(|elem| elem.sub_elements())
446 .filter_map(|elem| {
447 elem.get_reference_target()
448 .ok()
449 .and_then(|elem| ISignal::try_from(elem).ok())
450 })
451 }
452
453 pub fn add_data_transformation(
455 &self,
456 data_transformation: &DataTransformation,
457 ) -> Result<(), AutosarAbstractionError> {
458 let cbst = self
459 .element()
460 .get_or_create_sub_element(ElementName::ComBasedSignalGroupTransformations)?;
461 cbst.create_sub_element(ElementName::DataTransformationRefConditional)?
462 .create_sub_element(ElementName::DataTransformationRef)?
463 .set_reference_target(data_transformation.element())?;
464 Ok(())
465 }
466
467 pub fn data_transformations(&self) -> impl Iterator<Item = DataTransformation> + Send + 'static {
469 self.element()
470 .get_sub_element(ElementName::ComBasedSignalGroupTransformations)
471 .into_iter()
472 .flat_map(|elem| elem.sub_elements())
473 .filter_map(|elem| elem.get_sub_element(ElementName::DataTransformationRef))
474 .filter_map(|elem| elem.get_reference_target().ok())
475 .filter_map(|elem| elem.try_into().ok())
476 }
477
478 pub fn create_e2e_transformation_isignal_props(
480 &self,
481 transformer: &TransformationTechnology,
482 ) -> Result<EndToEndTransformationISignalProps, AutosarAbstractionError> {
483 let tsp = self
484 .element()
485 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
486 EndToEndTransformationISignalProps::new(tsp, transformer)
487 }
488
489 pub fn create_someip_transformation_isignal_props(
491 &self,
492 transformer: &TransformationTechnology,
493 ) -> Result<SomeIpTransformationISignalProps, AutosarAbstractionError> {
494 let tsp = self
495 .element()
496 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
497 SomeIpTransformationISignalProps::new(tsp, transformer)
498 }
499
500 pub fn transformation_isignal_props(&self) -> impl Iterator<Item = TransformationISignalProps> + Send + 'static {
502 self.element()
503 .get_sub_element(ElementName::TransformationISignalPropss)
504 .into_iter()
505 .flat_map(|elem| elem.sub_elements())
506 .filter_map(|elem| TransformationISignalProps::try_from(elem).ok())
507 }
508}
509
510#[derive(Debug, Clone, PartialEq, Eq, Hash)]
517pub struct SystemSignalGroup(Element);
518abstraction_element!(SystemSignalGroup, SystemSignalGroup);
519impl IdentifiableAbstractionElement for SystemSignalGroup {}
520
521impl SystemSignalGroup {
522 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
524 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
525 let signalgroup = pkg_elements.create_named_sub_element(ElementName::SystemSignalGroup, name)?;
526
527 Ok(Self(signalgroup))
528 }
529
530 pub fn add_signal(&self, signal: &SystemSignal) -> Result<(), AutosarAbstractionError> {
532 let ssrefs = self
533 .element()
534 .get_or_create_sub_element(ElementName::SystemSignalRefs)?;
535
536 ssrefs
539 .create_sub_element(ElementName::SystemSignalRef)?
540 .set_reference_target(signal.element())?;
541
542 Ok(())
543 }
544
545 pub fn signals(&self) -> impl Iterator<Item = SystemSignal> + Send + 'static {
547 self.element()
548 .get_sub_element(ElementName::SystemSignalRefs)
549 .into_iter()
550 .flat_map(|elem| elem.sub_elements())
551 .filter_map(|elem| {
552 elem.get_reference_target()
553 .ok()
554 .and_then(|elem| SystemSignal::try_from(elem).ok())
555 })
556 }
557}
558
559#[derive(Debug, Clone, PartialEq, Eq, Hash)]
563pub struct ISignalTriggering(Element);
564abstraction_element!(ISignalTriggering, ISignalTriggering);
565impl IdentifiableAbstractionElement for ISignalTriggering {}
566
567impl ISignalTriggering {
568 pub(crate) fn new<T: AbstractPhysicalChannel>(
569 signal: &ISignal,
570 channel: &T,
571 ) -> Result<Self, AutosarAbstractionError> {
572 let model = channel.element().model()?;
573 let base_path = channel.element().path()?;
574 let signal_name = signal
575 .name()
576 .ok_or(AutosarAbstractionError::InvalidParameter("invalid signal".to_string()))?;
577 let pt_name = format!("ST_{signal_name}");
578 let pt_name = make_unique_name(&model, &base_path, &pt_name);
579
580 let triggerings = channel
581 .element()
582 .get_or_create_sub_element(ElementName::ISignalTriggerings)?;
583 let st_elem = triggerings.create_named_sub_element(ElementName::ISignalTriggering, &pt_name)?;
584 st_elem
585 .create_sub_element(ElementName::ISignalRef)?
586 .set_reference_target(signal.element())?;
587
588 let pt = Self(st_elem);
589
590 Ok(pt)
591 }
592
593 pub(crate) fn new_group(
594 signal_group: &ISignalGroup,
595 channel: &PhysicalChannel,
596 ) -> Result<Self, AutosarAbstractionError> {
597 let model = channel.element().model()?;
598 let base_path = channel.element().path()?;
599 let signal_name = signal_group.name().ok_or(AutosarAbstractionError::InvalidParameter(
600 "invalid signal group".to_string(),
601 ))?;
602 let pt_name = format!("ST_{signal_name}");
603 let pt_name = make_unique_name(&model, &base_path, &pt_name);
604
605 let triggerings = channel
606 .element()
607 .get_or_create_sub_element(ElementName::ISignalTriggerings)?;
608 let st_elem = triggerings.create_named_sub_element(ElementName::ISignalTriggering, &pt_name)?;
609 st_elem
610 .create_sub_element(ElementName::ISignalGroupRef)?
611 .set_reference_target(signal_group.element())?;
612
613 let pt = Self(st_elem);
614
615 Ok(pt)
616 }
617
618 pub fn physical_channel(&self) -> Result<PhysicalChannel, AutosarAbstractionError> {
620 let channel_elem = self.element().named_parent()?.ok_or(AutosarDataError::ItemDeleted)?;
621 PhysicalChannel::try_from(channel_elem)
622 }
623
624 pub fn connect_to_ecu(
626 &self,
627 ecu: &EcuInstance,
628 direction: CommunicationDirection,
629 ) -> Result<ISignalPort, AutosarAbstractionError> {
630 for signal_port in self.signal_ports() {
631 if let (Ok(existing_ecu), Some(existing_direction)) =
632 (signal_port.ecu(), signal_port.communication_direction())
633 {
634 if existing_ecu == *ecu && existing_direction == direction {
635 return Ok(signal_port);
636 }
637 }
638 }
639
640 let channel = self.physical_channel()?;
641 let connector = channel
642 .ecu_connector(ecu)
643 .ok_or(AutosarAbstractionError::InvalidParameter(
644 "The ECU is not connected to the channel".to_string(),
645 ))?;
646
647 let name = self.name().ok_or(AutosarDataError::ItemDeleted)?;
648 let suffix = match direction {
649 CommunicationDirection::In => "Rx",
650 CommunicationDirection::Out => "Tx",
651 };
652 let port_name = format!("{name}_{suffix}",);
653 let sp_elem = connector
654 .element()
655 .get_or_create_sub_element(ElementName::EcuCommPortInstances)?
656 .create_named_sub_element(ElementName::ISignalPort, &port_name)?;
657 sp_elem
658 .create_sub_element(ElementName::CommunicationDirection)?
659 .set_character_data::<EnumItem>(direction.into())?;
660
661 self.element()
662 .get_or_create_sub_element(ElementName::ISignalPortRefs)?
663 .create_sub_element(ElementName::ISignalPortRef)?
664 .set_reference_target(&sp_elem)?;
665
666 Ok(ISignalPort(sp_elem))
667 }
668
669 pub fn signal_ports(&self) -> impl Iterator<Item = ISignalPort> + Send + 'static {
671 self.element()
672 .get_sub_element(ElementName::ISignalPortRefs)
673 .into_iter()
674 .flat_map(|elem| elem.sub_elements())
675 .filter_map(|elem| {
676 elem.get_reference_target()
677 .ok()
678 .and_then(|elem| ISignalPort::try_from(elem).ok())
679 })
680 }
681}
682
683#[derive(Debug, Clone, PartialEq, Eq, Hash)]
687pub struct ISignalPort(Element);
688abstraction_element!(ISignalPort, ISignalPort);
689impl IdentifiableAbstractionElement for ISignalPort {}
690
691impl ISignalPort {
692 pub fn ecu(&self) -> Result<EcuInstance, AutosarAbstractionError> {
694 let comm_connector_elem = self.element().named_parent()?.unwrap();
695 let ecu_elem = comm_connector_elem.named_parent()?.unwrap();
696 EcuInstance::try_from(ecu_elem)
697 }
698
699 pub fn set_communication_direction(
701 &self,
702 direction: CommunicationDirection,
703 ) -> Result<(), AutosarAbstractionError> {
704 self.element()
705 .get_or_create_sub_element(ElementName::CommunicationDirection)?
706 .set_character_data::<EnumItem>(direction.into())?;
707 Ok(())
708 }
709
710 #[must_use]
712 pub fn communication_direction(&self) -> Option<CommunicationDirection> {
713 self.element()
714 .get_sub_element(ElementName::CommunicationDirection)?
715 .character_data()?
716 .enum_value()?
717 .try_into()
718 .ok()
719 }
720}
721
722#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
726pub enum TransferProperty {
727 Pending,
729 Triggered,
731 TriggeredOnChange,
733 TriggeredOnChangeWithoutRepetition,
735 TriggeredWithoutRepetition,
737}
738
739impl From<TransferProperty> for EnumItem {
740 fn from(value: TransferProperty) -> Self {
741 match value {
742 TransferProperty::Pending => EnumItem::Pending,
743 TransferProperty::Triggered => EnumItem::Triggered,
744 TransferProperty::TriggeredOnChange => EnumItem::TriggeredOnChange,
745 TransferProperty::TriggeredOnChangeWithoutRepetition => EnumItem::TriggeredOnChangeWithoutRepetition,
746 TransferProperty::TriggeredWithoutRepetition => EnumItem::TriggeredWithoutRepetition,
747 }
748 }
749}
750
751impl TryFrom<EnumItem> for TransferProperty {
752 type Error = AutosarAbstractionError;
753
754 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
755 match value {
756 EnumItem::Pending => Ok(TransferProperty::Pending),
757 EnumItem::Triggered => Ok(TransferProperty::Triggered),
758 EnumItem::TriggeredOnChange => Ok(TransferProperty::TriggeredOnChange),
759 EnumItem::TriggeredOnChangeWithoutRepetition => Ok(TransferProperty::TriggeredOnChangeWithoutRepetition),
760 EnumItem::TriggeredWithoutRepetition => Ok(TransferProperty::TriggeredWithoutRepetition),
761 _ => Err(AutosarAbstractionError::ValueConversionError {
762 value: value.to_string(),
763 dest: "TransferProperty".to_string(),
764 }),
765 }
766 }
767}
768
769#[cfg(test)]
772mod tests {
773 use super::*;
774 use crate::{
775 AutosarModelAbstraction, ByteOrder, SystemCategory,
776 communication::{
777 AbstractFrame, AbstractPdu, CanAddressingMode, CanFrameType, DataTransformationSet, SomeIpMessageType,
778 SomeIpTransformationTechnologyConfig, TransformationTechnologyConfig,
779 },
780 datatype::{BaseTypeEncoding, CompuMethodContent, NumericalValueSpecification, SwBaseType, Unit},
781 };
782 use autosar_data::AutosarVersion;
783
784 #[test]
785 fn test_signal() {
786 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
787 let package = model.get_or_create_package("/test").unwrap();
788 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
789 let unit = Unit::new("unit", &package, Some("Unit Name")).unwrap();
790 let compu_method = CompuMethod::new("compu_method", &package, CompuMethodContent::Identical).unwrap();
791 let data_constr = DataConstr::new("data_constr", &package).unwrap();
792 let sw_base_type =
793 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
794
795 let sys_signal = package.create_system_signal("sys_signal").unwrap();
796 let signal = system
797 .create_isignal("signal", &package, 8, &sys_signal, Some(&sw_base_type))
798 .unwrap();
799
800 sys_signal.set_unit(&unit).unwrap();
801 sys_signal.set_compu_method(&compu_method).unwrap();
802 sys_signal.set_data_constr(&data_constr).unwrap();
803
804 assert_eq!(signal.length(), Some(8));
805 assert_eq!(signal.datatype(), Some(sw_base_type));
806 assert_eq!(signal.system_signal(), Some(sys_signal.clone()));
807 assert_eq!(sys_signal.unit(), Some(unit));
808 assert_eq!(sys_signal.compu_method(), Some(compu_method));
809 assert_eq!(sys_signal.data_constr(), Some(data_constr));
810
811 assert_eq!(signal.mappings().len(), 0);
813 let ipdu = system.create_isignal_ipdu("ipdu", &package, 8).unwrap();
814 let mapping = ipdu
815 .map_signal(
816 &signal,
817 0,
818 ByteOrder::MostSignificantByteLast,
819 None,
820 TransferProperty::Triggered,
821 )
822 .unwrap();
823 assert_eq!(signal.mappings().len(), 1);
824 assert_eq!(signal.mappings()[0], mapping.clone());
825 assert_eq!(mapping.signal().unwrap(), signal);
826
827 let init_value = NumericalValueSpecification {
829 label: None,
830 value: 0.0,
831 };
832 signal.set_init_value(Some(init_value.clone())).unwrap();
833 assert_eq!(signal.init_value(), Some(init_value.into()));
834
835 signal.set_init_value::<ValueSpecification>(None).unwrap();
836 assert_eq!(signal.init_value(), None);
837 }
838
839 #[test]
840 fn test_signal_data_transformations() {
841 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
842 let package = model.get_or_create_package("/test").unwrap();
843 let sw_base_type =
844 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
845 let signal = ISignal::new(
846 "signal",
847 &package,
848 8,
849 &SystemSignal::new("sys_signal", &package).unwrap(),
850 Some(&sw_base_type),
851 )
852 .unwrap();
853
854 let dts = DataTransformationSet::new("data_transformation_set", &package).unwrap();
855 let transformer = dts
856 .create_transformation_technology(
857 "someip_xf",
858 &TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
859 alignment: 8,
860 byte_order: ByteOrder::MostSignificantByteFirst,
861 interface_version: 1,
862 }),
863 )
864 .unwrap();
865 let data_transformation = dts
866 .create_data_transformation("someip_trans", &[&transformer], false)
867 .unwrap();
868
869 signal.add_data_transformation(&data_transformation).unwrap();
870
871 assert_eq!(signal.data_transformations().count(), 1);
872 assert_eq!(signal.data_transformations().next(), Some(data_transformation));
873
874 let someip_props = signal.create_someip_transformation_isignal_props(&transformer).unwrap();
875 someip_props.set_legacy_strings(Some(true)).unwrap();
876 someip_props.set_interface_version(Some(1)).unwrap();
877 someip_props.set_dynamic_length(Some(true)).unwrap();
878 someip_props.set_message_type(Some(SomeIpMessageType::Request)).unwrap();
879 someip_props.set_size_of_array_length(Some(8)).unwrap();
880 someip_props.set_size_of_string_length(Some(16)).unwrap();
881 someip_props.set_size_of_struct_length(Some(32)).unwrap();
882 someip_props.set_size_of_union_length(Some(64)).unwrap();
883
884 assert_eq!(signal.transformation_isignal_props().count(), 1);
885 }
886
887 #[test]
888 fn test_signal_group_data_transformations() {
889 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
890 let package = model.get_or_create_package("/test").unwrap();
891
892 let signal_group = ISignalGroup::new(
893 "signal_group",
894 &package,
895 &SystemSignalGroup::new("sys_signal_group", &package).unwrap(),
896 )
897 .unwrap();
898
899 let dts = DataTransformationSet::new("data_transformation_set", &package).unwrap();
900 let transformer = dts
901 .create_transformation_technology(
902 "someip_xf",
903 &TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
904 alignment: 8,
905 byte_order: ByteOrder::MostSignificantByteFirst,
906 interface_version: 1,
907 }),
908 )
909 .unwrap();
910 let data_transformation = dts
911 .create_data_transformation("someip_trans", &[&transformer], false)
912 .unwrap();
913
914 signal_group.add_data_transformation(&data_transformation).unwrap();
915 assert_eq!(signal_group.data_transformations().count(), 1);
916 assert_eq!(signal_group.data_transformations().next(), Some(data_transformation));
917
918 let _someipxf_props = signal_group
919 .create_someip_transformation_isignal_props(&transformer)
920 .unwrap();
921 let result = signal_group.create_e2e_transformation_isignal_props(&transformer);
923 assert!(result.is_err());
924
925 assert_eq!(signal_group.transformation_isignal_props().count(), 1);
926 }
927
928 #[test]
929 fn test_signal_group() {
930 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
931 let package = model.get_or_create_package("/test").unwrap();
932 let sys_signal_group = SystemSignalGroup::new("sys_signal_group", &package).unwrap();
933 let signal_group = ISignalGroup::new("signal_group", &package, &sys_signal_group).unwrap();
934 assert_eq!(signal_group.system_signal_group(), Some(sys_signal_group.clone()));
935
936 let sys_signal = SystemSignal::new("sys_signal", &package).unwrap();
937 let signal = ISignal::new("signal", &package, 8, &sys_signal, None).unwrap();
938 assert_eq!(signal.system_signal(), Some(sys_signal.clone()));
939
940 sys_signal_group.add_signal(&sys_signal).unwrap();
941 assert_eq!(sys_signal.signal_group(), Some(sys_signal_group.clone()));
942 assert_eq!(sys_signal_group.signals().count(), 1);
943
944 signal_group.add_signal(&signal).unwrap();
945 assert_eq!(signal_group.signals().count(), 1);
946 }
947
948 #[test]
949 fn test_signal_triggering() {
950 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
951 let package = model.get_or_create_package("/test").unwrap();
952 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
953 let cluster = system.create_can_cluster("cluster", &package, None).unwrap();
954 let channel = cluster.create_physical_channel("channel").unwrap();
955
956 let can_frame = system.create_can_frame("frame", &package, 8).unwrap();
957 channel
958 .trigger_frame(&can_frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)
959 .unwrap();
960 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
961 can_frame
962 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
963 .unwrap();
964
965 let sw_base_type =
966 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
967
968 let sys_signal = package.create_system_signal("sys_signal").unwrap();
969 let signal = system
970 .create_isignal("signal", &package, 8, &sys_signal, Some(&sw_base_type))
971 .unwrap();
972
973 pdu.map_signal(
974 &signal,
975 0,
976 ByteOrder::MostSignificantByteLast,
977 None,
978 TransferProperty::Pending,
979 )
980 .unwrap();
981 let pt = pdu.pdu_triggerings()[0].clone();
982
983 let st = signal.signal_triggerings()[0].clone();
985 assert_eq!(st, pt.signal_triggerings().next().unwrap());
986
987 assert_eq!(st.physical_channel().unwrap(), PhysicalChannel::Can(channel.clone()));
988
989 let ecuinstance = system.create_ecu_instance("ecu", &package).unwrap();
990 let controller = ecuinstance.create_can_communication_controller("controller").unwrap();
991 controller.connect_physical_channel("connection", &channel).unwrap();
992
993 assert_eq!(st.signal_ports().count(), 0);
994 let signal_port = st.connect_to_ecu(&ecuinstance, CommunicationDirection::In).unwrap();
995 assert_eq!(st.signal_ports().count(), 1);
996 assert_eq!(signal_port.ecu().unwrap(), ecuinstance);
997 assert_eq!(signal_port.communication_direction(), Some(CommunicationDirection::In));
998 signal_port
999 .set_communication_direction(CommunicationDirection::Out)
1000 .unwrap();
1001 assert_eq!(signal_port.communication_direction(), Some(CommunicationDirection::Out));
1002 signal_port.set_name("new_name").unwrap();
1003 assert_eq!(signal_port.name().unwrap(), "new_name");
1004 }
1005}