This commit is contained in:
Mateusz Gruszczyński
2026-09-17 08:52:02 +02:00
parent ff4f2b60e7
commit b7846c3b9f
87 changed files with 3783 additions and 1418 deletions
+48 -14
View File
@@ -193,7 +193,10 @@ async fn patch_device(
.get_device(&id)?
.ok_or_else(|| AppError::NotFound(format!("device {id}")))?;
if device.connection_type == ConnectionType::GreeCloud
&& (patch.ip.is_some() || patch.port.is_some() || patch.protocol_version.is_some() || patch.key.is_some())
&& (patch.ip.is_some()
|| patch.port.is_some()
|| patch.protocol_version.is_some()
|| patch.key.is_some())
{
return Err(AppError::BadRequest(
"IP, UDP port, local protocol and local key are not configurable for GREE Cloud devices".into(),
@@ -232,19 +235,35 @@ async fn patch_device(
if let Some(v) = patch.enabled {
device.enabled = v;
}
if let Some(v) = patch.energy_source { device.energy_source = v; }
if let Some(v) = patch.ha_energy_entity_id { device.ha_energy_entity_id = v.filter(|x| !x.trim().is_empty()); }
if let Some(v) = patch.ha_energy_unit { device.ha_energy_unit = v.filter(|x| !x.trim().is_empty()); }
if let Some(v) = patch.ha_energy_device_class { device.ha_energy_device_class = v.filter(|x| !x.trim().is_empty()); }
if let Some(v) = patch.ha_energy_state_class { device.ha_energy_state_class = v.filter(|x| !x.trim().is_empty()); }
if let Some(v) = patch.energy_source {
device.energy_source = v;
}
if let Some(v) = patch.ha_energy_entity_id {
device.ha_energy_entity_id = v.filter(|x| !x.trim().is_empty());
}
if let Some(v) = patch.ha_energy_unit {
device.ha_energy_unit = v.filter(|x| !x.trim().is_empty());
}
if let Some(v) = patch.ha_energy_device_class {
device.ha_energy_device_class = v.filter(|x| !x.trim().is_empty());
}
if let Some(v) = patch.ha_energy_state_class {
device.ha_energy_state_class = v.filter(|x| !x.trim().is_empty());
}
device.refresh_capabilities();
if device.energy_source == EnergySourcePreference::GreeCloud && !device.capabilities.energy_meter {
if device.energy_source == EnergySourcePreference::GreeCloud
&& !device.capabilities.energy_meter
{
return Err(AppError::BadRequest(
"GREE Cloud energy is not available for this device".into(),
));
}
if device.energy_source == EnergySourcePreference::HomeAssistant
&& device.ha_energy_entity_id.as_deref().unwrap_or_default().is_empty()
&& device
.ha_energy_entity_id
.as_deref()
.unwrap_or_default()
.is_empty()
{
return Err(AppError::BadRequest(
"select a Home Assistant cumulative energy sensor first".into(),
@@ -256,13 +275,21 @@ async fn patch_device(
"Home Assistant energy sensor must have device_class=energy".into(),
));
}
if !matches!(device.ha_energy_state_class.as_deref(), Some("total" | "total_increasing")) {
if !matches!(
device.ha_energy_state_class.as_deref(),
Some("total" | "total_increasing")
) {
return Err(AppError::BadRequest(
"Home Assistant energy sensor must have state_class=total or total_increasing".into(),
"Home Assistant energy sensor must have state_class=total or total_increasing"
.into(),
));
}
if !matches!(
device.ha_energy_unit.as_deref().map(str::to_ascii_lowercase).as_deref(),
device
.ha_energy_unit
.as_deref()
.map(str::to_ascii_lowercase)
.as_deref(),
Some("wh" | "kwh")
) {
return Err(AppError::BadRequest(
@@ -331,7 +358,10 @@ async fn delete_device(
.iter()
.filter(|group| {
!group.zone_ids.is_empty()
&& group.zone_ids.iter().all(|zone_id| removed_zone_ids.contains(zone_id))
&& group
.zone_ids
.iter()
.all(|zone_id| removed_zone_ids.contains(zone_id))
})
.map(|group| group.id.clone())
.collect();
@@ -380,7 +410,9 @@ async fn bind_device(
.get_device(&id)?
.ok_or_else(|| AppError::NotFound(format!("device {id}")))?;
if device.connection_type == ConnectionType::GreeCloud {
return Err(AppError::BadRequest("bind is only available for Local/LAN devices".into()));
return Err(AppError::BadRequest(
"bind is only available for Local/LAN devices".into(),
));
}
if device.simulated {
return Ok(Json(device));
@@ -426,7 +458,9 @@ async fn probe_device(
.get_device(&id)?
.ok_or_else(|| AppError::NotFound(format!("device {id}")))?;
if device.connection_type == ConnectionType::GreeCloud {
return Err(AppError::BadRequest("UDP probe is only available for Local/LAN devices".into()));
return Err(AppError::BadRequest(
"UDP probe is only available for Local/LAN devices".into(),
));
}
let response_time_ms = state
.providers