diff --git a/homeassistant/components/loqed/config_flow.py b/homeassistant/components/loqed/config_flow.py index c757d2f0080..5eecc0b3f59 100644 --- a/homeassistant/components/loqed/config_flow.py +++ b/homeassistant/components/loqed/config_flow.py @@ -44,9 +44,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) cloud_client = cloud_loqed.LoqedCloudAPI(cloud_api_client) lock_data = await cloud_client.async_get_locks() - except aiohttp.ClientError: + except aiohttp.ClientError as err: _LOGGER.error("HTTP Connection error to loqed API") - raise CannotConnect from aiohttp.ClientError + raise CannotConnect from err try: selected_lock = next( @@ -137,7 +137,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): errors["base"] = "invalid_auth" else: await self.async_set_unique_id( - re.sub(r"LOQED-([a-f0-9]+)\.local", r"\1", info["bridge_mdns_hostname"]) + re.sub( + r"LOQED-([a-f0-9]+)\.local", r"\1", info["bridge_mdns_hostname"] + ), + raise_on_progress=False, ) self._abort_if_unique_id_configured() diff --git a/homeassistant/components/loqed/const.py b/homeassistant/components/loqed/const.py index 0374e72d5f0..6b1c0311a2d 100644 --- a/homeassistant/components/loqed/const.py +++ b/homeassistant/components/loqed/const.py @@ -2,5 +2,3 @@ DOMAIN = "loqed" -OAUTH2_AUTHORIZE = "https://app.loqed.com/API/integration_oauth3/login.php" -OAUTH2_TOKEN = "https://app.loqed.com/API/integration_oauth3/token.php" diff --git a/homeassistant/components/loqed/coordinator.py b/homeassistant/components/loqed/coordinator.py index ec7d5467b49..507debc02ab 100644 --- a/homeassistant/components/loqed/coordinator.py +++ b/homeassistant/components/loqed/coordinator.py @@ -8,8 +8,8 @@ from loqedAPI import loqed from homeassistant.components import webhook from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_WEBHOOK_ID -from homeassistant.core import HomeAssistant, callback +from homeassistant.const import CONF_NAME, CONF_WEBHOOK_ID +from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import DOMAIN @@ -79,17 +79,16 @@ class LoqedDataCoordinator(DataUpdateCoordinator[StatusMessage]): ) -> None: """Initialize the Loqed Data Update coordinator.""" super().__init__(hass, _LOGGER, name="Loqed sensors") - self._hass = hass self._api = api self._entry = entry self.lock = lock + self.device_name = self._entry.data[CONF_NAME] async def _async_update_data(self) -> StatusMessage: """Fetch data from API endpoint.""" async with async_timeout.timeout(10): return await self._api.async_get_lock_details() - @callback async def _handle_webhook( self, hass: HomeAssistant, webhook_id: str, request: Request ) -> None: @@ -116,7 +115,7 @@ class LoqedDataCoordinator(DataUpdateCoordinator[StatusMessage]): self.hass, DOMAIN, "Loqed", webhook_id, self._handle_webhook ) webhook_url = webhook.async_generate_url(self.hass, webhook_id) - _LOGGER.info("Webhook URL: %s", webhook_url) + _LOGGER.debug("Webhook URL: %s", webhook_url) webhooks = await self.lock.getWebhooks() diff --git a/homeassistant/components/loqed/entity.py b/homeassistant/components/loqed/entity.py index 1b1731815b4..978fe844d61 100644 --- a/homeassistant/components/loqed/entity.py +++ b/homeassistant/components/loqed/entity.py @@ -23,7 +23,7 @@ class LoqedEntity(CoordinatorEntity[LoqedDataCoordinator]): self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, lock_id)}, manufacturer="LOQED", - name="LOQED Lock", + name=coordinator.device_name, model="Touch Smart Lock", connections={(CONNECTION_NETWORK_MAC, lock_id)}, ) diff --git a/homeassistant/components/loqed/lock.py b/homeassistant/components/loqed/lock.py index 5a7540ba89e..d34df19e2d1 100644 --- a/homeassistant/components/loqed/lock.py +++ b/homeassistant/components/loqed/lock.py @@ -24,7 +24,7 @@ async def async_setup_entry( """Set up the Loqed lock platform.""" coordinator = hass.data[DOMAIN][entry.entry_id] - async_add_entities([LoqedLock(coordinator, entry.data["name"])]) + async_add_entities([LoqedLock(coordinator)]) class LoqedLock(LoqedEntity, LockEntity): @@ -32,17 +32,17 @@ class LoqedLock(LoqedEntity, LockEntity): _attr_supported_features = LockEntityFeature.OPEN - def __init__(self, coordinator: LoqedDataCoordinator, name: str) -> None: + def __init__(self, coordinator: LoqedDataCoordinator) -> None: """Initialize the lock.""" super().__init__(coordinator) self._lock = coordinator.lock self._attr_unique_id = self._lock.id - self._attr_name = name + self._attr_name = None @property def changed_by(self) -> str: """Return internal ID of last used key.""" - return "KeyID " + str(self._lock.last_key_id) + return f"KeyID {self._lock.last_key_id}" @property def is_locking(self) -> bool | None: diff --git a/homeassistant/components/loqed/strings.json b/homeassistant/components/loqed/strings.json index 5448f01b7f9..6f3316b283f 100644 --- a/homeassistant/components/loqed/strings.json +++ b/homeassistant/components/loqed/strings.json @@ -12,8 +12,7 @@ }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", - "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", - "unknown": "[%key:common::config_flow::error::unknown%]" + "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]" }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" diff --git a/homeassistant/components/loqed/translations/en.json b/homeassistant/components/loqed/translations/en.json deleted file mode 100644 index a961f10cb1b..00000000000 --- a/homeassistant/components/loqed/translations/en.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "config": { - "abort": { - "already_configured": "Device is already configured" - }, - "error": { - "cannot_connect": "Failed to connect", - "invalid_auth": "Invalid authentication", - "unknown": "Unexpected error" - }, - "flow_title": "LOQED Touch Smartlock setup", - "step": { - "user": { - "data": { - "api_key": "API Key", - "name": "Name of your lock in the LOQED app." - }, - "description": "Login at {config_url} and: \n* Create an API-key by clicking 'Create' \n* Copy the created access token." - } - } - } -} \ No newline at end of file diff --git a/tests/components/loqed/test_init.py b/tests/components/loqed/test_init.py index 89b67ee3258..960ad9def6b 100644 --- a/tests/components/loqed/test_init.py +++ b/tests/components/loqed/test_init.py @@ -15,31 +15,6 @@ from homeassistant.setup import async_setup_component from tests.common import MockConfigEntry, load_fixture -async def test_webhook_rejects_invalid_message( - hass: HomeAssistant, - hass_client_no_auth, - integration: MockConfigEntry, - lock: loqed.Lock, -): - """Test webhook called with invalid message.""" - await async_setup_component(hass, "http", {"http": {}}) - client = await hass_client_no_auth() - - coordinator = hass.data[DOMAIN][integration.entry_id] - lock.receiveWebhook = AsyncMock(return_value={"error": "invalid hash"}) - - with patch.object(coordinator, "async_set_updated_data") as mock: - message = load_fixture("loqed/battery_update.json") - timestamp = 1653304609 - await client.post( - f"/api/webhook/{integration.data[CONF_WEBHOOK_ID]}", - data=message, - headers={"timestamp": str(timestamp), "hash": "incorrect hash"}, - ) - - mock.assert_not_called() - - async def test_webhook_accepts_valid_message( hass: HomeAssistant, hass_client_no_auth, @@ -49,20 +24,17 @@ async def test_webhook_accepts_valid_message( """Test webhook called with valid message.""" await async_setup_component(hass, "http", {"http": {}}) client = await hass_client_no_auth() - processed_message = json.loads(load_fixture("loqed/battery_update.json")) - coordinator = hass.data[DOMAIN][integration.entry_id] + processed_message = json.loads(load_fixture("loqed/lock_going_to_nightlock.json")) lock.receiveWebhook = AsyncMock(return_value=processed_message) - with patch.object(coordinator, "async_update_listeners") as mock: - message = load_fixture("loqed/battery_update.json") - timestamp = 1653304609 - await client.post( - f"/api/webhook/{integration.data[CONF_WEBHOOK_ID]}", - data=message, - headers={"timestamp": str(timestamp), "hash": "incorrect hash"}, - ) - - mock.assert_called() + message = load_fixture("loqed/battery_update.json") + timestamp = 1653304609 + await client.post( + f"/api/webhook/{integration.data[CONF_WEBHOOK_ID]}", + data=message, + headers={"timestamp": str(timestamp), "hash": "incorrect hash"}, + ) + lock.receiveWebhook.assert_called() async def test_setup_webhook_in_bridge( diff --git a/tests/components/loqed/test_lock.py b/tests/components/loqed/test_lock.py index 422b7ab6830..59e70212f92 100644 --- a/tests/components/loqed/test_lock.py +++ b/tests/components/loqed/test_lock.py @@ -21,7 +21,7 @@ async def test_lock_entity( integration: MockConfigEntry, ) -> None: """Test the lock entity.""" - entity_id = "lock.loqed_lock_home" + entity_id = "lock.home" state = hass.states.get(entity_id) @@ -37,7 +37,7 @@ async def test_lock_responds_to_bolt_state_updates( lock.bolt_state = "night_lock" coordinator.async_update_listeners() - entity_id = "lock.loqed_lock_home" + entity_id = "lock.home" state = hass.states.get(entity_id) @@ -50,7 +50,7 @@ async def test_lock_transition_to_unlocked( ) -> None: """Tests the lock transitions to unlocked state.""" - entity_id = "lock.loqed_lock_home" + entity_id = "lock.home" await hass.services.async_call( "lock", SERVICE_UNLOCK, {ATTR_ENTITY_ID: entity_id}, blocking=True @@ -64,7 +64,7 @@ async def test_lock_transition_to_locked( ) -> None: """Tests the lock transitions to locked state.""" - entity_id = "lock.loqed_lock_home" + entity_id = "lock.home" await hass.services.async_call( "lock", SERVICE_LOCK, {ATTR_ENTITY_ID: entity_id}, blocking=True @@ -78,7 +78,7 @@ async def test_lock_transition_to_open( ) -> None: """Tests the lock transitions to open state.""" - entity_id = "lock.loqed_lock_home" + entity_id = "lock.home" await hass.services.async_call( "lock", SERVICE_OPEN, {ATTR_ENTITY_ID: entity_id}, blocking=True