autosar_data_abstraction/communication/physical_channel/
can.rs

1use crate::{
2    AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3    communication::{
4        AbstractPhysicalChannel, CanAddressingMode, CanCluster, CanCommunicationConnector, CanFrame,
5        CanFrameTriggering, CanFrameType, PhysicalChannel,
6    },
7};
8use autosar_data::{Element, ElementName};
9
10/// The `CanPhysicalChannel` contains all of the communication on a CAN network
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct CanPhysicalChannel(Element);
13abstraction_element!(CanPhysicalChannel, CanPhysicalChannel);
14impl IdentifiableAbstractionElement for CanPhysicalChannel {}
15
16impl CanPhysicalChannel {
17    /// get the cluster containing this physical channel
18    ///
19    /// # Example
20    ///
21    /// ```
22    /// # use autosar_data::*;
23    /// # use autosar_data_abstraction::*;
24    /// # use autosar_data_abstraction::communication::*;
25    /// # fn main() -> Result<(), AutosarAbstractionError> {
26    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
27    /// # let package = model.get_or_create_package("/pkg1")?;
28    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
29    /// # let cluster = system.create_can_cluster("Cluster", &package, None)?;
30    /// let channel = cluster.create_physical_channel("Channel")?;
31    /// let cluster_2 = channel.cluster()?;
32    /// assert_eq!(cluster, cluster_2);
33    /// # Ok(())}
34    /// ```
35    pub fn cluster(&self) -> Result<CanCluster, AutosarAbstractionError> {
36        let cluster_elem = self.0.named_parent()?.unwrap();
37        CanCluster::try_from(cluster_elem)
38    }
39
40    /// remove this `CanPhysicalChannel` from the model
41    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
42        // remove all frame triggerings of this physical channel
43        for ft in self.frame_triggerings() {
44            ft.remove(deep)?;
45        }
46
47        // remove all pdu triggerings of this physical channel
48        for pt in self.pdu_triggerings() {
49            pt.remove(deep)?;
50        }
51
52        // remove all signal triggerings of this physical channel
53        for st in self.signal_triggerings() {
54            st.remove(deep)?;
55        }
56
57        // remove all connectors using this physical channel
58        for connector in self.connectors() {
59            connector.remove(deep)?;
60        }
61
62        AbstractionElement::remove(self, deep)
63    }
64
65    /// add a trigger for a CAN frame in this physical channel
66    ///
67    /// # Example
68    ///
69    /// ```
70    /// # use autosar_data::*;
71    /// # use autosar_data_abstraction::*;
72    /// # use autosar_data_abstraction::communication::*;
73    /// # fn main() -> Result<(), AutosarAbstractionError> {
74    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
75    /// # let package = model.get_or_create_package("/pkg1")?;
76    /// # let frame_package = model.get_or_create_package("/Frames")?;
77    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
78    /// # let cluster = system.create_can_cluster("Cluster", &package, None)?;
79    /// let channel = cluster.create_physical_channel("Channel")?;
80    /// let frame = system.create_can_frame("Frame", &frame_package, 8)?;
81    /// channel.trigger_frame(&frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)?;
82    /// # Ok(())}
83    /// ```
84    pub fn trigger_frame(
85        &self,
86        frame: &CanFrame,
87        identifier: u32,
88        addressing_mode: CanAddressingMode,
89        frame_type: CanFrameType,
90    ) -> Result<CanFrameTriggering, AutosarAbstractionError> {
91        CanFrameTriggering::new(self, frame, identifier, addressing_mode, frame_type)
92    }
93
94    /// iterate over all frame triggerings of this physical channel
95    ///
96    /// # Example
97    ///
98    /// ```
99    /// # use autosar_data::*;
100    /// # use autosar_data_abstraction::{*, communication::*};
101    /// # fn main() -> Result<(), AutosarAbstractionError> {
102    /// # let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
103    /// # let package = model.get_or_create_package("/pkg1")?;
104    /// # let system = package.create_system("System", SystemCategory::SystemExtract)?;
105    /// # let cluster = system.create_can_cluster("Cluster", &package, None)?;
106    /// # let channel = cluster.create_physical_channel("Channel")?;
107    /// # let frame = system.create_can_frame("Frame", &package, 8)?;
108    /// channel.trigger_frame(&frame, 0x100, CanAddressingMode::Standard, CanFrameType::Can20)?;
109    /// for ft in channel.frame_triggerings() {
110    ///     println!("Frame triggering: {:?}", ft);
111    /// }
112    /// # assert_eq!(channel.frame_triggerings().count(), 1);
113    /// # Ok(())}
114    pub fn frame_triggerings(&self) -> impl Iterator<Item = CanFrameTriggering> + Send + use<> {
115        self.0
116            .get_sub_element(ElementName::FrameTriggerings)
117            .into_iter()
118            .flat_map(|elem| elem.sub_elements())
119            .filter_map(|elem| CanFrameTriggering::try_from(elem).ok())
120    }
121}
122
123impl From<CanPhysicalChannel> for PhysicalChannel {
124    fn from(channel: CanPhysicalChannel) -> Self {
125        PhysicalChannel::Can(channel)
126    }
127}
128
129impl AbstractPhysicalChannel for CanPhysicalChannel {
130    type CommunicationConnectorType = CanCommunicationConnector;
131}
132
133//##################################################################
134
135#[cfg(test)]
136mod test {
137    use crate::{
138        AbstractionElement, AutosarModelAbstraction, ByteOrder, SystemCategory,
139        communication::{AbstractFrame, AbstractPhysicalChannel, CanAddressingMode, CanFrameType, PhysicalChannel},
140    };
141    use autosar_data::AutosarVersion;
142
143    #[test]
144    fn channel() {
145        let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
146        let pkg = model.get_or_create_package("/test").unwrap();
147        let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
148        let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
149
150        let channel = cluster.create_physical_channel("channel_name").unwrap();
151        let c2 = channel.cluster().unwrap();
152        assert_eq!(cluster, c2);
153
154        let wrapped_channel: PhysicalChannel = channel.clone().into();
155        assert_eq!(wrapped_channel, PhysicalChannel::Can(channel));
156    }
157
158    #[test]
159    fn remove_channel() {
160        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
161        let pkg = model.get_or_create_package("/test").unwrap();
162        let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
163        let cluster = system.create_can_cluster("CanCluster", &pkg, None).unwrap();
164
165        let channel = cluster.create_physical_channel("channel_name").unwrap();
166
167        let frame = system.create_can_frame("CanFrame", &pkg, 8).unwrap();
168        let _ = channel
169            .trigger_frame(&frame, 0x123, CanAddressingMode::Standard, CanFrameType::Can20)
170            .unwrap();
171        let isignal_ipdu = system.create_isignal_ipdu("ISignalIPdu", &pkg, 8).unwrap();
172        let _ = frame
173            .map_pdu(&isignal_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
174            .unwrap();
175
176        assert_eq!(channel.frame_triggerings().count(), 1);
177        assert_eq!(channel.pdu_triggerings().count(), 1);
178
179        channel.remove(true).unwrap();
180        assert!(cluster.physical_channel().is_none());
181        // the PDU was removed, because it was unused and deep removal was requested
182        assert!(isignal_ipdu.element().parent().is_err());
183    }
184}