autosar_data_abstraction/communication/physical_channel/
lin.rs

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