v0.7.13
This commit is contained in:
+16
@@ -208,6 +208,7 @@ async fn bootstrap(State(state): State<AppState>) -> Result<Json<Value>, AppErro
|
||||
|
||||
async fn build_bootstrap(state: &AppState) -> Result<Value, AppError> {
|
||||
let settings = state.settings.read().await.clone();
|
||||
let (received_frames_total, received_frames_by_device) = state.gree.received_frame_stats();
|
||||
Ok(json!({
|
||||
"devices": state.db.list_devices()?,
|
||||
"zones": state.db.list_zones()?,
|
||||
@@ -222,12 +223,15 @@ async fn build_bootstrap(state: &AppState) -> Result<Value, AppError> {
|
||||
"uptime_seconds": state.started.elapsed().as_secs(),
|
||||
"auth_required": !state.config.app_token.trim().is_empty(),
|
||||
"control_ready": state.initial_device_sync_complete.load(Ordering::Acquire),
|
||||
"gree_received_frames": received_frames_total,
|
||||
"gree_received_frames_by_device": received_frames_by_device,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
async fn system_info(State(state): State<AppState>) -> Result<Json<Value>, AppError> {
|
||||
let devices = state.db.list_devices()?;
|
||||
let (received_frames_total, received_frames_by_device) = state.gree.received_frame_stats();
|
||||
Ok(Json(json!({
|
||||
"version": env!("CARGO_PKG_VERSION"),
|
||||
"uptime_seconds": state.started.elapsed().as_secs(),
|
||||
@@ -238,6 +242,8 @@ async fn system_info(State(state): State<AppState>) -> Result<Json<Value>, AppEr
|
||||
"control_ready": state.initial_device_sync_complete.load(Ordering::Acquire),
|
||||
"bind": state.config.bind.to_string(),
|
||||
"gree_interface": if state.config.gree_interface.trim().is_empty() { "auto" } else { state.config.gree_interface.trim() },
|
||||
"gree_received_frames": received_frames_total,
|
||||
"gree_received_frames_by_device": received_frames_by_device,
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -607,6 +613,14 @@ async fn update_zone(State(state): State<AppState>, Path(id): Path<String>, Json
|
||||
}
|
||||
|
||||
async fn apply_zone_control_patch(state: &AppState, id: &str, patch: ZoneControlPatch) -> Result<Zone, AppError> {
|
||||
// Serialize quick-thermostat changes with the same device lock used by GREE polling and
|
||||
// manual-takeover detection. Without this, a poll that started just before a Web/HA
|
||||
// thermostat action could save an older zone snapshot afterwards and resurrect a false
|
||||
// "physical/pilot" takeover.
|
||||
let device_id = state.db.get_zone(id)?
|
||||
.ok_or_else(|| AppError::NotFound(format!("zone {id}")))?
|
||||
.device_id;
|
||||
let device_guard = state.lock_device_operation(&device_id).await;
|
||||
let mut zone = state.db.get_zone(id)?.ok_or_else(|| AppError::NotFound(format!("zone {id}")))?;
|
||||
let was_enabled = zone.enabled;
|
||||
let schedules = state.db.list_schedules()?;
|
||||
@@ -687,6 +701,8 @@ async fn apply_zone_control_patch(state: &AppState, id: &str, patch: ZoneControl
|
||||
zone.updated_at = Utc::now();
|
||||
state.db.save_zone(&zone)?;
|
||||
state.broadcast("zone.updated", serde_json::to_value(&zone)?);
|
||||
// Release before any device command below; engine::send_command acquires this same lock.
|
||||
drop(device_guard);
|
||||
if was_enabled && !zone.enabled {
|
||||
power_off_zone_device(state, &zone, "zone.quick_disabled").await;
|
||||
} else if patch.power == Some(false) {
|
||||
|
||||
Reference in New Issue
Block a user