dev/nm17 #2
6 changed files with 34 additions and 27 deletions
|
@ -15,7 +15,7 @@ derive_more = "0.99.17"
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
fred = { version = "6.3.0", features = ["nom"] }
|
fred = { version = "6.3.0", features = ["nom"] }
|
||||||
heapless = { version = "0.7.16", features = ["ufmt-impl"] }
|
heapless = { version = "0.7.16", features = ["ufmt-impl"] }
|
||||||
hex = { version = "0.4.3", default-features = false }
|
hex = { version = "0.4.3", default-features = false, features = ["std", "alloc"] }
|
||||||
hifitime = "3.8.2"
|
hifitime = "3.8.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
nom = { version = "7.1.3", default-features = false, features = ["std", "alloc"] }
|
nom = { version = "7.1.3", default-features = false, features = ["std", "alloc"] }
|
||||||
|
@ -30,4 +30,4 @@ serde_with = { version = "3.6.1", features = ["hex"] }
|
||||||
smallstr = { version = "0.3.0", features = ["std", "union"] }
|
smallstr = { version = "0.3.0", features = ["std", "union"] }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
tokio = { version = "1.28.2", features = ["full"] }
|
tokio = { version = "1.28.2", features = ["full"] }
|
||||||
ufmt = "0.2.0"
|
ufmt = { version = "0.2.0", features = ["std"] }
|
||||||
|
|
|
@ -8,9 +8,8 @@
|
||||||
- Поля
|
- Поля
|
||||||
- Вся информация о девайсе
|
- Вся информация о девайсе
|
||||||
- `devices_{device_id}_{tai_timestamp}_{sensor_id}`
|
- `devices_{device_id}_{tai_timestamp}_{sensor_id}`
|
||||||
- Поля
|
- Только значение
|
||||||
- `value`
|
|
||||||
- `unit`
|
|
||||||
- `devices_{device_id}`
|
- `devices_{device_id}`
|
||||||
- Поля
|
- Поля
|
||||||
- `exists`: bool
|
- `exists`: bool
|
||||||
|
- `unit`: str
|
||||||
|
|
|
@ -13,7 +13,6 @@ use crate::ingest_protocol::parser::parse_mac_address;
|
||||||
use hifitime::Epoch;
|
use hifitime::Epoch;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::formats::Separator;
|
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
|
@ -3,7 +3,6 @@ use nom::bytes::complete::tag;
|
||||||
use nom::bytes::complete::take_until1;
|
use nom::bytes::complete::take_until1;
|
||||||
use nom::bytes::complete::{take, take_while, take_while1};
|
use nom::bytes::complete::{take, take_while, take_while1};
|
||||||
use nom::character::complete::hex_digit1;
|
use nom::character::complete::hex_digit1;
|
||||||
use nom::{Parser};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::ingest_protocol::error::Error;
|
use crate::ingest_protocol::error::Error;
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use fred::prelude::*;
|
use fred::prelude::*;
|
||||||
|
|
||||||
use ntex::http::{StatusCode};
|
use ntex::http::StatusCode;
|
||||||
use ntex::web;
|
use ntex::web;
|
||||||
|
|
||||||
use ntex::web::{HttpRequest, HttpResponse};
|
use ntex::web::{HttpRequest, HttpResponse};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|
||||||
use crate::insert_header;
|
use crate::insert_header;
|
||||||
use crate::web_server::old_device_sensor_api::qs_parser::QSParserError;
|
use crate::web_server::old_device_sensor_api::qs_parser::QSParserError;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
|
@ -51,6 +48,9 @@ pub enum AppError {
|
||||||
json_err: Option<serde_json::Error>,
|
json_err: Option<serde_json::Error>,
|
||||||
query_error: Option<serde_qs::Error>,
|
query_error: Option<serde_qs::Error>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[display(fmt = "IDK")]
|
||||||
|
DeviceNotFound(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl web::error::WebResponseError for AppError {
|
impl web::error::WebResponseError for AppError {
|
||||||
|
@ -64,6 +64,7 @@ impl web::error::WebResponseError for AppError {
|
||||||
AppError::ApiKeyInvalid { .. } => StatusCode::BAD_REQUEST,
|
AppError::ApiKeyInvalid { .. } => StatusCode::BAD_REQUEST,
|
||||||
AppError::UnknownBody { .. } => StatusCode::BAD_REQUEST,
|
AppError::UnknownBody { .. } => StatusCode::BAD_REQUEST,
|
||||||
AppError::QSError(..) => StatusCode::BAD_REQUEST,
|
AppError::QSError(..) => StatusCode::BAD_REQUEST,
|
||||||
|
AppError::DeviceNotFound(..) => StatusCode::BAD_REQUEST
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +80,7 @@ impl web::error::WebResponseError for AppError {
|
||||||
"Can't figure out where and in what encoding the main data is"
|
"Can't figure out where and in what encoding the main data is"
|
||||||
}
|
}
|
||||||
AppError::QSError(..) => "UrlEncoded body or query params are incorrect",
|
AppError::QSError(..) => "UrlEncoded body or query params are incorrect",
|
||||||
|
AppError::DeviceNotFound(..) => "Device not found",
|
||||||
};
|
};
|
||||||
|
|
||||||
let status_code = self.status_code();
|
let status_code = self.status_code();
|
||||||
|
|
|
@ -2,16 +2,17 @@
|
||||||
|
|
||||||
pub mod qs_parser;
|
pub mod qs_parser;
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
use crate::ingest_protocol::{NMDeviceDataPacket, NMJsonPacket};
|
use crate::ingest_protocol::{NMDeviceDataPacket, NMJsonPacket};
|
||||||
use crate::web_server::app_error::AppError;
|
use crate::web_server::app_error::AppError;
|
||||||
|
|
||||||
|
|
||||||
|
use fred::types::RedisMap;
|
||||||
use ntex::http::{HttpMessage, StatusCode};
|
use ntex::http::{HttpMessage, StatusCode};
|
||||||
use ntex::util::{Bytes, HashMap};
|
use ntex::util::{Bytes, HashMap};
|
||||||
use ntex::{http, web};
|
use ntex::{http, web};
|
||||||
use fred::prelude::*;
|
use fred::prelude::*;
|
||||||
use hifitime::Epoch;
|
use hifitime::Epoch;
|
||||||
|
use ntex::web::types::State;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use ufmt::uwrite;
|
use ufmt::uwrite;
|
||||||
use crate::web_server::NMAppState;
|
use crate::web_server::NMAppState;
|
||||||
|
@ -21,10 +22,10 @@ use crate::web_server::old_device_sensor_api::qs_parser::QSParserError;
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("Device not found")]
|
#[error("Device not found")]
|
||||||
DeviceNotFound(String),
|
DeviceNotFound(String),
|
||||||
#[error("Time sent with the device is way to behind now")]
|
#[error("Time sent with the device is way too behind now")]
|
||||||
TimeIsLongBehindNow,
|
TimeIsLongBehindNow,
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
QSParserError(#[from] QSParserError)
|
QSParserError(#[from] QSParserError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ pub enum Error {
|
||||||
pub async fn device_handler<'a>(
|
pub async fn device_handler<'a>(
|
||||||
request: web::HttpRequest,
|
request: web::HttpRequest,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
app_state: &NMAppState,
|
app_state: State<NMAppState>,
|
||||||
) -> Result<web::HttpResponse, AppError> {
|
) -> Result<web::HttpResponse, AppError> {
|
||||||
let mut real_body: Option<NMJsonPacket> = None;
|
let mut real_body: Option<NMJsonPacket> = None;
|
||||||
let mut json_error = None;
|
let mut json_error = None;
|
||||||
|
@ -79,30 +80,36 @@ pub async fn device_handler<'a>(
|
||||||
for device in real_body.devices {
|
for device in real_body.devices {
|
||||||
let mut device_key_str = String::new();
|
let mut device_key_str = String::new();
|
||||||
|
|
||||||
let device_tai_timestamp = device.time
|
let now = Epoch::now().unwrap();
|
||||||
.unwrap_or(Epoch::now().unwrap())
|
let mut device_time = device.time
|
||||||
|
.unwrap_or(now);
|
||||||
|
|
||||||
|
// TODO: Добавить гистерезис
|
||||||
|
// Отчёт совместимости: отсутствует
|
||||||
|
if device_time > now {
|
||||||
|
device_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
let device_tai_timestamp = device_time
|
||||||
.to_duration_since_j1900()
|
.to_duration_since_j1900()
|
||||||
.to_seconds();
|
.to_seconds();
|
||||||
|
|
||||||
uwrite!(&mut device_key_str, "devices_{}", device.mac)?;
|
uwrite!(device_key_str, "devices_{}", hex::encode(device.mac));
|
||||||
|
|
||||||
|
|
||||||
let device_exists: bool = app_state.redis_client.hget(device_key_str.as_str(), "exists").await?;
|
let device_exists: bool = app_state.redis_client.hget(device_key_str.as_str(), "exists").await?;
|
||||||
|
|
||||||
if !device_exists {
|
if !device_exists {
|
||||||
return Err(Error::DeviceNotFound(device.mac))
|
return Err(AppError::DeviceNotFound(hex::encode(&device.mac)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// devices_{device_id}_{tai_timestamp}_{sensor_id}
|
// devices_{device_id}_{tai_timestamp}_{sensor_id}
|
||||||
for sensor in device.values {
|
for sensor in device.values {
|
||||||
let mut device_report_key_str = String::new();
|
let mut device_report_key_str = String::new();
|
||||||
uwrite!(&mut device_report_key_str, "devices_{}_{}_{}", device.mac, device_tai_timestamp, sensor.mac)?;
|
uwrite!(&mut device_report_key_str, "devices_{}_{}_{}", hex::encode(device.mac), device_tai_timestamp.to_string(), sensor.mac);
|
||||||
let mut device_report_key_str = String::new();
|
|
||||||
|
|
||||||
|
app_state.redis_client.set(
|
||||||
app_state.redis_client.hset(device_key_str.as_str(), HashMap::from([
|
device_key_str.as_str(), sensor.value.to_string(), None, None, false,
|
||||||
// TODO
|
).await?;
|
||||||
])).await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -112,5 +119,6 @@ pub async fn device_handler<'a>(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(web::HttpResponse::build(StatusCode::OK).finish())
|
Ok(web::HttpResponseBuilder::new(StatusCode::OK)
|
||||||
|
.finish())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue