#![allow(unused_variables)] mod body; mod error; mod header; use body::*; use error::*; use header::*; use super::db::*; use std::collections::VecDeque; const FLAG_DELIMITER: u8 = 0x7E; const FLAG_DELIMITER_ESCAPE: u8 = 0x7D; pub fn parse_inbound_msg( rawdata: &mut InboundDataWrapper, ) -> std::result::Result { let mut msg: Message = Message::default(); if rawdata.first_byte() != FLAG_DELIMITER { return Err(MessageError::NotOurProtocolError); } match msg.parse_header(rawdata) { Ok(_) => { msg.inbound_check(rawdata); } Err(e) => { println!("error parsing header {e}"); return Err(MessageError::BasicError); } }; Ok(msg) } #[derive(Default, Debug)] pub struct InboundDataWrapper { pub data: VecDeque, pub index: usize, pub started: bool, #[allow(dead_code)] pub ended: bool, pub escaped: Option, } impl InboundDataWrapper { pub fn new(data: Vec) -> InboundDataWrapper { InboundDataWrapper { data: data.into(), index: 0, started: false, ended: false, escaped: None, } } fn first_byte(&self) -> u8 { self.data[0] } } impl Iterator for InboundDataWrapper { type Item = u8; fn next(&mut self) -> Option { let mut res: Option = None; match self.escaped { Some(o) => return Some(o), None => {} } loop { match self.data.pop_front() { Some(o) => { if self.started { match o { FLAG_DELIMITER_ESCAPE => match self.data.pop_front() { Some(o) => match o { 0x02 => res = Some(FLAG_DELIMITER), 0x01 => res = Some(FLAG_DELIMITER_ESCAPE), _ => { self.escaped = Some(o); } }, None => res = None, }, FLAG_DELIMITER => { res = None; } _ => { res = Some(o); } } } if o == FLAG_DELIMITER && self.index == 0 { self.started = true; continue; } } None => { res = None; } }; break; } self.index += 1; res } } #[derive(Default, Debug)] pub struct Message { pub header: MessageHeader, pub content: MessageType, pub body: Vec, pub checksum: u8, valid: bool, } impl Message { #[allow(dead_code)] pub fn new() -> Self { let msg = Self::default(); return msg; } fn parse_header( &mut self, rawdata: &mut InboundDataWrapper, ) -> std::result::Result<(), NotOurProtocolError> { let data = rawdata.into_iter(); self.header.set_id(u16::from_be_bytes( vec![data.next().unwrap(), data.next().unwrap()] .try_into() .unwrap(), )); self.header.set_properties(u16::from_be_bytes( vec![data.next().unwrap(), data.next().unwrap()] .try_into() .unwrap(), )); self.header.parse_properties(); let mut rtid: [u8; 6] = [0; 6]; for i in 0..rtid.len() { rtid[i] = data.next().unwrap(); } self.header.set_raw_terminal_id(rtid); self.header.parse_terminal_id(); self.header.serial_number = u16::from_be_bytes( vec![data.next().unwrap(), data.next().unwrap()] .try_into() .unwrap(), ); for _ in 0..self.header.bodylength as usize { self.body.push(data.next().unwrap()); } self.checksum = data.next().unwrap(); self.parse_body(); Ok(()) } pub fn inbound_check(&mut self, rawdata: &mut InboundDataWrapper) { let data = rawdata.into_iter(); let mut check: u8 = 0; let _ = data.map(|b| check ^= b); self.inbound_validate(check); } fn inbound_validate(&mut self, check: u8) { self.valid = check == 0; } fn _is_valid(&self) -> bool { self.valid } fn parse_body(&mut self) { match self.header.get_id() { TerminalUniversalResponse::ID => { let obj = TerminalUniversalResponse::new(&self.body); self.content = MessageType::TerminalUniversalResponse(obj) } PlatformUniversalResponse::ID => { let obj = PlatformUniversalResponse::new(&self.body); self.content = MessageType::PlatformUniversalResponse(obj) } TerminalHeartbeat::ID => { let obj = TerminalHeartbeat::new(&self.body); self.content = MessageType::TerminalHeartbeat(obj) } TerminalRegistration::ID => { let obj = TerminalRegistration::new(&self.body); self.content = MessageType::TerminalRegistration(obj) } TerminalRegistrationReply::ID => { let obj = TerminalRegistrationReply::new(&self.body); self.content = MessageType::TerminalRegistrationReply(obj) } TerminalLogout::ID => { let obj = TerminalLogout::new(&self.body); self.content = MessageType::TerminalLogout(obj) } TerminalAuthentication::ID => { let obj = TerminalAuthentication::new(&self.body); self.content = MessageType::TerminalAuthentication(obj) } TerminalParameterSetting::ID => { let obj = TerminalParameterSetting::new(&self.body); self.content = MessageType::TerminalParameterSetting(obj) } QueryTerminalParameter::ID => { let obj = QueryTerminalParameter::new(&self.body); self.content = MessageType::QueryTerminalParameter(obj) } QueryTerminalParameterResponse::ID => { let obj = QueryTerminalParameterResponse::new(&self.body); self.content = MessageType::QueryTerminalParameterResponse(obj) } TerminalControl::ID => { let obj = TerminalControl::new(&self.body); self.content = MessageType::TerminalControl(obj) } LocationInformationReport::ID => { let obj = LocationInformationReport::new(&self.body); self.content = MessageType::LocationInformationReport(obj) } StartOfTrip::ID => { let obj = StartOfTrip::new(&self.body); self.content = MessageType::StartOfTrip(obj) } EndOfTrip::ID => { let obj = EndOfTrip::new(&self.body); self.content = MessageType::EndOfTrip(obj) } _ => { let obj = TerminalUniversalResponse::new(&self.body); self.content = MessageType::TerminalUniversalResponse(obj) } } } pub fn send_reply(inmsg: Option) -> Option { let mut reply: Message = Message::default(); match inmsg { Some(inmsg) => { let terminal_id = inmsg.header.get_raw_terminal_id().clone(); match inmsg.content { MessageType::TerminalRegistration(t) => { let content = t.generate_reply(terminal_id.into(), inmsg.header.serial_number); reply.header.build( TerminalRegistrationReply::ID, content.to_raw().len(), terminal_id, ); reply.content = MessageType::TerminalRegistrationReply(content); } MessageType::TerminalAuthentication(t) => { let content = t .generate_reply(TerminalAuthentication::ID, inmsg.header.serial_number); reply.header.build( PlatformUniversalResponse::ID, content.to_raw().len(), terminal_id, ); reply.content = MessageType::PlatformUniversalResponse(content); } MessageType::LocationInformationReport(t) => { let content = t.generate_reply( LocationInformationReport::ID, inmsg.header.serial_number, ); reply.header.build( PlatformUniversalResponse::ID, content.to_raw().len(), terminal_id, ); reply.content = MessageType::PlatformUniversalResponse(content); } MessageType::TerminalHeartbeat(t) => { let content = t.generate_reply(TerminalHeartbeat::ID, inmsg.header.serial_number); reply.header.build( PlatformUniversalResponse::ID, content.to_raw().len(), terminal_id, ); reply.content = MessageType::PlatformUniversalResponse(content); } MessageType::TerminalLogout(t) => { let content = t.generate_reply(TerminalHeartbeat::ID, inmsg.header.serial_number); reply.header.build( PlatformUniversalResponse::ID, content.to_raw().len(), terminal_id, ); reply.content = MessageType::PlatformUniversalResponse(content); } _ => { println!("no type"); return None; } } } None => {} } reply.outbound_finalize(); Some(reply) } pub fn store(inmsg: &Message) -> Option { let res = match inmsg.content { MessageType::LocationInformationReport(ref t) => Some(DbLog { serial: inmsg.header.serial_number, time: t.time.format("%Y-%m-%d %H:%M:%S").to_string(), latitude: t.latitude, longitude: t.longitude, speed: t.speed, height: t.height, direction: t.direction, is_satellite: t.is_satellite(), }), _ => None, }; res } pub fn outbound_finalize(&mut self) { let mut checksum: u8 = 0; for v in vec![self.header.to_raw(), self.content.to_raw()] { for b in v { checksum = checksum ^ b; } } self.checksum = checksum; self.valid = true; } pub fn to_raw(&self) -> VecDeque { let mut resp: VecDeque = VecDeque::new(); for b in self.header.to_raw() { for i in Self::escape_outbound(b) { resp.push_back(i); } } for b in self.content.to_raw() { for i in Self::escape_outbound(b) { resp.push_back(i); } } resp.push_back(self.checksum); resp.push_front(FLAG_DELIMITER); resp.push_back(FLAG_DELIMITER); resp } fn escape_outbound(in_data: u8) -> Vec { let mut res: Vec = Vec::new(); match in_data { FLAG_DELIMITER => res = vec![FLAG_DELIMITER_ESCAPE, 0x02], FLAG_DELIMITER_ESCAPE => res = vec![FLAG_DELIMITER_ESCAPE, 0x01], _ => { res.push(in_data); } } res } } impl std::fmt::Display for Message { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, "Message: (header: {}), (content: {}), checksum: {}, valid: {}", self.header, self.content, self.checksum, self.valid ) } } #[allow(dead_code)] #[derive(Debug, Clone)] pub enum MessageType { None, TerminalUniversalResponse(TerminalUniversalResponse), PlatformUniversalResponse(PlatformUniversalResponse), TerminalHeartbeat(TerminalHeartbeat), TerminalRegistration(TerminalRegistration), TerminalRegistrationReply(TerminalRegistrationReply), TerminalLogout(TerminalLogout), TerminalAuthentication(TerminalAuthentication), TerminalParameterSetting(TerminalParameterSetting), QueryTerminalParameter(QueryTerminalParameter), QueryTerminalParameterResponse(QueryTerminalParameterResponse), TerminalControl(TerminalControl), LocationInformationReport(LocationInformationReport), StartOfTrip(StartOfTrip), EndOfTrip(EndOfTrip), } impl Default for MessageType { fn default() -> Self { Self::None } } impl BodyMessage for MessageType { fn to_raw(&self) -> Vec { let res = match self { MessageType::TerminalRegistrationReply(o) => o.to_raw(), MessageType::PlatformUniversalResponse(o) => o.to_raw(), //MessageType::TerminalHeartbeat(o) => o.to_raw(), _ => vec![], }; res } } impl std::fmt::Display for MessageType { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let res = match self { MessageType::TerminalRegistration(o) => o.fmt(f), MessageType::LocationInformationReport(o) => o.fmt(f), MessageType::TerminalHeartbeat(o) => o.fmt(f), MessageType::TerminalAuthentication(o) => o.fmt(f), _ => write!(f, "{:?}", self), }; res } } /* { use std::fs::OpenOptions; use std::io::prelude::*; let mut file = OpenOptions::new() .write(true) .append(true) .open("data/log.txt") .unwrap(); //if let Err(e) = writeln!(file, ) { // eprintln!("Couldn't write to file: {}", e); //} file.write(format!("{},{},{}\n", t.time, t.latitude, t.longitude).as_bytes()) .unwrap(); } */