Skip to content

Commit

Permalink
Merge branch 'main' into tjd/object-pool
Browse files Browse the repository at this point in the history
Signed-off-by: Daan Steenbergen <[email protected]>
  • Loading branch information
GwnDaan authored Dec 4, 2023
2 parents 78f6b8a + 44006ea commit 8e9c96a
Show file tree
Hide file tree
Showing 7 changed files with 658 additions and 198 deletions.
21 changes: 5 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,9 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: tarpaulin
args: --release --all-features --out xml

# TODO: Code coverage badge on README (codecov.io?)

- name: PR coverage report comment
uses: 5monkeys/cobertura-action@v13
if: github.event_name == 'pull_request'
args: --release --all-features --engine llvm --out xml

- name: Upload to codecov.io
uses: codecov/codecov-action@v2
with:
path: 'cobertura.xml'
repo_token: ${{ secrets.GITHUB_TOKEN }}
only_changed_files: true
show_line: true
show_branch: true
skip_covered: false
# If we want to enforce a minimum coverage percentage, this is how.
minimum_coverage: 0
fail_below_threshold: false
fail_ci_if_error: true
2 changes: 1 addition & 1 deletion src/driver/can_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ mod tests {
Address(0x0F),
Priority::Six,
);
assert!(matches!(encode_result.is_err(), true));
assert!(encode_result.is_err());

let error_contents: EncodingError = encode_result.unwrap_err();
assert_eq!(error_contents.priority, Priority::Six);
Expand Down
37 changes: 37 additions & 0 deletions src/network_management/can_message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2023 Raven Industries inc.
use super::name::NAME;
use crate::driver::CanId;

pub struct CANMessage {
data: Vec<u8>,
identifier: CanId,
source_name: NAME,
destination_name: NAME,
}

impl CANMessage {
pub(super) fn new(data: Vec<u8>, identifier: CanId) -> CANMessage {
CANMessage {
data,
identifier,
source_name: NAME::default(),
destination_name: NAME::default(),
}
}

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
}
}
182 changes: 163 additions & 19 deletions src/network_management/control_function.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// Copyright 2023 Raven Industries inc.
#![allow(dead_code)]

use crate::driver::Address;
use crate::network_management::name::NAME;
use rand::Rng;
use std::time::Instant;
use std::cell::RefCell;
use std::rc::Rc;
use std::time::{Duration, Instant};

use super::network_manager::{MessageQueuePriority, NetworkManager};

#[derive(PartialEq, Eq, Clone, Copy)]
pub enum AddressClaimingState {
Expand Down Expand Up @@ -31,26 +34,164 @@ pub enum AddressClaimingState {

pub struct AddressClaimingData {
state: AddressClaimingState,
name: NAME,
timestamp: Option<Instant>,
preferred_address: u8,
preferred_address: Address,
random_delay: u8,
enabled: bool,
}

pub enum ControlFunction {
Internal {
name: NAME,
address_claim_data: AddressClaimingData,
},
External {
name: NAME,
},
}

impl ControlFunction {
pub fn new_internal_control_function(
name: NAME,
preferred_address: Address,
enabled: bool,
network: &mut NetworkManager,
) -> Rc<RefCell<Self>> {
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
}

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 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.into(),
ControlFunction::Internal {
address_claim_data: _,
} => claim_to_process.get_name().into(),
};

if (!claim_to_process.get_name().get_self_configurable_address()
&& preferred_address_name > claim_to_process.get_name().into())
|| <NAME as Into<u64>>::into(NAME::default()) == 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().into() {
// 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
}
}

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(preferred_address: u8, enabled: bool) -> AddressClaimingData {
pub fn new(name: NAME, preferred_address: Address, enabled: bool) -> AddressClaimingData {
AddressClaimingData {
state: AddressClaimingState::None,
name,
timestamp: None,
preferred_address,
random_delay: AddressClaimingData::generate_random_delay(),
Expand All @@ -71,10 +212,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
}
Expand All @@ -83,6 +228,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 != new_name {
self.state = AddressClaimingState::None; // Name changed, state no longer valid
}
self.name = new_name;
}

pub fn get_timestamp(&self) -> Option<Instant> {
self.timestamp
}
Expand All @@ -100,15 +256,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,
timestamp: None,
preferred_address: 0xFE_u8,
random_delay: AddressClaimingData::generate_random_delay(),
enabled: true,
}
}
}
2 changes: 2 additions & 0 deletions src/network_management/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Loading

0 comments on commit 8e9c96a

Please sign in to comment.