From f9b2a244e475ac5fd8aeecc421776d3e23fa1926 Mon Sep 17 00:00:00 2001 From: cpw Date: Thu, 25 Sep 2025 08:42:48 -0400 Subject: [PATCH] Update coordinator.py This fix discards state changes without a user_id in handle_lock_state_change. The reasoning is simple - handle_lock_state_change is fired WAY too early during the zwave lock notification process and sees very wrong values for the other elements of zwave lock state, at least with my schlage lock testing. (This is because zwave is actually a whole negotiation - with many different things changing and notifications flying back and forth from the lock to HA and back again, and the state change on the lock entity in HA is one of the very earliest in the sequence at least with my Schlage lock). Anyway, the key problem for the notification code is that the state change fires WAY before the zwave _notification_ that the lock has changed state, which is a much more reliable method of getting audit information about the changing state of the lock. Due to this out of sequence behaviour, handle_lock_state_change would fire well before handle_zwave_js_lock_event and the former would make very wrong assumptions based on the transient state the lock is in at the time that event is fired. This change is simple: if the lock state change event _has_ a user ID it has come from HA and NOT zwave, and thus we can act on it (I can't seem to get zwave to send a _notification_ back if we programmatically change the lock state from HA, which is annoying), but if it _doesn't_ have a user ID, it is an event that is part of an external change in state. As such, it's firing WAY too early in this circumstance, and should just be ignored - wait for the real zwave notification event instead. --- custom_components/keymaster/coordinator.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/custom_components/keymaster/coordinator.py b/custom_components/keymaster/coordinator.py index 4179c8bd..1754a9cd 100644 --- a/custom_components/keymaster/coordinator.py +++ b/custom_components/keymaster/coordinator.py @@ -526,6 +526,10 @@ async def _handle_lock_state_change( if not event: return + # Ignore events without a user_id - they're from zwave - let handle_zwave_js_lock_event handle it + if event.context.as_dict()["user_id"] is None: + return + changed_entity: str = event.data["entity_id"] # Don't do anything if the changed entity is not this lock