micodus_server/src/parser/header.rs
2024-12-31 10:56:23 +01:00

96 lines
2.6 KiB
Rust

use bcd_convert::BcdNumber;
use rand::prelude::*;
#[allow(dead_code)]
const PROPS_SIZE_MASK: u16 = 0x01FF;
#[allow(dead_code)]
const PROPS_SUBCONTRACT_MASK: u16 = 0x3000;
#[allow(dead_code)]
const PROPS_RESERVED_MASK: u16 = 0xC000;
#[allow(dead_code)]
const PROPS_DATAENCRYPTION_MASK: u16 = 0x0E00;
#[derive(Default, Debug)]
pub struct MessageHeader {
id: u16,
properties: u16,
pub bodylength: u8,
encryption: u8,
encrypted: bool,
subcontract: bool,
reserved: u16,
raw_terminal_id: [u8; 6],
pub terminal_id: u64,
pub serial_number: u16,
}
impl MessageHeader {
pub fn build(&mut self, id: u16, properties: usize, raw_terminal_id: [u8; 6]) {
let mut rng = rand::thread_rng();
self.id = id;
self.properties = properties as u16;
self.raw_terminal_id = raw_terminal_id;
self.serial_number = rng.gen();
}
pub fn get_id(&mut self) -> u16 {
self.id
}
pub fn set_id(&mut self, id: u16) {
self.id = id;
}
pub fn set_properties(&mut self, properties: u16) {
self.properties = properties;
}
pub fn parse_properties(&mut self) {
self.bodylength = (self.properties & PROPS_SIZE_MASK) as u8;
self.encryption = ((self.properties & PROPS_DATAENCRYPTION_MASK) as u16 >> 10) as u8;
self.encrypted = self.encryption != 0;
self.subcontract = ((self.properties & PROPS_SUBCONTRACT_MASK) as u16 >> 13) == 1;
self.reserved = ((self.properties & PROPS_RESERVED_MASK) as u16 >> 14) as u16;
}
pub fn set_raw_terminal_id(&mut self, rtid: [u8; 6]) {
self.raw_terminal_id = rtid;
}
pub fn get_raw_terminal_id(&self) -> [u8; 6] {
self.raw_terminal_id
}
pub fn parse_terminal_id(&mut self) {
let code = BcdNumber::try_from(&self.raw_terminal_id as &[u8]).unwrap();
self.terminal_id = code.to_u64().unwrap();
}
pub fn to_raw(&self) -> Vec<u8> {
let mut r: Vec<u8> = vec![];
for b in self.id.to_be_bytes() {
r.push(b);
}
for b in self.properties.to_be_bytes() {
r.push(b);
}
for b in self.raw_terminal_id.into_iter() {
r.push(b);
}
for b in self.serial_number.to_be_bytes() {
r.push(b);
}
r
}
}
impl std::fmt::Display for MessageHeader {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"message header: id: {:X?}, length: {}, terminal id: {}, serial: {:X?}",
self.id, self.bodylength, self.terminal_id, self.serial_number
)
}
}