From 3363ad6d50332d70d4cb12a84c8dd129b28079bd Mon Sep 17 00:00:00 2001 From: Adrian Del Grosso <10929341+ad3154@users.noreply.github.com> Date: Tue, 8 Aug 2023 19:25:11 -0500 Subject: [PATCH 1/4] Add core address claiming logic Added the basic address claiming logic. Needs still needs to be attached to the driver. --- src/network_management/can_message.rs | 28 +++ src/network_management/control_function.rs | 17 +- src/network_management/mod.rs | 2 + src/network_management/name.rs | 2 +- src/network_management/network_manager.rs | 239 +++++++++++++++++++++ 5 files changed, 285 insertions(+), 3 deletions(-) create mode 100644 src/network_management/can_message.rs create mode 100644 src/network_management/network_manager.rs diff --git a/src/network_management/can_message.rs b/src/network_management/can_message.rs new file mode 100644 index 0000000..cc4a86b --- /dev/null +++ b/src/network_management/can_message.rs @@ -0,0 +1,28 @@ +// Copyright 2023 Raven Industries inc. +#![allow(dead_code)] + +use super::name::DEFAULT_NAME; +use super::name::NAME; +use crate::driver::CanId; + +pub struct CANMessage { + data: Vec, + identifier: CanId, + source_name: NAME, + destination_name: NAME, +} + +impl CANMessage { + pub(super) fn new(data: Vec, identifier: CanId) -> CANMessage { + CANMessage { + data, + identifier, + source_name: NAME { + raw_name: DEFAULT_NAME, + }, + destination_name: NAME { + raw_name: DEFAULT_NAME, + }, + } + } +} diff --git a/src/network_management/control_function.rs b/src/network_management/control_function.rs index cc9c412..387f589 100644 --- a/src/network_management/control_function.rs +++ b/src/network_management/control_function.rs @@ -31,6 +31,7 @@ pub enum AddressClaimingState { pub struct AddressClaimingData { state: AddressClaimingState, + name: NAME, timestamp: Option, preferred_address: u8, random_delay: u8, @@ -39,7 +40,6 @@ pub struct AddressClaimingData { pub enum ControlFunction { Internal { - name: NAME, address_claim_data: AddressClaimingData, }, External { @@ -48,9 +48,10 @@ pub enum ControlFunction { } impl AddressClaimingData { - pub fn new(preferred_address: u8, enabled: bool) -> AddressClaimingData { + pub fn new(name: NAME, preferred_address: u8, enabled: bool) -> AddressClaimingData { AddressClaimingData { state: AddressClaimingState::None, + name, timestamp: None, preferred_address, random_delay: AddressClaimingData::generate_random_delay(), @@ -83,6 +84,17 @@ impl AddressClaimingData { self.state = new_state; } + pub fn get_name(&self) -> NAME { + self.name + } + + pub fn set_name(&mut self, new_name: NAME) { + if self.name.raw_name != new_name.raw_name { + self.state = AddressClaimingState::None; // Name changed, state no longer valid + } + self.name = new_name; + } + pub fn get_timestamp(&self) -> Option { self.timestamp } @@ -105,6 +117,7 @@ impl Default for AddressClaimingData { fn default() -> AddressClaimingData { AddressClaimingData { state: AddressClaimingState::None, + name: NAME { raw_name: 0 }, timestamp: None, preferred_address: 0xFE_u8, random_delay: AddressClaimingData::generate_random_delay(), diff --git a/src/network_management/mod.rs b/src/network_management/mod.rs index 869de20..99d372c 100644 --- a/src/network_management/mod.rs +++ b/src/network_management/mod.rs @@ -1,4 +1,6 @@ // Copyright 2023 Raven Industries inc. +pub mod can_message; pub mod common_parameter_group_numbers; pub mod control_function; pub mod name; +pub mod network_manager; diff --git a/src/network_management/name.rs b/src/network_management/name.rs index 3f78ef6..02d7557 100644 --- a/src/network_management/name.rs +++ b/src/network_management/name.rs @@ -1,5 +1,5 @@ // Copyright 2023 Raven Industries inc. -const DEFAULT_NAME: u64 = 0xFFFFFFFFFFFFFFFF; +pub const DEFAULT_NAME: u64 = 0xFFFFFFFFFFFFFFFF; #[derive(PartialEq, Eq, Clone, Copy)] pub enum NameField { diff --git a/src/network_management/network_manager.rs b/src/network_management/network_manager.rs new file mode 100644 index 0000000..ccb67dd --- /dev/null +++ b/src/network_management/network_manager.rs @@ -0,0 +1,239 @@ +// Copyright 2023 Raven Industries inc. +#![allow(dead_code)] +#![allow(unused_variables)] +use std::time::{Duration, Instant}; + +use super::control_function::{AddressClaimingState, ControlFunction}; +use crate::driver::{CanId, Type}; +use crate::network_management::can_message::CANMessage; +use crate::network_management::common_parameter_group_numbers::CommonParameterGroupNumbers; +use crate::network_management::name::DEFAULT_NAME; +use crate::network_management::name::NAME; +use std::collections::VecDeque; + +pub struct NetworkManager { + control_function_table: [Option; 253], + channel: u8, + control_function_handle_counter: usize, + inactive_control_functions: Vec, + address_claim_state_machines: Vec, + high_priority_can_message_tx_queue: VecDeque, + normal_priority_can_message_tx_queue: VecDeque, +} + +impl NetworkManager { + pub fn new(channel: u8) -> Self { + Self { + control_function_table: std::array::from_fn(|_| None), + channel, + control_function_handle_counter: 0, + inactive_control_functions: Vec::new(), + address_claim_state_machines: Vec::new(), + high_priority_can_message_tx_queue: VecDeque::new(), + normal_priority_can_message_tx_queue: VecDeque::new(), + } + } + + pub fn get_control_function_by_address(&self, address: usize) -> &Option { + &self.control_function_table[address] + } + + fn send_raw_can_message( + &self, + source_address: u8, + destination_address: u8, + parameter_group_number: u32, + priority: u8, + data: &[u8], + ) -> bool { + false // Todo, link up with the driver layer + } + + fn construct_request_for_address_claim() -> CANMessage { + const ADDRESS_CLAIM_REQUEST_LENGTH: usize = 3; + let pgn_to_request: u32 = CommonParameterGroupNumbers::AddressClaim as u32; + let request = vec![ + (pgn_to_request & 0xFF) as u8, + ((pgn_to_request >> 8) & 0xFF) as u8, + ((pgn_to_request >> 16) & 0xFF) as u8, + ]; + + let request_id = CanId::new(0, Type::Extended); // TODO Fix the ID once encoding method is available in CanId + CANMessage::new(request, request_id) + } + + fn construct_address_claim(source_address: u8, name: u64) -> CANMessage { + let pgn: u32 = CommonParameterGroupNumbers::AddressClaim as u32; + let address_claim = vec![ + (name & 0xFF) as u8, + ((name >> 8) & 0xFF) as u8, + ((name >> 16) & 0xFF) as u8, + ((name >> 24) & 0xFF) as u8, + ((name >> 32) & 0xFF) as u8, + ((name >> 40) & 0xFF) as u8, + ((name >> 48) & 0xFF) as u8, + ((name >> 56) & 0xFF) as u8, + ]; + + let request_id = CanId::new(0, Type::Extended); // TODO Fix the ID once encoding method is available in CanId + CANMessage::new(address_claim, request_id) + } + + fn update_address_claiming(&mut self) { + for address_claimer in &mut self.address_claim_state_machines { + match address_claimer { + ControlFunction::Internal { address_claim_data } => { + if address_claim_data.get_enabled() { + match address_claim_data.get_state() { + AddressClaimingState::None => { + address_claim_data.set_state(AddressClaimingState::WaitForClaim); + } + AddressClaimingState::WaitForClaim => { + if address_claim_data.get_timestamp().is_none() { + address_claim_data.set_timestamp(Some(Instant::now())) + } + if Instant::now() + .duration_since(address_claim_data.get_timestamp().unwrap()) + > Duration::from_millis( + address_claim_data.get_random_delay() as u64 + ) + { + address_claim_data + .set_state(AddressClaimingState::SendRequestForClaim); + } + } + AddressClaimingState::SendRequestForClaim => { + self.high_priority_can_message_tx_queue.push_back( + NetworkManager::construct_request_for_address_claim(), + ); + address_claim_data.set_state( + AddressClaimingState::WaitForRequestContentionPeriod, + ); + } + AddressClaimingState::WaitForRequestContentionPeriod => { + let contention_time_ms: u64 = 250; + + if Instant::now() + .duration_since(address_claim_data.get_timestamp().unwrap()) + > Duration::from_millis( + address_claim_data.get_random_delay() as u64 + + contention_time_ms, + ) + { + let device_at_our_address = self + .control_function_table + .get(address_claim_data.get_preferred_address() as usize); + + let device_at_our_address = &device_at_our_address + .unwrap() + .as_ref() + .unwrap_or(&ControlFunction::External { + name: NAME { + raw_name: DEFAULT_NAME, + }, + }); + let preferred_address_name: u64 = match device_at_our_address { + ControlFunction::External { name } => name.raw_name, + ControlFunction::Internal { address_claim_data } => { + address_claim_data.get_name().raw_name + } + }; + + if (!address_claim_data + .get_name() + .get_self_configurable_address() + && preferred_address_name + > address_claim_data.get_name().raw_name) + || DEFAULT_NAME == preferred_address_name + { + // Either our preferred address is free, this is the best case, or: + // Our address is not free, but we cannot be at an arbitrary address, and the address can be stolen by us + address_claim_data.set_state( + AddressClaimingState::SendPreferredAddressClaim, + ); + } else if !address_claim_data + .get_name() + .get_self_configurable_address() + { + // We cannot claim because we cannot tolerate an arbitrary address, and the CF at that spot wins due to its lower ISONAME + address_claim_data + .set_state(AddressClaimingState::UnableToClaim); + } else { + // We will move to another address if whoever is in our spot has a lower NAME + if preferred_address_name + < address_claim_data.get_name().raw_name + { + // We must scan the address space and move to a free address + address_claim_data.set_state( + AddressClaimingState::SendArbitraryAddressClaim, + ); + } else { + // Our address claim wins because it's lower than the device that's in our preferred spot + address_claim_data.set_state( + AddressClaimingState::SendPreferredAddressClaim, + ); + } + } + } + } + AddressClaimingState::SendPreferredAddressClaim + | AddressClaimingState::SendReclaimAddressOnRequest + | AddressClaimingState::ContendForPreferredAddress => { + self.high_priority_can_message_tx_queue.push_back( + NetworkManager::construct_address_claim( + address_claim_data.get_preferred_address(), + address_claim_data.get_name().raw_name, + ), + ); + address_claim_data + .set_state(AddressClaimingState::AddressClaimingComplete); + } + AddressClaimingState::SendArbitraryAddressClaim => { + for address in 129..247 { + let &device_at_our_address = &self.control_function_table + [address] + .as_ref() + .unwrap_or(&ControlFunction::External { + name: NAME { + raw_name: DEFAULT_NAME, + }, + }); + + let preferred_address_name: u64 = match device_at_our_address { + ControlFunction::External { name } => name.raw_name, + ControlFunction::Internal { address_claim_data } => { + address_claim_data.get_name().raw_name + } + }; + + if DEFAULT_NAME == preferred_address_name { + // Found an address we can use + self.high_priority_can_message_tx_queue.push_back( + NetworkManager::construct_address_claim( + address as u8, + address_claim_data.get_name().raw_name, + ), + ); + address_claim_data.set_state( + AddressClaimingState::AddressClaimingComplete, + ); + break; + } + } + } + AddressClaimingState::AddressClaimingComplete + | AddressClaimingState::UnableToClaim => { + // Nothing to do + } + } + } + } + _ => panic!("Only Internal CFs can perform address claiming"), + } + } + } + + pub fn update(mut self) { + self.update_address_claiming(); + } +} From 480014b83c3b9ec87f878a87978d5530c1069755 Mon Sep 17 00:00:00 2001 From: Adrian Del Grosso <10929341+ad3154@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:50:13 -0500 Subject: [PATCH 2/4] Address claiming cleanup Moved a lot of the address claim logic into the control_function file. Cleaned up todos involving CanId encoding when creating address claim messages. Removed some clippy allows. Changed some manual bitshifting to use to_le_bytes. Changed some raw integers to be "Pgn" "Address" and other types in driver. Still WIP --- src/network_management/can_message.rs | 2 - src/network_management/control_function.rs | 147 +++++++++-- src/network_management/network_manager.rs | 276 +++++++++------------ 3 files changed, 239 insertions(+), 186 deletions(-) diff --git a/src/network_management/can_message.rs b/src/network_management/can_message.rs index cc4a86b..caf4622 100644 --- a/src/network_management/can_message.rs +++ b/src/network_management/can_message.rs @@ -1,6 +1,4 @@ // Copyright 2023 Raven Industries inc. -#![allow(dead_code)] - use super::name::DEFAULT_NAME; use super::name::NAME; use crate::driver::CanId; diff --git a/src/network_management/control_function.rs b/src/network_management/control_function.rs index 387f589..4a0b9e0 100644 --- a/src/network_management/control_function.rs +++ b/src/network_management/control_function.rs @@ -1,9 +1,11 @@ // Copyright 2023 Raven Industries inc. -#![allow(dead_code)] - +use crate::driver::Address; +use crate::network_management::name::DEFAULT_NAME; use crate::network_management::name::NAME; use rand::Rng; -use std::time::Instant; +use std::time::{Duration, Instant}; + +use super::network_manager::{MessageQueuePriority, NetworkManager}; #[derive(PartialEq, Eq, Clone, Copy)] pub enum AddressClaimingState { @@ -33,7 +35,7 @@ pub struct AddressClaimingData { state: AddressClaimingState, name: NAME, timestamp: Option, - preferred_address: u8, + preferred_address: Address, random_delay: u8, enabled: bool, } @@ -47,8 +49,124 @@ pub enum ControlFunction { }, } +impl AddressClaimingState { + pub(super) fn new() -> Self { + Self::None + } + + pub(super) fn update_state_none(_claim_to_process: &AddressClaimingData) -> Self { + AddressClaimingState::WaitForClaim + } + + pub(super) fn update_state_wait_for_claim(claim_to_process: &AddressClaimingData) -> Self { + if Instant::now().duration_since(claim_to_process.get_timestamp().unwrap()) + > Duration::from_millis(claim_to_process.get_random_delay() as u64) + { + AddressClaimingState::SendRequestForClaim + } else { + AddressClaimingState::WaitForClaim + } + } + + pub(super) fn update_state_send_request_for_claim(network: &mut NetworkManager) -> Self { + network.enqueue_can_message( + NetworkManager::construct_request_for_address_claim(), + MessageQueuePriority::High); + AddressClaimingState::WaitForRequestContentionPeriod + } + + pub(super) fn update_state_wait_for_request_contention( + claim_to_process: &AddressClaimingData, + network: &mut NetworkManager, + ) -> Self { + let contention_time_ms: u64 = 250; + + if Instant::now().duration_since(claim_to_process.get_timestamp().unwrap()) + > Duration::from_millis(claim_to_process.get_random_delay() as u64 + contention_time_ms) + { + let is_device_at_our_address = + network.get_control_function_by_address(claim_to_process.get_preferred_address()); + let device_at_our_address = match is_device_at_our_address { + Some(_) => is_device_at_our_address.as_ref().unwrap(), + None => &ControlFunction::External { + name: NAME { + raw_name: (DEFAULT_NAME), + }, + }, + }; + + let preferred_address_name: u64 = match device_at_our_address { + ControlFunction::External { name } => name.raw_name, + ControlFunction::Internal { + address_claim_data: _, + } => claim_to_process.get_name().raw_name, + }; + + if (!claim_to_process.get_name().get_self_configurable_address() + && preferred_address_name > claim_to_process.get_name().raw_name) + || DEFAULT_NAME == preferred_address_name + { + // Either our preferred address is free, this is the best case, or: + // Our address is not free, but we cannot be at an arbitrary address, and the address can be stolen by us + AddressClaimingState::SendPreferredAddressClaim + } else if !claim_to_process.get_name().get_self_configurable_address() { + // We cannot claim because we cannot tolerate an arbitrary address, and the CF at that spot wins due to its lower ISONAME + AddressClaimingState::UnableToClaim + } else { + // We will move to another address if whoever is in our spot has a lower NAME + if preferred_address_name < claim_to_process.get_name().raw_name { + // We must scan the address space and move to a free address + AddressClaimingState::SendArbitraryAddressClaim + } else { + // Our address claim wins because it's lower than the device that's in our preferred spot + AddressClaimingState::SendPreferredAddressClaim + } + } + } else { + AddressClaimingState::WaitForRequestContentionPeriod + } + } + + pub(super) fn update_state_send_preferred_address_claim( + claim_to_process: &AddressClaimingData, + network: &mut NetworkManager, + ) -> Self { + network.enqueue_can_message( + NetworkManager::construct_address_claim( + claim_to_process.get_preferred_address(), + claim_to_process.get_name(), + ), + MessageQueuePriority::High, + ); + AddressClaimingState::AddressClaimingComplete + } + + pub(super) fn update_state_send_arbitrary_address_claim( + claim_to_process: &AddressClaimingData, + network: &mut NetworkManager, + ) -> Self { + let next_address = network.get_next_free_arbitrary_address(); + + if Address::NULL != next_address { + // Found an address we can use + network.enqueue_can_message( + NetworkManager::construct_address_claim(next_address, claim_to_process.get_name()), + MessageQueuePriority::High, + ); + return AddressClaimingState::AddressClaimingComplete; + } + AddressClaimingState::UnableToClaim + } +} + +impl Default for AddressClaimingState { + fn default() -> Self { + Self::new() + } +} + impl AddressClaimingData { - pub fn new(name: NAME, preferred_address: u8, enabled: bool) -> AddressClaimingData { + pub fn new(name: NAME, preferred_address: Address, enabled: bool) -> AddressClaimingData { AddressClaimingData { state: AddressClaimingState::None, name, @@ -72,10 +190,14 @@ impl AddressClaimingData { } } - pub fn get_preferred_address(&self) -> u8 { + pub fn get_preferred_address(&self) -> Address { self.preferred_address } + pub(super) fn set_preferred_address(&mut self, new_address: Address) { + self.preferred_address = new_address; + } + pub fn get_state(&self) -> AddressClaimingState { self.state } @@ -112,16 +234,3 @@ impl AddressClaimingData { (rng.gen_range(0..255) as f32 * 0.6_f32) as u8 } } - -impl Default for AddressClaimingData { - fn default() -> AddressClaimingData { - AddressClaimingData { - state: AddressClaimingState::None, - name: NAME { raw_name: 0 }, - timestamp: None, - preferred_address: 0xFE_u8, - random_delay: AddressClaimingData::generate_random_delay(), - enabled: true, - } - } -} diff --git a/src/network_management/network_manager.rs b/src/network_management/network_manager.rs index ccb67dd..f877648 100644 --- a/src/network_management/network_manager.rs +++ b/src/network_management/network_manager.rs @@ -1,225 +1,164 @@ // Copyright 2023 Raven Industries inc. -#![allow(dead_code)] -#![allow(unused_variables)] -use std::time::{Duration, Instant}; +use std::time::Instant; use super::control_function::{AddressClaimingState, ControlFunction}; -use crate::driver::{CanId, Type}; +use crate::driver::{Address, CanId, Pgn, Priority}; use crate::network_management::can_message::CANMessage; use crate::network_management::common_parameter_group_numbers::CommonParameterGroupNumbers; -use crate::network_management::name::DEFAULT_NAME; -use crate::network_management::name::NAME; +use crate::network_management::name::{DEFAULT_NAME, NAME}; use std::collections::VecDeque; +#[derive(Debug, Clone, Copy)] +pub(super) enum MessageQueuePriority { + /// High priority messages are always sent to the driver before normal ones + High, + /// Normal messages are sent to the driver when no high priority messages are in the queue (todo) + Normal, +} + pub struct NetworkManager { control_function_table: [Option; 253], - channel: u8, - control_function_handle_counter: usize, - inactive_control_functions: Vec, + // Todo inactive_control_functions: Vec, address_claim_state_machines: Vec, high_priority_can_message_tx_queue: VecDeque, normal_priority_can_message_tx_queue: VecDeque, } impl NetworkManager { - pub fn new(channel: u8) -> Self { + pub fn new() -> Self { Self { control_function_table: std::array::from_fn(|_| None), - channel, - control_function_handle_counter: 0, - inactive_control_functions: Vec::new(), + // Todo inactive_control_functions: Vec::new(), address_claim_state_machines: Vec::new(), high_priority_can_message_tx_queue: VecDeque::new(), normal_priority_can_message_tx_queue: VecDeque::new(), } } - pub fn get_control_function_by_address(&self, address: usize) -> &Option { - &self.control_function_table[address] + pub fn get_control_function_by_address(&self, address: Address) -> &Option { + &self.control_function_table[address.0 as usize] } - fn send_raw_can_message( - &self, - source_address: u8, - destination_address: u8, - parameter_group_number: u32, - priority: u8, - data: &[u8], - ) -> bool { - false // Todo, link up with the driver layer + pub(super) fn get_next_free_arbitrary_address(&self) -> Address { + for address in 129..247 { + let is_device_at_address = self.get_control_function_by_address(Address(address)); + let device_at_our_address = match is_device_at_address { + Some(_) => is_device_at_address.as_ref().unwrap(), + None => &ControlFunction::External { + name: NAME { + raw_name: (DEFAULT_NAME), + }, + }, + }; + + let preferred_address_name: u64 = match device_at_our_address { + ControlFunction::External { name } => name.raw_name, + ControlFunction::Internal { address_claim_data } => { + address_claim_data.get_name().raw_name + } + }; + + if DEFAULT_NAME == preferred_address_name { + return Address(address); + } + } + Address::NULL } - fn construct_request_for_address_claim() -> CANMessage { - const ADDRESS_CLAIM_REQUEST_LENGTH: usize = 3; + pub(super) fn construct_request_for_address_claim() -> CANMessage { let pgn_to_request: u32 = CommonParameterGroupNumbers::AddressClaim as u32; - let request = vec![ - (pgn_to_request & 0xFF) as u8, - ((pgn_to_request >> 8) & 0xFF) as u8, - ((pgn_to_request >> 16) & 0xFF) as u8, - ]; - - let request_id = CanId::new(0, Type::Extended); // TODO Fix the ID once encoding method is available in CanId - CANMessage::new(request, request_id) + let request = pgn_to_request.to_le_bytes().to_vec(); + let request_id = CanId::try_encode( + Pgn::from_raw(CommonParameterGroupNumbers::ParameterGroupNumberRequest as u32), + Address::NULL, + Address::BROADCAST, + Priority::Three, + ); + CANMessage::new(request, request_id.unwrap()) + } + + pub(super) fn construct_address_claim(source_address: Address, name: NAME) -> CANMessage { + let address_claim = name.raw_name.to_le_bytes().to_vec(); + + let request_id = CanId::try_encode( + Pgn::from_raw(CommonParameterGroupNumbers::AddressClaim as u32), + source_address, + Address::BROADCAST, + Priority::Default, + ); + CANMessage::new(address_claim, request_id.unwrap()) } - fn construct_address_claim(source_address: u8, name: u64) -> CANMessage { - let pgn: u32 = CommonParameterGroupNumbers::AddressClaim as u32; - let address_claim = vec![ - (name & 0xFF) as u8, - ((name >> 8) & 0xFF) as u8, - ((name >> 16) & 0xFF) as u8, - ((name >> 24) & 0xFF) as u8, - ((name >> 32) & 0xFF) as u8, - ((name >> 40) & 0xFF) as u8, - ((name >> 48) & 0xFF) as u8, - ((name >> 56) & 0xFF) as u8, - ]; - - let request_id = CanId::new(0, Type::Extended); // TODO Fix the ID once encoding method is available in CanId - CANMessage::new(address_claim, request_id) + pub(super) fn enqueue_can_message( + &mut self, + message: CANMessage, + queue_priority: MessageQueuePriority, + ) { + match queue_priority { + MessageQueuePriority::High => { + self.high_priority_can_message_tx_queue.push_back(message) + } + MessageQueuePriority::Normal => { + self.normal_priority_can_message_tx_queue.push_back(message) + } + } } fn update_address_claiming(&mut self) { - for address_claimer in &mut self.address_claim_state_machines { + let mut state_machines = std::mem::take(&mut self.address_claim_state_machines); + for address_claimer in &mut state_machines { match address_claimer { ControlFunction::Internal { address_claim_data } => { if address_claim_data.get_enabled() { match address_claim_data.get_state() { AddressClaimingState::None => { - address_claim_data.set_state(AddressClaimingState::WaitForClaim); + address_claim_data.set_state( + AddressClaimingState::update_state_none(address_claim_data), + ); } AddressClaimingState::WaitForClaim => { if address_claim_data.get_timestamp().is_none() { address_claim_data.set_timestamp(Some(Instant::now())) } - if Instant::now() - .duration_since(address_claim_data.get_timestamp().unwrap()) - > Duration::from_millis( - address_claim_data.get_random_delay() as u64 - ) - { - address_claim_data - .set_state(AddressClaimingState::SendRequestForClaim); - } + + address_claim_data.set_state( + AddressClaimingState::update_state_wait_for_claim( + address_claim_data, + ), + ); } AddressClaimingState::SendRequestForClaim => { - self.high_priority_can_message_tx_queue.push_back( - NetworkManager::construct_request_for_address_claim(), - ); address_claim_data.set_state( - AddressClaimingState::WaitForRequestContentionPeriod, + AddressClaimingState::update_state_send_request_for_claim(self), ); } AddressClaimingState::WaitForRequestContentionPeriod => { - let contention_time_ms: u64 = 250; - - if Instant::now() - .duration_since(address_claim_data.get_timestamp().unwrap()) - > Duration::from_millis( - address_claim_data.get_random_delay() as u64 - + contention_time_ms, - ) - { - let device_at_our_address = self - .control_function_table - .get(address_claim_data.get_preferred_address() as usize); - - let device_at_our_address = &device_at_our_address - .unwrap() - .as_ref() - .unwrap_or(&ControlFunction::External { - name: NAME { - raw_name: DEFAULT_NAME, - }, - }); - let preferred_address_name: u64 = match device_at_our_address { - ControlFunction::External { name } => name.raw_name, - ControlFunction::Internal { address_claim_data } => { - address_claim_data.get_name().raw_name - } - }; - - if (!address_claim_data - .get_name() - .get_self_configurable_address() - && preferred_address_name - > address_claim_data.get_name().raw_name) - || DEFAULT_NAME == preferred_address_name - { - // Either our preferred address is free, this is the best case, or: - // Our address is not free, but we cannot be at an arbitrary address, and the address can be stolen by us - address_claim_data.set_state( - AddressClaimingState::SendPreferredAddressClaim, - ); - } else if !address_claim_data - .get_name() - .get_self_configurable_address() - { - // We cannot claim because we cannot tolerate an arbitrary address, and the CF at that spot wins due to its lower ISONAME - address_claim_data - .set_state(AddressClaimingState::UnableToClaim); - } else { - // We will move to another address if whoever is in our spot has a lower NAME - if preferred_address_name - < address_claim_data.get_name().raw_name - { - // We must scan the address space and move to a free address - address_claim_data.set_state( - AddressClaimingState::SendArbitraryAddressClaim, - ); - } else { - // Our address claim wins because it's lower than the device that's in our preferred spot - address_claim_data.set_state( - AddressClaimingState::SendPreferredAddressClaim, - ); - } - } - } + address_claim_data.set_state( + AddressClaimingState::update_state_wait_for_request_contention( + address_claim_data, + self, + ), + ); } AddressClaimingState::SendPreferredAddressClaim | AddressClaimingState::SendReclaimAddressOnRequest | AddressClaimingState::ContendForPreferredAddress => { - self.high_priority_can_message_tx_queue.push_back( - NetworkManager::construct_address_claim( - address_claim_data.get_preferred_address(), - address_claim_data.get_name().raw_name, + address_claim_data.set_state( + AddressClaimingState::update_state_send_preferred_address_claim( + address_claim_data, + self, ), ); - address_claim_data - .set_state(AddressClaimingState::AddressClaimingComplete); } AddressClaimingState::SendArbitraryAddressClaim => { - for address in 129..247 { - let &device_at_our_address = &self.control_function_table - [address] - .as_ref() - .unwrap_or(&ControlFunction::External { - name: NAME { - raw_name: DEFAULT_NAME, - }, - }); - - let preferred_address_name: u64 = match device_at_our_address { - ControlFunction::External { name } => name.raw_name, - ControlFunction::Internal { address_claim_data } => { - address_claim_data.get_name().raw_name - } - }; - - if DEFAULT_NAME == preferred_address_name { - // Found an address we can use - self.high_priority_can_message_tx_queue.push_back( - NetworkManager::construct_address_claim( - address as u8, - address_claim_data.get_name().raw_name, - ), - ); - address_claim_data.set_state( - AddressClaimingState::AddressClaimingComplete, - ); - break; - } - } + address_claim_data.set_state( + AddressClaimingState::update_state_send_arbitrary_address_claim( + address_claim_data, + self, + ), + ); + address_claim_data + .set_preferred_address(self.get_next_free_arbitrary_address()); } AddressClaimingState::AddressClaimingComplete | AddressClaimingState::UnableToClaim => { @@ -231,9 +170,16 @@ impl NetworkManager { _ => panic!("Only Internal CFs can perform address claiming"), } } + std::mem::swap(&mut state_machines, &mut self.address_claim_state_machines); } pub fn update(mut self) { self.update_address_claiming(); } } + +impl Default for NetworkManager { + fn default() -> Self { + Self::new() + } +} From a4b8068d932ac07803ade4b3a7e8525ea2c02db0 Mon Sep 17 00:00:00 2001 From: Adrian Del Grosso <10929341+ad3154@users.noreply.github.com> Date: Fri, 11 Aug 2023 19:20:45 -0500 Subject: [PATCH 3/4] Changed CFs to be stored as Rc>, more general network manager additions Changed CFs to be stored differently. Added a function to send a CAN message. Added a way to create an ICF. Started adding receive message processing. --- src/network_management/can_message.rs | 19 +- src/network_management/control_function.rs | 91 +++++--- src/network_management/network_manager.rs | 236 ++++++++++++++++++--- 3 files changed, 275 insertions(+), 71 deletions(-) diff --git a/src/network_management/can_message.rs b/src/network_management/can_message.rs index caf4622..9905ffd 100644 --- a/src/network_management/can_message.rs +++ b/src/network_management/can_message.rs @@ -1,6 +1,5 @@ // Copyright 2023 Raven Industries inc. -use super::name::DEFAULT_NAME; -use super::name::NAME; +use super::name::{DEFAULT_NAME, NAME}; use crate::driver::CanId; pub struct CANMessage { @@ -23,4 +22,20 @@ impl CANMessage { }, } } + + pub fn get_data(&self) -> &[u8] { + self.data.as_slice() + } + + pub fn get_identifier(&self) -> CanId { + self.identifier + } + + pub fn get_source_name(&self) -> NAME { + self.source_name + } + + pub fn get_destination_name(&self) -> NAME { + self.destination_name + } } diff --git a/src/network_management/control_function.rs b/src/network_management/control_function.rs index 4a0b9e0..d4f55ce 100644 --- a/src/network_management/control_function.rs +++ b/src/network_management/control_function.rs @@ -3,6 +3,8 @@ use crate::driver::Address; use crate::network_management::name::DEFAULT_NAME; use crate::network_management::name::NAME; use rand::Rng; +use std::cell::RefCell; +use std::rc::Rc; use std::time::{Duration, Instant}; use super::network_manager::{MessageQueuePriority, NetworkManager}; @@ -49,6 +51,28 @@ pub enum ControlFunction { }, } +impl ControlFunction { + pub fn new_internal_control_function( + name: NAME, + preferred_address: Address, + enabled: bool, + network: &mut NetworkManager, + ) -> Rc> { + let cf = Rc::new(RefCell::new(ControlFunction::Internal { + address_claim_data: AddressClaimingData::new(name, preferred_address, enabled), + })); + network.on_new_internal_control_function(cf.clone()); + cf + } + + pub fn get_name(&self) -> NAME { + match self { + ControlFunction::Internal { address_claim_data } => address_claim_data.get_name(), + ControlFunction::External { name } => *name, + } + } +} + impl AddressClaimingState { pub(super) fn new() -> Self { Self::None @@ -71,7 +95,8 @@ impl AddressClaimingState { pub(super) fn update_state_send_request_for_claim(network: &mut NetworkManager) -> Self { network.enqueue_can_message( NetworkManager::construct_request_for_address_claim(), - MessageQueuePriority::High); + MessageQueuePriority::High, + ); AddressClaimingState::WaitForRequestContentionPeriod } @@ -86,41 +111,39 @@ impl AddressClaimingState { { let is_device_at_our_address = network.get_control_function_by_address(claim_to_process.get_preferred_address()); - let device_at_our_address = match is_device_at_our_address { - Some(_) => is_device_at_our_address.as_ref().unwrap(), - None => &ControlFunction::External { - name: NAME { - raw_name: (DEFAULT_NAME), - }, - }, - }; - - let preferred_address_name: u64 = match device_at_our_address { - ControlFunction::External { name } => name.raw_name, - ControlFunction::Internal { - address_claim_data: _, - } => claim_to_process.get_name().raw_name, - }; - - if (!claim_to_process.get_name().get_self_configurable_address() - && preferred_address_name > claim_to_process.get_name().raw_name) - || DEFAULT_NAME == preferred_address_name - { - // Either our preferred address is free, this is the best case, or: - // Our address is not free, but we cannot be at an arbitrary address, and the address can be stolen by us - AddressClaimingState::SendPreferredAddressClaim - } else if !claim_to_process.get_name().get_self_configurable_address() { - // We cannot claim because we cannot tolerate an arbitrary address, and the CF at that spot wins due to its lower ISONAME - AddressClaimingState::UnableToClaim - } else { - // We will move to another address if whoever is in our spot has a lower NAME - if preferred_address_name < claim_to_process.get_name().raw_name { - // We must scan the address space and move to a free address - AddressClaimingState::SendArbitraryAddressClaim - } else { - // Our address claim wins because it's lower than the device that's in our preferred spot + let is_valid_device: bool = is_device_at_our_address.is_some(); + + if is_valid_device { + let preferred_address_name: u64 = + match *is_device_at_our_address.as_ref().unwrap().clone().borrow() { + ControlFunction::External { name } => name.raw_name, + ControlFunction::Internal { + address_claim_data: _, + } => claim_to_process.get_name().raw_name, + }; + + if (!claim_to_process.get_name().get_self_configurable_address() + && preferred_address_name > claim_to_process.get_name().raw_name) + || DEFAULT_NAME == preferred_address_name + { + // Either our preferred address is free, this is the best case, or: + // Our address is not free, but we cannot be at an arbitrary address, and the address can be stolen by us AddressClaimingState::SendPreferredAddressClaim + } else if !claim_to_process.get_name().get_self_configurable_address() { + // We cannot claim because we cannot tolerate an arbitrary address, and the CF at that spot wins due to its lower ISONAME + AddressClaimingState::UnableToClaim + } else { + // We will move to another address if whoever is in our spot has a lower NAME + if preferred_address_name < claim_to_process.get_name().raw_name { + // We must scan the address space and move to a free address + AddressClaimingState::SendArbitraryAddressClaim + } else { + // Our address claim wins because it's lower than the device that's in our preferred spot + AddressClaimingState::SendPreferredAddressClaim + } } + } else { + AddressClaimingState::SendPreferredAddressClaim } } else { AddressClaimingState::WaitForRequestContentionPeriod diff --git a/src/network_management/network_manager.rs b/src/network_management/network_manager.rs index f877648..8976d0a 100644 --- a/src/network_management/network_manager.rs +++ b/src/network_management/network_manager.rs @@ -6,7 +6,9 @@ use crate::driver::{Address, CanId, Pgn, Priority}; use crate::network_management::can_message::CANMessage; use crate::network_management::common_parameter_group_numbers::CommonParameterGroupNumbers; use crate::network_management::name::{DEFAULT_NAME, NAME}; +use std::cell::RefCell; use std::collections::VecDeque; +use std::rc::Rc; #[derive(Debug, Clone, Copy)] pub(super) enum MessageQueuePriority { @@ -16,67 +18,86 @@ pub(super) enum MessageQueuePriority { Normal, } +#[derive(Debug, Clone, Copy)] +pub enum CANTransmitState { + /// Used to describe that a CAN message was accepted by the CAN stack to be sent + Success, + /// Used to describe that a CAN message was not accepted by the stack and will not be sent + Fail, +} + pub struct NetworkManager { - control_function_table: [Option; 253], - // Todo inactive_control_functions: Vec, - address_claim_state_machines: Vec, + control_function_table: [Option>>; 253], + inactive_control_functions: Vec>>, + address_claim_state_machines: Vec>>, high_priority_can_message_tx_queue: VecDeque, normal_priority_can_message_tx_queue: VecDeque, + receive_message_queue: VecDeque, } impl NetworkManager { pub fn new() -> Self { Self { control_function_table: std::array::from_fn(|_| None), - // Todo inactive_control_functions: Vec::new(), + inactive_control_functions: Vec::new(), address_claim_state_machines: Vec::new(), high_priority_can_message_tx_queue: VecDeque::new(), normal_priority_can_message_tx_queue: VecDeque::new(), + receive_message_queue: VecDeque::new(), } } - pub fn get_control_function_by_address(&self, address: Address) -> &Option { + pub fn get_control_function_by_address( + &self, + address: Address, + ) -> &Option>> { &self.control_function_table[address.0 as usize] } + pub fn get_control_function_address_by_name(&self, name: NAME) -> Address { + for (i, cf) in self.control_function_table.iter().enumerate() { + if let Some(extant_cf) = cf { + if extant_cf.borrow().get_name().raw_name == name.raw_name { + return Address(i as u8); + } + } + } + Address::NULL + } + + pub(super) fn on_new_internal_control_function( + &mut self, + new_cf: Rc>, + ) { + self.inactive_control_functions.push(new_cf.clone()); + self.address_claim_state_machines.push(new_cf); + } + pub(super) fn get_next_free_arbitrary_address(&self) -> Address { for address in 129..247 { let is_device_at_address = self.get_control_function_by_address(Address(address)); - let device_at_our_address = match is_device_at_address { - Some(_) => is_device_at_address.as_ref().unwrap(), - None => &ControlFunction::External { - name: NAME { - raw_name: (DEFAULT_NAME), - }, - }, - }; - - let preferred_address_name: u64 = match device_at_our_address { - ControlFunction::External { name } => name.raw_name, - ControlFunction::Internal { address_claim_data } => { - address_claim_data.get_name().raw_name - } - }; + let is_valid_device: bool = is_device_at_address.is_some(); - if DEFAULT_NAME == preferred_address_name { + if !is_valid_device { return Address(address); + } else { + let device_at_our_address = is_device_at_address.as_ref().unwrap().borrow(); + + let preferred_address_name: u64 = match &*device_at_our_address { + ControlFunction::External { name } => name.raw_name, + ControlFunction::Internal { address_claim_data } => { + address_claim_data.get_name().raw_name + } + }; + + if DEFAULT_NAME == preferred_address_name { + return Address(address); + } } } Address::NULL } - pub(super) fn construct_request_for_address_claim() -> CANMessage { - let pgn_to_request: u32 = CommonParameterGroupNumbers::AddressClaim as u32; - let request = pgn_to_request.to_le_bytes().to_vec(); - let request_id = CanId::try_encode( - Pgn::from_raw(CommonParameterGroupNumbers::ParameterGroupNumberRequest as u32), - Address::NULL, - Address::BROADCAST, - Priority::Three, - ); - CANMessage::new(request, request_id.unwrap()) - } - pub(super) fn construct_address_claim(source_address: Address, name: NAME) -> CANMessage { let address_claim = name.raw_name.to_le_bytes().to_vec(); @@ -89,11 +110,24 @@ impl NetworkManager { CANMessage::new(address_claim, request_id.unwrap()) } + pub(super) fn construct_request_for_address_claim() -> CANMessage { + let pgn_to_request: u32 = CommonParameterGroupNumbers::AddressClaim as u32; + let request = pgn_to_request.to_le_bytes().to_vec(); + let request_id = CanId::try_encode( + Pgn::from_raw(CommonParameterGroupNumbers::ParameterGroupNumberRequest as u32), + Address::NULL, + Address::BROADCAST, + Priority::Three, + ); + CANMessage::new(request, request_id.unwrap()) + } + pub(super) fn enqueue_can_message( &mut self, message: CANMessage, queue_priority: MessageQueuePriority, ) { + // Todo, max queue depth? match queue_priority { MessageQueuePriority::High => { self.high_priority_can_message_tx_queue.push_back(message) @@ -104,11 +138,48 @@ impl NetworkManager { } } + pub fn send_can_message( + &mut self, + parameter_group_number: Pgn, + data: &[u8], + source: Rc>, + destination: Rc>, + priority: Priority, + ) -> CANTransmitState { + if !data.is_empty() { + // Todo, handle lengths greater than 8 + + if data.len() <= 8 { + let source = source.borrow(); + let destination = destination.borrow(); + let message_id = CanId::try_encode( + parameter_group_number, + self.get_control_function_address_by_name(source.get_name()), + self.get_control_function_address_by_name(destination.get_name()), + priority, + ) + .unwrap_or(CanId::default()); + + if message_id.raw() != CanId::default().raw() { + self.enqueue_can_message( + CANMessage::new(data.to_vec(), message_id), + MessageQueuePriority::Normal, + ); + return CANTransmitState::Success; + } + } + } + CANTransmitState::Fail + } + fn update_address_claiming(&mut self) { let mut state_machines = std::mem::take(&mut self.address_claim_state_machines); for address_claimer in &mut state_machines { - match address_claimer { - ControlFunction::Internal { address_claim_data } => { + let mut address_claimer = address_claimer.borrow_mut(); + match *address_claimer { + ControlFunction::Internal { + ref mut address_claim_data, + } => { if address_claim_data.get_enabled() { match address_claim_data.get_state() { AddressClaimingState::None => { @@ -173,8 +244,77 @@ impl NetworkManager { std::mem::swap(&mut state_machines, &mut self.address_claim_state_machines); } + fn update_receive_messages(&mut self) { + while !self.receive_message_queue.is_empty() { + // Todo receive messages, need to generalize message handling + let current_message = self.receive_message_queue.front().unwrap(); + + // Process address claims and requests to claim + if DEFAULT_NAME == current_message.get_destination_name().raw_name { + // Broadcast Message + if current_message.get_identifier().pgn() + == Pgn::from_raw(CommonParameterGroupNumbers::AddressClaim as u32) + { + // Todo + } else if current_message.get_identifier().pgn() + == Pgn::from_raw( + CommonParameterGroupNumbers::ParameterGroupNumberRequest as u32, + ) + && current_message.get_data().len() >= 3 + { + let message_data = current_message.get_data(); + let requested_pgn: u32 = (message_data[0] as u32) + | ((message_data[1] as u32) << 8) + | ((message_data[2] as u32) << 16); + + if requested_pgn + == CommonParameterGroupNumbers::ParameterGroupNumberRequest as u32 + { + for internal_cf in &mut self.address_claim_state_machines { + let mut address_claimer = internal_cf.borrow_mut(); + match *address_claimer { + ControlFunction::Internal { + ref mut address_claim_data, + } => { + if address_claim_data.get_state() + == AddressClaimingState::AddressClaimingComplete + { + address_claim_data.set_state( + AddressClaimingState::SendReclaimAddressOnRequest, + ); + } + } + ControlFunction::External { name: _ } => {} + } + } + } + } else { + // Destination specific + } + + self.receive_message_queue.pop_front(); + } + } + } + + fn update_transmit_messages(&mut self) { + let should_continue_sending: bool = true; // Todo, check driver return values. + + while !self.high_priority_can_message_tx_queue.is_empty() { + // todo hand off to driver + self.high_priority_can_message_tx_queue.pop_front(); + } + + while should_continue_sending && !self.normal_priority_can_message_tx_queue.is_empty() { + // todo hand off to driver + self.normal_priority_can_message_tx_queue.pop_front(); + } + } + pub fn update(mut self) { + self.update_receive_messages(); self.update_address_claiming(); + self.update_transmit_messages(); } } @@ -183,3 +323,29 @@ impl Default for NetworkManager { Self::new() } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_creating_network_manager() { + let network = NetworkManager::new(); + network.update(); + } + + #[test] + fn test_creating_internal_control_function() { + let mut network = NetworkManager::new(); + let test_name = NAME::build(4, 0, 8, 5, 6, 3, 2, 7, 1, true); + + let new_cf = ControlFunction::new_internal_control_function( + test_name, + Address(0x81), + true, + &mut network, + ); + + assert_eq!(new_cf.borrow().get_name().raw_name, test_name.raw_name); + } +} From f38ee9de6d9e29c539c6a08c91965715b43d9eb7 Mon Sep 17 00:00:00 2001 From: Jannes Brands Date: Thu, 21 Sep 2023 14:37:30 +0200 Subject: [PATCH 4/4] refactoring --- examples/forward.rs | 5 +++- src/application_messages_7/mod.rs | 3 ++ src/common/mod.rs | 3 ++ .../address.rs | 0 .../can_id.rs | 2 +- .../can_message.rs | 4 +-- .../common_parameter_group_numbers.rs | 0 .../control_function.rs | 30 +++++++++---------- .../frame.rs | 2 +- .../mod.rs | 29 ++++++++++++++++++ .../name.rs | 0 .../network_manager.rs | 22 +++++++------- .../pgn.rs | 0 src/diagnostics_service_12/mod.rs | 3 ++ .../driver.rs | 2 +- src/{driver => driver_implementation}/mod.rs | 14 ++------- .../socketcan.rs | 13 ++++++-- src/file_server_client_13/mod.rs | 3 ++ src/lib.rs | 13 ++++++-- src/network_management/mod.rs | 6 ---- src/sequence_controller_client_14/mod.rs | 3 ++ src/task_controller_client_10/mod.rs | 3 ++ src/tractor_ecu_9/mod.rs | 3 ++ src/virtual_terminal_client_6/mod.rs | 3 ++ 24 files changed, 114 insertions(+), 52 deletions(-) create mode 100644 src/application_messages_7/mod.rs create mode 100644 src/common/mod.rs rename src/{driver => datalink_network_network_management_3_4_5}/address.rs (100%) rename src/{driver => datalink_network_network_management_3_4_5}/can_id.rs (99%) rename src/{network_management => datalink_network_network_management_3_4_5}/can_message.rs (86%) rename src/{network_management => datalink_network_network_management_3_4_5}/common_parameter_group_numbers.rs (100%) rename src/{network_management => datalink_network_network_management_3_4_5}/control_function.rs (90%) rename src/{driver => datalink_network_network_management_3_4_5}/frame.rs (90%) create mode 100644 src/datalink_network_network_management_3_4_5/mod.rs rename src/{network_management => datalink_network_network_management_3_4_5}/name.rs (100%) rename src/{network_management => datalink_network_network_management_3_4_5}/network_manager.rs (95%) rename src/{driver => datalink_network_network_management_3_4_5}/pgn.rs (100%) create mode 100644 src/diagnostics_service_12/mod.rs rename src/{driver => driver_implementation}/driver.rs (98%) rename src/{driver => driver_implementation}/mod.rs (61%) rename src/{driver => driver_implementation}/socketcan.rs (96%) create mode 100644 src/file_server_client_13/mod.rs delete mode 100644 src/network_management/mod.rs create mode 100644 src/sequence_controller_client_14/mod.rs create mode 100644 src/task_controller_client_10/mod.rs create mode 100644 src/tractor_ecu_9/mod.rs create mode 100644 src/virtual_terminal_client_6/mod.rs diff --git a/examples/forward.rs b/examples/forward.rs index a90c5fd..3ccea77 100644 --- a/examples/forward.rs +++ b/examples/forward.rs @@ -2,7 +2,10 @@ use std::sync::mpsc::channel; -use ag_iso_stack::driver::{Driver, DriverReadError, Frame, SocketcanDriver}; +use ag_iso_stack::{ + driver_implementation::{Driver, DriverReadError, SocketcanDriver}, + datalink_network_network_management_3_4_5::{Frame} +}; use clap::Parser; /// Forward CAN traffic from one interface to another diff --git a/src/application_messages_7/mod.rs b/src/application_messages_7/mod.rs new file mode 100644 index 0000000..a6c034e --- /dev/null +++ b/src/application_messages_7/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! Implement messages application layer ISO11783-7 \ No newline at end of file diff --git a/src/common/mod.rs b/src/common/mod.rs new file mode 100644 index 0000000..ac886fc --- /dev/null +++ b/src/common/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! common functionality for ISO 11783 implementation \ No newline at end of file diff --git a/src/driver/address.rs b/src/datalink_network_network_management_3_4_5/address.rs similarity index 100% rename from src/driver/address.rs rename to src/datalink_network_network_management_3_4_5/address.rs diff --git a/src/driver/can_id.rs b/src/datalink_network_network_management_3_4_5/can_id.rs similarity index 99% rename from src/driver/can_id.rs rename to src/datalink_network_network_management_3_4_5/can_id.rs index 51affdd..7de946f 100644 --- a/src/driver/can_id.rs +++ b/src/datalink_network_network_management_3_4_5/can_id.rs @@ -1,5 +1,5 @@ // Copyright 2023 Raven Industries inc. -use crate::driver::{Address, Pgn}; +use crate::datalink_network_network_management_3_4_5::{Address, Pgn}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Priority { diff --git a/src/network_management/can_message.rs b/src/datalink_network_network_management_3_4_5/can_message.rs similarity index 86% rename from src/network_management/can_message.rs rename to src/datalink_network_network_management_3_4_5/can_message.rs index 9905ffd..398da4a 100644 --- a/src/network_management/can_message.rs +++ b/src/datalink_network_network_management_3_4_5/can_message.rs @@ -1,6 +1,6 @@ // Copyright 2023 Raven Industries inc. use super::name::{DEFAULT_NAME, NAME}; -use crate::driver::CanId; +use crate::datalink_network_network_management_3_4_5::CanId; pub struct CANMessage { data: Vec, @@ -10,7 +10,7 @@ pub struct CANMessage { } impl CANMessage { - pub(super) fn new(data: Vec, identifier: CanId) -> CANMessage { + pub(crate) fn new(data: Vec, identifier: CanId) -> CANMessage { CANMessage { data, identifier, diff --git a/src/network_management/common_parameter_group_numbers.rs b/src/datalink_network_network_management_3_4_5/common_parameter_group_numbers.rs similarity index 100% rename from src/network_management/common_parameter_group_numbers.rs rename to src/datalink_network_network_management_3_4_5/common_parameter_group_numbers.rs diff --git a/src/network_management/control_function.rs b/src/datalink_network_network_management_3_4_5/control_function.rs similarity index 90% rename from src/network_management/control_function.rs rename to src/datalink_network_network_management_3_4_5/control_function.rs index d4f55ce..071c6dc 100644 --- a/src/network_management/control_function.rs +++ b/src/datalink_network_network_management_3_4_5/control_function.rs @@ -1,7 +1,7 @@ // Copyright 2023 Raven Industries inc. -use crate::driver::Address; -use crate::network_management::name::DEFAULT_NAME; -use crate::network_management::name::NAME; +use crate::datalink_network_network_management_3_4_5::Address; +use crate::datalink_network_network_management_3_4_5::name::DEFAULT_NAME; +use crate::datalink_network_network_management_3_4_5::name::NAME; use rand::Rng; use std::cell::RefCell; use std::rc::Rc; @@ -74,15 +74,15 @@ impl ControlFunction { } impl AddressClaimingState { - pub(super) fn new() -> Self { + pub(crate) fn new() -> Self { Self::None } - pub(super) fn update_state_none(_claim_to_process: &AddressClaimingData) -> Self { + pub(crate) fn update_state_none(_claim_to_process: &AddressClaimingData) -> Self { AddressClaimingState::WaitForClaim } - pub(super) fn update_state_wait_for_claim(claim_to_process: &AddressClaimingData) -> Self { + pub(crate) fn update_state_wait_for_claim(claim_to_process: &AddressClaimingData) -> Self { if Instant::now().duration_since(claim_to_process.get_timestamp().unwrap()) > Duration::from_millis(claim_to_process.get_random_delay() as u64) { @@ -92,7 +92,7 @@ impl AddressClaimingState { } } - pub(super) fn update_state_send_request_for_claim(network: &mut NetworkManager) -> Self { + pub(crate) fn update_state_send_request_for_claim(network: &mut NetworkManager) -> Self { network.enqueue_can_message( NetworkManager::construct_request_for_address_claim(), MessageQueuePriority::High, @@ -100,7 +100,7 @@ impl AddressClaimingState { AddressClaimingState::WaitForRequestContentionPeriod } - pub(super) fn update_state_wait_for_request_contention( + pub(crate) fn update_state_wait_for_request_contention( claim_to_process: &AddressClaimingData, network: &mut NetworkManager, ) -> Self { @@ -150,7 +150,7 @@ impl AddressClaimingState { } } - pub(super) fn update_state_send_preferred_address_claim( + pub(crate) fn update_state_send_preferred_address_claim( claim_to_process: &AddressClaimingData, network: &mut NetworkManager, ) -> Self { @@ -164,7 +164,7 @@ impl AddressClaimingState { AddressClaimingState::AddressClaimingComplete } - pub(super) fn update_state_send_arbitrary_address_claim( + pub(crate) fn update_state_send_arbitrary_address_claim( claim_to_process: &AddressClaimingData, network: &mut NetworkManager, ) -> Self { @@ -217,7 +217,7 @@ impl AddressClaimingData { self.preferred_address } - pub(super) fn set_preferred_address(&mut self, new_address: Address) { + pub(crate) fn set_preferred_address(&mut self, new_address: Address) { self.preferred_address = new_address; } @@ -225,7 +225,7 @@ impl AddressClaimingData { self.state } - pub(super) fn set_state(&mut self, new_state: AddressClaimingState) { + pub(crate) fn set_state(&mut self, new_state: AddressClaimingState) { self.state = new_state; } @@ -244,15 +244,15 @@ impl AddressClaimingData { self.timestamp } - pub(super) fn set_timestamp(&mut self, new_timestamp: Option) { + pub(crate) fn set_timestamp(&mut self, new_timestamp: Option) { self.timestamp = new_timestamp; } - pub(super) fn get_random_delay(&self) -> u8 { + pub(crate) fn get_random_delay(&self) -> u8 { self.random_delay } - pub(super) fn generate_random_delay() -> u8 { + pub(crate) fn generate_random_delay() -> u8 { let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); (rng.gen_range(0..255) as f32 * 0.6_f32) as u8 } diff --git a/src/driver/frame.rs b/src/datalink_network_network_management_3_4_5/frame.rs similarity index 90% rename from src/driver/frame.rs rename to src/datalink_network_network_management_3_4_5/frame.rs index 6a4744b..4389a60 100644 --- a/src/driver/frame.rs +++ b/src/datalink_network_network_management_3_4_5/frame.rs @@ -1,5 +1,5 @@ // Copyright 2023 Raven Industries inc. -use crate::driver::CanId; +use crate::datalink_network_network_management_3_4_5::CanId; #[derive(Debug, Default)] #[repr(transparent)] diff --git a/src/datalink_network_network_management_3_4_5/mod.rs b/src/datalink_network_network_management_3_4_5/mod.rs new file mode 100644 index 0000000..e68fd57 --- /dev/null +++ b/src/datalink_network_network_management_3_4_5/mod.rs @@ -0,0 +1,29 @@ +// Copyright 2023 Raven Industries inc. + +//! Data link layer ISO11783-3 +//! Network layer ISO11783-4 +//! Network management ISO11783-5 +//! +//! This module defines: +//! 1. An abstract `Driver` trait for different CAN drivers to implement +//! 2. `Frame`, `Pgn`, `Address`, et al types + +/*Data link layer ISO11783-3*/ +mod address; +mod can_id; +mod frame; +mod pgn; + +/*ISO11783-*/ + +pub mod can_message; +pub mod common_parameter_group_numbers; +pub mod control_function; +pub mod name; +pub mod network_manager; + + +pub use address::Address; +pub use can_id::{CanId, Priority, Type}; +pub use frame::{Channel, Frame}; +pub use pgn::Pgn; diff --git a/src/network_management/name.rs b/src/datalink_network_network_management_3_4_5/name.rs similarity index 100% rename from src/network_management/name.rs rename to src/datalink_network_network_management_3_4_5/name.rs diff --git a/src/network_management/network_manager.rs b/src/datalink_network_network_management_3_4_5/network_manager.rs similarity index 95% rename from src/network_management/network_manager.rs rename to src/datalink_network_network_management_3_4_5/network_manager.rs index 8976d0a..0f8c055 100644 --- a/src/network_management/network_manager.rs +++ b/src/datalink_network_network_management_3_4_5/network_manager.rs @@ -2,16 +2,18 @@ use std::time::Instant; use super::control_function::{AddressClaimingState, ControlFunction}; -use crate::driver::{Address, CanId, Pgn, Priority}; -use crate::network_management::can_message::CANMessage; -use crate::network_management::common_parameter_group_numbers::CommonParameterGroupNumbers; -use crate::network_management::name::{DEFAULT_NAME, NAME}; +use crate::datalink_network_network_management_3_4_5::{Address, CanId, Pgn, Priority}; +use crate::datalink_network_network_management_3_4_5::can_message::CANMessage; +use crate::datalink_network_network_management_3_4_5::common_parameter_group_numbers:: { + CommonParameterGroupNumbers +}; +use crate::datalink_network_network_management_3_4_5::name::{DEFAULT_NAME, NAME}; use std::cell::RefCell; use std::collections::VecDeque; use std::rc::Rc; #[derive(Debug, Clone, Copy)] -pub(super) enum MessageQueuePriority { +pub(crate) enum MessageQueuePriority { /// High priority messages are always sent to the driver before normal ones High, /// Normal messages are sent to the driver when no high priority messages are in the queue (todo) @@ -65,7 +67,7 @@ impl NetworkManager { Address::NULL } - pub(super) fn on_new_internal_control_function( + pub(crate) fn on_new_internal_control_function( &mut self, new_cf: Rc>, ) { @@ -73,7 +75,7 @@ impl NetworkManager { self.address_claim_state_machines.push(new_cf); } - pub(super) fn get_next_free_arbitrary_address(&self) -> Address { + pub(crate) fn get_next_free_arbitrary_address(&self) -> Address { for address in 129..247 { let is_device_at_address = self.get_control_function_by_address(Address(address)); let is_valid_device: bool = is_device_at_address.is_some(); @@ -98,7 +100,7 @@ impl NetworkManager { Address::NULL } - pub(super) fn construct_address_claim(source_address: Address, name: NAME) -> CANMessage { + pub(crate) fn construct_address_claim(source_address: Address, name: NAME) -> CANMessage { let address_claim = name.raw_name.to_le_bytes().to_vec(); let request_id = CanId::try_encode( @@ -110,7 +112,7 @@ impl NetworkManager { CANMessage::new(address_claim, request_id.unwrap()) } - pub(super) fn construct_request_for_address_claim() -> CANMessage { + pub(crate) fn construct_request_for_address_claim() -> CANMessage { let pgn_to_request: u32 = CommonParameterGroupNumbers::AddressClaim as u32; let request = pgn_to_request.to_le_bytes().to_vec(); let request_id = CanId::try_encode( @@ -122,7 +124,7 @@ impl NetworkManager { CANMessage::new(request, request_id.unwrap()) } - pub(super) fn enqueue_can_message( + pub(crate) fn enqueue_can_message( &mut self, message: CANMessage, queue_priority: MessageQueuePriority, diff --git a/src/driver/pgn.rs b/src/datalink_network_network_management_3_4_5/pgn.rs similarity index 100% rename from src/driver/pgn.rs rename to src/datalink_network_network_management_3_4_5/pgn.rs diff --git a/src/diagnostics_service_12/mod.rs b/src/diagnostics_service_12/mod.rs new file mode 100644 index 0000000..b18e3a1 --- /dev/null +++ b/src/diagnostics_service_12/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! Diagnostics services ISO11783-12 \ No newline at end of file diff --git a/src/driver/driver.rs b/src/driver_implementation/driver.rs similarity index 98% rename from src/driver/driver.rs rename to src/driver_implementation/driver.rs index fa7d0dc..37303f0 100644 --- a/src/driver/driver.rs +++ b/src/driver_implementation/driver.rs @@ -1,5 +1,5 @@ // Copyright 2023 Raven Industries inc. -use crate::driver::Frame; +use crate::datalink_network_network_management_3_4_5::Frame; #[derive(Debug)] #[non_exhaustive] diff --git a/src/driver/mod.rs b/src/driver_implementation/mod.rs similarity index 61% rename from src/driver/mod.rs rename to src/driver_implementation/mod.rs index 0e39c02..e1d601a 100644 --- a/src/driver/mod.rs +++ b/src/driver_implementation/mod.rs @@ -1,25 +1,17 @@ // Copyright 2023 Raven Industries inc. -//! CAN Driver layer -//! + +//! Driver implementation for different interfaces //! This module defines: //! 1. An abstract `Driver` trait for different CAN drivers to implement -//! 2. `Frame`, `Pgn`, `Address`, et al types -mod address; -mod can_id; + mod driver; -mod frame; -mod pgn; #[cfg(feature = "socketcan")] mod socketcan; -pub use address::Address; -pub use can_id::{CanId, Priority, Type}; pub use driver::{Driver, DriverCloseError, DriverOpenError, DriverReadError, DriverWriteError}; -pub use frame::{Channel, Frame}; -pub use pgn::Pgn; #[cfg(feature = "socketcan")] pub use self::socketcan::SocketcanDriver; diff --git a/src/driver/socketcan.rs b/src/driver_implementation/socketcan.rs similarity index 96% rename from src/driver/socketcan.rs rename to src/driver_implementation/socketcan.rs index 09b0e35..a88ce3d 100644 --- a/src/driver/socketcan.rs +++ b/src/driver_implementation/socketcan.rs @@ -4,8 +4,17 @@ use std::time::Instant; use socketcan::frame::{CanDataFrame, CanFrame, Frame}; use socketcan::{CanSocket, EmbeddedFrame, ExtendedId, Id, Socket, StandardId}; -use crate::driver::{ - CanId, Channel, Driver, DriverCloseError, DriverOpenError, DriverReadError, DriverWriteError, +use crate::driver_implementation::{ + Driver, + DriverCloseError, + DriverOpenError, + DriverReadError, + DriverWriteError +}; + +use crate::datalink_network_network_management_3_4_5::{ + CanId, + Channel, Frame as InternalFrame, Type, }; diff --git a/src/file_server_client_13/mod.rs b/src/file_server_client_13/mod.rs new file mode 100644 index 0000000..f8dec8f --- /dev/null +++ b/src/file_server_client_13/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! File server ISO11783-13 \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 2b835fb..61461b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,5 +3,14 @@ #![allow(clippy::needless_return)] #![allow(clippy::module_inception)] -pub mod driver; -pub mod network_management; +pub mod common; +pub mod driver_implementation; + +pub mod datalink_network_network_management_3_4_5; +pub mod virtual_terminal_client_6; +pub mod application_messages_7; +pub mod tractor_ecu_9; +pub mod task_controller_client_10; +pub mod diagnostics_service_12; +pub mod file_server_client_13; +pub mod sequence_controller_client_14; diff --git a/src/network_management/mod.rs b/src/network_management/mod.rs deleted file mode 100644 index 99d372c..0000000 --- a/src/network_management/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2023 Raven Industries inc. -pub mod can_message; -pub mod common_parameter_group_numbers; -pub mod control_function; -pub mod name; -pub mod network_manager; diff --git a/src/sequence_controller_client_14/mod.rs b/src/sequence_controller_client_14/mod.rs new file mode 100644 index 0000000..5710960 --- /dev/null +++ b/src/sequence_controller_client_14/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! Sequence control ISO11783-14 \ No newline at end of file diff --git a/src/task_controller_client_10/mod.rs b/src/task_controller_client_10/mod.rs new file mode 100644 index 0000000..0dbef25 --- /dev/null +++ b/src/task_controller_client_10/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! Task controller and management information system data interchange ISO11783-10 \ No newline at end of file diff --git a/src/tractor_ecu_9/mod.rs b/src/tractor_ecu_9/mod.rs new file mode 100644 index 0000000..bf2ca4d --- /dev/null +++ b/src/tractor_ecu_9/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! Tractor ECU ISO11783-9 \ No newline at end of file diff --git a/src/virtual_terminal_client_6/mod.rs b/src/virtual_terminal_client_6/mod.rs new file mode 100644 index 0000000..dbf68af --- /dev/null +++ b/src/virtual_terminal_client_6/mod.rs @@ -0,0 +1,3 @@ +// Copyright 2023 Raven Industries inc. + +//! Virtual terminal ISO11783-6 \ No newline at end of file