1use crate::communication::{AbstractIpdu, FlexrayCluster, FlexrayCommunicationConnector, IPdu, NPdu, TpAddress};
2use crate::{
3 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
4};
5use autosar_data::{Element, ElementName, EnumItem};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct FlexrayArTpConfig(Element);
12abstraction_element!(FlexrayArTpConfig, FlexrayArTpConfig);
13impl IdentifiableAbstractionElement for FlexrayArTpConfig {}
14
15impl FlexrayArTpConfig {
16 pub(crate) fn new(
17 name: &str,
18 package: &ArPackage,
19 cluster: &FlexrayCluster,
20 ) -> Result<Self, AutosarAbstractionError> {
21 let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
22
23 let tp_config_elem = pkg_elem.create_named_sub_element(ElementName::FlexrayArTpConfig, name)?;
24 let tp_config = Self(tp_config_elem);
25 tp_config.set_cluster(cluster)?;
26
27 Ok(tp_config)
28 }
29
30 pub fn set_cluster(&self, cluster: &FlexrayCluster) -> Result<(), AutosarAbstractionError> {
32 self.element()
33 .get_or_create_sub_element(ElementName::CommunicationClusterRef)?
34 .set_reference_target(cluster.element())?;
35 Ok(())
36 }
37
38 #[must_use]
40 pub fn cluster(&self) -> Option<FlexrayCluster> {
41 self.element()
42 .get_sub_element(ElementName::CommunicationClusterRef)
43 .and_then(|refelem| refelem.get_reference_target().ok())
44 .and_then(|elem| elem.try_into().ok())
45 }
46
47 pub fn create_tp_address(&self, name: &str, address: u32) -> Result<TpAddress, AutosarAbstractionError> {
49 let tp_addresses_elem = self.element().get_or_create_sub_element(ElementName::TpAddresss)?;
50 TpAddress::new(name, &tp_addresses_elem, address)
51 }
52
53 pub fn tp_addresses(&self) -> impl Iterator<Item = TpAddress> + Send + use<> {
55 self.element()
56 .get_sub_element(ElementName::TpAddresss)
57 .into_iter()
58 .flat_map(|elem| elem.sub_elements())
59 .filter_map(|elem| elem.try_into().ok())
60 }
61
62 pub fn create_flexray_ar_tp_channel(
64 &self,
65 ack_type: FrArTpAckType,
66 extended_addressing: bool,
67 maximum_message_length: MaximumMessageLengthType,
68 minimum_separation_time: f32,
69 multicast_segmentation: bool,
70 ) -> Result<FlexrayArTpChannel, AutosarAbstractionError> {
71 let tp_channels_elem = self.element().get_or_create_sub_element(ElementName::TpChannels)?;
72 FlexrayArTpChannel::new(
73 &tp_channels_elem,
74 ack_type,
75 extended_addressing,
76 maximum_message_length,
77 minimum_separation_time,
78 multicast_segmentation,
79 )
80 }
81
82 pub fn flexray_ar_tp_channels(&self) -> impl Iterator<Item = FlexrayArTpChannel> + Send + use<> {
84 self.element()
85 .get_sub_element(ElementName::TpChannels)
86 .into_iter()
87 .flat_map(|tp_channels_elem| tp_channels_elem.sub_elements())
88 .filter_map(|tp_channel_elem| tp_channel_elem.try_into().ok())
89 }
90
91 pub fn create_flexray_ar_tp_node(&self, name: &str) -> Result<FlexrayArTpNode, AutosarAbstractionError> {
93 let tp_nodes_elem = self.element().get_or_create_sub_element(ElementName::TpNodes)?;
94 FlexrayArTpNode::new(name, &tp_nodes_elem)
95 }
96
97 pub fn flexray_ar_tp_nodes(&self) -> impl Iterator<Item = FlexrayArTpNode> + Send + use<> {
99 self.element()
100 .get_sub_element(ElementName::TpNodes)
101 .into_iter()
102 .flat_map(|tp_nodes_elem| tp_nodes_elem.sub_elements())
103 .filter_map(|tp_node_elem| tp_node_elem.try_into().ok())
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Hash)]
111pub struct FlexrayArTpChannel(Element);
112abstraction_element!(FlexrayArTpChannel, FlexrayArTpChannel);
113
114impl FlexrayArTpChannel {
115 pub(crate) fn new(
116 parent: &Element,
117 ack_type: FrArTpAckType,
118 extended_addressing: bool,
119 maximum_message_length: MaximumMessageLengthType,
120 minimum_separation_time: f32,
121 multicast_segmentation: bool,
122 ) -> Result<Self, AutosarAbstractionError> {
123 let tp_channel_elem = parent.create_sub_element(ElementName::FlexrayArTpChannel)?;
124 let tp_channel = Self(tp_channel_elem);
125
126 tp_channel.set_ack_type(ack_type)?;
127 tp_channel.set_extended_addressing(extended_addressing)?;
128 tp_channel.set_maximum_message_length(maximum_message_length)?;
129 tp_channel.set_minimum_separation_time(minimum_separation_time)?;
130 tp_channel.set_multicast_segmentation(multicast_segmentation)?;
131
132 Ok(tp_channel)
133 }
134
135 pub fn set_ack_type(&self, ack_type: FrArTpAckType) -> Result<(), AutosarAbstractionError> {
137 self.element()
138 .get_or_create_sub_element(ElementName::AckType)?
139 .set_character_data::<EnumItem>(ack_type.into())?;
140 Ok(())
141 }
142
143 #[must_use]
145 pub fn ack_type(&self) -> Option<FrArTpAckType> {
146 self.element()
147 .get_sub_element(ElementName::AckType)?
148 .character_data()?
149 .enum_value()?
150 .try_into()
151 .ok()
152 }
153
154 pub fn set_extended_addressing(&self, extended_addressing: bool) -> Result<(), AutosarAbstractionError> {
158 self.element()
159 .get_or_create_sub_element(ElementName::ExtendedAddressing)?
160 .set_character_data(extended_addressing)?;
161 Ok(())
162 }
163
164 #[must_use]
168 pub fn extended_addressing(&self) -> Option<bool> {
169 self.element()
170 .get_sub_element(ElementName::ExtendedAddressing)?
171 .character_data()?
172 .parse_bool()
173 }
174
175 pub fn set_maximum_message_length(
177 &self,
178 maximum_message_length: MaximumMessageLengthType,
179 ) -> Result<(), AutosarAbstractionError> {
180 self.element()
181 .get_or_create_sub_element(ElementName::MaximumMessageLength)?
182 .set_character_data::<EnumItem>(maximum_message_length.into())?;
183 Ok(())
184 }
185
186 #[must_use]
188 pub fn maximum_message_length(&self) -> Option<MaximumMessageLengthType> {
189 self.element()
190 .get_sub_element(ElementName::MaximumMessageLength)?
191 .character_data()?
192 .enum_value()?
193 .try_into()
194 .ok()
195 }
196
197 pub fn set_minimum_separation_time(&self, minimum_separation_time: f32) -> Result<(), AutosarAbstractionError> {
199 self.element()
200 .get_or_create_sub_element(ElementName::MinimumSeparationTime)?
201 .set_character_data(f64::from(minimum_separation_time))?;
202 Ok(())
203 }
204
205 #[must_use]
207 pub fn minimum_separation_time(&self) -> Option<f32> {
208 self.element()
209 .get_sub_element(ElementName::MinimumSeparationTime)?
210 .character_data()?
211 .float_value()
212 .map(|v| v as f32)
213 }
214
215 pub fn set_multicast_segmentation(&self, multicast_segmentation: bool) -> Result<(), AutosarAbstractionError> {
217 self.element()
218 .get_or_create_sub_element(ElementName::MulticastSegmentation)?
219 .set_character_data(multicast_segmentation)?;
220 Ok(())
221 }
222
223 #[must_use]
225 pub fn multicast_segmentation(&self) -> Option<bool> {
226 self.element()
227 .get_sub_element(ElementName::MulticastSegmentation)?
228 .character_data()?
229 .parse_bool()
230 }
231
232 pub fn create_flexray_ar_tp_connection<T: AbstractIpdu>(
234 &self,
235 name: Option<&str>,
236 direct_tp_sdu: &T,
237 source: &FlexrayArTpNode,
238 target: &FlexrayArTpNode,
239 ) -> Result<FlexrayArTpConnection, AutosarAbstractionError> {
240 let parent = self.element().get_or_create_sub_element(ElementName::TpConnections)?;
241 FlexrayArTpConnection::new(name, &parent, &direct_tp_sdu.clone().into(), source, target)
242 }
243
244 pub fn flexray_ar_tp_connections(&self) -> impl Iterator<Item = FlexrayArTpConnection> + Send + use<> {
246 self.element()
247 .get_sub_element(ElementName::TpConnections)
248 .into_iter()
249 .flat_map(|tp_connections_elem| tp_connections_elem.sub_elements())
250 .filter_map(|tp_connection_elem| tp_connection_elem.try_into().ok())
251 }
252
253 pub fn add_n_pdu(&self, n_pdu: &NPdu) -> Result<(), AutosarAbstractionError> {
258 let npdu_refs_elem = self.element().get_or_create_sub_element(ElementName::NPduRefs)?;
259 npdu_refs_elem
260 .create_sub_element(ElementName::NPduRef)?
261 .set_reference_target(n_pdu.element())?;
262 Ok(())
263 }
264
265 pub fn n_pdus(&self) -> impl Iterator<Item = NPdu> + Send + use<> {
267 self.element()
268 .get_sub_element(ElementName::NPduRefs)
269 .into_iter()
270 .flat_map(|npdu_refs_elem| npdu_refs_elem.sub_elements())
271 .filter_map(|npdu_ref_elem| {
272 npdu_ref_elem
273 .get_reference_target()
274 .ok()
275 .and_then(|npdu_elem| npdu_elem.try_into().ok())
276 })
277 }
278}
279
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
284pub enum FrArTpAckType {
285 AckWithoutRt,
287 AckWithRt,
289 NoAck,
291}
292
293impl TryFrom<EnumItem> for FrArTpAckType {
294 type Error = AutosarAbstractionError;
295
296 fn try_from(item: EnumItem) -> Result<Self, Self::Error> {
297 match item {
298 EnumItem::AckWithoutRt => Ok(Self::AckWithoutRt),
299 EnumItem::AckWithRt => Ok(Self::AckWithRt),
300 EnumItem::NoAck => Ok(Self::NoAck),
301 _ => Err(AutosarAbstractionError::ValueConversionError {
302 value: item.to_string(),
303 dest: "FrArTpAckType".to_string(),
304 }),
305 }
306 }
307}
308
309impl From<FrArTpAckType> for EnumItem {
310 fn from(val: FrArTpAckType) -> Self {
311 match val {
312 FrArTpAckType::AckWithoutRt => EnumItem::AckWithoutRt,
313 FrArTpAckType::AckWithRt => EnumItem::AckWithRt,
314 FrArTpAckType::NoAck => EnumItem::NoAck,
315 }
316 }
317}
318
319#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
323pub enum MaximumMessageLengthType {
324 I4g,
326 Iso,
328 Iso6,
330}
331
332impl TryFrom<EnumItem> for MaximumMessageLengthType {
333 type Error = AutosarAbstractionError;
334
335 fn try_from(item: EnumItem) -> Result<Self, Self::Error> {
336 match item {
337 EnumItem::I4G => Ok(Self::I4g),
338 EnumItem::Iso => Ok(Self::Iso),
339 EnumItem::Iso6 => Ok(Self::Iso6),
340 _ => Err(AutosarAbstractionError::ValueConversionError {
341 value: item.to_string(),
342 dest: "MaximumMessageLengthType".to_string(),
343 }),
344 }
345 }
346}
347
348impl From<MaximumMessageLengthType> for EnumItem {
349 fn from(val: MaximumMessageLengthType) -> Self {
350 match val {
351 MaximumMessageLengthType::I4g => EnumItem::I4G,
352 MaximumMessageLengthType::Iso => EnumItem::Iso,
353 MaximumMessageLengthType::Iso6 => EnumItem::Iso6,
354 }
355 }
356}
357
358#[derive(Debug, Clone, PartialEq, Eq, Hash)]
365pub struct FlexrayArTpConnection(Element);
366abstraction_element!(FlexrayArTpConnection, FlexrayArTpConnection);
367
368impl IdentifiableAbstractionElement for FlexrayArTpConnection {
369 fn name(&self) -> Option<String> {
375 self.element()
376 .get_sub_element(ElementName::Ident)
377 .and_then(|elem| elem.item_name())
378 }
379
380 fn set_name(&self, name: &str) -> Result<(), AutosarAbstractionError> {
382 if let Some(ident_elem) = self.element().get_sub_element(ElementName::Ident) {
383 ident_elem.set_item_name(name)?;
384 } else {
385 self.element().create_named_sub_element(ElementName::Ident, name)?;
386 }
387 Ok(())
388 }
389}
390
391impl FlexrayArTpConnection {
392 pub(crate) fn new(
393 name: Option<&str>,
394 parent: &Element,
395 direct_tp_sdu: &IPdu,
396 source: &FlexrayArTpNode,
397 target: &FlexrayArTpNode,
398 ) -> Result<Self, AutosarAbstractionError> {
399 let tp_connection_elem = parent.create_sub_element(ElementName::FlexrayArTpConnection)?;
400 if let Some(name) = name {
401 tp_connection_elem.create_named_sub_element(ElementName::Ident, name)?;
402 }
403 let tp_connection = Self(tp_connection_elem);
404 tp_connection.set_direct_tp_sdu(direct_tp_sdu)?;
405 tp_connection.set_source(source)?;
406 tp_connection.add_target(target)?;
407
408 Ok(tp_connection)
409 }
410
411 pub fn set_direct_tp_sdu<T: AbstractIpdu>(&self, direct_tp_sdu: &T) -> Result<(), AutosarAbstractionError> {
413 self.element()
414 .get_or_create_sub_element(ElementName::DirectTpSduRef)?
415 .set_reference_target(direct_tp_sdu.element())?;
416 Ok(())
417 }
418
419 #[must_use]
421 pub fn direct_tp_sdu(&self) -> Option<IPdu> {
422 self.element()
423 .get_sub_element(ElementName::DirectTpSduRef)
424 .and_then(|refelem| refelem.get_reference_target().ok())
425 .and_then(|elem| elem.try_into().ok())
426 }
427
428 pub fn set_source(&self, source: &FlexrayArTpNode) -> Result<(), AutosarAbstractionError> {
430 self.element()
431 .get_or_create_sub_element(ElementName::SourceRef)?
432 .set_reference_target(source.element())?;
433 Ok(())
434 }
435
436 #[must_use]
438 pub fn source(&self) -> Option<FlexrayArTpNode> {
439 self.element()
440 .get_sub_element(ElementName::SourceRef)
441 .and_then(|refelem| refelem.get_reference_target().ok())
442 .and_then(|elem| elem.try_into().ok())
443 }
444
445 pub fn add_target(&self, target: &FlexrayArTpNode) -> Result<(), AutosarAbstractionError> {
449 self.element()
450 .get_or_create_sub_element(ElementName::TargetRefs)?
451 .create_sub_element(ElementName::TargetRef)?
452 .set_reference_target(target.element())?;
453 Ok(())
454 }
455
456 pub fn targets(&self) -> impl Iterator<Item = FlexrayArTpNode> + Send + use<> {
458 self.element()
459 .get_sub_element(ElementName::TargetRefs)
460 .into_iter()
461 .flat_map(|target_refs_elem| target_refs_elem.sub_elements())
462 .filter_map(|target_ref_elem| {
463 target_ref_elem
464 .get_reference_target()
465 .ok()
466 .and_then(|target_elem| target_elem.try_into().ok())
467 })
468 }
469
470 pub fn set_reversed_tp_sdu<T: AbstractIpdu>(
475 &self,
476 reversed_tp_sdu: Option<&T>,
477 ) -> Result<(), AutosarAbstractionError> {
478 if let Some(reversed_tp_sdu) = reversed_tp_sdu {
479 self.element()
480 .get_or_create_sub_element(ElementName::ReversedTpSduRef)?
481 .set_reference_target(reversed_tp_sdu.element())?;
482 } else if let Some(reversed_tp_sdu_elem) = self.element().get_sub_element(ElementName::ReversedTpSduRef) {
483 self.element().remove_sub_element(reversed_tp_sdu_elem)?;
484 }
485 Ok(())
486 }
487
488 #[must_use]
490 pub fn reversed_tp_sdu(&self) -> Option<IPdu> {
491 self.element()
492 .get_sub_element(ElementName::ReversedTpSduRef)
493 .and_then(|refelem| refelem.get_reference_target().ok())
494 .and_then(|elem| elem.try_into().ok())
495 }
496}
497
498#[derive(Debug, Clone, PartialEq, Eq, Hash)]
504pub struct FlexrayArTpNode(Element);
505abstraction_element!(FlexrayArTpNode, FlexrayArTpNode);
506impl IdentifiableAbstractionElement for FlexrayArTpNode {}
507
508impl FlexrayArTpNode {
509 pub(crate) fn new(name: &str, parent: &Element) -> Result<Self, AutosarAbstractionError> {
510 let tp_node_elem = parent.create_named_sub_element(ElementName::FlexrayArTpNode, name)?;
511 Ok(Self(tp_node_elem))
512 }
513
514 pub fn set_tp_address(&self, tp_address: Option<&TpAddress>) -> Result<(), AutosarAbstractionError> {
518 if let Some(tp_address) = tp_address {
519 self.element()
520 .get_or_create_sub_element(ElementName::TpAddressRef)?
521 .set_reference_target(tp_address.element())?;
522 } else {
523 let _ = self.element().remove_sub_element_kind(ElementName::TpAddressRef);
524 }
525 Ok(())
526 }
527
528 #[must_use]
530 pub fn tp_address(&self) -> Option<TpAddress> {
531 self.element()
532 .get_sub_element(ElementName::TpAddressRef)
533 .and_then(|refelem| refelem.get_reference_target().ok())
534 .and_then(|elem| elem.try_into().ok())
535 }
536
537 pub fn add_communication_connector(
543 &self,
544 connector: &FlexrayCommunicationConnector,
545 ) -> Result<(), AutosarAbstractionError> {
546 self.element()
548 .get_or_create_sub_element(ElementName::ConnectorRefs)?
549 .create_sub_element(ElementName::ConnectorRef)?
550 .set_reference_target(connector.element())?;
551 Ok(())
552 }
553
554 pub fn communication_connectors(&self) -> impl Iterator<Item = FlexrayCommunicationConnector> + Send + use<> {
556 self.element()
557 .get_sub_element(ElementName::ConnectorRefs)
558 .into_iter()
559 .flat_map(|connector_refs_elem| connector_refs_elem.sub_elements())
560 .filter_map(|connector_ref_elem| {
561 connector_ref_elem
562 .get_reference_target()
563 .ok()
564 .and_then(|connector_elem| connector_elem.try_into().ok())
565 })
566 }
567}
568
569#[cfg(test)]
572mod test {
573 use super::*;
574 use crate::{
575 AutosarModelAbstraction, SystemCategory,
576 communication::{DiagPduType, FlexrayChannelName, FlexrayClusterSettings},
577 };
578 use autosar_data::AutosarVersion;
579
580 #[test]
581 fn test_flexray_ar_transport_protocol() {
582 let model = AutosarModelAbstraction::create("DoipTp.arxml", AutosarVersion::LATEST);
583 let package = model.get_or_create_package("/pkg1").unwrap();
584
585 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
586 let flexray_cluster = system
587 .create_flexray_cluster("flexray_cluster", &package, &FlexrayClusterSettings::default())
588 .unwrap();
589 let flexray_channel = flexray_cluster
590 .create_physical_channel("flexray_channel_a", FlexrayChannelName::A)
591 .unwrap();
592 let ecu_instance = system.create_ecu_instance("ecu_instance", &package).unwrap();
593 let communication_controller = ecu_instance
594 .create_flexray_communication_controller("can_ctrl")
595 .unwrap();
596 let connector = communication_controller
597 .connect_physical_channel("name", &flexray_channel)
598 .unwrap();
599
600 let tp_sdu = system
602 .create_dcm_ipdu("diag", &package, 1024, DiagPduType::DiagRequest)
603 .unwrap();
604
605 let npdu1 = system.create_n_pdu("npdu1", &package, 64).unwrap();
607 let npdu2 = system.create_n_pdu("npdu2", &package, 64).unwrap();
608
609 let fr_ar_tp_config = system
610 .create_flexray_ar_tp_config("FrArTpConfig", &package, &flexray_cluster)
611 .unwrap();
612 assert_eq!(fr_ar_tp_config.cluster(), Some(flexray_cluster));
613
614 let fr_ar_tp_channel = fr_ar_tp_config
615 .create_flexray_ar_tp_channel(
616 FrArTpAckType::AckWithRt,
617 true,
618 MaximumMessageLengthType::I4g,
619 0.001,
620 false,
621 )
622 .unwrap();
623 assert_eq!(fr_ar_tp_config.flexray_ar_tp_channels().count(), 1);
624 assert_eq!(fr_ar_tp_channel.ack_type(), Some(FrArTpAckType::AckWithRt));
625 assert_eq!(fr_ar_tp_channel.extended_addressing(), Some(true));
626 assert_eq!(
627 fr_ar_tp_channel.maximum_message_length(),
628 Some(MaximumMessageLengthType::I4g)
629 );
630 assert_eq!(fr_ar_tp_channel.minimum_separation_time(), Some(0.001));
631 assert_eq!(fr_ar_tp_channel.multicast_segmentation(), Some(false));
632
633 fr_ar_tp_channel.add_n_pdu(&npdu1).unwrap();
634 fr_ar_tp_channel.add_n_pdu(&npdu2).unwrap();
635 assert_eq!(fr_ar_tp_channel.n_pdus().count(), 2);
636
637 let fr_ar_tp_node_source = fr_ar_tp_config.create_flexray_ar_tp_node("node_s").unwrap();
638 let tp_address_source = fr_ar_tp_config.create_tp_address("tp_address_s", 1).unwrap();
639 fr_ar_tp_node_source.set_tp_address(Some(&tp_address_source)).unwrap();
640 assert_eq!(fr_ar_tp_node_source.tp_address(), Some(tp_address_source));
641 fr_ar_tp_node_source.add_communication_connector(&connector).unwrap();
642 assert_eq!(fr_ar_tp_node_source.communication_connectors().count(), 1);
643 assert_eq!(fr_ar_tp_node_source.communication_connectors().next(), Some(connector));
644
645 let fr_ar_tp_node_target = fr_ar_tp_config.create_flexray_ar_tp_node("node_t").unwrap();
646 let tp_address_target = fr_ar_tp_config.create_tp_address("tp_address_t", 2).unwrap();
647 fr_ar_tp_node_target.set_tp_address(Some(&tp_address_target)).unwrap();
648 assert_eq!(fr_ar_tp_node_target.tp_address(), Some(tp_address_target));
649
650 assert_eq!(fr_ar_tp_config.tp_addresses().count(), 2);
651 assert_eq!(fr_ar_tp_config.flexray_ar_tp_nodes().count(), 2);
652
653 let flexray_ar_tp_connection = fr_ar_tp_channel
654 .create_flexray_ar_tp_connection(Some("conn"), &tp_sdu, &fr_ar_tp_node_source, &fr_ar_tp_node_target)
655 .unwrap();
656 assert_eq!(fr_ar_tp_channel.flexray_ar_tp_connections().count(), 1);
657 assert_eq!(flexray_ar_tp_connection.direct_tp_sdu(), Some(tp_sdu.into()));
658 assert_eq!(flexray_ar_tp_connection.source(), Some(fr_ar_tp_node_source));
659 assert_eq!(flexray_ar_tp_connection.targets().count(), 1);
660
661 assert_eq!(flexray_ar_tp_connection.name(), Some("conn".to_string()));
662 flexray_ar_tp_connection.set_name("new_name").unwrap();
663 assert_eq!(flexray_ar_tp_connection.name(), Some("new_name".to_string()));
664
665 let reversed_tp_sdu = system
666 .create_dcm_ipdu("reversed_tp_sdu", &package, 1024, DiagPduType::DiagResponse)
667 .unwrap();
668 flexray_ar_tp_connection
669 .set_reversed_tp_sdu(Some(&reversed_tp_sdu))
670 .unwrap();
671 assert_eq!(
672 flexray_ar_tp_connection.reversed_tp_sdu(),
673 Some(reversed_tp_sdu.clone().into())
674 );
675
676 let fr_ar_tp_node_extra = fr_ar_tp_config.create_flexray_ar_tp_node("node_extra").unwrap();
677 flexray_ar_tp_connection.add_target(&fr_ar_tp_node_extra).unwrap();
678 assert_eq!(flexray_ar_tp_connection.targets().count(), 2);
679 }
680}