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;
|
pub mod parser;
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::io::AsyncWriteExt;
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@ -15,8 +19,7 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn apiserver() -> io::Result<()> {
|
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,
|
Ok(o) => o,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("error: {e}");
|
println!("error: {e}");
|
||||||
@ -27,7 +30,7 @@ pub async fn apiserver() -> io::Result<()> {
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
match listener.accept().await {
|
match listener.accept().await {
|
||||||
Ok((mut socket, _addr)) => {
|
Ok((socket, _remote_addr)) => {
|
||||||
let mut buf = vec![0; 256];
|
let mut buf = vec![0; 256];
|
||||||
|
|
||||||
match socket.readable().await {
|
match socket.readable().await {
|
||||||
@ -46,8 +49,8 @@ pub async fn apiserver() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = buf.to_vec();
|
let mut rawdata = buf.to_vec();
|
||||||
let msg = parse_msg(data);
|
let msg = parse_inbound_msg(&mut rawdata);
|
||||||
println!("{:X?}", msg);
|
println!("{:X?}", msg);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -58,51 +61,3 @@ pub async fn apiserver() -> io::Result<()> {
|
|||||||
});
|
});
|
||||||
Ok(())
|
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