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 { let mut r: Vec = 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 ) } }