This commit is contained in:
Mateusz Gruszczyński
2026-08-24 23:20:06 +02:00
parent 76a6f050ae
commit 7de006e841
10 changed files with 34 additions and 26 deletions
+5 -3
View File
@@ -230,13 +230,15 @@ async fn poll_device(state: &AppState, device: &mut Device) {
log_poll_health_transition(state, device, previous_failures).await;
}
async fn log_poll_health_transition(state: &AppState, device: &Device, previous_failures: u32) {
async fn log_poll_health_transition(state: &AppState, device: &Device, previous_failures: u8) {
let threshold = state.settings.read().await.notifications.communication_failure_threshold.max(2);
if device.communication_failures >= threshold && previous_failures < threshold {
let current_failures = u32::from(device.communication_failures);
let previous_failures = u32::from(previous_failures);
if current_failures >= threshold && previous_failures < threshold {
state.log("warn", "device.offline", &format!("{} did not respond {} times in a row", device.name, device.communication_failures), json!({
"device_id": device.id, "consecutive_failures": device.communication_failures, "threshold": threshold
}));
} else if device.communication_failures == 0 && previous_failures >= threshold {
} else if current_failures == 0 && previous_failures >= threshold {
state.log("info", "device.recovered", &format!("{} is responding again", device.name), json!({"device_id": device.id}));
}
}
+5 -5
View File
@@ -42,8 +42,8 @@ pub async fn dispatch(state: AppState, level: String, kind: String, message: Str
let title = format!("GREE Controller - {}", if level == "error" { "error" } else if level == "warn" { "warning" } else { "event" });
let result = match cfg.provider.as_str() {
"pushover" => send_pushover(&state, &cfg, &title, &message).await,
"slack" => send_webhook(&state, &cfg.slack_webhook_url, json!({"text": format!("*{}*\\n{}", title, message)})).await,
"discord" => send_webhook(&state, &cfg.discord_webhook_url, json!({"content": format!("**{}**\\n{}", title, message)})).await,
"slack" => send_webhook(&cfg.slack_webhook_url, json!({"text": format!("*{}*\\n{}", title, message)})).await,
"discord" => send_webhook(&cfg.discord_webhook_url, json!({"content": format!("**{}**\\n{}", title, message)})).await,
_ => Err("unsupported notification provider".into()),
};
if let Err(err) = result {
@@ -59,7 +59,7 @@ async fn send_pushover(state: &AppState, cfg: &NotificationSettings, title: &str
if response.status().is_success() { Ok(()) } else { Err(format!("Pushover HTTP {}", response.status())) }
}
async fn send_webhook(state: &AppState, url: &str, body: Value) -> Result<(), String> {
async fn send_webhook(url: &str, body: Value) -> Result<(), String> {
let parsed = url::Url::parse(url).map_err(|_| "invalid webhook URL".to_string())?;
if parsed.scheme() != "https" { return Err("webhook URL must use HTTPS".into()); }
let host = parsed.host_str().unwrap_or_default().to_ascii_lowercase();
@@ -76,8 +76,8 @@ async fn send_webhook(state: &AppState, url: &str, body: Value) -> Result<(), St
pub async fn test(state: &AppState, cfg: NotificationSettings) -> Result<(), String> {
match cfg.provider.as_str() {
"pushover" => send_pushover(state, &cfg, "GREE Controller", "Test notification").await,
"slack" => send_webhook(state, &cfg.slack_webhook_url, json!({"text":"GREE Controller - test notification"})).await,
"discord" => send_webhook(state, &cfg.discord_webhook_url, json!({"content":"GREE Controller - test notification"})).await,
"slack" => send_webhook(&cfg.slack_webhook_url, json!({"text":"GREE Controller - test notification"})).await,
"discord" => send_webhook(&cfg.discord_webhook_url, json!({"content":"GREE Controller - test notification"})).await,
_ => Err("unsupported notification provider".into()),
}
}