Update PySwitchbot to improve connection reliability (#75692)

This commit is contained in:
J. Nick Koston 2022-07-24 16:38:07 -05:00 committed by GitHub
parent c9ae409d9a
commit d890598da7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 16 additions and 80 deletions

View File

@ -1,9 +1,6 @@
"""Support for Switchbot devices."""
from collections.abc import Mapping
import logging
from types import MappingProxyType
from typing import Any
import switchbot
@ -24,11 +21,8 @@ from .const import (
ATTR_BOT,
ATTR_CURTAIN,
ATTR_HYGROMETER,
COMMON_OPTIONS,
CONF_RETRY_COUNT,
CONF_RETRY_TIMEOUT,
DEFAULT_RETRY_COUNT,
DEFAULT_RETRY_TIMEOUT,
DOMAIN,
)
from .coordinator import SwitchbotDataUpdateCoordinator
@ -49,8 +43,6 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Switchbot from a config entry."""
hass.data.setdefault(DOMAIN, {})
domain_data = hass.data[DOMAIN]
if CONF_ADDRESS not in entry.data and CONF_MAC in entry.data:
# Bleak uses addresses not mac addresses which are are actually
# UUIDs on some platforms (MacOS).
@ -65,10 +57,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if not entry.options:
hass.config_entries.async_update_entry(
entry,
options={
CONF_RETRY_COUNT: DEFAULT_RETRY_COUNT,
CONF_RETRY_TIMEOUT: DEFAULT_RETRY_TIMEOUT,
},
options={CONF_RETRY_COUNT: DEFAULT_RETRY_COUNT},
)
sensor_type: str = entry.data[CONF_SENSOR_TYPE]
@ -78,13 +67,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
raise ConfigEntryNotReady(
f"Could not find Switchbot {sensor_type} with address {address}"
)
if COMMON_OPTIONS not in domain_data:
domain_data[COMMON_OPTIONS] = entry.options
common_options: Mapping[str, int] = domain_data[COMMON_OPTIONS]
switchbot.DEFAULT_RETRY_TIMEOUT = common_options[CONF_RETRY_TIMEOUT]
cls = CLASS_BY_DEVICE.get(sensor_type, switchbot.SwitchbotDevice)
device = cls(
device=ble_device,
@ -92,7 +74,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
retry_count=entry.options[CONF_RETRY_COUNT],
)
coordinator = hass.data[DOMAIN][entry.entry_id] = SwitchbotDataUpdateCoordinator(
hass, _LOGGER, ble_device, device, common_options
hass, _LOGGER, ble_device, device
)
entry.async_on_unload(coordinator.async_start())
if not await coordinator.async_wait_ready():
@ -106,6 +88,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True
async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
sensor_type = entry.data[CONF_SENSOR_TYPE]
@ -119,11 +106,3 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.pop(DOMAIN)
return unload_ok
async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle options update."""
# Update entity options stored in hass.
common_options: MappingProxyType[str, Any] = hass.data[DOMAIN][COMMON_OPTIONS]
if entry.options != common_options:
await hass.config_entries.async_reload(entry.entry_id)

View File

@ -17,14 +17,7 @@ from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.service_info.bluetooth import BluetoothServiceInfo
from .const import (
CONF_RETRY_COUNT,
CONF_RETRY_TIMEOUT,
DEFAULT_RETRY_COUNT,
DEFAULT_RETRY_TIMEOUT,
DOMAIN,
SUPPORTED_MODEL_TYPES,
)
from .const import CONF_RETRY_COUNT, DEFAULT_RETRY_COUNT, DOMAIN, SUPPORTED_MODEL_TYPES
_LOGGER = logging.getLogger(__name__)
@ -140,11 +133,6 @@ class SwitchbotOptionsFlowHandler(OptionsFlow):
"""Manage Switchbot options."""
if user_input is not None:
# Update common entity options for all other entities.
for entry in self.hass.config_entries.async_entries(DOMAIN):
if entry.unique_id != self.config_entry.unique_id:
self.hass.config_entries.async_update_entry(
entry, options=user_input
)
return self.async_create_entry(title="", data=user_input)
options = {
@ -153,13 +141,7 @@ class SwitchbotOptionsFlowHandler(OptionsFlow):
default=self.config_entry.options.get(
CONF_RETRY_COUNT, DEFAULT_RETRY_COUNT
),
): int,
vol.Optional(
CONF_RETRY_TIMEOUT,
default=self.config_entry.options.get(
CONF_RETRY_TIMEOUT, DEFAULT_RETRY_TIMEOUT
),
): int,
): int
}
return self.async_show_form(step_id="init", data_schema=vol.Schema(options))

View File

