add logging in sql db

This commit is contained in:
Paul 2024-12-31 15:13:04 +01:00
parent 268020b28a
commit ac9300a048
8 changed files with 235 additions and 34 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
/data

86
Cargo.lock generated
View File

@ -17,6 +17,18 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -142,6 +154,18 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]] [[package]]
name = "funty" name = "funty"
version = "2.0.0" version = "2.0.0"
@ -165,6 +189,24 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
]
[[package]]
name = "hashlink"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
dependencies = [
"hashbrown",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.61" version = "0.1.61"
@ -210,6 +252,17 @@ version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libsqlite3-sys"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@ -242,6 +295,7 @@ dependencies = [
"encoding_rs", "encoding_rs",
"lazy_static", "lazy_static",
"rand", "rand",
"rusqlite",
"tokio", "tokio",
] ]
@ -318,6 +372,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]]
name = "pkg-config"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.20" version = "0.2.20"
@ -390,6 +450,20 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "rusqlite"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e"
dependencies = [
"bitflags",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"smallvec",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -505,6 +579,18 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"

View File

@ -10,4 +10,5 @@ chrono = { version = "0.4" }
encoding_rs = { version = "0.8" } encoding_rs = { version = "0.8" }
lazy_static = { version = "1.5" } lazy_static = { version = "1.5" }
rand = { version = "0.8" } rand = { version = "0.8" }
rusqlite = { version = "0.32.0", features = ["bundled"] }
tokio = { version = "1.42", features = ["full", "sync"] } tokio = { version = "1.42", features = ["full", "sync"] }

42
src/db.rs Normal file
View File

@ -0,0 +1,42 @@
use rusqlite::*;
const DBPATH: &'static str = "data/tracker.db";
const STATEMENTS: [&str; 2] = [
"CREATE TABLE log (id integer primary key autoincrement, time text, latitude float, longitude float);",
"CREATE INDEX idx_time on log (time);",];
const QUERY_INSERT: &'static str =
"INSERT INTO log (time, latitude, longitude) values (:time, :latitude, :longitude)";
pub fn connectdb() -> Result<Connection> {
let conn = Connection::open(DBPATH)?;
Ok(conn)
}
pub fn initdb(conn: &Connection) -> Result<()> {
create_tables(&conn)?;
set_pragmas(&conn)?;
Ok(())
}
fn create_tables(conn: &Connection) -> Result<()> {
for s in STATEMENTS {
match conn.execute(s, params![]) {
Ok(_) => {}
Err(err) => println!("update failed: {}", err),
}
}
Ok(())
}
fn set_pragmas(conn: &Connection) -> Result<()> {
conn.pragma_update(Some(DatabaseName::Main), "journal_mode", "WAL")?;
Ok(())
}
pub fn insert(conn: &Connection, time: &String, latitude: &f64, longitude: &f64) -> Result<()> {
match conn.execute(QUERY_INSERT, params![time, latitude, longitude]) {
Ok(inserted) => println!("{} rows were inserted", inserted),
Err(err) => println!("insert failed: {}", err),
}
Ok(())
}

View File

@ -1,5 +1,7 @@
mod db;
mod parser; mod parser;
use crate::db::*;
use crate::parser::*; use crate::parser::*;
use std::io; use std::io;
@ -11,9 +13,21 @@ const BUFSIZE: usize = 1024;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
//test();
let conn = connectdb().unwrap();
initdb(&conn).unwrap();
apiserver().await.unwrap(); apiserver().await.unwrap();
} }
#[allow(dead_code)]
fn test() {
use bcd_convert::BcdNumber;
let data: Vec<u8> = vec![0x36, 0x31, 0x33, 0x32, 0x31, 0x31, 0x38];
let code = BcdNumber::try_from(&data as &[u8]).unwrap();
println!("{code}");
std::process::exit(0);
}
async fn apiserver() -> io::Result<()> { async fn apiserver() -> io::Result<()> {
let listener = match TcpListener::bind(ADDR).await { let listener = match TcpListener::bind(ADDR).await {
Ok(o) => o, Ok(o) => o,

View File

@ -4,7 +4,6 @@ use chrono::prelude::*;
use encoding_rs::*; use encoding_rs::*;
#[allow(dead_code)] #[allow(dead_code)]
pub trait BodyMessage { pub trait BodyMessage {
fn build(&self) {} fn build(&self) {}
@ -23,6 +22,7 @@ pub trait BodyMessage {
fn parse(&mut self, rawbody: &Vec<u8>) {} fn parse(&mut self, rawbody: &Vec<u8>) {}
} }
#[allow(dead_code)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct TerminalUniversalResponse { pub struct TerminalUniversalResponse {
pub answer_serial_no: u16, pub answer_serial_no: u16,
@ -30,12 +30,14 @@ pub struct TerminalUniversalResponse {
pub result: u8, pub result: u8,
} }
#[allow(dead_code)]
impl TerminalUniversalResponse { impl TerminalUniversalResponse {
pub const ID: u16 = 0x0001; pub const ID: u16 = 0x0001;
pub fn debug() {} pub fn debug() {}
} }
#[allow(dead_code)]
impl BodyMessage for TerminalUniversalResponse { impl BodyMessage for TerminalUniversalResponse {
fn parse(&mut self, rawbody: &Vec<u8>) {} fn parse(&mut self, rawbody: &Vec<u8>) {}
} }
@ -44,7 +46,7 @@ impl BodyMessage for TerminalUniversalResponse {
pub struct PlatformUniversalResponse { pub struct PlatformUniversalResponse {
pub answer_serial_no: u16, pub answer_serial_no: u16,
pub answer_id: u16, pub answer_id: u16,
pub result: u8, pub result: PlatformUniversalResponseResult,
} }
impl PlatformUniversalResponse { impl PlatformUniversalResponse {
@ -62,11 +64,27 @@ impl BodyMessage for PlatformUniversalResponse {
for b in self.answer_id.to_be_bytes() { for b in self.answer_id.to_be_bytes() {
res.push(b); res.push(b);
} }
res.push(self.result); res.push(self.result.clone() as u8);
res 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)] #[derive(Default, Debug, Clone)]
pub struct TerminalHeartbeat {} pub struct TerminalHeartbeat {}
@ -79,7 +97,7 @@ impl TerminalHeartbeat {
let mut res = PlatformUniversalResponse::default(); let mut res = PlatformUniversalResponse::default();
res.answer_serial_no = serial; res.answer_serial_no = serial;
res.answer_id = answer_id; res.answer_id = answer_id;
res.result = TerminalRegistrationResult::Success as u8; res.result = PlatformUniversalResponseResult::Success;
res res
} }
} }
@ -108,9 +126,7 @@ impl TerminalRegistration {
let mut res = TerminalRegistrationReply::default(); let mut res = TerminalRegistrationReply::default();
res.answer_serial_no = serial; res.answer_serial_no = serial;
res.result = TerminalRegistrationResult::Success as u8; res.result = TerminalRegistrationResult::Success as u8;
//res.authentication_code = String::from_utf8(terminal_id).unwrap(); res.authentication_code = self.terminal_id.into();
println!("{:?}", terminal_id);
res.authentication_code = vec![0x36, 0x31, 0x33, 0x32, 0x31, 0x31, 0x38];
res res
} }
} }
@ -166,7 +182,7 @@ impl std::fmt::Display for TerminalRegistration {
} }
#[allow(dead_code)] #[allow(dead_code)]
enum TerminalRegistrationResult { pub enum TerminalRegistrationResult {
Success = 0x00, Success = 0x00,
VehicleRegistered, VehicleRegistered,
VehicleNotInDatabase, VehicleNotInDatabase,
@ -212,7 +228,7 @@ impl TerminalLogout {
let mut res = PlatformUniversalResponse::default(); let mut res = PlatformUniversalResponse::default();
res.answer_serial_no = serial; res.answer_serial_no = serial;
res.answer_id = answer_id; res.answer_id = answer_id;
res.result = TerminalRegistrationResult::Success as u8; res.result = PlatformUniversalResponseResult::Success;
res res
} }
} }
@ -239,7 +255,7 @@ impl TerminalAuthentication {
let mut res = PlatformUniversalResponse::default(); let mut res = PlatformUniversalResponse::default();
res.answer_serial_no = serial; res.answer_serial_no = serial;
res.answer_id = answer_id; res.answer_id = answer_id;
res.result = TerminalRegistrationResult::Success as u8; res.result = PlatformUniversalResponseResult::Success;
res res
} }
} }
@ -263,6 +279,7 @@ impl std::fmt::Display for TerminalAuthentication {
} }
} }
#[allow(dead_code)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct TerminalParameterSetting { pub struct TerminalParameterSetting {
pub total_parameters: u8, pub total_parameters: u8,
@ -277,6 +294,7 @@ impl BodyMessage for TerminalParameterSetting {
fn parse(&mut self, rawbody: &Vec<u8>) {} fn parse(&mut self, rawbody: &Vec<u8>) {}
} }
#[allow(dead_code)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct TerminalParameterData { pub struct TerminalParameterData {
pub parameter_id: u32, pub parameter_id: u32,
@ -300,6 +318,7 @@ impl BodyMessage for QueryTerminalParameter {
fn parse(&mut self, rawbody: &Vec<u8>) {} fn parse(&mut self, rawbody: &Vec<u8>) {}
} }
#[allow(dead_code)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct QueryTerminalParameterResponse { pub struct QueryTerminalParameterResponse {
pub response_serial_no: u16, pub response_serial_no: u16,
@ -315,6 +334,7 @@ impl BodyMessage for QueryTerminalParameterResponse {
fn parse(&mut self, rawbody: &Vec<u8>) {} fn parse(&mut self, rawbody: &Vec<u8>) {}
} }
#[allow(dead_code)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct TerminalControl { pub struct TerminalControl {
pub command_word: u8, pub command_word: u8,
@ -343,15 +363,29 @@ pub struct LocationInformationReport {
impl LocationInformationReport { impl LocationInformationReport {
pub const ID: u16 = 0x0200; pub const ID: u16 = 0x0200;
pub const TABLE: &'static str = "LocationInformationReport";
pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse {
let mut res = PlatformUniversalResponse::default(); let mut res = PlatformUniversalResponse::default();
res.answer_serial_no = serial; res.answer_serial_no = serial;
res.answer_id = answer_id; res.answer_id = answer_id;
res.result = TerminalRegistrationResult::Success as u8; res.result = PlatformUniversalResponseResult::Success;
res res
} }
fn parse_time(&mut self, timeslice: [u8; 6]) {
let code = BcdNumber::try_from(&timeslice 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 { fn parse_latitude(&self, latitude: u32) -> f64 {
let mut res = latitude as f64 / 1_000_000.; let mut res = latitude as f64 / 1_000_000.;
if self.status.south { if self.status.south {
@ -434,16 +468,7 @@ impl BodyMessage for LocationInformationReport {
for i in 0..tmptime.len() { for i in 0..tmptime.len() {
tmptime[i] = *bd.next().unwrap(); tmptime[i] = *bd.next().unwrap();
} }
let code = BcdNumber::try_from(&tmptime as &[u8]).unwrap(); self.parse_time(tmptime);
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!("{tmptime:?} {code} {time} {e}");
}
};
res = true; res = true;
() ()
} }

View File

@ -67,20 +67,20 @@ impl MessageHeader {
} }
pub fn to_raw(&self) -> Vec<u8> { pub fn to_raw(&self) -> Vec<u8> {
let mut r: Vec<u8> = vec![]; let mut raw: Vec<u8> = vec![];
for b in self.id.to_be_bytes() { for b in self.id.to_be_bytes() {
r.push(b); raw.push(b);
} }
for b in self.properties.to_be_bytes() { for b in self.properties.to_be_bytes() {
r.push(b); raw.push(b);
} }
for b in self.raw_terminal_id.into_iter() { for b in self.raw_terminal_id.into_iter() {
r.push(b); raw.push(b);
} }
for b in self.serial_number.to_be_bytes() { for b in self.serial_number.to_be_bytes() {
r.push(b); raw.push(b);
} }
r raw
} }
} }
@ -88,7 +88,7 @@ impl std::fmt::Display for MessageHeader {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!( write!(
f, f,
"message header: id: {:X?}, length: {}, terminal id: {}, serial: {:X?}", "id: {:X?}, length: {}, terminal id: {}, serial: {:X?}",
self.id, self.bodylength, self.terminal_id, self.serial_number self.id, self.bodylength, self.terminal_id, self.serial_number
) )
} }

View File

@ -6,6 +6,8 @@ use body::*;
use error::*; use error::*;
use header::*; use header::*;
use crate::db::*;
use std::collections::VecDeque; use std::collections::VecDeque;
const FLAG_DELIMITER: u8 = 0x7E; const FLAG_DELIMITER: u8 = 0x7E;
@ -65,20 +67,23 @@ impl Iterator for InboundDataWrapper {
match self.data.pop_front() { match self.data.pop_front() {
Some(o) => { Some(o) => {
if self.started { if self.started {
if o == FLAG_DELIMITER { match o {
match self.data.pop_front() { FLAG_DELIMITER_ESCAPE => match self.data.pop_front() {
Some(o) => match o { Some(o) => match o {
0x02 => res = Some(FLAG_DELIMITER), 0x02 => res = Some(FLAG_DELIMITER),
0x01 => res = Some(FLAG_DELIMITER_ESCAPE), 0x01 => res = Some(FLAG_DELIMITER_ESCAPE),
_ => { _ => {
self.escaped = Some(o); self.escaped = Some(o);
self.ended = true;
} }
}, },
None => {} None => res = None,
},
FLAG_DELIMITER => {
res = None;
}
_ => {
res = Some(o);
} }
} else {
res = Some(o);
} }
} }
if o == FLAG_DELIMITER && self.index == 0 { if o == FLAG_DELIMITER && self.index == 0 {
@ -105,6 +110,7 @@ pub struct Message {
pub body: Vec<u8>, pub body: Vec<u8>,
pub checksum: u8, pub checksum: u8,
valid: bool, valid: bool,
pub status: bool,
} }
impl Message { impl Message {
@ -299,6 +305,32 @@ impl Message {
pub fn store(inmsg: &Message) { pub fn store(inmsg: &Message) {
match inmsg.content { match inmsg.content {
MessageType::LocationInformationReport(ref t) => { MessageType::LocationInformationReport(ref t) => {
/*{
use std::fs::OpenOptions;
use std::io::prelude::*;
let mut file = OpenOptions::new()
.write(true)
.append(true)
.open("data/log.txt")
.unwrap();
//if let Err(e) = writeln!(file, ) {
// eprintln!("Couldn't write to file: {}", e);
//}
file.write(format!("{},{},{}\n", t.time, t.latitude, t.longitude).as_bytes())
.unwrap();
}*/
let conn = connectdb().unwrap();
insert(
&conn,
&t.time.format("%Y-%m-%d %H:%M:%S").to_string(),
&t.latitude,
&t.longitude,
)
.unwrap();
println!("{:?}", t); println!("{:?}", t);
} }
_ => {} _ => {}