Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions custom_components/keymaster/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions custom_components/keymaster/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
17 changes: 12 additions & 5 deletions tests/test_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()


Expand Down Expand Up @@ -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)

Expand Down