update micodus_server
This commit is contained in:
parent
97b2783672
commit
99b779c5f7
73
src/main.rs
73
src/main.rs
@ -1,10 +1,14 @@
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::RwLock;
|
||||
pub mod parser;
|
||||
|
||||
const FLAG: u8 = 0x7e;
|
||||
pub use crate::parser::*;
|
||||
|
||||
use std::io;
|
||||
//use std::sync::Arc;
|
||||
|
||||
use tokio::net::TcpListener;
|
||||
//use tokio::sync::RwLock;
|
||||
|
||||
const ADDR: &'static str = "0.0.0.0:7700";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@ -15,8 +19,7 @@ async fn main() {
|
||||
}
|
||||
|
||||
pub async fn apiserver() -> io::Result<()> {
|
||||
let addr = "0.0.0.0:7700";
|
||||
let listener = match TcpListener::bind(addr).await {
|
||||
let listener = match TcpListener::bind(ADDR).await {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
println!("error: {e}");
|
||||
@ -27,7 +30,7 @@ pub async fn apiserver() -> io::Result<()> {
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((mut socket, _addr)) => {
|
||||
Ok((socket, _remote_addr)) => {
|
||||
let mut buf = vec![0; 256];
|
||||
|
||||
match socket.readable().await {
|
||||
@ -46,8 +49,8 @@ pub async fn apiserver() -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let data = buf.to_vec();
|
||||
let msg = parse_msg(data);
|
||||
let mut rawdata = buf.to_vec();
|
||||
let msg = parse_inbound_msg(&mut rawdata);
|
||||
println!("{:X?}", msg);
|
||||
}
|
||||
Err(err) => {
|
||||
@ -58,51 +61,3 @@ pub async fn apiserver() -> io::Result<()> {
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_msg(data: Vec<u8>) -> Message {
|
||||
if data[0] == FLAG {
|
||||
println!("first flag ok");
|
||||
};
|
||||
|
||||
let mut msg: Message = Message::default();
|
||||
|
||||
msg.Header.Id = msg.Header.Id + (data[1] << 1) as u16 + data[2] as u16;
|
||||
msg.Header.Properties = msg.Header.Properties + (data[3] << 1) as u16 + data[4] as u16;
|
||||
for (i, v) in data[5..11].iter().enumerate() {
|
||||
msg.Header.TerminalId[i] = *v;
|
||||
}
|
||||
msg.Header.SerialNumber = msg.Header.SerialNumber + (data[11] << 1) as u16 + data[12] as u16;
|
||||
|
||||
let endbody = 13 + msg.Header.Properties as usize;
|
||||
let range: std::ops::Range<usize> = 13..(endbody);
|
||||
let check_idx = 13 + msg.Header.Properties as usize;
|
||||
let endflag: u8 = check_idx as u8 + 1;
|
||||
|
||||
for i in data[range].iter() {
|
||||
msg.Body.push(*i);
|
||||
}
|
||||
|
||||
msg.Check = data[check_idx];
|
||||
|
||||
if data[endflag as usize] == FLAG {
|
||||
println!("end flag ok");
|
||||
} else {
|
||||
println!("error with endflag");
|
||||
}
|
||||
msg
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Message {
|
||||
pub Header: MessageHeader,
|
||||
pub Body: Vec<u8>,
|
||||
pub Check: u8,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct MessageHeader {
|
||||
pub Id: u16,
|
||||
pub Properties: u16,
|
||||
pub TerminalId: [u8; 6],
|
||||
pub SerialNumber: u16,
|
||||
}
|
||||
|
113
src/parser/body.rs
Normal file
113
src/parser/body.rs
Normal file
@ -0,0 +1,113 @@
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalUniversalResponse {
|
||||
pub answer_serial_no: u16,
|
||||
pub answer_id: u16,
|
||||
pub result: u8,
|
||||
}
|
||||
|
||||
impl BodyMessage for TerminalUniversalResponse {}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct PlatformUniversalResponse {
|
||||
pub answer_serial_no: u16,
|
||||
pub answer_id: u16,
|
||||
pub result: u8,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalHeartbeat {}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalRegistration {
|
||||
pub provincial_id: u16,
|
||||
pub city_and_prefecture_id: u16,
|
||||
pub manufacturer_id: [u8; 5],
|
||||
pub terminal_models: [u8; 8],
|
||||
pub terminal_id: [u8; 7],
|
||||
pub license_plate_color: u8,
|
||||
pub license_plate: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalRegistrationReply {
|
||||
pub answer_serial_no: u16,
|
||||
pub result: u8,
|
||||
pub authentication_code: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalLogout {}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalAuthentication {
|
||||
pub authentication_code: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalParameterSetting {
|
||||
pub total_parameters: u8,
|
||||
pub parameters: Vec<TerminalParameterData>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalParameterData {
|
||||
pub parameter_id: u32,
|
||||
pub parameter_length: u8,
|
||||
pub parameter_value: u8,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct QueryTerminalParameter {}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct QueryTerminalParameterResponse {
|
||||
pub response_serial_no: u16,
|
||||
pub response_parameter_quantity: u16,
|
||||
pub parameters: Vec<TerminalParameterData>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TerminalControl {
|
||||
pub command_word: u8,
|
||||
pub command_parameter: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct LocationInformationReport {
|
||||
pub alert_mark: u32,
|
||||
pub status: u32,
|
||||
pub latitude: u32,
|
||||
pub longitude: u32,
|
||||
pub height: u32,
|
||||
pub speed: u32,
|
||||
pub direction: u32,
|
||||
pub time: u32,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct StartOfTrip {}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct EndOfTrip {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BodyType {
|
||||
TerminalUniversalResponse = 0x0001,
|
||||
PlatformUniversalResponse = 0x8001,
|
||||
TerminalHeartbeat = 0x0002,
|
||||
TerminalRegistration = 0x0100,
|
||||
TerminalRegistrationReply = 0x8100,
|
||||
TerminalLogout = 0x0003,
|
||||
TerminalAuthentication = 0x0102,
|
||||
TerminalParameterSetting = 0x8103,
|
||||
QueryTerminalParameter = 0x8104,
|
||||
QueryTerminalParameterResponse = 0x0104,
|
||||
TerminalControl = 0x8105,
|
||||
LocationInformationReport = 0x0200,
|
||||
StartOfTrip = 0x0202,
|
||||
EndOfTrip = 0x0203,
|
||||
}
|
||||
|
||||
pub trait BodyMessage {
|
||||
fn parse() {}
|
||||
}
|
98
src/parser/mod.rs
Normal file
98
src/parser/mod.rs
Normal file
@ -0,0 +1,98 @@
|
||||
mod body;
|
||||
|
||||
use body::*;
|
||||
|
||||
const FLAGDELIMITER: u8 = 0x7E;
|
||||
|
||||
#[allow(dead_code)]
|
||||
const PropsSizeMask: u16 = 0x01FF;
|
||||
const PropsSubcontractMask: u16 = 0x3000;
|
||||
const PropsReservedMask: u16 = 0xC000;
|
||||
const PropsDataEncryptionMask: u16 = 0x0E00;
|
||||
|
||||
pub fn parse_inbound_msg(rawdata: &mut Vec<u8>) -> Message {
|
||||
let mut msg: Message = Message::default();
|
||||
|
||||
msg.parse_header(rawdata);
|
||||
msg.check(rawdata);
|
||||
|
||||
msg
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Message {
|
||||
pub header: MessageHeader,
|
||||
pub body: Vec<u8>,
|
||||
pub checksum: u8,
|
||||
valid: bool,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn parse_header(&mut self, rawdata: &mut Vec<u8>) {
|
||||
let mut data = rawdata.clone().into_iter();
|
||||
let first_byte = data.next().unwrap();
|
||||
if first_byte == FLAGDELIMITER {
|
||||
println!("first flag ok");
|
||||
};
|
||||
self.header.id = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16;
|
||||
self.header.properties = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16;
|
||||
for i in 0..self.header.terminal_id.len() {
|
||||
self.header.terminal_id[i] = data.next().unwrap();
|
||||
}
|
||||
self.parse_properties();
|
||||
|
||||
self.header.serial_number =
|
||||
((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16;
|
||||
|
||||
for _ in 0..self.header.properties as usize {
|
||||
self.body.push(data.next().unwrap());
|
||||
}
|
||||
|
||||
self.checksum = data.next().unwrap();
|
||||
|
||||
if data.next().unwrap() == FLAGDELIMITER {
|
||||
println!("end flag ok");
|
||||
} else {
|
||||
println!("error with endflag");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_properties(&mut self) {
|
||||
self.header.bodylength = (self.header.properties & PropsSizeMask) as u8;
|
||||
}
|
||||
|
||||
pub fn check(&mut self, rawdata: &mut Vec<u8>) {
|
||||
let mut data = rawdata.into_iter();
|
||||
data.next().unwrap();
|
||||
let mut check: u8 = 0;
|
||||
|
||||
loop {
|
||||
let b = data.next().unwrap();
|
||||
if *b == FLAGDELIMITER {
|
||||
break;
|
||||
}
|
||||
check = *b ^ check;
|
||||
}
|
||||
|
||||
self.validate(check);
|
||||
}
|
||||
|
||||
fn validate(&mut self, check: u8) {
|
||||
println!("{}", BodyType::TerminalHeartbeat as u16);
|
||||
self.valid = check == 0;
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.valid
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct MessageHeader {
|
||||
pub id: u16,
|
||||
properties: u16,
|
||||
pub bodylength: u8,
|
||||
pub encryption: bool,
|
||||
pub terminal_id: [u8; 6],
|
||||
pub serial_number: u16,
|
||||
}
|
Loading…
Reference in New Issue
Block a user