1use crate::communication::{AbstractIpdu, CanCluster, CanCommunicationConnector, IPdu, NPdu};
2use crate::{
3 AbstractionElement, ArPackage, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement,
4 abstraction_element,
5};
6use autosar_data::{Element, ElementName, EnumItem};
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct CanTpConfig(Element);
15abstraction_element!(CanTpConfig, CanTpConfig);
16impl IdentifiableAbstractionElement for CanTpConfig {}
17
18impl CanTpConfig {
19 pub(crate) fn new(name: &str, package: &ArPackage, cluster: &CanCluster) -> Result<Self, AutosarAbstractionError> {
20 let pkg_elem = package.element().get_or_create_sub_element(ElementName::Elements)?;
21 let tp_config_elem = pkg_elem.create_named_sub_element(ElementName::CanTpConfig, name)?;
22 let tp_config = Self(tp_config_elem);
23 tp_config.set_cluster(cluster)?;
24
25 Ok(tp_config)
26 }
27
28 pub fn set_cluster(&self, cluster: &CanCluster) -> Result<(), AutosarAbstractionError> {
30 self.element()
31 .get_or_create_sub_element(ElementName::CommunicationClusterRef)?
32 .set_reference_target(cluster.element())?;
33 Ok(())
34 }
35
36 #[must_use]
38 pub fn cluster(&self) -> Option<CanCluster> {
39 self.element()
40 .get_sub_element(ElementName::CommunicationClusterRef)
41 .and_then(|elem| elem.get_reference_target().ok())
42 .and_then(|target| CanCluster::try_from(target).ok())
43 }
44
45 pub fn create_can_tp_ecu(
47 &self,
48 ecu_instance: &EcuInstance,
49 cycle_time_main_function: Option<f64>,
50 ) -> Result<CanTpEcu, AutosarAbstractionError> {
51 let ecu_collection = self.element().get_or_create_sub_element(ElementName::TpEcus)?;
52
53 CanTpEcu::new(&ecu_collection, ecu_instance, cycle_time_main_function)
54 }
55
56 pub fn can_tp_ecus(&self) -> impl Iterator<Item = CanTpEcu> + Send + use<> {
58 self.element()
59 .get_sub_element(ElementName::TpEcus)
60 .into_iter()
61 .flat_map(|ecu_collection| ecu_collection.sub_elements())
62 .filter_map(|tp_ecu_elem| CanTpEcu::try_from(tp_ecu_elem).ok())
63 }
64
65 pub fn create_can_tp_address(&self, name: &str, address: u32) -> Result<CanTpAddress, AutosarAbstractionError> {
67 let addresses_container = self.element().get_or_create_sub_element(ElementName::TpAddresss)?;
68 CanTpAddress::new(name, &addresses_container, address)
69 }
70
71 pub fn can_tp_addresses(&self) -> impl Iterator<Item = CanTpAddress> + Send + use<> {
73 self.element()
74 .get_sub_element(ElementName::TpAddresss)
75 .into_iter()
76 .flat_map(|addresses_container| {
77 addresses_container
78 .sub_elements()
79 .filter_map(|address_elem| CanTpAddress::try_from(address_elem).ok())
80 })
81 }
82
83 pub fn create_can_tp_channel(
85 &self,
86 name: &str,
87 channel_id: u32,
88 mode: CanTpChannelMode,
89 ) -> Result<CanTpChannel, AutosarAbstractionError> {
90 let channels_container = self.element().get_or_create_sub_element(ElementName::TpChannels)?;
91 CanTpChannel::new(name, &channels_container, channel_id, mode)
92 }
93
94 pub fn can_tp_channels(&self) -> impl Iterator<Item = CanTpChannel> + Send + use<> {
96 self.element()
97 .get_sub_element(ElementName::TpChannels)
98 .into_iter()
99 .flat_map(|channels_container| {
100 channels_container
101 .sub_elements()
102 .filter_map(|channel_elem| CanTpChannel::try_from(channel_elem).ok())
103 })
104 }
105
106 pub fn create_can_tp_connection<T: AbstractIpdu>(
108 &self,
109 name: Option<&str>,
110 addressing_format: CanTpAddressingFormat,
111 can_tp_channel: &CanTpChannel,
112 data_pdu: &NPdu,
113 tp_sdu: &T,
114 padding_activation: bool,
115 ) -> Result<CanTpConnection, AutosarAbstractionError> {
116 let connections_container = self.element().get_or_create_sub_element(ElementName::TpConnections)?;
117 CanTpConnection::new(
118 name,
119 &connections_container,
120 addressing_format,
121 can_tp_channel,
122 data_pdu,
123 &tp_sdu.clone().into(),
124 padding_activation,
125 )
126 }
127
128 pub fn can_tp_connections(&self) -> impl Iterator<Item = CanTpConnection> + Send + use<> {
130 self.element()
131 .get_sub_element(ElementName::TpConnections)
132 .into_iter()
133 .flat_map(|connections_container| {
134 connections_container
135 .sub_elements()
136 .filter_map(|connection_elem| CanTpConnection::try_from(connection_elem).ok())
137 })
138 }
139
140 pub fn create_can_tp_node(&self, name: &str) -> Result<CanTpNode, AutosarAbstractionError> {
142 let nodes_container = self.element().get_or_create_sub_element(ElementName::TpNodes)?;
143 CanTpNode::new(name, &nodes_container)
144 }
145
146 pub fn can_tp_nodes(&self) -> impl Iterator<Item = CanTpNode> + Send + use<> {
148 self.element()
149 .get_sub_element(ElementName::TpNodes)
150 .into_iter()
151 .flat_map(|nodes_container| {
152 nodes_container
153 .sub_elements()
154 .filter_map(|node_elem| CanTpNode::try_from(node_elem).ok())
155 })
156 }
157}
158
159#[derive(Debug, Clone, PartialEq)]
163pub struct CanTpEcu(Element);
164abstraction_element!(CanTpEcu, CanTpEcu);
165
166impl CanTpEcu {
167 pub(crate) fn new(
168 parent: &Element,
169 ecu_instance: &EcuInstance,
170 cycle_time_main_function: Option<f64>,
171 ) -> Result<Self, AutosarAbstractionError> {
172 let tp_ecu_elem = parent.create_sub_element(ElementName::CanTpEcu)?;
173 let tp_ecu = Self(tp_ecu_elem);
174
175 tp_ecu.set_ecu_instance(ecu_instance)?;
176 tp_ecu.set_cycle_time_main_function(cycle_time_main_function)?;
177
178 Ok(tp_ecu)
179 }
180
181 pub fn set_ecu_instance(&self, ecu_instance: &EcuInstance) -> Result<(), AutosarAbstractionError> {
183 self.element()
184 .get_or_create_sub_element(ElementName::EcuInstanceRef)?
185 .set_reference_target(ecu_instance.element())?;
186 Ok(())
187 }
188
189 #[must_use]
191 pub fn ecu_instance(&self) -> Option<EcuInstance> {
192 self.element()
193 .get_sub_element(ElementName::EcuInstanceRef)
194 .and_then(|elem| elem.get_reference_target().ok())
195 .and_then(|target| EcuInstance::try_from(target).ok())
196 }
197
198 pub fn set_cycle_time_main_function(&self, cycle_time: Option<f64>) -> Result<(), AutosarAbstractionError> {
200 if let Some(cycle_time) = cycle_time {
201 self.element()
202 .get_or_create_sub_element(ElementName::CycleTimeMainFunction)?
203 .set_character_data(cycle_time)?;
204 } else {
205 let _ = self
206 .element()
207 .remove_sub_element_kind(ElementName::CycleTimeMainFunction);
208 }
209 Ok(())
210 }
211
212 #[must_use]
214 pub fn cycle_time_main_function(&self) -> Option<f64> {
215 self.element()
216 .get_sub_element(ElementName::CycleTimeMainFunction)
217 .and_then(|elem| elem.character_data())
218 .and_then(|cdata| cdata.parse_float())
219 }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq, Hash)]
226pub struct CanTpAddress(Element);
227abstraction_element!(CanTpAddress, CanTpAddress);
228impl IdentifiableAbstractionElement for CanTpAddress {}
229
230impl CanTpAddress {
231 pub(crate) fn new(name: &str, parent: &Element, tp_address: u32) -> Result<Self, AutosarAbstractionError> {
232 let address_elem = parent.create_named_sub_element(ElementName::CanTpAddress, name)?;
233 let address = Self(address_elem);
234 address.set_tp_address(tp_address)?;
235
236 Ok(address)
237 }
238
239 pub fn set_tp_address(&self, tp_address: u32) -> Result<(), AutosarAbstractionError> {
241 self.element()
242 .get_or_create_sub_element(ElementName::TpAddress)?
243 .set_character_data(u64::from(tp_address))?;
244 Ok(())
245 }
246
247 #[must_use]
249 pub fn tp_address(&self) -> Option<u32> {
250 self.element()
251 .get_sub_element(ElementName::TpAddress)
252 .and_then(|elem| elem.character_data())
253 .and_then(|cdata| cdata.parse_integer())
254 }
255}
256
257#[derive(Debug, Clone, PartialEq, Eq, Hash)]
261pub struct CanTpChannel(Element);
262abstraction_element!(CanTpChannel, CanTpChannel);
263impl IdentifiableAbstractionElement for CanTpChannel {}
264
265impl CanTpChannel {
266 pub(crate) fn new(
267 name: &str,
268 parent: &Element,
269 channel_id: u32,
270 mode: CanTpChannelMode,
271 ) -> Result<Self, AutosarAbstractionError> {
272 let channel_elem = parent.create_named_sub_element(ElementName::CanTpChannel, name)?;
273 let channel = Self(channel_elem);
274
275 channel.set_channel_id(channel_id)?;
276 channel.set_channel_mode(mode)?;
277
278 Ok(channel)
279 }
280
281 pub fn set_channel_id(&self, channel_id: u32) -> Result<(), AutosarAbstractionError> {
283 self.element()
284 .get_or_create_sub_element(ElementName::ChannelId)?
285 .set_character_data(u64::from(channel_id))?;
286 Ok(())
287 }
288
289 #[must_use]
291 pub fn channel_id(&self) -> Option<u32> {
292 self.element()
293 .get_sub_element(ElementName::ChannelId)
294 .and_then(|elem| elem.character_data())
295 .and_then(|cdata| cdata.parse_integer())
296 }
297
298 pub fn set_channel_mode(&self, mode: CanTpChannelMode) -> Result<(), AutosarAbstractionError> {
300 self.element()
301 .get_or_create_sub_element(ElementName::ChannelMode)?
302 .set_character_data::<EnumItem>(mode.into())?;
303 Ok(())
304 }
305
306 #[must_use]
308 pub fn channel_mode(&self) -> Option<CanTpChannelMode> {
309 self.element()
310 .get_sub_element(ElementName::ChannelMode)
311 .and_then(|elem| elem.character_data())
312 .and_then(|cdata| cdata.enum_value())
313 .and_then(|enumitem| enumitem.try_into().ok())
314 }
315}
316
317#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
321pub enum CanTpChannelMode {
322 FullDuplex,
324 HalfDuplex,
326}
327
328impl From<CanTpChannelMode> for EnumItem {
329 fn from(mode: CanTpChannelMode) -> Self {
330 match mode {
331 CanTpChannelMode::FullDuplex => EnumItem::FullDuplexMode,
332 CanTpChannelMode::HalfDuplex => EnumItem::HalfDuplexMode,
333 }
334 }
335}
336
337impl TryFrom<EnumItem> for CanTpChannelMode {
338 type Error = AutosarAbstractionError;
339
340 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
341 match value {
342 EnumItem::FullDuplexMode => Ok(CanTpChannelMode::FullDuplex),
343 EnumItem::HalfDuplexMode => Ok(CanTpChannelMode::HalfDuplex),
344 _ => Err(AutosarAbstractionError::ValueConversionError {
345 value: value.to_string(),
346 dest: "CanTpChannelMode".to_string(),
347 }),
348 }
349 }
350}
351
352#[derive(Debug, Clone, PartialEq, Eq, Hash)]
357pub struct CanTpConnection(Element);
358abstraction_element!(CanTpConnection, CanTpConnection);
359
360impl IdentifiableAbstractionElement for CanTpConnection {
361 fn name(&self) -> Option<String> {
367 self.element()
368 .get_sub_element(ElementName::Ident)
369 .and_then(|elem| elem.item_name())
370 }
371
372 fn set_name(&self, name: &str) -> Result<(), AutosarAbstractionError> {
374 if let Some(ident_elem) = self.element().get_sub_element(ElementName::Ident) {
376 ident_elem.set_item_name(name)?;
377 } else {
378 self.element().create_named_sub_element(ElementName::Ident, name)?;
379 }
380 Ok(())
381 }
382}
383
384impl CanTpConnection {
385 pub(crate) fn new(
386 name: Option<&str>,
387 parent: &Element,
388 addressing_format: CanTpAddressingFormat,
389 can_tp_channel: &CanTpChannel,
390 data_pdu: &NPdu,
391 tp_sdu: &IPdu,
392 padding_activation: bool,
393 ) -> Result<Self, AutosarAbstractionError> {
394 let connection_elem = parent.create_sub_element(ElementName::CanTpConnection)?;
395 let connection = Self(connection_elem);
396
397 if let Some(name) = name {
398 connection.set_name(name)?;
399 }
400 connection.set_addressing_format(addressing_format)?;
401 connection.set_channel(can_tp_channel)?;
402 connection.set_data_pdu(data_pdu)?;
403 connection.set_tp_sdu(tp_sdu)?;
404 connection.set_padding_activation(padding_activation)?;
405
406 Ok(connection)
407 }
408
409 pub fn set_channel(&self, channel: &CanTpChannel) -> Result<(), AutosarAbstractionError> {
411 self.element()
412 .get_or_create_sub_element(ElementName::CanTpChannelRef)?
413 .set_reference_target(channel.element())?;
414 Ok(())
415 }
416
417 #[must_use]
419 pub fn channel(&self) -> Option<CanTpChannel> {
420 self.element()
421 .get_sub_element(ElementName::CanTpChannelRef)
422 .and_then(|elem| elem.get_reference_target().ok())
423 .and_then(|target| CanTpChannel::try_from(target).ok())
424 }
425
426 pub fn set_data_pdu(&self, data_pdu: &NPdu) -> Result<(), AutosarAbstractionError> {
428 self.element()
429 .get_or_create_sub_element(ElementName::DataPduRef)?
430 .set_reference_target(data_pdu.element())?;
431 Ok(())
432 }
433
434 #[must_use]
438 pub fn data_pdu(&self) -> Option<NPdu> {
439 self.element()
440 .get_sub_element(ElementName::DataPduRef)
441 .and_then(|elem| elem.get_reference_target().ok())
442 .and_then(|target| NPdu::try_from(target).ok())
443 }
444
445 pub fn set_tp_sdu<T: AbstractIpdu>(&self, tp_sdu: &T) -> Result<(), AutosarAbstractionError> {
447 self.element()
448 .get_or_create_sub_element(ElementName::TpSduRef)?
449 .set_reference_target(tp_sdu.element())?;
450 Ok(())
451 }
452
453 #[must_use]
457 pub fn tp_sdu(&self) -> Option<IPdu> {
458 self.element()
459 .get_sub_element(ElementName::TpSduRef)
460 .and_then(|elem| elem.get_reference_target().ok())
461 .and_then(|target| IPdu::try_from(target).ok())
462 }
463
464 pub fn set_addressing_format(
466 &self,
467 addressing_format: CanTpAddressingFormat,
468 ) -> Result<(), AutosarAbstractionError> {
469 self.element()
470 .get_or_create_sub_element(ElementName::AddressingFormat)?
471 .set_character_data::<EnumItem>(addressing_format.into())?;
472 Ok(())
473 }
474
475 #[must_use]
477 pub fn addressing_format(&self) -> Option<CanTpAddressingFormat> {
478 self.element()
479 .get_sub_element(ElementName::AddressingFormat)
480 .and_then(|elem| elem.character_data())
481 .and_then(|cdata| cdata.enum_value())
482 .and_then(|enumitem| enumitem.try_into().ok())
483 }
484
485 pub fn set_padding_activation(&self, padding_activation: bool) -> Result<(), AutosarAbstractionError> {
487 self.element()
488 .get_or_create_sub_element(ElementName::PaddingActivation)?
489 .set_character_data(padding_activation)?;
490 Ok(())
491 }
492
493 #[must_use]
495 pub fn padding_activation(&self) -> Option<bool> {
496 self.element()
497 .get_sub_element(ElementName::PaddingActivation)
498 .and_then(|elem| elem.character_data())
499 .and_then(|cdata| cdata.parse_bool())
500 }
501
502 pub fn set_transmitter(&self, transmitter: &CanTpNode) -> Result<(), AutosarAbstractionError> {
506 self.element()
507 .get_or_create_sub_element(ElementName::TransmitterRef)?
508 .set_reference_target(transmitter.element())?;
509 Ok(())
510 }
511
512 #[must_use]
514 pub fn transmitter(&self) -> Option<CanTpNode> {
515 self.element()
516 .get_sub_element(ElementName::TransmitterRef)
517 .and_then(|elem| elem.get_reference_target().ok())
518 .and_then(|target| CanTpNode::try_from(target).ok())
519 }
520
521 pub fn add_receiver(&self, receiver: &CanTpNode) -> Result<(), AutosarAbstractionError> {
525 let receivers = self.element().get_or_create_sub_element(ElementName::ReceiverRefs)?;
526 let receiver_ref_elem = receivers.create_sub_element(ElementName::ReceiverRef)?;
527 receiver_ref_elem.set_reference_target(receiver.element())?;
528 Ok(())
529 }
530
531 pub fn receivers(&self) -> impl Iterator<Item = CanTpNode> + Send + use<> {
533 self.element()
534 .get_sub_element(ElementName::ReceiverRefs)
535 .into_iter()
536 .flat_map(|receivers| {
537 receivers.sub_elements().filter_map(|receiver_ref_elem| {
538 receiver_ref_elem
539 .get_reference_target()
540 .ok()
541 .and_then(|target| CanTpNode::try_from(target).ok())
542 })
543 })
544 }
545}
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
551pub enum CanTpAddressingFormat {
552 Extended,
554 Mixed,
556 Mixed29Bit,
558 NormalFixed,
560 Standard,
562}
563
564impl From<CanTpAddressingFormat> for EnumItem {
565 fn from(format: CanTpAddressingFormat) -> Self {
566 match format {
567 CanTpAddressingFormat::Extended => EnumItem::Extended,
568 CanTpAddressingFormat::Mixed => EnumItem::Mixed,
569 CanTpAddressingFormat::Mixed29Bit => EnumItem::Mixed29Bit,
570 CanTpAddressingFormat::NormalFixed => EnumItem::Normalfixed,
571 CanTpAddressingFormat::Standard => EnumItem::Standard,
572 }
573 }
574}
575
576impl TryFrom<EnumItem> for CanTpAddressingFormat {
577 type Error = AutosarAbstractionError;
578
579 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
580 match value {
581 EnumItem::Extended => Ok(CanTpAddressingFormat::Extended),
582 EnumItem::Mixed => Ok(CanTpAddressingFormat::Mixed),
583 EnumItem::Mixed29Bit => Ok(CanTpAddressingFormat::Mixed29Bit),
584 EnumItem::Normalfixed => Ok(CanTpAddressingFormat::NormalFixed),
585 EnumItem::Standard => Ok(CanTpAddressingFormat::Standard),
586 _ => Err(AutosarAbstractionError::ValueConversionError {
587 value: value.to_string(),
588 dest: "CanTpAddressingFormat".to_string(),
589 }),
590 }
591 }
592}
593
594#[derive(Debug, Clone, PartialEq, Eq, Hash)]
598pub struct CanTpNode(Element);
599abstraction_element!(CanTpNode, CanTpNode);
600
601impl IdentifiableAbstractionElement for CanTpNode {}
602
603impl CanTpNode {
604 pub(crate) fn new(name: &str, parent: &Element) -> Result<Self, AutosarAbstractionError> {
605 let node_elem = parent.create_named_sub_element(ElementName::CanTpNode, name)?;
606 Ok(Self(node_elem))
607 }
608
609 pub fn set_address(&self, address: &CanTpAddress) -> Result<(), AutosarAbstractionError> {
611 self.element()
612 .get_or_create_sub_element(ElementName::TpAddressRef)?
613 .set_reference_target(address.element())?;
614 Ok(())
615 }
616
617 #[must_use]
619 pub fn address(&self) -> Option<CanTpAddress> {
620 self.element()
621 .get_sub_element(ElementName::TpAddressRef)
622 .and_then(|elem| elem.get_reference_target().ok())
623 .and_then(|target| CanTpAddress::try_from(target).ok())
624 }
625
626 pub fn set_connector(&self, connector: &CanCommunicationConnector) -> Result<(), AutosarAbstractionError> {
631 self.element()
632 .get_or_create_sub_element(ElementName::ConnectorRef)?
633 .set_reference_target(connector.element())?;
634 Ok(())
635 }
636
637 #[must_use]
639 pub fn connector(&self) -> Option<CanCommunicationConnector> {
640 self.element()
641 .get_sub_element(ElementName::ConnectorRef)
642 .and_then(|elem| elem.get_reference_target().ok())
643 .and_then(|target| CanCommunicationConnector::try_from(target).ok())
644 }
645}
646
647#[cfg(test)]
650mod test {
651 use super::*;
652 use crate::{AutosarModelAbstraction, SystemCategory, communication::DiagPduType};
653 use autosar_data::AutosarVersion;
654
655 #[test]
656 fn can_transport_protocol() {
657 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
658 let package = model.get_or_create_package("/pkg1").unwrap();
659
660 let system = package.create_system("system", SystemCategory::EcuExtract).unwrap();
661 let can_cluster = system.create_can_cluster("can_cluster", &package, None).unwrap();
662 let can_channel = can_cluster.create_physical_channel("can_channel").unwrap();
663 let ecu_instance = system.create_ecu_instance("ecu_instance", &package).unwrap();
664 let communication_controller = ecu_instance.create_can_communication_controller("can_ctrl").unwrap();
665 let connector = communication_controller
666 .connect_physical_channel("name", &can_channel)
667 .unwrap();
668
669 let can_tp_config = system
670 .create_can_tp_config("can_tp_config", &package, &can_cluster)
671 .unwrap();
672 assert_eq!(can_tp_config.cluster().unwrap(), can_cluster);
673
674 let tp_ecu = can_tp_config.create_can_tp_ecu(&ecu_instance, Some(1.0)).unwrap();
675 assert_eq!(can_tp_config.can_tp_ecus().count(), 1);
676 assert_eq!(can_tp_config.can_tp_ecus().next().unwrap(), tp_ecu);
677 assert_eq!(tp_ecu.ecu_instance().unwrap().name().unwrap(), "ecu_instance");
678 assert_eq!(tp_ecu.cycle_time_main_function().unwrap(), 1.0);
679
680 let address = can_tp_config.create_can_tp_address("address", 0x1234).unwrap();
681 assert_eq!(address.tp_address().unwrap(), 0x1234);
682 assert_eq!(can_tp_config.can_tp_addresses().count(), 1);
683 assert_eq!(can_tp_config.can_tp_addresses().next().unwrap(), address);
684
685 let channel = can_tp_config
686 .create_can_tp_channel("channel", 1, CanTpChannelMode::FullDuplex)
687 .unwrap();
688 let channel2 = can_tp_config
689 .create_can_tp_channel("channel2", 2, CanTpChannelMode::FullDuplex)
690 .unwrap();
691 assert_eq!(can_tp_config.can_tp_channels().count(), 2);
692 assert_eq!(channel.channel_id().unwrap(), 1);
693 assert_eq!(channel.channel_mode().unwrap(), CanTpChannelMode::FullDuplex);
694
695 let data_pdu = system.create_n_pdu("data_pdu", &package, 8).unwrap();
696 let data_pdu2 = system.create_n_pdu("data_pdu2", &package, 8).unwrap();
697 let tp_sdu = system
698 .create_dcm_ipdu("ipdu", &package, 4096, DiagPduType::DiagRequest)
699 .unwrap();
700 let tp_sdu2 = system
701 .create_dcm_ipdu("ipdu2", &package, 4096, DiagPduType::DiagResponse)
702 .unwrap();
703
704 let connection = can_tp_config
705 .create_can_tp_connection(
706 Some("connection"),
707 CanTpAddressingFormat::Standard,
708 &channel,
709 &data_pdu,
710 &tp_sdu,
711 false,
712 )
713 .unwrap();
714 assert_eq!(can_tp_config.can_tp_connections().count(), 1);
715 assert_eq!(can_tp_config.can_tp_connections().next().unwrap(), connection);
716
717 assert_eq!(connection.name().unwrap(), "connection");
718 connection
720 .element()
721 .remove_sub_element_kind(ElementName::Ident)
722 .unwrap();
723 assert_eq!(connection.name(), None);
724 connection.set_name("new_name").unwrap();
725 assert_eq!(connection.name().unwrap(), "new_name");
726
727 assert_eq!(connection.channel().unwrap(), channel);
728 connection.set_channel(&channel2).unwrap();
729 assert_eq!(connection.channel().unwrap(), channel2);
730
731 assert_eq!(connection.data_pdu().unwrap(), data_pdu);
732 connection.set_data_pdu(&data_pdu2).unwrap();
733 assert_eq!(connection.data_pdu().unwrap(), data_pdu2);
734
735 assert_eq!(connection.tp_sdu().unwrap(), tp_sdu.into());
736 connection.set_tp_sdu(&tp_sdu2).unwrap();
737 assert_eq!(connection.tp_sdu().unwrap(), tp_sdu2.into());
738
739 assert_eq!(connection.addressing_format().unwrap(), CanTpAddressingFormat::Standard);
740 connection
741 .set_addressing_format(CanTpAddressingFormat::Extended)
742 .unwrap();
743 assert_eq!(connection.addressing_format().unwrap(), CanTpAddressingFormat::Extended);
744
745 assert!(!connection.padding_activation().unwrap());
746 connection.set_padding_activation(true).unwrap();
747 assert!(connection.padding_activation().unwrap());
748
749 let node = can_tp_config.create_can_tp_node("node").unwrap();
750 assert_eq!(can_tp_config.can_tp_nodes().count(), 1);
751 assert_eq!(can_tp_config.can_tp_nodes().next().unwrap(), node);
752
753 node.set_address(&address).unwrap();
754 assert_eq!(node.address().unwrap(), address);
755 node.set_connector(&connector).unwrap();
756 assert_eq!(node.connector().unwrap(), connector);
757 connection.set_transmitter(&node).unwrap();
758 assert_eq!(connection.transmitter().unwrap(), node);
759
760 connection.add_receiver(&node).unwrap();
761 assert_eq!(connection.receivers().count(), 1);
762 }
763}