first commit
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
use crate::models::HomeAssistantSettings;
|
||||
|
||||
pub async fn read_temperature(
|
||||
client: &reqwest::Client,
|
||||
settings: &HomeAssistantSettings,
|
||||
entity_override: Option<&str>,
|
||||
) -> Result<f64> {
|
||||
if settings.url.trim().is_empty() { bail!("Home Assistant URL is not configured") }
|
||||
if settings.token.trim().is_empty() { bail!("Home Assistant token is not configured") }
|
||||
let entity = entity_override.filter(|v| !v.trim().is_empty())
|
||||
.unwrap_or(settings.default_entity_id.trim());
|
||||
if entity.is_empty() { bail!("Home Assistant entity_id is not configured") }
|
||||
|
||||
let mut base = Url::parse(settings.url.trim()).context("invalid Home Assistant URL")?;
|
||||
if !matches!(base.scheme(), "http" | "https") { bail!("Home Assistant URL must use http or https") }
|
||||
let path = format!("api/states/{}", entity.trim_start_matches('/'));
|
||||
base = base.join(&path).context("cannot build Home Assistant API URL")?;
|
||||
|
||||
let response = client.get(base)
|
||||
.bearer_auth(settings.token.trim())
|
||||
.header("Accept", "application/json")
|
||||
.send().await.context("Home Assistant request failed")?;
|
||||
if !response.status().is_success() {
|
||||
let status = response.status();
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
bail!("Home Assistant returned {status}: {}", body.chars().take(200).collect::<String>())
|
||||
}
|
||||
let payload: Value = response.json().await.context("invalid Home Assistant JSON")?;
|
||||
let state = payload.get("state").and_then(Value::as_str)
|
||||
.ok_or_else(|| anyhow!("Home Assistant state is missing"))?;
|
||||
let mut temperature: f64 = state.parse().context("Home Assistant state is not a number")?;
|
||||
let unit = payload.pointer("/attributes/unit_of_measurement").and_then(Value::as_str).unwrap_or("°C");
|
||||
if unit.eq_ignore_ascii_case("°F") || unit.eq_ignore_ascii_case("F") {
|
||||
temperature = (temperature - 32.0) * 5.0 / 9.0;
|
||||
}
|
||||
Ok((temperature * 10.0).round() / 10.0)
|
||||
}
|
||||
Reference in New Issue
Block a user