pub mod client;
pub mod server;
use crate::Node;
use canadensis_core::transport::{Receiver, Transmitter, Transport};
use canadensis_core::SubjectId;
use canadensis_data_types::uavcan::node::id_1_0;
use canadensis_data_types::uavcan::pnp::{
node_id_allocation_data_1_0, node_id_allocation_data_2_0,
};
use canadensis_encoding::{Deserialize, Message, Serialize};
use core::convert::TryFrom;
use crc_any::CRCu64;
pub trait AllocationMessage<T: Transport>: Message + Serialize + Deserialize {
const SUBJECT: SubjectId;
const PAYLOAD_SIZE_MAX: usize;
fn with_unique_id(id: &[u8; 16]) -> Self;
fn matches_unique_id(&self, id: &[u8; 16]) -> bool;
fn node_id(&self) -> Option<T::NodeId>;
fn with_node_id(self, id: T::NodeId) -> Self;
}
impl<T: Transport> AllocationMessage<T> for node_id_allocation_data_1_0::NodeIDAllocationData
where
T::NodeId: Into<u16>,
{
const SUBJECT: SubjectId = node_id_allocation_data_1_0::SUBJECT;
const PAYLOAD_SIZE_MAX: usize = 9;
fn with_unique_id(id: &[u8; 16]) -> Self {
let id_hash = crc_64we_48_bits(id);
Self {
unique_id_hash: id_hash,
allocated_node_id: heapless::Vec::new(),
}
}
fn matches_unique_id(&self, id: &[u8; 16]) -> bool {
let id_hash = crc_64we_48_bits(id);
self.unique_id_hash == id_hash
}
fn node_id(&self) -> Option<T::NodeId> {
self.allocated_node_id.iter().next().and_then(|id| {
T::NodeId::try_from(id.value).ok()
})
}
fn with_node_id(self, id: T::NodeId) -> Self {
Self {
unique_id_hash: self.unique_id_hash,
allocated_node_id: heapless::Vec::from_array([id_1_0::ID { value: id.into() }]),
}
}
}
fn crc_64we_48_bits(id: &[u8; 16]) -> u64 {
let mut crc = CRCu64::crc64we();
crc.digest(id);
let value = crc.get_crc();
value & 0x0000_ffff_ffff_ffff
}
impl<T: Transport> AllocationMessage<T> for node_id_allocation_data_2_0::NodeIDAllocationData
where
T::NodeId: Into<u16>,
{
const SUBJECT: SubjectId = node_id_allocation_data_2_0::SUBJECT;
const PAYLOAD_SIZE_MAX: usize = 18;
fn with_unique_id(id: &[u8; 16]) -> Self {
Self {
unique_id: *id,
node_id: id_1_0::ID { value: 0 },
}
}
fn matches_unique_id(&self, id: &[u8; 16]) -> bool {
self.unique_id == *id
}
fn node_id(&self) -> Option<<T as Transport>::NodeId> {
T::NodeId::try_from(self.node_id.value).ok()
}
fn with_node_id(self, id: T::NodeId) -> Self {
Self {
unique_id: self.unique_id,
node_id: id_1_0::ID { value: id.into() },
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum NewError<N: Node> {
Subscribe(<N::Receiver as Receiver<N::Clock>>::Error),
OutOfMemory,
Duplicate,
Publish(<N::Transmitter as Transmitter<N::Clock>>::Error),
}