This commit is contained in:
Mateusz Gruszczyński
2026-09-01 12:07:04 +02:00
parent 6207bc4de6
commit e496f911da
25 changed files with 227 additions and 309 deletions
+5 -27
View File
@@ -23,24 +23,6 @@ async fn clear_group_control_sources(state: &AppState, reason: &str) -> Result<(
Ok(())
}
async fn set_all_groups_power(state: &AppState, power: bool) -> Result<(), AppError> {
let mut group_ids: Vec<String> = state.db.list_groups()?.into_iter().map(|group| group.id).collect();
group_ids.sort();
group_ids.dedup();
let mut _group_guards = Vec::with_capacity(group_ids.len());
for group_id in &group_ids {
_group_guards.push(state.lock_group_operation(group_id).await);
}
for mut group in state.db.list_groups()? {
if group.power_enabled == power { continue; }
group.power_enabled = power;
group.updated_at = Utc::now();
state.db.save_group(&group)?;
state.broadcast("group.updated", serde_json::to_value(&group)?);
}
Ok(())
}
fn clear_all_local_thermostat_overrides(state: &AppState) -> Result<usize, AppError> {
let mut cleared = 0;
for mut zone in state.db.list_zones()? {
@@ -123,9 +105,6 @@ async fn update_house_control(State(state): State<AppState>, Json(input): Json<H
};
state.broadcast("settings.updated", payload.clone());
clear_group_control_sources(&state, "Whole-house mode control took ownership").await?;
if activate_all {
set_all_groups_power(&state, true).await?;
}
// run_zone_control_now takes the same cycle lock, so release the mutation window first.
drop(cycle_guard);
if activate_all {
@@ -157,10 +136,10 @@ async fn update_house_power(State(state): State<AppState>, Json(input): Json<Hou
}
}
// Global power is a true cascade across group gates. OFF clears the current takeover
// markers once, then each enabled device is re-cleared atomically with its OFF command.
// A later pilot action is therefore not erased by subsequent controller cycles.
set_all_groups_power(&state, input.power).await?;
// Whole-house power is independent from group-control enablement. OFF clears current
// ownership markers and powers devices down, but preserves which groups the user has
// enabled for future group actions. A later house ON therefore does not silently turn
// disabled group control back on.
clear_group_control_sources(&state, if input.power { "Whole-house power control resumed automation" } else { "Whole-house power disabled" }).await?;
if !input.power {
let zone_snapshot = state.db.list_zones()?;
@@ -205,7 +184,7 @@ async fn update_house_power(State(state): State<AppState>, Json(input): Json<Hou
let settings = state.settings.read().await;
let settings_payload = public_settings(&settings);
drop(settings);
state.log("info", "house.power_all", if input.power { "Whole-house automation enabled; thermostat arbiter resumed" } else { "Whole-house power disabled; all groups and enabled devices powered off" }, json!({
state.log("info", "house.power_all", if input.power { "Whole-house automation enabled; thermostat arbiter resumed" } else { "Whole-house power disabled; enabled devices powered off while group-control preferences were preserved" }, json!({
"power": input.power,
"failed": failed.len(),
}));
@@ -237,7 +216,6 @@ async fn update_house_preset(State(state): State<AppState>, Json(input): Json<Ho
public_settings(&settings)
};
state.broadcast("settings.updated", settings_payload.clone());
set_all_groups_power(&state, true).await?;
clear_group_control_sources(&state, "Whole-house preset control took ownership").await?;
let schedules = state.db.list_schedules()?;