@ -15,15 +15,11 @@ SUPPORTED_MODEL_TYPES = {
# Config Defaults
DEFAULT_RETRY_COUNT = 3
DEFAULT_RETRY_TIMEOUT = 5
# Config Options
CONF_RETRY_COUNT = "retry_count"
CONF_SCAN_TIMEOUT = "scan_timeout"
# Deprecated config Entry Options to be removed in 2023.4
CONF_TIME_BETWEEN_UPDATE_COMMAND = "update_time"
CONF_RETRY_TIMEOUT = "retry_timeout"
# Data
COMMON_OPTIONS = "common_options"
CONF_SCAN_TIMEOUT = "scan_timeout"

View File

@ -2,7 +2,6 @@
from __future__ import annotations
import asyncio
from collections.abc import Mapping
import logging
from typing import Any, cast
@ -16,8 +15,6 @@ from homeassistant.components.bluetooth.passive_update_coordinator import (
)
from homeassistant.core import HomeAssistant, callback
from .const import CONF_RETRY_COUNT
_LOGGER = logging.getLogger(__name__)
@ -38,21 +35,14 @@ class SwitchbotDataUpdateCoordinator(PassiveBluetoothDataUpdateCoordinator):
logger: logging.Logger,
ble_device: BLEDevice,
device: switchbot.SwitchbotDevice,
common_options: Mapping[str, int],
) -> None:
"""Initialize global switchbot data updater."""
super().__init__(hass, logger, ble_device.address)
self.ble_device = ble_device
self.device = device
self.common_options = common_options
self.data: dict[str, Any] = {}
self._ready_event = asyncio.Event()
@property
def retry_count(self) -> int:
"""Return retry count."""
return self.common_options[CONF_RETRY_COUNT]
@callback
def _async_handle_bluetooth_event(
self,

View File

@ -2,7 +2,7 @@
"domain": "switchbot",
"name": "SwitchBot",
"documentation": "https://www.home-assistant.io/integrations/switchbot",
"requirements": ["PySwitchbot==0.15.0"],
"requirements": ["PySwitchbot==0.15.1"],
"config_flow": true,
"dependencies": ["bluetooth"],
"codeowners": ["@danielhiversen", "@RenierM26", "@murtas"],

View File

@ -24,8 +24,7 @@
"step": {
"init": {
"data": {
"retry_count": "Retry count",
"retry_timeout": "Timeout between retries"
"retry_count": "Retry count"
}
}
}

View File

@ -24,8 +24,7 @@
"step": {
"init": {
"data": {
"retry_count": "Retry count",
"retry_timeout": "Timeout between retries"
"retry_count": "Retry count"
}
}
}

View File

@ -37,7 +37,7 @@ PyRMVtransport==0.3.3
PySocks==1.7.1
# homeassistant.components.switchbot
PySwitchbot==0.15.0
PySwitchbot==0.15.1
# homeassistant.components.transport_nsw
PyTransportNSW==0.1.1

View File

@ -33,7 +33,7 @@ PyRMVtransport==0.3.3
PySocks==1.7.1
# homeassistant.components.switchbot
PySwitchbot==0.15.0
PySwitchbot==0.15.1
# homeassistant.components.transport_nsw
PyTransportNSW==0.1.1

View File

@ -2,10 +2,7 @@
from unittest.mock import patch
from homeassistant.components.switchbot.const import (
CONF_RETRY_COUNT,
CONF_RETRY_TIMEOUT,
)
from homeassistant.components.switchbot.const import CONF_RETRY_COUNT
from homeassistant.config_entries import SOURCE_BLUETOOTH, SOURCE_USER
from homeassistant.const import CONF_ADDRESS, CONF_NAME, CONF_PASSWORD, CONF_SENSOR_TYPE
from homeassistant.data_entry_flow import FlowResultType
@ -276,7 +273,6 @@ async def test_options_flow(hass):
},
options={
CONF_RETRY_COUNT: 10,
CONF_RETRY_TIMEOUT: 10,
},
unique_id="aabbccddeeff",
)
@ -294,14 +290,12 @@ async def test_options_flow(hass):
result["flow_id"],
user_input={
CONF_RETRY_COUNT: 3,
CONF_RETRY_TIMEOUT: 5,
},
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["data"][CONF_RETRY_COUNT] == 3
assert result["data"][CONF_RETRY_TIMEOUT] == 5
assert len(mock_setup_entry.mock_calls) == 2
@ -319,16 +313,13 @@ async def test_options_flow(hass):
result["flow_id"],
user_input={
CONF_RETRY_COUNT: 6,
CONF_RETRY_TIMEOUT: 6,
},
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["data"][CONF_RETRY_COUNT] == 6
assert result["data"][CONF_RETRY_TIMEOUT] == 6
assert len(mock_setup_entry.mock_calls) == 1
assert entry.options[CONF_RETRY_COUNT] == 6
assert entry.options[CONF_RETRY_TIMEOUT] == 6