diff --git a/custom_components/lock_code_manager/binary_sensor.py b/custom_components/lock_code_manager/binary_sensor.py index 1b7250c2..99bc45a8 100644 --- a/custom_components/lock_code_manager/binary_sensor.py +++ b/custom_components/lock_code_manager/binary_sensor.py @@ -49,19 +49,12 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> bool: """Set up config entry.""" - coordinators: list[LockUsercodeUpdateCoordinator] = list( - hass.data[DOMAIN][config_entry.entry_id][COORDINATORS].values() - ) @callback def add_pin_enabled_entity(slot_num: int, ent_reg: er.EntityRegistry) -> None: """Add PIN enabled binary sensor entities for slot.""" async_add_entities( - [ - LockCodeManagerPINSyncedEntity( - hass, ent_reg, config_entry, coordinators, slot_num - ) - ], + [LockCodeManagerPINSyncedEntity(hass, ent_reg, config_entry, slot_num)], True, ) @@ -84,14 +77,12 @@ def __init__( hass: HomeAssistant, ent_reg: er.EntityRegistry, config_entry: ConfigEntry, - coordinators: list[LockUsercodeUpdateCoordinator], slot_num: int, ) -> None: """Initialize entity.""" BaseLockCodeManagerEntity.__init__( self, hass, ent_reg, config_entry, slot_num, ATTR_PIN_SYNCED_TO_LOCKS ) - self.coordinators = coordinators self._entity_id_map: dict[str, str] = {} self._issue_reg: ir.IssueRegistry | None = None self._call_later_unsub: Callable | None = None @@ -114,18 +105,7 @@ async def async_update_usercodes( """Update usercodes on locks based on state change.""" if not states: states = {} - disabling_entity_ids = ( - state["entity_id"] - for key, state in states.items() - if (key != CONF_NUMBER_OF_USES and state["state"] != STATE_ON) - or ( - key == CONF_NUMBER_OF_USES - and ( - state["state"] in (STATE_UNAVAILABLE, STATE_UNKNOWN) - or int(float(state["state"])) == 0 - ) - ) - ) + coordinators: list[LockUsercodeUpdateCoordinator] = [] for lock in self.locks: lock_slot_sensor_state = self._lock_slot_sensor_state(lock) if self.is_on: @@ -145,17 +125,17 @@ async def async_update_usercodes( if lock_slot_sensor_state == pin_state.state: continue + await lock.async_set_usercode( + int(self.slot_num), pin_state.state, name_state.state + ) + _LOGGER.info( - "%s (%s): Setting usercode for %s slot %s", + "%s (%s): Set usercode for %s slot %s", self.config_entry.entry_id, self.config_entry.title, lock.lock.entity_id, self.slot_num, ) - - await lock.async_set_usercode( - int(self.slot_num), pin_state.state, name_state.state - ) else: if lock_slot_sensor_state in ( "", @@ -163,9 +143,34 @@ async def async_update_usercodes( ): continue + if not ( + disabling_entity_ids := list( + state["entity_id"] + for key, state in states.items() + if ( + key not in (CONF_NUMBER_OF_USES, CONF_PIN) + and state["state"] != STATE_ON + ) + or ( + key == CONF_NUMBER_OF_USES + and ( + state["state"] in (STATE_UNAVAILABLE, STATE_UNKNOWN) + or int(float(state["state"])) == 0 + ) + ) + or ( + key == CONF_PIN + and state["state"] != self._lock_slot_sensor_state(lock) + ) + ) + ): + return + + await lock.async_clear_usercode(int(self.slot_num)) + _LOGGER.info( ( - "%s (%s): Clearing usercode for lock %s slot %s because the " + "%s (%s): Cleared usercode for lock %s slot %s because the " "following entities indicate the slot is disabled: %s" ), self.config_entry.entry_id, @@ -175,12 +180,14 @@ async def async_update_usercodes( ", ".join(disabling_entity_ids), ) - await lock.async_clear_usercode(int(self.slot_num)) - - await asyncio.gather( - *[coordinator.async_refresh() for coordinator in self.coordinators] + coordinators.append( + self.hass.data[DOMAIN][COORDINATORS][lock.lock.entity_id] ) + await asyncio.gather( + *[coordinator.async_refresh() for coordinator in coordinators] + ) + async def _update_state(self, _: datetime | None = None) -> None: """Update binary sensor state by getting dependent states.""" if self._call_later_unsub: diff --git a/tests/test_binary_sensor.py b/tests/test_binary_sensor.py index b1c23cda..b49c3224 100644 --- a/tests/test_binary_sensor.py +++ b/tests/test_binary_sensor.py @@ -136,9 +136,9 @@ async def test_binary_sensor_entity( ) await hass.async_block_till_done() - assert hass.data[LOCK_DATA][LOCK_1_ENTITY_ID]["service_calls"]["set_usercode"] == [ - (2, "0987", "test2") - ] + assert hass.data[LOCK_DATA][LOCK_1_ENTITY_ID]["service_calls"]["set_usercode"][ + -1 + ] == (2, "0987", "test2") new_config = copy.deepcopy(BASE_CONFIG) new_config[CONF_SLOTS][2][CONF_CALENDAR] = "calendar.test_2" diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 9ebab10c..028a81c3 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -2,6 +2,7 @@ import logging +from homeassistant.const import STATE_UNAVAILABLE from homeassistant.core import HomeAssistant _LOGGER = logging.getLogger(__name__) @@ -13,7 +14,7 @@ async def test_sensor_entity( lock_code_manager_config_entry, ): """Test sensor entity.""" - for code_slot, pin in ((1, "1234"), (2, "5678")): + for code_slot, pin in ((1, "1234"), (2, STATE_UNAVAILABLE)): state = hass.states.get(f"sensor.test_1_code_slot_{code_slot}") assert state assert state.state == pin