mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 14:57:09 +00:00
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:
parent
a1ecefee21
commit
5c35ccb9ca
@ -38,13 +38,16 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|||||||
from .const import (
|
from .const import (
|
||||||
CONF_ENCRYPTION_KEY,
|
CONF_ENCRYPTION_KEY,
|
||||||
CONF_KEY_ID,
|
CONF_KEY_ID,
|
||||||
|
CONF_LOCK_NIGHTLATCH,
|
||||||
CONF_RETRY_COUNT,
|
CONF_RETRY_COUNT,
|
||||||
CONNECTABLE_SUPPORTED_MODEL_TYPES,
|
CONNECTABLE_SUPPORTED_MODEL_TYPES,
|
||||||
|
DEFAULT_LOCK_NIGHTLATCH,
|
||||||
DEFAULT_RETRY_COUNT,
|
DEFAULT_RETRY_COUNT,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES,
|
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES,
|
||||||
SUPPORTED_LOCK_MODELS,
|
SUPPORTED_LOCK_MODELS,
|
||||||
SUPPORTED_MODEL_TYPES,
|
SUPPORTED_MODEL_TYPES,
|
||||||
|
SupportedModels,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -355,7 +358,7 @@ class SwitchbotOptionsFlowHandler(OptionsFlow):
|
|||||||
# Update common entity options for all other entities.
|
# Update common entity options for all other entities.
|
||||||
return self.async_create_entry(title="", data=user_input)
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
|
||||||
options = {
|
options: dict[vol.Optional, Any] = {
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_RETRY_COUNT,
|
CONF_RETRY_COUNT,
|
||||||
default=self.config_entry.options.get(
|
default=self.config_entry.options.get(
|
||||||
@ -363,5 +366,16 @@ class SwitchbotOptionsFlowHandler(OptionsFlow):
|
|||||||
),
|
),
|
||||||
): int
|
): 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))
|
return self.async_show_form(step_id="init", data_schema=vol.Schema(options))
|
||||||
|
@ -64,11 +64,13 @@ HASS_SENSOR_TYPE_TO_SWITCHBOT_MODEL = {
|
|||||||
|
|
||||||
# Config Defaults
|
# Config Defaults
|
||||||
DEFAULT_RETRY_COUNT = 3
|
DEFAULT_RETRY_COUNT = 3
|
||||||
|
DEFAULT_LOCK_NIGHTLATCH = False
|
||||||
|
|
||||||
# Config Options
|
# Config Options
|
||||||
CONF_RETRY_COUNT = "retry_count"
|
CONF_RETRY_COUNT = "retry_count"
|
||||||
CONF_KEY_ID = "key_id"
|
CONF_KEY_ID = "key_id"
|
||||||
CONF_ENCRYPTION_KEY = "encryption_key"
|
CONF_ENCRYPTION_KEY = "encryption_key"
|
||||||
|
CONF_LOCK_NIGHTLATCH = "lock_force_nightlatch"
|
||||||
|
|
||||||
# Deprecated config Entry Options to be removed in 2023.4
|
# Deprecated config Entry Options to be removed in 2023.4
|
||||||
CONF_TIME_BETWEEN_UPDATE_COMMAND = "update_time"
|
CONF_TIME_BETWEEN_UPDATE_COMMAND = "update_time"
|
||||||
|
@ -9,6 +9,7 @@ from homeassistant.components.lock import LockEntity, LockEntityFeature
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from .const import CONF_LOCK_NIGHTLATCH, DEFAULT_LOCK_NIGHTLATCH
|
||||||
from .coordinator import SwitchbotConfigEntry, SwitchbotDataUpdateCoordinator
|
from .coordinator import SwitchbotConfigEntry, SwitchbotDataUpdateCoordinator
|
||||||
from .entity import SwitchbotEntity
|
from .entity import SwitchbotEntity
|
||||||
|
|
||||||
@ -19,7 +20,8 @@ async def async_setup_entry(
|
|||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Switchbot lock based on a config entry."""
|
"""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
|
# noinspection PyAbstractClass
|
||||||
@ -30,11 +32,13 @@ class SwitchBotLock(SwitchbotEntity, LockEntity):
|
|||||||
_attr_name = None
|
_attr_name = None
|
||||||
_device: switchbot.SwitchbotLock
|
_device: switchbot.SwitchbotLock
|
||||||
|
|
||||||
def __init__(self, coordinator: SwitchbotDataUpdateCoordinator) -> None:
|
def __init__(
|
||||||
|
self, coordinator: SwitchbotDataUpdateCoordinator, force_nightlatch
|
||||||
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._async_update_attrs()
|
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
|
self._attr_supported_features = LockEntityFeature.OPEN
|
||||||
|
|
||||||
def _async_update_attrs(self) -> None:
|
def _async_update_attrs(self) -> None:
|
||||||
@ -55,7 +59,7 @@ class SwitchBotLock(SwitchbotEntity, LockEntity):
|
|||||||
|
|
||||||
async def async_unlock(self, **kwargs: Any) -> None:
|
async def async_unlock(self, **kwargs: Any) -> None:
|
||||||
"""Unlock the lock."""
|
"""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()
|
self._last_run_success = await self._device.unlock_without_unlatch()
|
||||||
else:
|
else:
|
||||||
self._last_run_success = await self._device.unlock()
|
self._last_run_success = await self._device.unlock()
|
||||||
|
@ -54,7 +54,8 @@
|
|||||||
"step": {
|
"step": {
|
||||||
"init": {
|
"init": {
|
||||||
"data": {
|
"data": {
|
||||||
"retry_count": "Retry count"
|
"retry_count": "Retry count",
|
||||||
|
"lock_force_nightlatch": "Force Nightlatch operation mode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ from switchbot import SwitchbotAccountConnectionError, SwitchbotAuthenticationEr
|
|||||||
from homeassistant.components.switchbot.const import (
|
from homeassistant.components.switchbot.const import (
|
||||||
CONF_ENCRYPTION_KEY,
|
CONF_ENCRYPTION_KEY,
|
||||||
CONF_KEY_ID,
|
CONF_KEY_ID,
|
||||||
|
CONF_LOCK_NIGHTLATCH,
|
||||||
CONF_RETRY_COUNT,
|
CONF_RETRY_COUNT,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import SOURCE_BLUETOOTH, SOURCE_USER
|
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 len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
assert entry.options[CONF_RETRY_COUNT] == 6
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user