This commit is contained in:
Mateusz Gruszczyński
2026-09-16 14:24:40 +02:00
parent d0ae3d0f6a
commit 3f9acb1675
28 changed files with 726 additions and 127 deletions
+54 -3
View File
@@ -2,6 +2,7 @@ fn map_home_assistant_integration_error(error: anyhow::Error) -> AppError {
let message = error.to_string();
if message.contains("Home Assistant URL is not configured")
|| message.contains("Home Assistant token is not configured")
|| message.contains("Home Assistant Supervisor token is not available")
|| message.contains("invalid Home Assistant URL")
|| message.contains("Home Assistant URL must use http or https")
|| message.contains("cannot build Home Assistant API URL")
@@ -45,10 +46,58 @@ async fn test_home_assistant(
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
let settings = state.settings.read().await.clone();
home_assistant::test_connection(&state.http, &settings.home_assistant)
let sample = home_assistant::test_connection(&state.http, &settings.home_assistant)
.await
.map_err(map_home_assistant_integration_error)?;
Ok(Json(json!({"ok": true})))
Ok(Json(json!({
"ok": true,
"auth_mode": home_assistant::auth_mode(&settings.home_assistant),
"sample": sample,
})))
}
async fn list_home_assistant_entities(
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
let settings = state.settings.read().await.home_assistant.clone();
if !home_assistant::token_configured(&settings)
|| home_assistant::effective_url(&settings).trim().is_empty()
{
return Ok(Json(json!({
"configured": false,
"entities": [],
})));
}
let mut entities = home_assistant::list_entities(&state.http, &settings)
.await
.map_err(map_home_assistant_integration_error)?
.into_iter()
.filter_map(|entity| {
let entity_id = entity.get("entity_id")?.as_str()?.trim();
if entity_id.is_empty() {
return None;
}
let attributes = entity.get("attributes").and_then(Value::as_object);
Some(json!({
"entity_id": entity_id,
"name": attributes.and_then(|value| value.get("friendly_name")).and_then(Value::as_str).unwrap_or_default(),
"state": entity.get("state").and_then(Value::as_str).unwrap_or_default(),
"unit": attributes.and_then(|value| value.get("unit_of_measurement")).and_then(Value::as_str).unwrap_or_default(),
"device_class": attributes.and_then(|value| value.get("device_class")).and_then(Value::as_str).unwrap_or_default(),
}))
})
.collect::<Vec<_>>();
entities.sort_by(|a, b| {
a.get("entity_id")
.and_then(Value::as_str)
.unwrap_or_default()
.cmp(b.get("entity_id").and_then(Value::as_str).unwrap_or_default())
});
Ok(Json(json!({
"configured": true,
"entities": entities,
})))
}
#[derive(Debug, Deserialize)]
@@ -116,7 +165,9 @@ async fn list_home_assistant_energy_sensors(
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
let settings = state.settings.read().await.home_assistant.clone();
if settings.url.trim().is_empty() || settings.token.trim().is_empty() {
if !home_assistant::token_configured(&settings)
|| home_assistant::effective_url(&settings).trim().is_empty()
{
return Ok(Json(json!({
"configured": false,
"sensors": [],