From e367930505ee304abc42c352fbb256ee3be53271 Mon Sep 17 00:00:00 2001 From: nm17 Date: Wed, 6 Mar 2024 23:14:29 +0400 Subject: [PATCH] feat(old_device_sensor_api): initial work --- docs/kv_db_arch.md | 3 + src/web_server/app_error.rs | 2 +- src/web_server/mod.rs | 4 +- src/web_server/old_device_sensor_api/mod.rs | 105 ++++++++++++++++++ .../qs_parser.rs} | 69 +----------- 5 files changed, 116 insertions(+), 67 deletions(-) create mode 100644 src/web_server/old_device_sensor_api/mod.rs rename src/web_server/{old_devices_api/mod.rs => old_device_sensor_api/qs_parser.rs} (61%) diff --git a/docs/kv_db_arch.md b/docs/kv_db_arch.md index c468b02..0f35c79 100644 --- a/docs/kv_db_arch.md +++ b/docs/kv_db_arch.md @@ -11,3 +11,6 @@ - Поля - `value` - `unit` + - `devices_{device_id}` + - Поля + - `exists`: bool diff --git a/src/web_server/app_error.rs b/src/web_server/app_error.rs index 1ff7276..5195244 100644 --- a/src/web_server/app_error.rs +++ b/src/web_server/app_error.rs @@ -12,7 +12,7 @@ use thiserror::Error; use crate::insert_header; -use crate::web_server::old_devices_api::QSParserError; +use crate::web_server::old_device_sensor_api::QSParserError; use rust_decimal::Decimal; use serde_json::json; diff --git a/src/web_server/mod.rs b/src/web_server/mod.rs index e6a12d5..bcc3d93 100644 --- a/src/web_server/mod.rs +++ b/src/web_server/mod.rs @@ -6,7 +6,7 @@ use fred::prelude::*; pub(crate) mod app_error; pub mod old_app_api; -mod old_devices_api; +mod old_device_sensor_api; pub mod utils; #[derive(Clone)] @@ -14,7 +14,7 @@ pub struct NMAppState { pub redis_client: RedisClient, } -use crate::web_server::old_devices_api::device_handler; +use crate::web_server::old_device_sensor_api::device_handler; use ntex::web; diff --git a/src/web_server/old_device_sensor_api/mod.rs b/src/web_server/old_device_sensor_api/mod.rs new file mode 100644 index 0000000..e0bb540 --- /dev/null +++ b/src/web_server/old_device_sensor_api/mod.rs @@ -0,0 +1,105 @@ +mod qs_parser; + +use std::str::FromStr; +use crate::ingest_protocol::{NMDeviceDataPacket, NMJsonPacket}; +use crate::web_server::app_error::AppError; + + +use ntex::http::{HttpMessage, StatusCode}; +use ntex::util::{Bytes, HashMap}; +use ntex::{http, web}; +use fred::prelude::*; +use hifitime::Epoch; +use thiserror::Error; +use ufmt::uwrite; +use crate::web_server::NMAppState; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Device not found")] + DeviceNotFound(String), + #[error("Time sent with the device is way to behind now")] + TimeIsLongBehindNow, +} + + +pub async fn device_handler<'a>( + request: web::HttpRequest, + body: Bytes, + app_state: &NMAppState, +) -> Result { + let mut real_body: Option = None; + let mut json_error = None; + let mut query_error = None; + + dbg!(&request.content_type()); + dbg!(&request.query_string()); + + if request.method() == http::Method::POST { + match request.content_type() { + "application/json" => match serde_json::from_slice::(body.as_ref()) { + Ok(json_body) => real_body = Some(json_body), + Err(error) => json_error = Some(error), + }, + "application/x-www-form-urlencoded" => { + match serde_qs::from_bytes::(body.as_ref()) { + Ok(qs_body) => { + real_body = Some(NMJsonPacket { + devices: Vec::from([qs_body]), + }) + } + Err(error) => query_error = Some(error), + } + } + _ => {} + } + } else if request.method() == http::Method::GET { + match serde_qs::from_str::(request.query_string()) { + Ok(qs_body) => { + real_body = Some(NMJsonPacket { + devices: Vec::from([qs_body]), + }) + } + Err(error) => query_error = Some(error), + } + } + + if let Some(real_body) = real_body { + for device in real_body.devices { + let mut device_key_str = String::new(); + + let device_tai_timestamp = device.time + .unwrap_or(Epoch::now().unwrap()) + .to_duration_since_j1900() + .to_seconds(); + + uwrite!(&mut device_key_str, "devices_{}", device.mac)?; + + + let device_exists: bool = app_state.redis_client.hget(device_key_str.as_str(), "exists").await?; + + if !device_exists { + return Err(Error::DeviceNotFound(device.mac)) + } + + // devices_{device_id}_{tai_timestamp}_{sensor_id} + for sensor in device.values { + let mut device_report_key_str = String::new(); + uwrite!(&mut device_report_key_str, "devices_{}_{}_{}", device.mac, device_tai_timestamp, sensor.mac)?; + let mut device_report_key_str = String::new(); + + + app_state.redis_client.hset(device_key_str.as_str(), HashMap::from([ + // TODO + ])).await?; + } + } + } else { + return Err(AppError::UnknownBody { + json_err: json_error, + query_error, + }); + } + + Ok(web::HttpResponse::build(StatusCode::OK).finish()) +} diff --git a/src/web_server/old_devices_api/mod.rs b/src/web_server/old_device_sensor_api/qs_parser.rs similarity index 61% rename from src/web_server/old_devices_api/mod.rs rename to src/web_server/old_device_sensor_api/qs_parser.rs index 1410e13..d517356 100644 --- a/src/web_server/old_devices_api/mod.rs +++ b/src/web_server/old_device_sensor_api/qs_parser.rs @@ -1,21 +1,14 @@ use std::collections::HashSet; use std::num::ParseFloatError; use std::str::FromStr; -use crate::ingest_protocol::error::Error; -use crate::ingest_protocol::parser::parse_mac_address; -use crate::ingest_protocol::{NMDeviceDataPacket, NMJsonPacket, SensorValue}; -use crate::web_server::app_error::AppError; - - -use ntex::http::{HttpMessage, StatusCode}; -use ntex::util::{Bytes, HashMap}; -use ntex::{http, web}; use std::sync::Arc; -use fred::bytes_utils::Str; -use hifitime::efmt::consts::ISO8601; use hifitime::Epoch; +use ntex::util::HashMap; use rust_decimal::Decimal; use thiserror::Error; +use crate::ingest_protocol::error::Error; +use crate::ingest_protocol::{NMDeviceDataPacket, SensorValue}; +use crate::ingest_protocol::parser::parse_mac_address; /// В иделае было бы хорошо сделать всё как у [serde_json::Error], но это слишком большая морока #[derive(Error, Clone, Debug)] @@ -118,56 +111,4 @@ pub async fn parse_nm_qs_format(input: &str) -> Result( - request: web::HttpRequest, - body: Bytes, -) -> Result { - let mut real_body: Option = None; - let mut json_error = None; - let mut query_error = None; - - dbg!(&request.content_type()); - dbg!(&request.query_string()); - - if request.method() == http::Method::POST { - match request.content_type() { - "application/json" => match serde_json::from_slice::(body.as_ref()) { - Ok(json_body) => real_body = Some(json_body), - Err(error) => json_error = Some(error), - }, - "application/x-www-form-urlencoded" => { - match serde_qs::from_bytes::(body.as_ref()) { - Ok(qs_body) => { - real_body = Some(NMJsonPacket { - devices: Vec::from([qs_body]), - }) - } - Err(error) => query_error = Some(error), - } - } - _ => {} - } - } else if request.method() == http::Method::GET { - match serde_qs::from_str::(request.query_string()) { - Ok(qs_body) => { - real_body = Some(NMJsonPacket { - devices: Vec::from([qs_body]), - }) - } - Err(error) => query_error = Some(error), - } - } - - if let Some(_body) = real_body { - // TODO - } else { - return Err(AppError::UnknownBody { - json_err: json_error, - query_error, - }); - } - - Ok(web::HttpResponse::build(StatusCode::OK).finish()) -} +} \ No newline at end of file