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