611 lines
16 KiB
Rust
611 lines
16 KiB
Rust
#![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<u8>) -> std::slice::Iter<'a, u8> {
|
|
rawbody.into_iter()
|
|
}
|
|
|
|
fn print(&mut self, rawbody: &Vec<u8>) {
|
|
println!("{:?}", rawbody);
|
|
}
|
|
|
|
fn to_raw(&self) -> Vec<u8> {
|
|
vec![]
|
|
}
|
|
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
#[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<u8>) {}
|
|
}
|
|
|
|
#[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<u8>) {}
|
|
}
|
|
|
|
impl BodyMessage for PlatformUniversalResponse {
|
|
fn to_raw(&self) -> Vec<u8> {
|
|
let mut res: Vec<u8> = 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<u8>) {}
|
|
|
|
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<u8>, 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<u8>) {
|
|
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<u8> = &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<u8>,
|
|
}
|
|
|
|
impl TerminalRegistrationReply {
|
|
pub const ID: u16 = 0x8100;
|
|
}
|
|
|
|
impl BodyMessage for TerminalRegistrationReply {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
|
|
fn to_raw(&self) -> Vec<u8> {
|
|
let mut res: Vec<u8> = 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<u8>) {}
|
|
}
|
|
|
|
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<u8>) {
|
|
let mut bd = rawbody.into_iter();
|
|
let plate_decode: &mut Vec<u8> = &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<TerminalParameterData>,
|
|
}
|
|
|
|
impl TerminalParameterSetting {
|
|
pub const ID: u16 = 0x8103;
|
|
}
|
|
|
|
impl BodyMessage for TerminalParameterSetting {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
#[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<u8>) {}
|
|
}
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct QueryTerminalParameter {}
|
|
impl QueryTerminalParameter {
|
|
pub const ID: u16 = 0x8104;
|
|
}
|
|
|
|
impl BodyMessage for QueryTerminalParameter {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct QueryTerminalParameterResponse {
|
|
pub response_serial_no: u16,
|
|
pub response_parameter_quantity: u16,
|
|
pub parameters: Vec<TerminalParameterData>,
|
|
}
|
|
|
|
impl QueryTerminalParameterResponse {
|
|
pub const ID: u16 = 0x0104;
|
|
}
|
|
|
|
impl BodyMessage for QueryTerminalParameterResponse {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
#[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<u8>) {}
|
|
}
|
|
|
|
#[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<u8>) {
|
|
let res: bool;
|
|
let mut bd = rawbody.into_iter();
|
|
//let z: [u8; 4] = bd.take(4).collect::<Vec<&u8>>().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<u32> for LocationInformationReportStatus {
|
|
fn from(status: u32) -> Self {
|
|
let mut res = LocationInformationReportStatus::default();
|
|
let bits = status.view_bits::<Lsb0>();
|
|
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<u8>) {}
|
|
}
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct LocationInformationQueryResponse {}
|
|
impl LocationInformationQueryResponse {
|
|
pub const ID: u16 = 0x0201;
|
|
}
|
|
|
|
impl BodyMessage for LocationInformationQueryResponse {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct StartOfTrip {}
|
|
impl StartOfTrip {
|
|
pub const ID: u16 = 0x0202;
|
|
}
|
|
|
|
impl BodyMessage for StartOfTrip {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct EndOfTrip {}
|
|
impl EndOfTrip {
|
|
pub const ID: u16 = 0x0203;
|
|
}
|
|
|
|
impl BodyMessage for EndOfTrip {
|
|
fn parse(&mut self, rawbody: &Vec<u8>) {}
|
|
}
|
|
|
|
/*
|
|
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<u8>) -> std::slice::Iter<'a, u8> {
|
|
rawbody.into_iter()
|
|
}
|
|
}*/
|
|
#[allow(unused)]
|
|
impl $t {
|
|
pub fn new(rawbody: &Vec<u8>) -> 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
|
|
);
|