autosar_data_abstraction/communication/physical_channel/
flexray.rs

1use crate::{
2    AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3    communication::{
4        AbstractPhysicalChannel, FlexrayCluster, FlexrayCommunicationConnector, FlexrayCommunicationCycle,
5        FlexrayFrame, FlexrayFrameTriggering, PhysicalChannel,
6    },
7};
8use autosar_data::{Element, ElementName, EnumItem};
9
10/// the `FlexrayPhysicalChannel` represents either channel A or B of Flexray cluster
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct FlexrayPhysicalChannel(Element);
13abstraction_element!(FlexrayPhysicalChannel, FlexrayPhysicalChannel);
14impl IdentifiableAbstractionElement for FlexrayPhysicalChannel {}
15
16impl FlexrayPhysicalChannel {
17    /// get the channel name of a `FlexrayPhysicalChannel`
18    #[must_use]
19    pub fn channel_name(&self) -> Option<FlexrayChannelName> {
20        let cn = self
21            .0
22            .get_sub_element(ElementName::ChannelName)?
23            .character_data()?
24            .enum_value()?;
25        match cn {
26            EnumItem::ChannelA => Some(FlexrayChannelName::A),
27            EnumItem::ChannelB => Some(FlexrayChannelName::B),
28            _ => None,
29        }
30    }
31
32    /// get the cluster containing this physical channel
33    ///
34    /// # Example
35    ///
36    /// ```
37    /// # use autosar_data::*;
38    /// # use autosar_data_abstraction::*;
39    /// # use autosar_data_abstraction::communication::*;
40    /// # fn main() -> Result<(), AutosarAbstractionError> {
41    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
42    /// # let package = model.get_or_create_package("/pkg1")?;
43    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
44    /// # let cluster = system.create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())?;
45    /// let channel = cluster.create_physical_channel("Channel", FlexrayChannelName::A)?;
46    /// let cluster_2 = channel.cluster()?;
47    /// assert_eq!(cluster, cluster_2);
48    /// # Ok(())}
49    /// ```
50    ///
51    /// # Errors
52    ///
53    /// - [`AutosarAbstractionError::ModelError`] An error occurred in the Autosar model
54    pub fn cluster(&self) -> Result<FlexrayCluster, AutosarAbstractionError> {
55        let cluster_elem = self.0.named_parent()?.unwrap();
56        FlexrayCluster::try_from(cluster_elem)
57    }
58
59    /// add a trigger for a flexray frame in this physical channel
60    ///
61    /// # Example
62    ///
63    /// ```
64    /// # use autosar_data::*;
65    /// # use autosar_data_abstraction::*;
66    /// # use autosar_data_abstraction::communication::*;
67    /// # fn main() -> Result<(), AutosarAbstractionError> {
68    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
69    /// # let package = model.get_or_create_package("/pkg1")?;
70    /// # let frame_package = model.get_or_create_package("/Frames")?;
71    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
72    /// # let cluster = system.create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())?;
73    /// let channel = cluster.create_physical_channel("Channel", FlexrayChannelName::A)?;
74    /// let frame = system.create_flexray_frame("Frame", &frame_package, 64)?;
75    /// let timing = FlexrayCommunicationCycle::Repetition {base_cycle: 1, cycle_repetition: CycleRepetition::C1};
76    /// channel.trigger_frame(&frame, 1, &timing)?;
77    /// # Ok(())}
78    /// ```
79    pub fn trigger_frame(
80        &self,
81        frame: &FlexrayFrame,
82        slot_id: u16,
83        timing: &FlexrayCommunicationCycle,
84    ) -> Result<FlexrayFrameTriggering, AutosarAbstractionError> {
85        FlexrayFrameTriggering::new(self, frame, slot_id, timing)
86    }
87
88    /// iterate over all frame triggerings of this physical channel
89    ///
90    /// # Example
91    ///
92    /// ```
93    /// # use autosar_data::*;
94    /// # use autosar_data_abstraction::{*, communication::*};
95    /// # fn main() -> Result<(), AutosarAbstractionError> {
96    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
97    /// # let package = model.get_or_create_package("/pkg1")?;
98    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
99    /// # let cluster = system.create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())?;
100    /// # let channel = cluster.create_physical_channel("Channel", FlexrayChannelName::A)?;
101    /// # let frame = system.create_flexray_frame("Frame", &package, 64)?;
102    /// # let timing = FlexrayCommunicationCycle::Repetition {base_cycle: 1, cycle_repetition: CycleRepetition::C1};
103    /// channel.trigger_frame(&frame, 1, &timing)?;
104    /// for ft in channel.frame_triggerings() {
105    ///     println!("Frame triggering: {:?}", ft);
106    /// }
107    /// # assert_eq!(channel.frame_triggerings().count(), 1);
108    /// # Ok(())}
109    pub fn frame_triggerings(&self) -> impl Iterator<Item = FlexrayFrameTriggering> + Send + use<> {
110        self.0
111            .get_sub_element(ElementName::FrameTriggerings)
112            .into_iter()
113            .flat_map(|elem| elem.sub_elements())
114            .filter_map(|elem| FlexrayFrameTriggering::try_from(elem).ok())
115    }
116}
117
118impl From<FlexrayPhysicalChannel> for PhysicalChannel {
119    fn from(channel: FlexrayPhysicalChannel) -> Self {
120        PhysicalChannel::Flexray(channel)
121    }
122}
123
124impl AbstractPhysicalChannel for FlexrayPhysicalChannel {
125    type CommunicationConnectorType = FlexrayCommunicationConnector;
126}
127
128//##################################################################
129
130/// A flexray cluster may contain the channels A and/or B.
131///
132/// This enum is an abstraction over the \<CHANNEL-NAME\> element.
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum FlexrayChannelName {
135    /// Channel A
136    A,
137    /// Channel B
138    B,
139}
140
141//##################################################################
142
143#[cfg(test)]
144mod test {
145    use crate::{
146        AbstractionElement, AutosarModelAbstraction, SystemCategory,
147        communication::{FlexrayChannelName, FlexrayClusterSettings},
148    };
149    use autosar_data::{AutosarVersion, ElementName};
150
151    #[test]
152    fn channel() {
153        let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
154        let pkg = model.get_or_create_package("/test").unwrap();
155        let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
156        let settings = FlexrayClusterSettings::default();
157        let cluster = system.create_flexray_cluster("FlxCluster", &pkg, &settings).unwrap();
158
159        let channel = cluster
160            .create_physical_channel("channel_name", FlexrayChannelName::A)
161            .unwrap();
162        let c2 = channel.cluster().unwrap();
163        assert_eq!(cluster, c2);
164
165        let wrapped_channel: super::PhysicalChannel = channel.clone().into();
166        assert_eq!(wrapped_channel, super::PhysicalChannel::Flexray(channel.clone()));
167
168        // damage the channel info by removing the channel name
169        let elem_channelname = channel.element().get_sub_element(ElementName::ChannelName).unwrap();
170        elem_channelname.remove_character_data().unwrap();
171        assert!(channel.channel_name().is_none());
172
173        // now there is no longer a channel A
174        let channel2 = cluster.create_physical_channel("channel_name2", FlexrayChannelName::A);
175        assert!(channel2.is_ok());
176    }
177}