pub mod store;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub use store::DataStore;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DataType {
pub data: HashMap<String, serde_json::Value>,
pub address: String,
pub timestamp: i64,
pub name: String,
}
impl DataType {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64, name: String) -> Self {
Self {
data,
address,
timestamp,
name,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64, name: String) -> Self {
Self::new(data, address, timestamp.round() as i64, name)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BatteryLevelData {
#[serde(flatten)]
pub base: DataType,
pub level: i32,
}
impl BatteryLevelData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let level = data.get("level")
.and_then(|v| v.as_i64())
.unwrap_or(0) as i32;
Self {
base: DataType::new(data, address, timestamp, "battery_level".to_string()),
level,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct HeartRateData {
#[serde(flatten)]
pub base: DataType,
pub rate: i32,
}
impl HeartRateData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let rate = data.get("rate")
.and_then(|v| v.as_i64())
.unwrap_or(0) as i32;
Self {
base: DataType::new(data, address, timestamp, "heart_rate".to_string()),
rate,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct TemperatureData {
#[serde(flatten)]
pub base: DataType,
pub level: f64,
}
impl TemperatureData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let level = data.get("level")
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
Self {
base: DataType::new(data, address, timestamp, "temperature".to_string()),
level,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PressureData {
#[serde(flatten)]
pub base: DataType,
pub level: f64,
}
impl PressureData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let level = data.get("level")
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
Self {
base: DataType::new(data, address, timestamp, "pressure".to_string()),
level,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BloodPressureData {
#[serde(flatten)]
pub base: DataType,
pub sys: i32,
pub dias: i32,
}
impl BloodPressureData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let sys = data.get("sys")
.and_then(|v| v.as_i64())
.unwrap_or(0) as i32;
let dias = data.get("dias")
.and_then(|v| v.as_i64())
.unwrap_or(0) as i32;
Self {
base: DataType::new(data, address, timestamp, "blood_pressure".to_string()),
sys,
dias,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct HumidityData {
#[serde(flatten)]
pub base: DataType,
pub level: f64,
}
impl HumidityData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let level = data.get("level")
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
Self {
base: DataType::new(data, address, timestamp, "humidity".to_string()),
level,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AlertData {
#[serde(flatten)]
pub base: DataType,
pub id: String,
}
impl AlertData {
pub fn new(data: HashMap<String, serde_json::Value>, address: String, timestamp: i64) -> Self {
let id = data.get("id")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
Self {
base: DataType::new(data, address, timestamp, "alert".to_string()),
id,
}
}
pub fn from_timestamp_f64(data: HashMap<String, serde_json::Value>, address: String, timestamp: f64) -> Self {
Self::new(data, address, timestamp.round() as i64)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
pub enum IoTData {
#[serde(rename = "battery_level")]
BatteryLevel(BatteryLevelData),
#[serde(rename = "heart_rate")]
HeartRate(HeartRateData),
#[serde(rename = "temperature")]
Temperature(TemperatureData),
#[serde(rename = "pressure")]
Pressure(PressureData),
#[serde(rename = "blood_pressure")]
BloodPressure(BloodPressureData),
#[serde(rename = "humidity")]
Humidity(HumidityData),
#[serde(rename = "alert")]
Alert(AlertData),
#[serde(rename = "generic")]
Generic(DataType),
}
impl IoTData {
pub fn address(&self) -> &str {
match self {
IoTData::BatteryLevel(d) => &d.base.address,
IoTData::HeartRate(d) => &d.base.address,
IoTData::Temperature(d) => &d.base.address,
IoTData::Pressure(d) => &d.base.address,
IoTData::BloodPressure(d) => &d.base.address,
IoTData::Humidity(d) => &d.base.address,
IoTData::Alert(d) => &d.base.address,
IoTData::Generic(d) => &d.address,
}
}
pub fn timestamp(&self) -> i64 {
match self {
IoTData::BatteryLevel(d) => d.base.timestamp,
IoTData::HeartRate(d) => d.base.timestamp,
IoTData::Temperature(d) => d.base.timestamp,
IoTData::Pressure(d) => d.base.timestamp,
IoTData::BloodPressure(d) => d.base.timestamp,
IoTData::Humidity(d) => d.base.timestamp,
IoTData::Alert(d) => d.base.timestamp,
IoTData::Generic(d) => d.timestamp,
}
}
pub fn name(&self) -> &str {
match self {
IoTData::BatteryLevel(d) => &d.base.name,
IoTData::HeartRate(d) => &d.base.name,
IoTData::Temperature(d) => &d.base.name,
IoTData::Pressure(d) => &d.base.name,
IoTData::BloodPressure(d) => &d.base.name,
IoTData::Humidity(d) => &d.base.name,
IoTData::Alert(d) => &d.base.name,
IoTData::Generic(d) => &d.name,
}
}
}