Files
gree-controller/src/state.rs
T
2026-08-24 23:11:41 +02:00

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; });
}
}
}