updated micodus_server

This commit is contained in:
Paul 2024-12-28 14:09:29 +01:00
parent 83dd157ae1
commit fc074169be
5 changed files with 369 additions and 85 deletions

174
Cargo.lock generated
View File

@ -17,6 +17,21 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "autocfg"
version = "1.4.0"
@ -65,6 +80,12 @@ dependencies = [
"wyz",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byteorder"
version = "1.5.0"
@ -77,12 +98,41 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
[[package]]
name = "cc"
version = "1.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "encoding_rs"
version = "0.8.35"
@ -115,6 +165,39 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "js-sys"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -137,6 +220,12 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
@ -149,6 +238,7 @@ version = "0.1.0"
dependencies = [
"bcd-convert",
"bitvec",
"chrono",
"encoding_rs",
"lazy_static",
"rand",
@ -175,6 +265,15 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "object"
version = "0.36.7"
@ -184,6 +283,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "parking_lot"
version = "0.12.3"
@ -297,6 +402,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
@ -400,6 +511,69 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.52.0"

View File

@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
bcd-convert = { version = "0.1" }
bitvec = { version = "1.0.1" }
chrono = { version = "0.4" }
encoding_rs = { version = "0.8" }
lazy_static = { version = "1.5" }
rand = { version = "0.8" }

View File

@ -73,9 +73,9 @@ pub async fn apiserver() -> io::Result<()> {
pub fn handle(buf: &Vec<u8>) -> Option<Vec<u8>> {
let mut rawdata = InboundDataWrapper::new(buf.to_vec());
let reply = match parse_inbound_msg(&mut rawdata) {
Ok(mut o) => {
Ok(o) => {
println!("query: {}", o);
println!("raw query: {:X?}", o.to_raw());
//println!("raw query: {:X?}", o.to_raw());
Message::store(&o);
Message::set_reply(o)
}
@ -86,9 +86,10 @@ pub fn handle(buf: &Vec<u8>) -> Option<Vec<u8>> {
};
match reply {
Some(mut o) => {
Some(o) => {
println!("reply: {}", o);
println!("raw reply {:X?}", o.to_raw());
//println!("raw reply {:X?}", o.to_raw());
println!("\n");
return Some(o.to_raw().into());
}
None => {

View File

@ -1,33 +1,19 @@
use bcd_convert::BcdNumber;
use bitvec::prelude::*;
use chrono::prelude::*;
use encoding_rs::*;
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()
// }
//}
impl $t {
pub fn new(rawbody: &Vec<u8>) -> Self {
let mut res = Self::default();
res.parse(rawbody);
res
}
})*
};
}
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![]
}
@ -95,6 +81,12 @@ impl TerminalHeartbeat {
}
}
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,
@ -191,6 +183,7 @@ impl TerminalRegistrationReply {
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() {
@ -260,6 +253,12 @@ impl BodyMessage for TerminalAuthentication {
}
}
impl std::fmt::Display for TerminalAuthentication {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "authentication_code: {}", self.authentication_code,)
}
}
#[derive(Default, Debug, Clone)]
pub struct TerminalParameterSetting {
pub total_parameters: u8,
@ -329,13 +328,13 @@ impl BodyMessage for TerminalControl {
#[derive(Default, Debug, Clone)]
pub struct LocationInformationReport {
pub alert_mark: u32,
pub status: u32,
pub latitude: u32,
pub longitude: u32,
pub status: LocationInformationReportStatus,
pub latitude: f64,
pub longitude: f64,
pub height: u16,
pub speed: u16,
pub direction: u16,
pub time: String,
pub time: NaiveDateTime,
}
impl LocationInformationReport {
@ -348,6 +347,22 @@ impl LocationInformationReport {
res.result = TerminalRegistrationResult::Success as u8;
res
}
fn parse_latitude(&self, lat: u32) -> f64 {
let mut res = lat as f64 / 1_000_000f64;
if self.status.south {
res = -res
};
res
}
fn parse_longitude(&self, long: u32) -> f64 {
let mut res = long as f64 / 1_000_000f64;
if self.status.west {
res = -res
};
res
}
}
impl BodyMessage for LocationInformationReport {
@ -363,7 +378,7 @@ impl BodyMessage for LocationInformationReport {
.try_into()
.unwrap(),
);
self.status = u32::from_be_bytes(
let status = u32::from_be_bytes(
vec![
*bd.next().unwrap(),
*bd.next().unwrap(),
@ -373,7 +388,8 @@ impl BodyMessage for LocationInformationReport {
.try_into()
.unwrap(),
);
self.latitude = u32::from_be_bytes(
self.status = status.into();
self.latitude = self.parse_latitude(u32::from_be_bytes(
vec![
*bd.next().unwrap(),
*bd.next().unwrap(),
@ -382,8 +398,8 @@ impl BodyMessage for LocationInformationReport {
]
.try_into()
.unwrap(),
);
self.longitude = u32::from_be_bytes(
));
self.longitude = self.parse_longitude(u32::from_be_bytes(
vec![
*bd.next().unwrap(),
*bd.next().unwrap(),
@ -392,7 +408,7 @@ impl BodyMessage for LocationInformationReport {
]
.try_into()
.unwrap(),
);
));
self.height = u16::from_be_bytes(
vec![*bd.next().unwrap(), *bd.next().unwrap()]
.try_into()
@ -412,8 +428,55 @@ impl BodyMessage for LocationInformationReport {
for i in 0..tmptime.len() {
tmptime[i] = *bd.next().unwrap();
}
println!("{:X?}", rawbody);
println!("{:?}", tmptime);
let code = BcdNumber::try_from(&tmptime as &[u8]).unwrap();
self.time = format!("{}", code.to_u64().unwrap());
println!("{}", code);
let time = format!("{}", code.to_u64().unwrap());
println!("{}", time);
self.time = NaiveDateTime::parse_from_str(time.as_str(), "%y%m%d%H%M%S").unwrap();
}
}
impl std::fmt::Display for LocationInformationReport {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"latitude: {}, longitude: {}, direction: {}, speed: {}",
self.latitude, self.longitude, self.direction, self.speed
)
}
}
#[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
}
}
@ -437,6 +500,7 @@ impl BodyMessage for EndOfTrip {
fn parse(&mut self, rawbody: &Vec<u8>) {}
}
/*
struct BCDTime {
pub time: String,
}
@ -444,6 +508,26 @@ struct BCDTime {
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()
}
}*/
impl $t {
pub fn new(rawbody: &Vec<u8>) -> Self {
let mut res = Self::default();
res.parse(rawbody);
res
}
})*
};
}
generate_impl!(
TerminalUniversalResponse,

View File

@ -8,7 +8,8 @@ use header::*;
use std::collections::VecDeque;
const FLAGDELIMITER: u8 = 0x7E;
const FLAG_DELIMITER: u8 = 0x7E;
const FLAG_DELIMITER_ESCAPE: u8 = 0x7D;
pub fn parse_inbound_msg(
rawdata: &mut InboundDataWrapper,
@ -31,18 +32,20 @@ pub fn parse_inbound_msg(
#[derive(Default, Debug)]
pub struct InboundDataWrapper {
pub data: VecDeque<u8>,
pub count: usize,
pub start: bool,
pub end: bool,
pub index: usize,
pub started: bool,
pub ended: bool,
pub escaped: Option<u8>,
}
impl InboundDataWrapper {
pub fn new(data: Vec<u8>) -> InboundDataWrapper {
InboundDataWrapper {
data: data.into(),
count: 0,
start: false,
end: false,
index: 0,
started: false,
ended: false,
escaped: None,
}
}
}
@ -51,21 +54,34 @@ impl Iterator for InboundDataWrapper {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
let res: Option<u8>;
let mut res: Option<u8> = None;
match self.escaped {
Some(o) => return Some(o),
None => {}
}
loop {
match self.data.pop_front() {
Some(o) => {
if o == FLAGDELIMITER {
if self.start {
self.end = true;
res = None;
break;
if self.started {
if o == FLAG_DELIMITER {
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 => {}
}
} else {
res = Some(o);
}
self.start = true;
}
if o == FLAG_DELIMITER && self.index == 0 {
self.started = true;
continue;
}
res = Some(o);
}
None => {
res = None;
@ -73,7 +89,7 @@ impl Iterator for InboundDataWrapper {
};
break;
}
self.count += 1;
self.index += 1;
res
}
@ -155,63 +171,64 @@ impl Message {
fn parse_body(&mut self) {
match self.header.get_id() {
TerminalUniversalResponse::ID => {
self.content = MessageType::TerminalUniversalResponse(
TerminalUniversalResponse::new(&self.body),
)
let obj = TerminalUniversalResponse::new(&self.body);
self.content = MessageType::TerminalUniversalResponse(obj)
}
PlatformUniversalResponse::ID => {
self.content = MessageType::PlatformUniversalResponse(
PlatformUniversalResponse::new(&self.body),
)
let obj = PlatformUniversalResponse::new(&self.body);
self.content = MessageType::PlatformUniversalResponse(obj)
}
TerminalHeartbeat::ID => {
self.content = MessageType::TerminalHeartbeat(TerminalHeartbeat::new(&self.body))
let obj = TerminalHeartbeat::new(&self.body);
self.content = MessageType::TerminalHeartbeat(obj)
}
TerminalRegistration::ID => {
self.content =
MessageType::TerminalRegistration(TerminalRegistration::new(&self.body))
let obj = TerminalRegistration::new(&self.body);
self.content = MessageType::TerminalRegistration(obj)
}
TerminalRegistrationReply::ID => {
self.content = MessageType::TerminalRegistrationReply(
TerminalRegistrationReply::new(&self.body),
)
let obj = TerminalRegistrationReply::new(&self.body);
self.content = MessageType::TerminalRegistrationReply(obj)
}
TerminalLogout::ID => {
self.content = MessageType::TerminalLogout(TerminalLogout::new(&self.body))
let obj = TerminalLogout::new(&self.body);
self.content = MessageType::TerminalLogout(obj)
}
TerminalAuthentication::ID => {
self.content =
MessageType::TerminalAuthentication(TerminalAuthentication::new(&self.body))
let obj = TerminalAuthentication::new(&self.body);
self.content = MessageType::TerminalAuthentication(obj)
}
TerminalParameterSetting::ID => {
self.content =
MessageType::TerminalParameterSetting(TerminalParameterSetting::new(&self.body))
let obj = TerminalParameterSetting::new(&self.body);
self.content = MessageType::TerminalParameterSetting(obj)
}
QueryTerminalParameter::ID => {
self.content =
MessageType::QueryTerminalParameter(QueryTerminalParameter::new(&self.body))
let obj = QueryTerminalParameter::new(&self.body);
self.content = MessageType::QueryTerminalParameter(obj)
}
QueryTerminalParameterResponse::ID => {
self.content = MessageType::QueryTerminalParameterResponse(
QueryTerminalParameterResponse::new(&self.body),
)
let obj = QueryTerminalParameterResponse::new(&self.body);
self.content = MessageType::QueryTerminalParameterResponse(obj)
}
TerminalControl::ID => {
self.content = MessageType::TerminalControl(TerminalControl::new(&self.body))
let obj = TerminalControl::new(&self.body);
self.content = MessageType::TerminalControl(obj)
}
LocationInformationReport::ID => {
self.content = MessageType::LocationInformationReport(
LocationInformationReport::new(&self.body),
)
let obj = LocationInformationReport::new(&self.body);
self.content = MessageType::LocationInformationReport(obj)
}
StartOfTrip::ID => {
self.content = MessageType::StartOfTrip(StartOfTrip::new(&self.body))
let obj = StartOfTrip::new(&self.body);
self.content = MessageType::StartOfTrip(obj)
}
EndOfTrip::ID => {
let obj = EndOfTrip::new(&self.body);
self.content = MessageType::EndOfTrip(obj)
}
EndOfTrip::ID => self.content = MessageType::EndOfTrip(EndOfTrip::new(&self.body)),
_ => {
self.content = MessageType::TerminalUniversalResponse(
TerminalUniversalResponse::new(&self.body),
)
let obj = TerminalUniversalResponse::new(&self.body);
self.content = MessageType::TerminalUniversalResponse(obj)
}
}
}
@ -297,7 +314,7 @@ impl Message {
self.valid = true;
}
pub fn to_raw(&mut self) -> VecDeque<u8> {
pub fn to_raw(&self) -> VecDeque<u8> {
let mut resp: VecDeque<u8> = vec![].into();
for b in self.header.to_raw() {
@ -310,8 +327,8 @@ impl Message {
resp.push_back(self.checksum);
resp.push_front(FLAGDELIMITER);
resp.push_back(FLAGDELIMITER);
resp.push_front(FLAG_DELIMITER);
resp.push_back(FLAG_DELIMITER);
resp
}
}
@ -320,7 +337,7 @@ impl std::fmt::Display for Message {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"Message: (header: {}), content: {}, checksum: {}, valid: {}",
"Message: (header: {}), (content: {}), checksum: {}, valid: {}",
self.header, self.content, self.checksum, self.valid
)
}
@ -365,6 +382,13 @@ impl BodyMessage for MessageType {
impl std::fmt::Display for MessageType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
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
}
}