use std::str::from_utf8; use chrono::Local; use crate::{command::RequestSerializer, security::Security}; pub struct PacketBuilder { command: S, packet: [u8; 40], } impl PacketBuilder { pub fn builder(device_id: u64, command: S) -> Self { #[rustfmt::skip] let mut packet = [ // 2 bytes - StaicHeader 0x5a, 0x5a, // 2 bytes - mMessageType 0x01, 0x11, // 2 bytes - PacketLenght 0x00, 0x00, // 2 bytes 0x20, 0x00, // 4 bytes - MessageId 0x00, 0x00, 0x00, 0x00, // 8 bytes - Date&Time 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 6 bytes - mDeviceID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12 bytes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; packet[12..20].copy_from_slice(&Self::packet_time()); packet[20..28].copy_from_slice(&device_id.to_le_bytes()[0..8]); Self { command, packet } } fn packet_time() -> [u8; 8] { let mut t = Local::now() .format("%Y%m%d%H%M%S%f") .to_string() .as_bytes() .to_vec(); t.truncate(16); let mut b = [0; 8]; for (index, chars) in t.chunks(2).enumerate() { b[7 - index] = from_utf8(chars).unwrap().parse().unwrap(); } b } pub fn finalize(self, msg_type: u8) -> Vec { let mut packet = self.packet.to_vec(); if msg_type != 1 { packet[3] = 0x10; packet[6] = 0x7b; } else { packet.extend(Security::aes_encrypt(&self.command.serialize())); } // packet length packet[4..6].copy_from_slice(&(self.packet.len() as u16 + 16).to_le_bytes()); // append a basic checksum data (16 bytes) to the packet packet.extend(Security::encode32_data(&self.packet)); packet } } #[cfg(test)] mod test { use std::str::from_utf8; #[test] fn packet_time() { let t = b"2023092913400641"; let b_ref = b")\x06(\r\x1d\t\x17\x14"; let mut b = [0; 8]; for (index, chars) in t.chunks(2).enumerate() { b[7 - index] = from_utf8(chars).unwrap().parse().unwrap(); } assert_eq!(&b, b_ref); } }