Skip to content

Commit 90bba12

Browse files
mosandltclaude
andcommitted
debug: A/B-diag log for SHC privacy_mode write-lock race
The SHC fetcher in shc.py overwrites _shc_state_cache.privacy_mode without honoring the _privacy_set_at write-lock that __init__.py:1690 respects. Suspected cause of the "privacy flips back ON after user-toggle OFF" bug (second OFF-toggle works on retry). Pure debug-only patch — no behavior change. When debug logging is enabled on the integration, logs an "AB-DIAG privacy_mode race" line whenever the fetcher would have flipped a privacy state that was within the active write-lock window. Lets us confirm the hypothesis before applying the actual FORCE-RULE fix. Behavior is unchanged: entry["privacy_mode"] = new_priv is still written. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 21650da commit 90bba12

1 file changed

Lines changed: 20 additions & 1 deletion

File tree

  • custom_components/bosch_shc_camera

custom_components/bosch_shc_camera/shc.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,26 @@ async def async_update_shc_states(
222222
)
223223
if isinstance(svc, dict):
224224
val = svc.get("state", {}).get("value", "")
225-
entry["privacy_mode"] = (val.upper() == "ENABLED")
225+
new_priv = (val.upper() == "ENABLED")
226+
# A/B-Diag (debug-only, behavior unchanged) — see CLAUDE.md TODO
227+
# 2026-04-27: privacy flips back after user-toggle OFF. Hypothesis:
228+
# this fetcher overwrites _shc_state_cache without honoring the
229+
# _privacy_set_at write-lock that __init__.py:1690 respects. Logs
230+
# the would-be-blocked race so we can confirm before applying the
231+
# FORCE-RULE fix.
232+
if _LOGGER.isEnabledFor(logging.DEBUG):
233+
old_priv = entry.get("privacy_mode")
234+
lock_ts = coordinator._privacy_set_at.get(cam_id)
235+
age = (time.monotonic() - lock_ts) if lock_ts is not None else None
236+
ttl = getattr(coordinator, "_WRITE_LOCK_SECS", 0)
237+
locked = age is not None and age < ttl
238+
if old_priv is not None and old_priv != new_priv and locked:
239+
_LOGGER.debug(
240+
"AB-DIAG privacy_mode race: cam=%s old=%s new=%s "
241+
"lock_age=%.1fs lock_ttl=%.1fs (would-be-blocked)",
242+
cam_id[:8], old_priv, new_priv, age, ttl,
243+
)
244+
entry["privacy_mode"] = new_priv
226245

227246

228247
# ── SHC setters ──────────────────────────────────────────────────────────────

0 commit comments

Comments
 (0)