From 703ffcf82e4900aa4a7515f64f4d8fbb3fb3ce7d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 18 Mar 2026 05:21:29 +0000 Subject: [PATCH] fix: sync {camera}/motion topic from camera_activity updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit applyCameraActivity expanded camera_activity into many per-camera topics ({camera}/enabled/state, {camera}/detect/state, etc.) but never synced the motion field into {camera}/motion. This caused a critical bug: a stale retained MQTT "OFF" value in {camera}/motion would permanently override the live motion state from camera_activity.motion. In useCameraActivity the detectingMotion check (truthy string "OFF") took priority over camera_activity.motion, so activeMotion was always false even with real motion present. Now applyCameraActivity writes state.motion → {camera}/motion ("ON"/ "OFF"), keeping it in sync with the authoritative camera_activity data. https://claude.ai/code/session_019B4dJXtcxvHn97ZaqHUB62 --- web/src/api/ws.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/src/api/ws.ts b/web/src/api/ws.ts index 845ad1fa6..6e4e87eaf 100644 --- a/web/src/api/ws.ts +++ b/web/src/api/ws.ts @@ -149,6 +149,12 @@ function applyCameraActivity(payload: string) { for (const [name, state] of Object.entries(activity)) { applyTopicUpdate(`camera_activity/${name}`, state); + // Sync motion state so {camera}/motion topic stays up-to-date with + // camera_activity and doesn't remain stale from a retained MQTT value. + if (state.motion !== undefined) { + applyTopicUpdate(`${name}/motion`, state.motion ? "ON" : "OFF"); + } + const cameraConfig = state?.config; if (!cameraConfig) continue;