This commit is contained in:
Mateusz Gruszczyński committed 2026-09-23 09:44:23 +02:00
1 parent f08613a254
commit 3b71b057cd
15 files changed
+75 -47

No files matched your search

+15 -4
View File
@@ -909,6 +909,14 @@ fn flow_condition_kind_runtime(kind: &str) -> bool {
)
}
fn apply_flow_zone_power_enabled_state(zone: &mut Zone, power: Option<bool>) {
// OFF controls the thermostat/unit runtime only. It must not disable the administrative Zone.
// Keep the historical ON recovery so installations affected by the old OFF behavior can heal.
if power == Some(true) {
zone.enabled = true;
}
}
async fn apply_flow_zone_action(state: &AppState, zone_id: &str, preset: Option<&str>, action: &DeviceCommand) -> Result<bool, AppError> {
let _schedule_guard = state.lock_schedule_operation().await;
// Match the canonical thermostat ordering used by Web/HA zone control. This prevents
@@ -921,7 +929,10 @@ async fn apply_flow_zone_action(state: &AppState, zone_id: &str, preset: Option<
// remains an explicit gate unless this Flow action is the actor re-enabling it.
if !zone.enabled && action.power != Some(true) { return Ok(false); }
let device_id = zone.device_id.clone();
if let Some(power) = action.power { zone.enabled = power; }
// Flow thermostat OFF is a runtime climate command, not the persistent administrative
// Zone enabled/disabled switch. Keep the zone enabled so later Flow/schedule evaluation can
// continue normally.
apply_flow_zone_power_enabled_state(&mut zone, action.power);
if let Some(mode) = action.mode.as_deref() {
match mode { "auto" => zone.inherit_house_mode = true, "heat" | "cool" => { zone.mode = mode.to_string(); zone.inherit_house_mode = false; }, _ => return Err(AppError::BadRequest("unsupported Flow thermostat mode".into())) }
}
@@ -967,9 +978,9 @@ async fn apply_flow_zone_action(state: &AppState, zone_id: &str, preset: Option<
..Default::default()
};
if action.power == Some(false) {
// Disabled zones are intentionally skipped by the normal thermostat cycle. Perform the
// physical OFF under the canonical zone -> device lock order so the durable Flow intent
// cannot leave a unit running and polling/manual control cannot interleave with the frame.
// OFF remains an explicit physical command once the Flow action fires, but it must not
// disable the Zone itself. Send it under the canonical zone -> device lock order so the
// persisted thermostat hand-back and the device frame cannot race polling/manual control.
// Swing can safely share this explicit frame because it is outside thermostat regulation.
let _device_guard = state.lock_device_operation(&device_id).await;
send_command_locked_forced(