48 lines
1.6 KiB
Rust
48 lines
1.6 KiB
Rust
use std::{sync::{Arc, atomic::AtomicBool}, time::Instant};
|
|
use chrono::Utc;
|
|
use serde_json::Value;
|
|
use tokio::sync::{broadcast, RwLock};
|
|
use crate::{config::Config, db::Db, models::{ApiEvent, RuntimeSettings}, protocol::GreeClient};
|
|
|
|
#[derive(Clone)]
|
|
pub struct AppState {
|
|
pub db: Db,
|
|
pub settings: Arc<RwLock<RuntimeSettings>>,
|
|
pub config: Arc<Config>,
|
|
pub gree: GreeClient,
|
|
pub events: broadcast::Sender<ApiEvent>,
|
|
pub http: reqwest::Client,
|
|
pub outdoor_temperature: Arc<RwLock<Option<f64>>>,
|
|
pub debug_gree_frames: Arc<AtomicBool>,
|
|
pub started: Instant,
|
|
}
|
|
|
|
impl AppState {
|
|
pub fn broadcast(&self, event: impl Into<String>, data: Value) {
|
|
let _ = self.events.send(ApiEvent {
|
|
event: event.into(),
|
|
timestamp: Utc::now(),
|
|
data,
|
|
});
|
|
}
|
|
|
|
pub fn log(&self, level: &str, kind: &str, message: &str, metadata: Value) {
|
|
if let Err(err) = self.db.log_event(level, kind, message, &metadata) {
|
|
tracing::warn!(error=?err, "cannot persist event log");
|
|
}
|
|
self.broadcast("log.created", serde_json::json!({
|
|
"level": level,
|
|
"kind": kind,
|
|
"message": message,
|
|
"metadata": metadata,
|
|
}));
|
|
if let Ok(handle) = tokio::runtime::Handle::try_current() {
|
|
let state = self.clone();
|
|
let level = level.to_string();
|
|
let kind = kind.to_string();
|
|
let message = message.to_string();
|
|
handle.spawn(async move { crate::notifications::dispatch(state, level, kind, message, metadata).await; });
|
|
}
|
|
}
|
|
}
|