diff --git a/custom_components/keymaster/coordinator.py b/custom_components/keymaster/coordinator.py index 9c4f70fc..b51531b9 100644 --- a/custom_components/keymaster/coordinator.py +++ b/custom_components/keymaster/coordinator.py @@ -836,10 +836,20 @@ async def _lock_unlocked( parent_kmlock.code_slots[code_slot_num].accesslimit_count = ( accesslimit_count - 1 ) + # Immediately notify entities of the count change + self.async_set_updated_data(dict(self.kmlocks)) + # Check if slot should be deactivated (e.g., count reached 0) + await self._update_slot( + parent_kmlock, parent_kmlock.code_slots[code_slot_num], code_slot_num + ) elif kmlock.code_slots[code_slot_num].accesslimit_count_enabled: accesslimit_count = kmlock.code_slots[code_slot_num].accesslimit_count if isinstance(accesslimit_count, int) and accesslimit_count > 0: kmlock.code_slots[code_slot_num].accesslimit_count = accesslimit_count - 1 + # Immediately notify entities of the count change + self.async_set_updated_data(dict(self.kmlocks)) + # Check if slot should be deactivated (e.g., count reached 0) + await self._update_slot(kmlock, kmlock.code_slots[code_slot_num], code_slot_num) if kmlock.code_slots[code_slot_num].notifications and not kmlock.lock_notifications: if kmlock.code_slots[code_slot_num].name: diff --git a/custom_components/keymaster/number.py b/custom_components/keymaster/number.py index 44ede98d..79875d68 100644 --- a/custom_components/keymaster/number.py +++ b/custom_components/keymaster/number.py @@ -193,4 +193,5 @@ async def async_set_native_value(self, value: float) -> None: value = int(value) if self._set_property_value(value): self._attr_native_value = value + self.async_write_ha_state() # Immediate UI update await self.coordinator.async_refresh() diff --git a/tests/test_number.py b/tests/test_number.py index 3a4cdcef..0d01bab2 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -442,12 +442,16 @@ async def test_number_entity_async_set_value(hass: HomeAssistant, number_config_ entity = KeymasterNumber(entity_description=entity_description) - # Mock coordinator.async_refresh - with patch.object(coordinator, "async_refresh", new=AsyncMock()) as mock_refresh: + # Mock coordinator.async_refresh and async_write_ha_state (entity not registered) + with ( + patch.object(coordinator, "async_refresh", new=AsyncMock()) as mock_refresh, + patch.object(entity, "async_write_ha_state") as mock_write_state, + ): await entity.async_set_native_value(5) - # Should update value and call refresh + # Should update value, write state immediately, and call refresh assert entity._attr_native_value == 5 + mock_write_state.assert_called_once() mock_refresh.assert_called_once() @@ -541,8 +545,11 @@ async def test_number_entity_converts_float_to_int_for_accesslimit_count( entity = KeymasterNumber(entity_description=entity_description) - # Mock coordinator.async_refresh - with patch.object(coordinator, "async_refresh", new=AsyncMock()): + # Mock coordinator.async_refresh and async_write_ha_state (entity not registered) + with ( + patch.object(coordinator, "async_refresh", new=AsyncMock()), + patch.object(entity, "async_write_ha_state"), + ): # Pass a float value (like NumberEntity would from the frontend) await entity.async_set_native_value(5.0)