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 && connector_ecu_instance == *ecu_instance
81 {
82 return Some(connector);
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
141impl PhysicalChannel {
142 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
144 match self {
145 PhysicalChannel::Can(cpc) => cpc.remove(deep),
146 PhysicalChannel::Ethernet(epc) => epc.remove(deep),
147 PhysicalChannel::Flexray(fpc) => fpc.remove(deep),
148 PhysicalChannel::Lin(lpc) => lpc.remove(deep),
149 }
150 }
151}
152
153#[cfg(test)]
156mod test {
157 use super::*;
158 use crate::{
159 AutosarModelAbstraction, ByteOrder, SystemCategory,
160 communication::{AbstractFrame, CanAddressingMode, CanFrameType, TransferProperty},
161 };
162 use autosar_data::AutosarVersion;
163
164 #[test]
165 fn abstract_physical_channel() {
166 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
167 let pkg = model.get_or_create_package("/test").unwrap();
168 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
169 let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
170 let channel = cluster.create_physical_channel("channel_name").unwrap();
171
172 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
173 let can_controller = ecu.create_can_communication_controller("Controller").unwrap();
174 let connector = can_controller.connect_physical_channel("Connector", &channel).unwrap();
175
176 let frame = system.create_can_frame("Frame", &pkg, 8).unwrap();
177 let isignal_ipdu = system.create_isignal_ipdu("ISignalIPdu", &pkg, 8).unwrap();
178
179 let system_signal = pkg.create_system_signal("SystemSignal").unwrap();
180 let signal = system.create_isignal("Signal", &pkg, 8, &system_signal, None).unwrap();
181 isignal_ipdu
182 .map_signal(
183 &signal,
184 0,
185 ByteOrder::MostSignificantByteLast,
186 None,
187 TransferProperty::Triggered,
188 )
189 .unwrap();
190 frame
191 .map_pdu(&isignal_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
192 .unwrap();
193
194 let frame_triggering = channel
195 .trigger_frame(&frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)
196 .unwrap();
197
198 assert_eq!(channel.frame_triggerings().count(), 1);
199 assert_eq!(channel.frame_triggerings().next(), Some(frame_triggering));
200 assert_eq!(channel.pdu_triggerings().count(), 1);
201 assert_eq!(
202 channel.pdu_triggerings().next().unwrap().pdu().unwrap(),
203 isignal_ipdu.into()
204 );
205 assert_eq!(channel.signal_triggerings().count(), 1);
206
207 assert_eq!(channel.connectors().count(), 1);
208 assert_eq!(channel.ecu_connector(&ecu).unwrap(), connector);
209 }
210}