autosar_data_abstraction/communication/mod.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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
//! # Communication between ECUs in a system
//!
//! This module contains the communication related elements of the AUTOSAR metamodel.
//!
//! Currently, the following bus types are supported:
//! - CAN
//! - Ethernet
//! - Flexray
//!
//! For each of the bus types, the following elements are available:
//! - Communication using Frames, PDUs and signals
//! - Network management
//! - Diagnostic transport protocol
//!
//! Ethernet also has support for:
//! - Old communication odel (using `SocketConnectionBundles`)
//! - New communication model (using `StaticSocketConnections`)
//! - `SomeIP`
//!
//! # Example
//!
//! ```
//! use autosar_data::*;
//! use autosar_data_abstraction::*;
//! use autosar_data_abstraction::communication::*;
//! use autosar_data_abstraction::datatype::*;
//!
//! # fn main() -> Result<(), AutosarAbstractionError> {
//! let model = AutosarModel::new();
//! model.create_file("can.arxml", AutosarVersion::LATEST)?;
//! let system_package = ArPackage::get_or_create(&model, "/System")?;
//! let system = system_package.create_system("System", SystemCategory::SystemExtract)?;
//! let cluster_package = ArPackage::get_or_create(&model, "/Network/Clusters")?;
//!
//! let settings = CanClusterSettings {
//! can_fd_baudrate: Some(2000000),
//! ..Default::default()
//! };
//! let can_cluster = system.create_can_cluster("CanCluster", &cluster_package, &settings)?;
//! assert_eq!(can_cluster.element().element_name(), ElementName::CanCluster);
//! let can_channel = can_cluster.create_physical_channel("CanChannel")?;
//!
//! let ecu_package = ArPackage::get_or_create(&model, "/Ecus")?;
//!
//! // create ECU A and connect it to the CAN channel
//! let ecu_instance_a = system.create_ecu_instance("Ecu_A", &ecu_package)?;
//! let canctrl_a = ecu_instance_a.create_can_communication_controller("CanController")?;
//! let channels_iter = canctrl_a.connected_channels();
//! assert_eq!(channels_iter.count(), 0);
//! canctrl_a.connect_physical_channel("Ecu_A_connector", &can_channel)?;
//! let channels_iter = canctrl_a.connected_channels();
//! assert_eq!(channels_iter.count(), 1);
//!
//! // create ECU B and connect it to the CAN channel
//! let ecu_instance_b = system.create_ecu_instance("Ecu_B", &ecu_package)?;
//! let canctrl_b = ecu_instance_b.create_can_communication_controller("CanController")?;
//! canctrl_b.connect_physical_channel("Ecu_B_connector", &can_channel)?;
//!
//! let frame_package = ArPackage::get_or_create(&model, "/Network/Frames")?;
//! let pdu_package = ArPackage::get_or_create(&model, "/Network/Pdus")?;
//! let isignal_package = ArPackage::get_or_create(&model, "/Network/Signals")?;
//! let syssignal_package = ArPackage::get_or_create(&model, "/System/Signals")?;
//!
//! // create a base type for the CAN signals
//! let base_type_package = ArPackage::get_or_create(&model, "/BaseTypes")?;
//! let base_type_u8 = base_type_package.create_sw_base_type(
//! "uint8",
//! 8,
//! BaseTypeEncoding::None,
//! None,
//! None,
//! Some("uint8"),
//! )?;
//!
//! // create a frame which contains one Pdu: Id 0x101, length 8
//! let frame = system.create_can_frame("frame", &frame_package, 8)?;
//! let pdu = system.create_isignal_ipdu("pdu", &pdu_package, 8)?;
//! let ss_pdusignal1 = syssignal_package.create_system_signal("ss_pdusignal1")?;
//! let pdusignal1 = system
//! .create_isignal("pdusignal1", &isignal_package, 4, &ss_pdusignal1, Some(&base_type_u8))?;
//! let ss_pdusignal2 = syssignal_package.create_system_signal("ss_pdusignal2")?;
//! let pdusignal2 = system
//! .create_isignal("pdusignal2", &isignal_package, 4, &ss_pdusignal2, Some(&base_type_u8))?;
//! // map signal 1 to the first 4 bytes of the Pdu
//! pdu.map_signal(
//! &pdusignal1,
//! 0,
//! ByteOrder::MostSignificantByteFirst,
//! None,
//! TransferProperty::Triggered,
//! )?;
//! // map signal 2 to the second 4 bytes of the Pdu
//! pdu.map_signal(
//! &pdusignal2,
//! 8, // since this signal uses ByteOrder::MostSignificantByteFirst, it starts at byte 8 and ends at byte 4
//! ByteOrder::MostSignificantByteFirst,
//! None,
//! TransferProperty::Triggered,
//! )?;
//! // map the pdu to the frame
//! frame.map_pdu(
//! &pdu,
//! 0,
//! ByteOrder::MostSignificantByteLast,
//! None,
//! )?;
//! // trigger the frame on the CAN channel (id 0x101)
//! let frame_triggering = can_channel
//! .trigger_frame(&frame, 0x101, CanAddressingMode::Standard, CanFrameType::Can20)?;
//!
//! // frame connection: Ecu_B -> Ecu_A
//! frame_triggering.connect_to_ecu(&ecu_instance_a, CommunicationDirection::In)?;
//! frame_triggering.connect_to_ecu(&ecu_instance_b, CommunicationDirection::Out)?;
//! # Ok(())}
//! ```
use crate::AutosarAbstractionError;
use autosar_data::EnumItem;
mod cluster;
mod controller;
mod datatransformation;
mod frame;
mod network_management;
mod pdu;
mod physical_channel;
mod signal;
mod transport_layer;
pub use cluster::*;
pub use controller::*;
pub use datatransformation::*;
pub use frame::*;
pub use network_management::*;
pub use pdu::*;
pub use physical_channel::*;
pub use signal::*;
pub use transport_layer::*;
//#########################################################
/// The [`CommunicationDirection`] is used by the communication ports for frames, PDUs and signals
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CommunicationDirection {
/// The communication is incoming
In,
/// The communication is outgoing
Out,
}
impl TryFrom<EnumItem> for CommunicationDirection {
type Error = AutosarAbstractionError;
fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
match value {
EnumItem::In => Ok(CommunicationDirection::In),
EnumItem::Out => Ok(CommunicationDirection::Out),
_ => Err(AutosarAbstractionError::ValueConversionError {
value: value.to_string(),
dest: "CommunicationDirection".to_string(),
}),
}
}
}
impl From<CommunicationDirection> for EnumItem {
fn from(value: CommunicationDirection) -> Self {
match value {
CommunicationDirection::In => EnumItem::In,
CommunicationDirection::Out => EnumItem::Out,
}
}
}
//#########################################################
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_communication_direction() {
// convert from CommunicationDirection to EnumItem
let in_dir = CommunicationDirection::In;
let out_dir = CommunicationDirection::Out;
let in_enum: EnumItem = in_dir.into();
let out_enum: EnumItem = out_dir.into();
assert_eq!(in_enum, EnumItem::In);
assert_eq!(out_enum, EnumItem::Out);
// convert from EnumItem to CommunicationDirection
let in_dir_converted: CommunicationDirection = in_enum.try_into().unwrap();
let out_dir_converted: CommunicationDirection = out_enum.try_into().unwrap();
assert_eq!(in_dir_converted, CommunicationDirection::In);
assert_eq!(out_dir_converted, CommunicationDirection::Out);
// conversion of an enumItem other than In or Out should fail
let bad = CommunicationDirection::try_from(EnumItem::Abstract);
assert!(bad.is_err());
}
}