Allow Switchbot users to force nightlatch (#124326)

* Add option to force nightlatch operation mode

* Fix format

* Make the new option available only for lock pro entry

* use senor_type instead of switchbot model + tests

* Update homeassistant/components/switchbot/lock.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Michal Jál 2024-09-04 15:03:59 +02:00 committed by GitHub
parent a1ecefee21
commit 5c35ccb9ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 90 additions and 6 deletions

View File

@ -38,13 +38,16 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import (
CONF_ENCRYPTION_KEY,
CONF_KEY_ID,
CONF_LOCK_NIGHTLATCH,
CONF_RETRY_COUNT,
CONNECTABLE_SUPPORTED_MODEL_TYPES,
DEFAULT_LOCK_NIGHTLATCH,
DEFAULT_RETRY_COUNT,
DOMAIN,
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES,
SUPPORTED_LOCK_MODELS,
SUPPORTED_MODEL_TYPES,
SupportedModels,
)
_LOGGER = logging.getLogger(__name__)
@ -355,7 +358,7 @@ class SwitchbotOptionsFlowHandler(OptionsFlow):
# Update common entity options for all other entities.
return self.async_create_entry(title="", data=user_input)
options = {
options: dict[vol.Optional, Any] = {
vol.Optional(
CONF_RETRY_COUNT,
default=self.config_entry.options.get(
@ -363,5 +366,16 @@ class SwitchbotOptionsFlowHandler(OptionsFlow):
),
): int
}
if self.config_entry.data.get(CONF_SENSOR_TYPE) == SupportedModels.LOCK_PRO:
options.update(
{
vol.Optional(
CONF_LOCK_NIGHTLATCH,
default=self.config_entry.options.get(
CONF_LOCK_NIGHTLATCH, DEFAULT_LOCK_NIGHTLATCH
),
): bool
}
)
return self.async_show_form(step_id="init", data_schema=vol.Schema(options))

View File

@ -64,11 +64,13 @@ HASS_SENSOR_TYPE_TO_SWITCHBOT_MODEL = {
# Config Defaults
DEFAULT_RETRY_COUNT = 3
DEFAULT_LOCK_NIGHTLATCH = False
# Config Options
CONF_RETRY_COUNT = "retry_count"
CONF_KEY_ID = "key_id"
CONF_ENCRYPTION_KEY = "encryption_key"
CONF_LOCK_NIGHTLATCH = "lock_force_nightlatch"
# Deprecated config Entry Options to be removed in 2023.4
CONF_TIME_BETWEEN_UPDATE_COMMAND = "update_time"

View File

@ -9,6 +9,7 @@ from homeassistant.components.lock import LockEntity, LockEntityFeature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_LOCK_NIGHTLATCH, DEFAULT_LOCK_NIGHTLATCH
from .coordinator import SwitchbotConfigEntry, SwitchbotDataUpdateCoordinator
from .entity import SwitchbotEntity
@ -19,7 +20,8 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Switchbot lock based on a config entry."""
async_add_entities([(SwitchBotLock(entry.runtime_data))])
force_nightlatch = entry.options.get(CONF_LOCK_NIGHTLATCH, DEFAULT_LOCK_NIGHTLATCH)
async_add_entities([SwitchBotLock(entry.runtime_data, force_nightlatch)])
# noinspection PyAbstractClass
@ -30,11 +32,13 @@ class SwitchBotLock(SwitchbotEntity, LockEntity):
_attr_name = None
_device: switchbot.SwitchbotLock
def __init__(self, coordinator: SwitchbotDataUpdateCoordinator) -> None:
def __init__(
self, coordinator: SwitchbotDataUpdateCoordinator, force_nightlatch
) -> None:
"""Initialize the entity."""
super().__init__(coordinator)
self._async_update_attrs()
if self._device.is_night_latch_enabled():
if self._device.is_night_latch_enabled() or force_nightlatch:
self._attr_supported_features = LockEntityFeature.OPEN
def _async_update_attrs(self) -> None:
@ -55,7 +59,7 @@ class SwitchBotLock(SwitchbotEntity, LockEntity):
async def async_unlock(self, **kwargs: Any) -> None:
"""Unlock the lock."""
if self._device.is_night_latch_enabled():
if self._attr_supported_features & (LockEntityFeature.OPEN):
self._last_run_success = await self._device.unlock_without_unlatch()
else:
self._last_run_success = await self._device.unlock()

View File

@ -54,7 +54,8 @@
"step": {
"init": {
"data": {
"retry_count": "Retry count"
"retry_count": "Retry count",
"lock_force_nightlatch": "Force Nightlatch operation mode"
}
}
}

View File

@ -7,6 +7,7 @@ from switchbot import SwitchbotAccountConnectionError, SwitchbotAuthenticationEr
from homeassistant.components.switchbot.const import (
CONF_ENCRYPTION_KEY,
CONF_KEY_ID,
CONF_LOCK_NIGHTLATCH,
CONF_RETRY_COUNT,
)
from homeassistant.config_entries import SOURCE_BLUETOOTH, SOURCE_USER
@ -782,3 +783,65 @@ async def test_options_flow(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1
assert entry.options[CONF_RETRY_COUNT] == 6
async def test_options_flow_lock_pro(hass: HomeAssistant) -> None:
"""Test updating options."""
entry = MockConfigEntry(
domain=DOMAIN,
data={
CONF_ADDRESS: "aa:bb:cc:dd:ee:ff",
CONF_NAME: "test-name",
CONF_PASSWORD: "test-password",
CONF_SENSOR_TYPE: "lock_pro",
},
options={CONF_RETRY_COUNT: 10},
unique_id="aabbccddeeff",
)
entry.add_to_hass(hass)
# Test Force night_latch should be disabled by default.
with patch_async_setup_entry() as mock_setup_entry:
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(entry.entry_id)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "init"
assert result["errors"] is None
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
CONF_RETRY_COUNT: 3,
},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_LOCK_NIGHTLATCH] is False
assert len(mock_setup_entry.mock_calls) == 1
# Test Set force night_latch to be enabled.
with patch_async_setup_entry() as mock_setup_entry:
result = await hass.config_entries.options.async_init(entry.entry_id)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "init"
assert result["errors"] is None
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
CONF_LOCK_NIGHTLATCH: True,
},
)
await hass.async_block_till_done()
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["data"][CONF_LOCK_NIGHTLATCH] is True
assert len(mock_setup_entry.mock_calls) == 0
assert entry.options[CONF_LOCK_NIGHTLATCH] is True