autosar_data_abstraction/communication/physical_channel/
mod.rs1use crate::communication::{AbstractCommunicationConnector, CommunicationConnector, ISignalTriggering, PduTriggering};
2use crate::{AbstractionElement, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement};
3use autosar_data::{Element, ElementName};
4
5mod can;
6mod ethernet;
7mod flexray;
8mod lin;
9
10pub use can::*;
11pub use ethernet::*;
12pub use flexray::*;
13pub use lin::*;
14
15pub trait AbstractPhysicalChannel: AbstractionElement + Into<PhysicalChannel> {
19 type CommunicationConnectorType: AbstractCommunicationConnector;
21
22 fn pdu_triggerings(&self) -> impl Iterator<Item = PduTriggering> + Send + use<Self> {
24 self.element()
25 .get_sub_element(ElementName::PduTriggerings)
26 .into_iter()
27 .flat_map(|triggerings| triggerings.sub_elements())
28 .filter_map(|triggering| PduTriggering::try_from(triggering).ok())
29 }
30
31 fn signal_triggerings(&self) -> impl Iterator<Item = ISignalTriggering> + Send + use<Self> {
33 self.element()
34 .get_sub_element(ElementName::ISignalTriggerings)
35 .into_iter()
36 .flat_map(|triggerings| triggerings.sub_elements())
37 .filter_map(|triggering| ISignalTriggering::try_from(triggering).ok())
38 }
39
40 fn connectors(&self) -> impl Iterator<Item = Self::CommunicationConnectorType> + Send + use<Self> {
62 self.element()
63 .get_sub_element(ElementName::CommConnectors)
64 .into_iter()
65 .flat_map(|connectors| connectors.sub_elements())
66 .filter_map(|ccrc| {
67 ccrc.get_sub_element(ElementName::CommunicationConnectorRef)
68 .and_then(|connector| connector.get_reference_target().ok())
69 .and_then(|connector| Self::CommunicationConnectorType::try_from(connector).ok())
70 })
71 }
72
73 #[must_use]
75 fn ecu_connector(&self, ecu_instance: &EcuInstance) -> Option<Self::CommunicationConnectorType> {
76 for connector in self.connectors() {
79 if let Ok(connector_ecu_instance) = connector.ecu_instance() {
80 if connector_ecu_instance == *ecu_instance {
81 return Some(connector);
82 }
83 }
84 }
85
86 None
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq)]
96pub enum PhysicalChannel {
97 Can(CanPhysicalChannel),
99 Ethernet(EthernetPhysicalChannel),
101 Flexray(FlexrayPhysicalChannel),
103 Lin(LinPhysicalChannel),
105}
106
107impl AbstractPhysicalChannel for PhysicalChannel {
108 type CommunicationConnectorType = CommunicationConnector;
109}
110
111impl AbstractionElement for PhysicalChannel {
112 fn element(&self) -> &autosar_data::Element {
113 match self {
114 PhysicalChannel::Can(cpc) => cpc.element(),
115 PhysicalChannel::Ethernet(epc) => epc.element(),
116 PhysicalChannel::Flexray(fpc) => fpc.element(),
117 PhysicalChannel::Lin(lpc) => lpc.element(),
118 }
119 }
120}
121
122impl IdentifiableAbstractionElement for PhysicalChannel {}
123
124impl TryFrom<Element> for PhysicalChannel {
125 type Error = AutosarAbstractionError;
126
127 fn try_from(element: Element) -> Result<Self, Self::Error> {
128 match element.element_name() {
129 ElementName::CanPhysicalChannel => Ok(Self::Can(CanPhysicalChannel::try_from(element)?)),
130 ElementName::EthernetPhysicalChannel => Ok(Self::Ethernet(EthernetPhysicalChannel::try_from(element)?)),
131 ElementName::FlexrayPhysicalChannel => Ok(Self::Flexray(FlexrayPhysicalChannel::try_from(element)?)),
132 ElementName::LinPhysicalChannel => Ok(Self::Lin(LinPhysicalChannel::try_from(element)?)),
133 _ => Err(AutosarAbstractionError::ConversionError {
134 element,
135 dest: "PhysicalChannel".to_string(),
136 }),
137 }
138 }
139}
140
141#[cfg(test)]
144mod test {
145 use super::*;
146 use crate::{
147 AutosarModelAbstraction, ByteOrder, SystemCategory,
148 communication::{AbstractFrame, CanAddressingMode, CanFrameType, TransferProperty},
149 };
150 use autosar_data::AutosarVersion;
151
152 #[test]
153 fn abstract_physical_channel() {
154 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
155 let pkg = model.get_or_create_package("/test").unwrap();
156 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
157 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
158 let channel = cluster.create_physical_channel("channel_name").unwrap();
159
160 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
161 let can_controller = ecu.create_can_communication_controller("Controller").unwrap();
162 let connector = can_controller.connect_physical_channel("Connector", &channel).unwrap();
163
164 let frame = system.create_can_frame("Frame", &pkg, 8).unwrap();
165 let isignal_ipdu = system.create_isignal_ipdu("ISignalIPdu", &pkg, 8).unwrap();
166
167 let system_signal = pkg.create_system_signal("SystemSignal").unwrap();
168 let signal = system.create_isignal("Signal", &pkg, 8, &system_signal, None).unwrap();
169 isignal_ipdu
170 .map_signal(
171 &signal,
172 0,
173 ByteOrder::MostSignificantByteLast,
174 None,
175 TransferProperty::Triggered,
176 )
177 .unwrap();
178 frame
179 .map_pdu(&isignal_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
180 .unwrap();
181
182 let frame_triggering = channel
183 .trigger_frame(&frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)
184 .unwrap();
185
186 assert_eq!(channel.frame_triggerings().count(), 1);
187 assert_eq!(channel.frame_triggerings().next(), Some(frame_triggering));
188 assert_eq!(channel.pdu_triggerings().count(), 1);
189 assert_eq!(
190 channel.pdu_triggerings().next().unwrap().pdu().unwrap(),
191 isignal_ipdu.into()
192 );
193 assert_eq!(channel.signal_triggerings().count(), 1);
194
195 assert_eq!(channel.connectors().count(), 1);
196 assert_eq!(channel.ecu_connector(&ecu).unwrap(), connector);
197 }
198}