1use crate::communication::{
2 AbstractPhysicalChannel, CommunicationDirection, DataTransformation, EndToEndTransformationISignalProps,
3 PhysicalChannel, SomeIpTransformationISignalProps, TransformationTechnology,
4};
5use crate::datatype::{CompuMethod, DataConstr, SwBaseType, Unit, ValueSpecification};
6use crate::{
7 AbstractionElement, ArPackage, AutosarAbstractionError, EcuInstance, abstraction_element,
8 communication::ISignalToIPduMapping, make_unique_name,
9};
10use crate::{
11 IdentifiableAbstractionElement, SenderReceiverToSignalMapping, get_reference_parents, is_used,
12 is_used_system_element,
13};
14use autosar_data::{AutosarDataError, Element, ElementName, EnumItem, WeakElement};
15
16use super::TransformationISignalProps;
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct ISignal(Element);
21abstraction_element!(ISignal, ISignal);
22impl IdentifiableAbstractionElement for ISignal {}
23
24impl ISignal {
25 pub(crate) fn new(
26 name: &str,
27 package: &ArPackage,
28 bit_length: u64,
29 syssignal: &SystemSignal,
30 datatype: Option<&SwBaseType>,
31 ) -> Result<Self, AutosarAbstractionError> {
32 if bit_length > u64::from(u32::MAX) * 8 {
33 return Err(AutosarAbstractionError::InvalidParameter(format!(
35 "isignal {name}: bit length {bit_length} is too big"
36 )));
37 }
38
39 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
40 let elem_isignal = pkg_elements.create_named_sub_element(ElementName::ISignal, name)?;
41
42 elem_isignal
43 .create_sub_element(ElementName::DataTypePolicy)?
44 .set_character_data(EnumItem::Override)?;
45
46 let isignal = Self(elem_isignal);
47 isignal.set_length(bit_length)?;
48 isignal.set_system_signal(syssignal)?;
49
50 if let Some(datatype) = datatype {
51 isignal.set_datatype(datatype)?;
52 }
53
54 Ok(isignal)
55 }
56
57 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
59 let signal_mappings = self.mappings();
60 let signal_triggerings = self.signal_triggerings();
61
62 for transformation_prop in self.transformation_isignal_props() {
63 transformation_prop.remove(deep)?;
64 }
65
66 let data_transformations: Vec<DataTransformation> = self.data_transformations().collect();
67
68 let opt_signal_group = self.signal_group();
69 let opt_system_signal = self.system_signal();
70 let opt_datatype = self.datatype();
71
72 AbstractionElement::remove(self, deep)?;
73
74 for signal_mapping in signal_mappings {
76 signal_mapping.remove(deep)?;
77 }
78 for signal_triggering in signal_triggerings {
80 signal_triggering.remove(deep)?;
81 }
82
83 if deep {
84 if let Some(signal_group) = opt_signal_group
85 && signal_group.signals().count() == 0
86 {
87 signal_group.remove(deep)?;
89 }
90
91 if let Some(datatype) = opt_datatype
92 && !is_used(datatype.element())
93 {
94 datatype.remove(deep)?;
96 }
97
98 if let Some(system_signal) = opt_system_signal
99 && !is_used(system_signal.element())
100 {
101 system_signal.remove(deep)?;
103 }
104
105 for data_transformation in data_transformations {
106 if !is_used(data_transformation.element()) {
107 data_transformation.remove(deep)?;
109 }
110 }
111 }
112
113 Ok(())
114 }
115
116 pub fn set_datatype(&self, datatype: &SwBaseType) -> Result<(), AutosarAbstractionError> {
118 self.element()
119 .get_or_create_sub_element(ElementName::NetworkRepresentationProps)?
120 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
121 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
122 .get_or_create_sub_element(ElementName::BaseTypeRef)?
123 .set_reference_target(datatype.element())?;
124 Ok(())
125 }
126
127 #[must_use]
129 pub fn datatype(&self) -> Option<SwBaseType> {
130 self.element()
131 .get_sub_element(ElementName::NetworkRepresentationProps)?
132 .get_sub_element(ElementName::SwDataDefPropsVariants)?
133 .get_sub_element(ElementName::SwDataDefPropsConditional)?
134 .get_sub_element(ElementName::BaseTypeRef)?
135 .get_reference_target()
136 .ok()?
137 .try_into()
138 .ok()
139 }
140
141 pub fn set_length(&self, bit_length: u64) -> Result<(), AutosarAbstractionError> {
143 self.element()
144 .get_or_create_sub_element(ElementName::Length)?
145 .set_character_data(bit_length)?;
146 Ok(())
147 }
148
149 #[must_use]
151 pub fn length(&self) -> Option<u64> {
152 self.element()
153 .get_sub_element(ElementName::Length)?
154 .character_data()?
155 .parse_integer()
156 }
157
158 pub fn set_init_value<T: Into<ValueSpecification>>(
162 &self,
163 value_spec: Option<T>,
164 ) -> Result<(), AutosarAbstractionError> {
165 if let Some(value_spec) = value_spec {
166 let value_spec: ValueSpecification = value_spec.into();
167 if !matches!(
168 value_spec,
169 ValueSpecification::Numerical(_) | ValueSpecification::Text(_) | ValueSpecification::Array(_)
170 ) {
171 return Err(AutosarAbstractionError::InvalidParameter(
172 "The init value must be a NumericalValueSpecification, TextValueSpecification or ArrayValueSpecification".to_string(),
173 ));
174 }
175 let init_value_elem = self.element().get_or_create_sub_element(ElementName::InitValue)?;
176 value_spec.store(&init_value_elem)?;
177 } else {
178 let _ = self.element().remove_sub_element_kind(ElementName::InitValue);
180 }
181 Ok(())
182 }
183
184 #[must_use]
186 pub fn init_value(&self) -> Option<ValueSpecification> {
187 let init_value_elem = self
188 .element()
189 .get_sub_element(ElementName::InitValue)?
190 .get_sub_element_at(0)?;
191 ValueSpecification::load(&init_value_elem)
192 }
193
194 pub fn set_system_signal(&self, syssignal: &SystemSignal) -> Result<(), AutosarAbstractionError> {
196 self.element()
197 .get_or_create_sub_element(ElementName::SystemSignalRef)?
198 .set_reference_target(syssignal.element())?;
199 Ok(())
200 }
201
202 #[must_use]
204 pub fn system_signal(&self) -> Option<SystemSignal> {
205 self.element()
206 .get_sub_element(ElementName::SystemSignalRef)?
207 .get_reference_target()
208 .ok()?
209 .try_into()
210 .ok()
211 }
212
213 #[must_use]
218 pub fn mappings(&self) -> Vec<ISignalToIPduMapping> {
219 let model_result = self.element().model();
220 let path_result = self.element().path();
221 if let (Ok(model), Ok(path)) = (model_result, path_result) {
222 model
223 .get_references_to(&path)
224 .iter()
225 .filter_map(|e| {
226 e.upgrade()
227 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
228 .and_then(|elem| ISignalToIPduMapping::try_from(elem).ok())
229 })
230 .collect()
231 } else {
232 vec![]
233 }
234 }
235
236 #[must_use]
238 pub fn signal_group(&self) -> Option<ISignalGroup> {
239 let path = self.element().path().ok()?;
240 let referrers = self.element().model().ok()?.get_references_to(&path);
241
242 for elem in referrers
243 .iter()
244 .filter_map(|weak| weak.upgrade().and_then(|elem| elem.named_parent().ok().flatten()))
245 {
246 if let Ok(grp) = ISignalGroup::try_from(elem) {
247 return Some(grp);
248 }
249 }
250 None
251 }
252
253 #[must_use]
255 pub fn signal_triggerings(&self) -> Vec<ISignalTriggering> {
256 let model_result = self.element().model();
257 let path_result = self.element().path();
258 if let (Ok(model), Ok(path)) = (model_result, path_result) {
259 model
260 .get_references_to(&path)
261 .iter()
262 .filter_map(|e| {
263 e.upgrade()
264 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
265 .and_then(|elem| ISignalTriggering::try_from(elem).ok())
266 })
267 .collect()
268 } else {
269 vec![]
270 }
271 }
272
273 pub fn add_data_transformation(
275 &self,
276 data_transformation: &DataTransformation,
277 ) -> Result<(), AutosarAbstractionError> {
278 let transformations = self
279 .element()
280 .get_or_create_sub_element(ElementName::DataTransformations)?;
281 transformations
282 .create_sub_element(ElementName::DataTransformationRefConditional)?
283 .create_sub_element(ElementName::DataTransformationRef)?
284 .set_reference_target(data_transformation.element())?;
285
286 Ok(())
287 }
288
289 pub fn data_transformations(&self) -> impl Iterator<Item = DataTransformation> + Send + use<> {
291 self.element()
292 .get_sub_element(ElementName::DataTransformations)
293 .into_iter()
294 .flat_map(|elem| elem.sub_elements())
295 .filter_map(|elem| elem.get_sub_element(ElementName::DataTransformationRef))
296 .filter_map(|elem| elem.get_reference_target().ok())
297 .filter_map(|elem| elem.try_into().ok())
298 }
299
300 pub fn create_e2e_transformation_isignal_props(
302 &self,
303 transformer: &TransformationTechnology,
304 ) -> Result<EndToEndTransformationISignalProps, AutosarAbstractionError> {
305 let tsp = self
306 .element()
307 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
308 EndToEndTransformationISignalProps::new(tsp, transformer)
309 }
310
311 pub fn create_someip_transformation_isignal_props(
313 &self,
314 transformer: &TransformationTechnology,
315 ) -> Result<SomeIpTransformationISignalProps, AutosarAbstractionError> {
316 let tsp = self
317 .element()
318 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
319 SomeIpTransformationISignalProps::new(tsp, transformer)
320 }
321
322 pub fn transformation_isignal_props(&self) -> impl Iterator<Item = TransformationISignalProps> + Send + use<> {
324 self.element()
325 .get_sub_element(ElementName::TransformationISignalPropss)
326 .into_iter()
327 .flat_map(|elem| elem.sub_elements())
328 .filter_map(|elem| TransformationISignalProps::try_from(elem).ok())
329 }
330}
331
332#[derive(Debug, Clone, PartialEq, Eq, Hash)]
338pub struct SystemSignal(Element);
339abstraction_element!(SystemSignal, SystemSignal);
340impl IdentifiableAbstractionElement for SystemSignal {}
341
342impl SystemSignal {
343 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
345 let package_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
346 let elem_syssignal = package_elements.create_named_sub_element(ElementName::SystemSignal, name)?;
347
348 Ok(Self(elem_syssignal))
349 }
350
351 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
353 let model = self.element().model()?;
355 let path = self.element().path()?;
356 let referrers = model.get_references_to(&path);
357 for elem in referrers
358 .iter()
359 .filter_map(WeakElement::upgrade)
360 .filter_map(|refelem| refelem.named_parent().ok().flatten())
361 {
362 if let Ok(isignal) = ISignal::try_from(elem) {
363 isignal.remove(deep)?;
364 }
365 }
366
367 let opt_unit = self.unit();
368 let opt_compu_method = self.compu_method();
369 let opt_data_constr = self.data_constr();
370
371 AbstractionElement::remove(self, deep)?;
372
373 if deep {
374 if let Some(unit) = opt_unit
375 && !is_used(unit.element())
376 {
377 unit.remove(deep)?;
379 }
380
381 if let Some(compu_method) = opt_compu_method
382 && !is_used(compu_method.element())
383 {
384 compu_method.remove(deep)?;
386 }
387
388 if let Some(data_constr) = opt_data_constr
389 && !is_used(data_constr.element())
390 {
391 data_constr.remove(deep)?;
393 }
394 }
395
396 Ok(())
397 }
398
399 pub fn signal_group(&self) -> Option<SystemSignalGroup> {
401 let path = self.element().path().ok()?;
402 let referrers = self.element().model().ok()?.get_references_to(&path);
403 for elem in referrers
404 .iter()
405 .filter_map(WeakElement::upgrade)
406 .filter_map(|refelem| refelem.named_parent().ok().flatten())
407 {
408 if let Ok(grp) = SystemSignalGroup::try_from(elem) {
409 return Some(grp);
410 }
411 }
412 None
413 }
414
415 pub fn set_unit(&self, unit: &Unit) -> Result<(), AutosarAbstractionError> {
417 self.element()
418 .get_or_create_sub_element(ElementName::PhysicalProps)?
419 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
420 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
421 .get_or_create_sub_element(ElementName::UnitRef)?
422 .set_reference_target(unit.element())?;
423 Ok(())
424 }
425
426 #[must_use]
428 pub fn unit(&self) -> Option<Unit> {
429 self.element()
430 .get_sub_element(ElementName::PhysicalProps)?
431 .get_sub_element(ElementName::SwDataDefPropsVariants)?
432 .get_sub_element(ElementName::SwDataDefPropsConditional)?
433 .get_sub_element(ElementName::UnitRef)?
434 .get_reference_target()
435 .ok()?
436 .try_into()
437 .ok()
438 }
439
440 pub fn set_compu_method(&self, compu_method: &CompuMethod) -> Result<(), AutosarAbstractionError> {
442 self.element()
443 .get_or_create_sub_element(ElementName::PhysicalProps)?
444 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
445 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
446 .get_or_create_sub_element(ElementName::CompuMethodRef)?
447 .set_reference_target(compu_method.element())?;
448 Ok(())
449 }
450
451 #[must_use]
453 pub fn compu_method(&self) -> Option<CompuMethod> {
454 self.element()
455 .get_sub_element(ElementName::PhysicalProps)?
456 .get_sub_element(ElementName::SwDataDefPropsVariants)?
457 .get_sub_element(ElementName::SwDataDefPropsConditional)?
458 .get_sub_element(ElementName::CompuMethodRef)?
459 .get_reference_target()
460 .ok()?
461 .try_into()
462 .ok()
463 }
464
465 pub fn set_data_constr(&self, data_constr: &DataConstr) -> Result<(), AutosarAbstractionError> {
467 self.element()
468 .get_or_create_sub_element(ElementName::PhysicalProps)?
469 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
470 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
471 .get_or_create_sub_element(ElementName::DataConstrRef)?
472 .set_reference_target(data_constr.element())?;
473 Ok(())
474 }
475
476 #[must_use]
478 pub fn data_constr(&self) -> Option<DataConstr> {
479 self.element()
480 .get_sub_element(ElementName::PhysicalProps)?
481 .get_sub_element(ElementName::SwDataDefPropsVariants)?
482 .get_sub_element(ElementName::SwDataDefPropsConditional)?
483 .get_sub_element(ElementName::DataConstrRef)?
484 .get_reference_target()
485 .ok()?
486 .try_into()
487 .ok()
488 }
489}
490
491#[derive(Debug, Clone, PartialEq, Eq, Hash)]
495pub struct ISignalGroup(Element);
496abstraction_element!(ISignalGroup, ISignalGroup);
497impl IdentifiableAbstractionElement for ISignalGroup {}
498
499impl ISignalGroup {
500 pub(crate) fn new(
501 name: &str,
502 package: &ArPackage,
503 system_signal_group: &SystemSignalGroup,
504 ) -> Result<Self, AutosarAbstractionError> {
505 let sig_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
506 let elem_isiggrp = sig_pkg_elements.create_named_sub_element(ElementName::ISignalGroup, name)?;
507
508 elem_isiggrp
509 .create_sub_element(ElementName::SystemSignalGroupRef)?
510 .set_reference_target(system_signal_group.element())?;
511
512 Ok(Self(elem_isiggrp))
513 }
514
515 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
517 let signals = if deep {
518 self.signals().collect::<Vec<_>>()
519 } else {
520 vec![]
521 };
522
523 let opt_system_signal_group = self.system_signal_group();
524
525 let ref_parents = get_reference_parents(self.element())?;
526
527 AbstractionElement::remove(self, deep)?;
528
529 for (_named_parent, parent) in ref_parents {
530 if parent.element_name() == ElementName::SenderReceiverToSignalMapping
531 && let Ok(sender_receiver_to_signal_mapping) = SenderReceiverToSignalMapping::try_from(parent)
532 {
533 sender_receiver_to_signal_mapping.remove(deep)?;
534 }
535 }
536
537 if deep {
538 for signal in signals {
540 if !is_used_system_element(signal.element()) {
541 signal.remove(deep)?;
543 }
544 }
545
546 if let Some(system_signal_group) = opt_system_signal_group
548 && !is_used(system_signal_group.element())
549 {
550 system_signal_group.remove(deep)?;
551 }
552 }
553
554 Ok(())
555 }
556
557 pub fn add_signal(&self, signal: &ISignal) -> Result<(), AutosarAbstractionError> {
559 let syssig_grp_of_signal = signal.system_signal().and_then(|ss| ss.signal_group());
561 let syssig_grp = self.system_signal_group();
562 if syssig_grp != syssig_grp_of_signal {
563 return Err(AutosarAbstractionError::InvalidParameter(
564 "The isignal and the system signal must both be part of corresponding signal groups".to_string(),
565 ));
566 }
567
568 let isrefs = self.element().get_or_create_sub_element(ElementName::ISignalRefs)?;
569
570 isrefs
573 .create_sub_element(ElementName::ISignalRef)?
574 .set_reference_target(signal.element())?;
575
576 Ok(())
577 }
578
579 #[must_use]
581 pub fn system_signal_group(&self) -> Option<SystemSignalGroup> {
582 self.element()
583 .get_sub_element(ElementName::SystemSignalGroupRef)?
584 .get_reference_target()
585 .ok()?
586 .try_into()
587 .ok()
588 }
589
590 pub fn signals(&self) -> impl Iterator<Item = ISignal> + Send + use<> {
594 self.element()
595 .get_sub_element(ElementName::ISignalRefs)
596 .into_iter()
597 .flat_map(|elem| elem.sub_elements())
598 .filter_map(|elem| {
599 elem.get_reference_target()
600 .ok()
601 .and_then(|elem| ISignal::try_from(elem).ok())
602 })
603 }
604
605 pub fn add_data_transformation(
607 &self,
608 data_transformation: &DataTransformation,
609 ) -> Result<(), AutosarAbstractionError> {
610 let cbst = self
611 .element()
612 .get_or_create_sub_element(ElementName::ComBasedSignalGroupTransformations)?;
613 cbst.create_sub_element(ElementName::DataTransformationRefConditional)?
614 .create_sub_element(ElementName::DataTransformationRef)?
615 .set_reference_target(data_transformation.element())?;
616 Ok(())
617 }
618
619 pub fn data_transformations(&self) -> impl Iterator<Item = DataTransformation> + Send + use<> {
621 self.element()
622 .get_sub_element(ElementName::ComBasedSignalGroupTransformations)
623 .into_iter()
624 .flat_map(|elem| elem.sub_elements())
625 .filter_map(|elem| elem.get_sub_element(ElementName::DataTransformationRef))
626 .filter_map(|elem| elem.get_reference_target().ok())
627 .filter_map(|elem| elem.try_into().ok())
628 }
629
630 pub fn create_e2e_transformation_isignal_props(
632 &self,
633 transformer: &TransformationTechnology,
634 ) -> Result<EndToEndTransformationISignalProps, AutosarAbstractionError> {
635 let tsp = self
636 .element()
637 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
638 EndToEndTransformationISignalProps::new(tsp, transformer)
639 }
640
641 pub fn create_someip_transformation_isignal_props(
643 &self,
644 transformer: &TransformationTechnology,
645 ) -> Result<SomeIpTransformationISignalProps, AutosarAbstractionError> {
646 let tsp = self
647 .element()
648 .get_or_create_sub_element(ElementName::TransformationISignalPropss)?;
649 SomeIpTransformationISignalProps::new(tsp, transformer)
650 }
651
652 pub fn transformation_isignal_props(&self) -> impl Iterator<Item = TransformationISignalProps> + Send + use<> {
654 self.element()
655 .get_sub_element(ElementName::TransformationISignalPropss)
656 .into_iter()
657 .flat_map(|elem| elem.sub_elements())
658 .filter_map(|elem| TransformationISignalProps::try_from(elem).ok())
659 }
660}
661
662#[derive(Debug, Clone, PartialEq, Eq, Hash)]
669pub struct SystemSignalGroup(Element);
670abstraction_element!(SystemSignalGroup, SystemSignalGroup);
671impl IdentifiableAbstractionElement for SystemSignalGroup {}
672
673impl SystemSignalGroup {
674 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
676 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
677 let signalgroup = pkg_elements.create_named_sub_element(ElementName::SystemSignalGroup, name)?;
678
679 Ok(Self(signalgroup))
680 }
681
682 pub fn add_signal(&self, signal: &SystemSignal) -> Result<(), AutosarAbstractionError> {
684 let ssrefs = self
685 .element()
686 .get_or_create_sub_element(ElementName::SystemSignalRefs)?;
687
688 ssrefs
691 .create_sub_element(ElementName::SystemSignalRef)?
692 .set_reference_target(signal.element())?;
693
694 Ok(())
695 }
696
697 pub fn signals(&self) -> impl Iterator<Item = SystemSignal> + Send + use<> {
699 self.element()
700 .get_sub_element(ElementName::SystemSignalRefs)
701 .into_iter()
702 .flat_map(|elem| elem.sub_elements())
703 .filter_map(|elem| {
704 elem.get_reference_target()
705 .ok()
706 .and_then(|elem| SystemSignal::try_from(elem).ok())
707 })
708 }
709}
710
711#[derive(Debug, Clone, PartialEq, Eq, Hash)]
715pub struct ISignalTriggering(Element);
716abstraction_element!(ISignalTriggering, ISignalTriggering);
717impl IdentifiableAbstractionElement for ISignalTriggering {}
718
719impl ISignalTriggering {
720 pub(crate) fn new<T: AbstractPhysicalChannel>(
721 signal: &ISignal,
722 channel: &T,
723 ) -> Result<Self, AutosarAbstractionError> {
724 let model = channel.element().model()?;
725 let base_path = channel.element().path()?;
726 let signal_name = signal
727 .name()
728 .ok_or(AutosarAbstractionError::InvalidParameter("invalid signal".to_string()))?;
729 let pt_name = format!("ST_{signal_name}");
730 let pt_name = make_unique_name(&model, &base_path, &pt_name);
731
732 let triggerings = channel
733 .element()
734 .get_or_create_sub_element(ElementName::ISignalTriggerings)?;
735 let st_elem = triggerings.create_named_sub_element(ElementName::ISignalTriggering, &pt_name)?;
736 st_elem
737 .create_sub_element(ElementName::ISignalRef)?
738 .set_reference_target(signal.element())?;
739
740 let pt = Self(st_elem);
741
742 Ok(pt)
743 }
744
745 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
747 let opt_signal = self.signal();
748 for sp in self.signal_ports() {
749 sp.remove(deep)?;
750 }
751
752 AbstractionElement::remove(self, deep)?;
753
754 if deep
755 && let Some(signal) = opt_signal
756 && !is_used_system_element(signal.element())
757 {
758 signal.remove(deep)?;
760 }
761
762 Ok(())
763 }
764
765 pub(crate) fn new_group(
766 signal_group: &ISignalGroup,
767 channel: &PhysicalChannel,
768 ) -> Result<Self, AutosarAbstractionError> {
769 let model = channel.element().model()?;
770 let base_path = channel.element().path()?;
771 let signal_name = signal_group.name().ok_or(AutosarAbstractionError::InvalidParameter(
772 "invalid signal group".to_string(),
773 ))?;
774 let pt_name = format!("ST_{signal_name}");
775 let pt_name = make_unique_name(&model, &base_path, &pt_name);
776
777 let triggerings = channel
778 .element()
779 .get_or_create_sub_element(ElementName::ISignalTriggerings)?;
780 let st_elem = triggerings.create_named_sub_element(ElementName::ISignalTriggering, &pt_name)?;
781 st_elem
782 .create_sub_element(ElementName::ISignalGroupRef)?
783 .set_reference_target(signal_group.element())?;
784
785 let pt = Self(st_elem);
786
787 Ok(pt)
788 }
789
790 pub fn physical_channel(&self) -> Result<PhysicalChannel, AutosarAbstractionError> {
792 let channel_elem = self.element().named_parent()?.ok_or(AutosarDataError::ItemDeleted)?;
793 PhysicalChannel::try_from(channel_elem)
794 }
795
796 pub fn connect_to_ecu(
798 &self,
799 ecu: &EcuInstance,
800 direction: CommunicationDirection,
801 ) -> Result<ISignalPort, AutosarAbstractionError> {
802 for signal_port in self.signal_ports() {
803 if let (Ok(existing_ecu), Some(existing_direction)) =
804 (signal_port.ecu(), signal_port.communication_direction())
805 && existing_ecu == *ecu
806 && existing_direction == direction
807 {
808 return Ok(signal_port);
809 }
810 }
811
812 let channel = self.physical_channel()?;
813 let connector = channel
814 .ecu_connector(ecu)
815 .ok_or(AutosarAbstractionError::InvalidParameter(
816 "The ECU is not connected to the channel".to_string(),
817 ))?;
818
819 let name = self.name().ok_or(AutosarDataError::ItemDeleted)?;
820 let suffix = match direction {
821 CommunicationDirection::In => "Rx",
822 CommunicationDirection::Out => "Tx",
823 };
824 let port_name = format!("{name}_{suffix}",);
825 let sp_elem = connector
826 .element()
827 .get_or_create_sub_element(ElementName::EcuCommPortInstances)?
828 .create_named_sub_element(ElementName::ISignalPort, &port_name)?;
829 sp_elem
830 .create_sub_element(ElementName::CommunicationDirection)?
831 .set_character_data::<EnumItem>(direction.into())?;
832
833 self.element()
834 .get_or_create_sub_element(ElementName::ISignalPortRefs)?
835 .create_sub_element(ElementName::ISignalPortRef)?
836 .set_reference_target(&sp_elem)?;
837
838 Ok(ISignalPort(sp_elem))
839 }
840
841 pub fn signal(&self) -> Option<ISignal> {
843 let signal_elem = self
844 .element()
845 .get_sub_element(ElementName::ISignalRef)?
846 .get_reference_target()
847 .ok()?;
848 ISignal::try_from(signal_elem).ok()
849 }
850
851 pub fn signal_ports(&self) -> impl Iterator<Item = ISignalPort> + Send + use<> {
853 self.element()
854 .get_sub_element(ElementName::ISignalPortRefs)
855 .into_iter()
856 .flat_map(|elem| elem.sub_elements())
857 .filter_map(|elem| {
858 elem.get_reference_target()
859 .ok()
860 .and_then(|elem| ISignalPort::try_from(elem).ok())
861 })
862 }
863}
864
865#[derive(Debug, Clone, PartialEq, Eq, Hash)]
869pub struct ISignalPort(Element);
870abstraction_element!(ISignalPort, ISignalPort);
871impl IdentifiableAbstractionElement for ISignalPort {}
872
873impl ISignalPort {
874 pub fn ecu(&self) -> Result<EcuInstance, AutosarAbstractionError> {
876 let comm_connector_elem = self.element().named_parent()?.unwrap();
877 let ecu_elem = comm_connector_elem.named_parent()?.unwrap();
878 EcuInstance::try_from(ecu_elem)
879 }
880
881 pub fn set_communication_direction(
883 &self,
884 direction: CommunicationDirection,
885 ) -> Result<(), AutosarAbstractionError> {
886 self.element()
887 .get_or_create_sub_element(ElementName::CommunicationDirection)?
888 .set_character_data::<EnumItem>(direction.into())?;
889 Ok(())
890 }
891
892 #[must_use]
894 pub fn communication_direction(&self) -> Option<CommunicationDirection> {
895 self.element()
896 .get_sub_element(ElementName::CommunicationDirection)?
897 .character_data()?
898 .enum_value()?
899 .try_into()
900 .ok()
901 }
902}
903
904#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
908pub enum TransferProperty {
909 Pending,
911 Triggered,
913 TriggeredOnChange,
915 TriggeredOnChangeWithoutRepetition,
917 TriggeredWithoutRepetition,
919}
920
921impl From<TransferProperty> for EnumItem {
922 fn from(value: TransferProperty) -> Self {
923 match value {
924 TransferProperty::Pending => EnumItem::Pending,
925 TransferProperty::Triggered => EnumItem::Triggered,
926 TransferProperty::TriggeredOnChange => EnumItem::TriggeredOnChange,
927 TransferProperty::TriggeredOnChangeWithoutRepetition => EnumItem::TriggeredOnChangeWithoutRepetition,
928 TransferProperty::TriggeredWithoutRepetition => EnumItem::TriggeredWithoutRepetition,
929 }
930 }
931}
932
933impl TryFrom<EnumItem> for TransferProperty {
934 type Error = AutosarAbstractionError;
935
936 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
937 match value {
938 EnumItem::Pending => Ok(TransferProperty::Pending),
939 EnumItem::Triggered => Ok(TransferProperty::Triggered),
940 EnumItem::TriggeredOnChange => Ok(TransferProperty::TriggeredOnChange),
941 EnumItem::TriggeredOnChangeWithoutRepetition => Ok(TransferProperty::TriggeredOnChangeWithoutRepetition),
942 EnumItem::TriggeredWithoutRepetition => Ok(TransferProperty::TriggeredWithoutRepetition),
943 _ => Err(AutosarAbstractionError::ValueConversionError {
944 value: value.to_string(),
945 dest: "TransferProperty".to_string(),
946 }),
947 }
948 }
949}
950
951#[cfg(test)]
954mod tests {
955 use super::*;
956 use crate::{
957 AutosarModelAbstraction, ByteOrder, SystemCategory,
958 communication::{
959 AbstractFrame, AbstractPdu, CanAddressingMode, CanFrameType, DataTransformationSet, SignalPdu,
960 SomeIpMessageType, SomeIpTransformationTechnologyConfig, TransformationTechnologyConfig,
961 },
962 datatype::{BaseTypeEncoding, CompuMethodContent, NumericalValueSpecification, SwBaseType, Unit},
963 };
964 use autosar_data::AutosarVersion;
965
966 #[test]
967 fn test_signal() {
968 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
969 let package = model.get_or_create_package("/test").unwrap();
970 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
971 let unit = Unit::new("unit", &package, Some("Unit Name")).unwrap();
972 let compu_method = CompuMethod::new("compu_method", &package, CompuMethodContent::Identical).unwrap();
973 let data_constr = DataConstr::new("data_constr", &package).unwrap();
974 let sw_base_type =
975 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
976
977 let sys_signal = package.create_system_signal("sys_signal").unwrap();
978 let signal = system
979 .create_isignal("signal", &package, 8, &sys_signal, Some(&sw_base_type))
980 .unwrap();
981
982 sys_signal.set_unit(&unit).unwrap();
983 sys_signal.set_compu_method(&compu_method).unwrap();
984 sys_signal.set_data_constr(&data_constr).unwrap();
985
986 assert_eq!(signal.length(), Some(8));
987 assert_eq!(signal.datatype(), Some(sw_base_type));
988 assert_eq!(signal.system_signal(), Some(sys_signal.clone()));
989 assert_eq!(sys_signal.unit(), Some(unit));
990 assert_eq!(sys_signal.compu_method(), Some(compu_method));
991 assert_eq!(sys_signal.data_constr(), Some(data_constr));
992
993 assert_eq!(signal.mappings().len(), 0);
995 let ipdu = system.create_isignal_ipdu("ipdu", &package, 8).unwrap();
996 let mapping = ipdu
997 .map_signal(
998 &signal,
999 0,
1000 ByteOrder::MostSignificantByteLast,
1001 None,
1002 TransferProperty::Triggered,
1003 )
1004 .unwrap();
1005 assert_eq!(signal.mappings().len(), 1);
1006 assert_eq!(signal.mappings()[0], mapping.clone());
1007 assert_eq!(mapping.signal().unwrap(), signal);
1008
1009 let init_value = NumericalValueSpecification {
1011 label: None,
1012 value: 0.0,
1013 };
1014 signal.set_init_value(Some(init_value.clone())).unwrap();
1015 assert_eq!(signal.init_value(), Some(init_value.into()));
1016
1017 signal.set_init_value::<ValueSpecification>(None).unwrap();
1018 assert_eq!(signal.init_value(), None);
1019 }
1020
1021 #[test]
1022 fn test_signal_data_transformations() {
1023 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
1024 let package = model.get_or_create_package("/test").unwrap();
1025 let sw_base_type =
1026 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
1027 let signal = ISignal::new(
1028 "signal",
1029 &package,
1030 8,
1031 &SystemSignal::new("sys_signal", &package).unwrap(),
1032 Some(&sw_base_type),
1033 )
1034 .unwrap();
1035
1036 let dts = DataTransformationSet::new("data_transformation_set", &package).unwrap();
1037 let transformer = dts
1038 .create_transformation_technology(
1039 "someip_xf",
1040 &TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
1041 alignment: 8,
1042 byte_order: ByteOrder::MostSignificantByteFirst,
1043 interface_version: 1,
1044 }),
1045 )
1046 .unwrap();
1047 let data_transformation = dts
1048 .create_data_transformation("someip_trans", &[&transformer], false)
1049 .unwrap();
1050
1051 signal.add_data_transformation(&data_transformation).unwrap();
1052
1053 assert_eq!(signal.data_transformations().count(), 1);
1054 assert_eq!(signal.data_transformations().next(), Some(data_transformation));
1055
1056 let someip_props = signal.create_someip_transformation_isignal_props(&transformer).unwrap();
1057 someip_props.set_legacy_strings(Some(true)).unwrap();
1058 someip_props.set_interface_version(Some(1)).unwrap();
1059 someip_props.set_dynamic_length(Some(true)).unwrap();
1060 someip_props.set_message_type(Some(SomeIpMessageType::Request)).unwrap();
1061 someip_props.set_size_of_array_length(Some(8)).unwrap();
1062 someip_props.set_size_of_string_length(Some(16)).unwrap();
1063 someip_props.set_size_of_struct_length(Some(32)).unwrap();
1064 someip_props.set_size_of_union_length(Some(64)).unwrap();
1065
1066 assert_eq!(signal.transformation_isignal_props().count(), 1);
1067 }
1068
1069 #[test]
1070 fn test_signal_group_data_transformations() {
1071 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
1072 let package = model.get_or_create_package("/test").unwrap();
1073
1074 let signal_group = ISignalGroup::new(
1075 "signal_group",
1076 &package,
1077 &SystemSignalGroup::new("sys_signal_group", &package).unwrap(),
1078 )
1079 .unwrap();
1080
1081 let dts = DataTransformationSet::new("data_transformation_set", &package).unwrap();
1082 let transformer = dts
1083 .create_transformation_technology(
1084 "someip_xf",
1085 &TransformationTechnologyConfig::SomeIp(SomeIpTransformationTechnologyConfig {
1086 alignment: 8,
1087 byte_order: ByteOrder::MostSignificantByteFirst,
1088 interface_version: 1,
1089 }),
1090 )
1091 .unwrap();
1092 let data_transformation = dts
1093 .create_data_transformation("someip_trans", &[&transformer], false)
1094 .unwrap();
1095
1096 signal_group.add_data_transformation(&data_transformation).unwrap();
1097 assert_eq!(signal_group.data_transformations().count(), 1);
1098 assert_eq!(signal_group.data_transformations().next(), Some(data_transformation));
1099
1100 let _someipxf_props = signal_group
1101 .create_someip_transformation_isignal_props(&transformer)
1102 .unwrap();
1103 let result = signal_group.create_e2e_transformation_isignal_props(&transformer);
1105 assert!(result.is_err());
1106
1107 assert_eq!(signal_group.transformation_isignal_props().count(), 1);
1108 }
1109
1110 #[test]
1111 fn test_signal_group() {
1112 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
1113 let package = model.get_or_create_package("/test").unwrap();
1114 let sys_signal_group = SystemSignalGroup::new("sys_signal_group", &package).unwrap();
1115 let signal_group = ISignalGroup::new("signal_group", &package, &sys_signal_group).unwrap();
1116 assert_eq!(signal_group.system_signal_group(), Some(sys_signal_group.clone()));
1117
1118 let sys_signal = SystemSignal::new("sys_signal", &package).unwrap();
1119 let signal = ISignal::new("signal", &package, 8, &sys_signal, None).unwrap();
1120 assert_eq!(signal.system_signal(), Some(sys_signal.clone()));
1121
1122 sys_signal_group.add_signal(&sys_signal).unwrap();
1123 assert_eq!(sys_signal.signal_group(), Some(sys_signal_group.clone()));
1124 assert_eq!(sys_signal_group.signals().count(), 1);
1125
1126 signal_group.add_signal(&signal).unwrap();
1127 assert_eq!(signal_group.signals().count(), 1);
1128 }
1129
1130 #[test]
1131 fn test_signal_triggering() {
1132 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
1133 let package = model.get_or_create_package("/test").unwrap();
1134 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1135 let cluster = system.create_can_cluster("cluster", &package, None).unwrap();
1136 let channel = cluster.create_physical_channel("channel").unwrap();
1137
1138 let can_frame = system.create_can_frame("frame", &package, 8).unwrap();
1139 channel
1140 .trigger_frame(&can_frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)
1141 .unwrap();
1142 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
1143 can_frame
1144 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
1145 .unwrap();
1146
1147 let sw_base_type =
1148 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
1149
1150 let sys_signal = package.create_system_signal("sys_signal").unwrap();
1151 let signal = system
1152 .create_isignal("signal", &package, 8, &sys_signal, Some(&sw_base_type))
1153 .unwrap();
1154
1155 pdu.map_signal(
1156 &signal,
1157 0,
1158 ByteOrder::MostSignificantByteLast,
1159 None,
1160 TransferProperty::Pending,
1161 )
1162 .unwrap();
1163 let pt = pdu.pdu_triggerings()[0].clone();
1164
1165 let st = signal.signal_triggerings()[0].clone();
1167 assert_eq!(st, pt.signal_triggerings().next().unwrap());
1168
1169 assert_eq!(st.physical_channel().unwrap(), PhysicalChannel::Can(channel.clone()));
1170
1171 let ecuinstance = system.create_ecu_instance("ecu", &package).unwrap();
1172 let controller = ecuinstance.create_can_communication_controller("controller").unwrap();
1173 controller.connect_physical_channel("connection", &channel).unwrap();
1174
1175 assert_eq!(st.signal_ports().count(), 0);
1176 let signal_port = st.connect_to_ecu(&ecuinstance, CommunicationDirection::In).unwrap();
1177 assert_eq!(st.signal_ports().count(), 1);
1178 assert_eq!(signal_port.ecu().unwrap(), ecuinstance);
1179 assert_eq!(signal_port.communication_direction(), Some(CommunicationDirection::In));
1180 signal_port
1181 .set_communication_direction(CommunicationDirection::Out)
1182 .unwrap();
1183 assert_eq!(signal_port.communication_direction(), Some(CommunicationDirection::Out));
1184 signal_port.set_name("new_name").unwrap();
1185 assert_eq!(signal_port.name().unwrap(), "new_name");
1186 }
1187
1188 #[test]
1189 fn test_remove_signal() {
1190 let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
1191 let package = model.get_or_create_package("/test").unwrap();
1192 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
1193 let sw_base_type =
1194 SwBaseType::new("sw_base_type", &package, 8, BaseTypeEncoding::None, None, None, None).unwrap();
1195 let sys_signal = package.create_system_signal("sys_signal").unwrap();
1196 let signal = system
1197 .create_isignal("signal", &package, 8, &sys_signal, Some(&sw_base_type))
1198 .unwrap();
1199
1200 let cluster = system.create_can_cluster("cluster", &package, None).unwrap();
1201 let channel = cluster.create_physical_channel("channel").unwrap();
1202 let can_frame = system.create_can_frame("frame", &package, 8).unwrap();
1203 channel
1204 .trigger_frame(&can_frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)
1205 .unwrap();
1206 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
1207 can_frame
1208 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
1209 .unwrap();
1210 pdu.map_signal(
1211 &signal,
1212 0,
1213 ByteOrder::MostSignificantByteLast,
1214 None,
1215 TransferProperty::Pending,
1216 )
1217 .unwrap();
1218
1219 signal.remove(true).unwrap();
1220
1221 assert_eq!(channel.signal_triggerings().count(), 0);
1222 assert_eq!(pdu.mapped_signals().count(), 0);
1223 }
1224}