#![allow(unused_variables)] use bcd_convert::BcdNumber; use bitvec::prelude::*; use chrono::prelude::*; use encoding_rs::*; #[allow(dead_code)] pub trait BodyMessage { fn build(&self) {} fn body_to_iter<'a>(&'a self, rawbody: &'a Vec) -> std::slice::Iter<'a, u8> { rawbody.into_iter() } fn print(&mut self, rawbody: &Vec) { println!("{:?}", rawbody); } fn to_raw(&self) -> Vec { vec![] } fn parse(&mut self, rawbody: &Vec) {} } #[allow(dead_code)] #[derive(Default, Debug, Clone)] pub struct TerminalUniversalResponse { pub answer_serial_no: u16, pub answer_id: u16, pub result: u8, } #[allow(dead_code)] impl TerminalUniversalResponse { pub const ID: u16 = 0x0001; pub fn debug() {} } #[allow(dead_code)] impl BodyMessage for TerminalUniversalResponse { fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct PlatformUniversalResponse { pub answer_serial_no: u16, pub answer_id: u16, pub result: PlatformUniversalResponseResult, } impl PlatformUniversalResponse { pub const ID: u16 = 0x8001; pub fn parse(&mut self, rawbody: &Vec) {} } impl BodyMessage for PlatformUniversalResponse { fn to_raw(&self) -> Vec { let mut res: Vec = vec![]; for b in self.answer_serial_no.to_be_bytes() { res.push(b); } for b in self.answer_id.to_be_bytes() { res.push(b); } res.push(self.result.clone() as u8); res } } #[allow(dead_code)] #[derive(Debug, Clone)] pub enum PlatformUniversalResponseResult { Success = 0x00, Failed, MessageError, NotSupported, AlertProcessingConfirm, } impl Default for PlatformUniversalResponseResult { fn default() -> Self { PlatformUniversalResponseResult::Success } } #[derive(Default, Debug, Clone)] pub struct TerminalHeartbeat {} impl TerminalHeartbeat { pub const ID: u16 = 0x0002; pub fn parse(&mut self, rawbody: &Vec) {} pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { let mut res = PlatformUniversalResponse::default(); res.answer_serial_no = serial; res.answer_id = answer_id; res.result = PlatformUniversalResponseResult::Success; res } } impl std::fmt::Display for TerminalHeartbeat { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:?}", self) } } #[derive(Default, Debug, Clone)] pub struct TerminalRegistration { pub provincial_id: u16, pub city_and_prefecture_id: u16, pub manufacturer_id: [u8; 5], pub terminal_models: [u8; 20], //8 or 20 bytes pub terminal_id: [u8; 7], pub license_plate_color: u8, pub license_plate: String, } impl TerminalRegistration { pub const ID: u16 = 0x0100; pub fn generate_reply(&self, terminal_id: Vec, serial: u16) -> TerminalRegistrationReply { let mut res = TerminalRegistrationReply::default(); res.answer_serial_no = serial; res.result = TerminalRegistrationResult::Success as u8; res.authentication_code = self.terminal_id.into(); res } } impl BodyMessage for TerminalRegistration { fn parse(&mut self, rawbody: &Vec) { let mut bd = rawbody.into_iter(); //self.body_to_iter(rawbody); self.provincial_id = u16::from_be_bytes( vec![*bd.next().unwrap(), *bd.next().unwrap()] .try_into() .unwrap(), ); self.city_and_prefecture_id = u16::from_be_bytes( vec![*bd.next().unwrap(), *bd.next().unwrap()] .try_into() .unwrap(), ); for i in 0..self.manufacturer_id.len() { self.manufacturer_id[i] = *bd.next().unwrap(); } for i in 0..self.terminal_models.len() { self.terminal_models[i] = *bd.next().unwrap(); } for i in 0..self.terminal_id.len() { self.terminal_id[i] = *bd.next().unwrap(); } self.license_plate_color = *bd.next().unwrap(); let plate_decode: &mut Vec = &mut vec![]; while let Some(i) = bd.next() { plate_decode.push(*i); } let (cow, _encoding_used, _had_errors) = GBK.decode(plate_decode); self.license_plate = cow.into(); } } impl std::fmt::Display for TerminalRegistration { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, "provincial: {}, city/pref: {}, manufacturer: {:?}, model: {:?}, terminal id: {}, license_plate_color: {}, license_plate: {}", self.provincial_id, self.city_and_prefecture_id, self.manufacturer_id, self.terminal_models, String::from_utf8(self.terminal_id.try_into().unwrap()).unwrap(), self.license_plate_color, self.license_plate, ) } } #[allow(dead_code)] pub enum TerminalRegistrationResult { Success = 0x00, VehicleRegistered, VehicleNotInDatabase, TerminalRegistered, VehicleNotInDatabase2, } #[derive(Default, Debug, Clone)] pub struct TerminalRegistrationReply { pub answer_serial_no: u16, pub result: u8, pub authentication_code: Vec, } impl TerminalRegistrationReply { pub const ID: u16 = 0x8100; } impl BodyMessage for TerminalRegistrationReply { fn parse(&mut self, rawbody: &Vec) {} fn to_raw(&self) -> Vec { let mut res: Vec = vec![]; for b in self.answer_serial_no.to_be_bytes() { res.push(b); } res.push(self.result); //for b in self.authentication_code.as_bytes() { for b in self.authentication_code.iter() { res.push(*b); } res } } #[derive(Default, Debug, Clone)] pub struct TerminalLogout {} impl TerminalLogout { pub const ID: u16 = 0x0003; pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { let mut res = PlatformUniversalResponse::default(); res.answer_serial_no = serial; res.answer_id = answer_id; res.result = PlatformUniversalResponseResult::Success; res } } impl BodyMessage for TerminalLogout { fn parse(&mut self, rawbody: &Vec) {} } impl std::fmt::Display for TerminalLogout { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self) } } #[derive(Default, Debug, Clone)] pub struct TerminalAuthentication { pub authentication_code: String, } impl TerminalAuthentication { pub const ID: u16 = 0x0102; pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { let mut res = PlatformUniversalResponse::default(); res.answer_serial_no = serial; res.answer_id = answer_id; res.result = PlatformUniversalResponseResult::Success; res } } impl BodyMessage for TerminalAuthentication { fn parse(&mut self, rawbody: &Vec) { let mut bd = rawbody.into_iter(); let plate_decode: &mut Vec = &mut vec![]; while let Some(i) = bd.next() { plate_decode.push(*i); } let (cow, _encoding_used, _had_errors) = GBK.decode(plate_decode); self.authentication_code = cow.into(); } } impl std::fmt::Display for TerminalAuthentication { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "authentication_code: {}", self.authentication_code,) } } #[allow(dead_code)] #[derive(Default, Debug, Clone)] pub struct TerminalParameterSetting { pub total_parameters: u8, pub parameters: Vec, } impl TerminalParameterSetting { pub const ID: u16 = 0x8103; } impl BodyMessage for TerminalParameterSetting { fn parse(&mut self, rawbody: &Vec) {} } #[allow(dead_code)] #[derive(Default, Debug, Clone)] pub struct TerminalParameterData { pub parameter_id: u32, pub parameter_length: u8, pub parameter_value: u8, } impl TerminalParameterData {} impl BodyMessage for TerminalParameterData { fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct QueryTerminalParameter {} impl QueryTerminalParameter { pub const ID: u16 = 0x8104; } impl BodyMessage for QueryTerminalParameter { fn parse(&mut self, rawbody: &Vec) {} } #[allow(dead_code)] #[derive(Default, Debug, Clone)] pub struct QueryTerminalParameterResponse { pub response_serial_no: u16, pub response_parameter_quantity: u16, pub parameters: Vec, } impl QueryTerminalParameterResponse { pub const ID: u16 = 0x0104; } impl BodyMessage for QueryTerminalParameterResponse { fn parse(&mut self, rawbody: &Vec) {} } #[allow(dead_code)] #[derive(Default, Debug, Clone)] pub struct TerminalControl { pub command_word: u8, pub command_parameter: String, } impl TerminalControl { pub const ID: u16 = 0x8105; } impl BodyMessage for TerminalControl { fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct LocationInformationReport { pub alert_mark: u32, pub status: LocationInformationReportStatus, pub latitude: f64, pub longitude: f64, pub height: u16, pub speed: u16, pub direction: u16, pub time: NaiveDateTime, } impl LocationInformationReport { pub const ID: u16 = 0x0200; //pub const TABLE: &'static str = "LocationInformationReport"; pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { let mut res = PlatformUniversalResponse::default(); res.answer_serial_no = serial; res.answer_id = answer_id; res.result = PlatformUniversalResponseResult::Success; res } fn parse_time(&mut self, timeslice: [u8; 6]) { let code = BcdNumber::try_from(×lice as &[u8]).unwrap(); let time = format!("{}", code.to_u64().unwrap()); match NaiveDateTime::parse_from_str(time.as_str(), "%y%m%d%H%M%S") { Ok(o) => { self.time = o; } Err(e) => { println!("{timeslice:?} {code} {time} {e}"); } }; } fn parse_latitude(&self, latitude: u32) -> f64 { let mut res = latitude as f64 / 1_000_000.; if self.status.south { res = -res }; res } fn parse_longitude(&self, longitude: u32) -> f64 { let mut res = longitude as f64 / 1_000_000.; if self.status.west { res = -res }; res } pub fn is_satellite(&self) -> bool { self.status.gps | self.status.beidou | self.status.glonass } } impl BodyMessage for LocationInformationReport { fn parse(&mut self, rawbody: &Vec) { let res: bool; let mut bd = rawbody.into_iter(); //let z: [u8; 4] = bd.take(4).collect::>().try_into().unwrap(); self.alert_mark = u32::from_be_bytes( vec![ *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), ] .try_into() .unwrap(), ); let status = u32::from_be_bytes( vec![ *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), ] .try_into() .unwrap(), ); self.status = status.into(); self.latitude = self.parse_latitude(u32::from_be_bytes( vec![ *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), ] .try_into() .unwrap(), )); self.longitude = self.parse_longitude(u32::from_be_bytes( vec![ *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), *bd.next().unwrap(), ] .try_into() .unwrap(), )); self.height = u16::from_be_bytes( vec![*bd.next().unwrap(), *bd.next().unwrap()] .try_into() .unwrap(), ); self.speed = u16::from_be_bytes( vec![*bd.next().unwrap(), *bd.next().unwrap()] .try_into() .unwrap(), ); self.direction = u16::from_be_bytes( vec![*bd.next().unwrap(), *bd.next().unwrap()] .try_into() .unwrap(), ); let mut tmptime: [u8; 6] = [0; 6]; for i in 0..tmptime.len() { tmptime[i] = *bd.next().unwrap(); } self.parse_time(tmptime); () } } impl std::fmt::Display for LocationInformationReport { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, "latitude: {}, longitude: {}, direction: {}, speed: {}, time: {}", self.latitude, self.longitude, self.direction, self.speed, self.time ) } } #[derive(Default, Debug, Clone)] pub struct LocationInformationReportStatus { acc: bool, positionning: bool, south: bool, west: bool, stop_running: bool, secret: bool, vehicule_power_loop_disconnected: bool, gps: bool, beidou: bool, glonass: bool, } impl From for LocationInformationReportStatus { fn from(status: u32) -> Self { let mut res = LocationInformationReportStatus::default(); let bits = status.view_bits::(); res.acc = bits[0]; res.positionning = bits[1]; res.south = bits[2]; res.west = bits[3]; res.stop_running = bits[4]; res.secret = bits[5]; res.vehicule_power_loop_disconnected = bits[11]; res.gps = bits[18]; res.beidou = bits[19]; res.glonass = bits[20]; res } } #[derive(Default, Debug, Clone)] pub struct LocationInformationQuery {} impl LocationInformationQuery { pub const ID: u16 = 0x8201; } impl BodyMessage for LocationInformationQuery { fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct LocationInformationQueryResponse {} impl LocationInformationQueryResponse { pub const ID: u16 = 0x0201; } impl BodyMessage for LocationInformationQueryResponse { fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct StartOfTrip {} impl StartOfTrip { pub const ID: u16 = 0x0202; } impl BodyMessage for StartOfTrip { fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct EndOfTrip {} impl EndOfTrip { pub const ID: u16 = 0x0203; } impl BodyMessage for EndOfTrip { fn parse(&mut self, rawbody: &Vec) {} } /* struct BCDTime { pub time: String, } impl BCDTime { pub fn parse() {} } */ macro_rules! generate_impl { ($($t:ty),*) => { $( /*impl BodyMessage for $t { fn build() {} fn body_to_iter<'a>(&'a self, rawbody: &'a Vec) -> std::slice::Iter<'a, u8> { rawbody.into_iter() } }*/ #[allow(unused)] impl $t { pub fn new(rawbody: &Vec) -> Self { let mut res = Self::default(); res.parse(rawbody); res } })* }; } generate_impl!( TerminalUniversalResponse, PlatformUniversalResponse, TerminalHeartbeat, TerminalRegistration, TerminalRegistrationReply, TerminalLogout, TerminalAuthentication, TerminalParameterSetting, TerminalParameterData, QueryTerminalParameter, QueryTerminalParameterResponse, TerminalControl, LocationInformationReport, LocationInformationQuery, LocationInformationQueryResponse, StartOfTrip, EndOfTrip );