use crate::protocol::address::{Address, IndividualAddress};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TelegramType {
GroupValueRead,
GroupValueResponse,
GroupValueWrite,
}
impl std::fmt::Display for TelegramType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::GroupValueRead => write!(f, "GroupValueRead"),
Self::GroupValueResponse => write!(f, "GroupValueResponse"),
Self::GroupValueWrite => write!(f, "GroupValueWrite"),
}
}
}
#[derive(Debug, Clone)]
pub struct Telegram {
pub source: IndividualAddress,
pub destination: Address,
pub payload: Vec<u8>,
pub priority: Priority,
pub direction: Direction,
pub telegram_type: TelegramType,
pub gateway_id: Option<u16>,
pub timestamp: std::time::SystemTime,
}
impl Telegram {
#[must_use]
pub fn new_outgoing(source: IndividualAddress, destination: Address, payload: Vec<u8>) -> Self {
let telegram_type = if payload.is_empty() {
TelegramType::GroupValueRead
} else {
TelegramType::GroupValueWrite
};
Self {
source,
destination,
payload,
priority: Priority::Normal,
direction: Direction::Outgoing,
telegram_type,
gateway_id: None,
timestamp: std::time::SystemTime::now(),
}
}
#[must_use]
pub fn new_incoming(source: IndividualAddress, destination: Address, payload: Vec<u8>) -> Self {
Self {
source,
destination,
payload,
priority: Priority::Normal,
direction: Direction::Incoming,
telegram_type: TelegramType::GroupValueWrite,
gateway_id: None,
timestamp: std::time::SystemTime::now(),
}
}
#[must_use]
pub fn is_group_telegram(&self) -> bool {
matches!(self.destination, Address::Group(_))
}
#[must_use]
pub fn is_individual_telegram(&self) -> bool {
matches!(self.destination, Address::Individual(_))
}
#[must_use]
pub fn payload_len(&self) -> usize {
self.payload.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.payload.is_empty()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Priority {
System = 0,
#[default]
Normal = 1,
Urgent = 2,
Low = 3,
}
impl PartialOrd for Priority {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Priority {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let self_priority = match self {
Priority::System => 0,
Priority::Urgent => 1,
Priority::Normal => 2,
Priority::Low => 3,
};
let other_priority = match other {
Priority::System => 0,
Priority::Urgent => 1,
Priority::Normal => 2,
Priority::Low => 3,
};
self_priority.cmp(&other_priority)
}
}
impl Priority {
#[must_use]
pub fn from_u8(value: u8) -> Self {
match value & 0x03 {
0 => Priority::System,
2 => Priority::Urgent,
3 => Priority::Low,
_ => Priority::Normal,
}
}
#[must_use]
pub fn to_u8(self) -> u8 {
self as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
Incoming,
Outgoing,
}
impl std::fmt::Display for Direction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Direction::Incoming => write!(f, "incoming"),
Direction::Outgoing => write!(f, "outgoing"),
}
}
}