This commit is contained in:
Paulus Schoutsen 2022-12-11 14:58:31 -05:00 committed by GitHub
commit 9b4d86399e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 108 additions and 83 deletions

View File

@ -4,7 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/androidtv",
"requirements": [
"adb-shell[async]==0.4.3",
"androidtv[async]==0.0.69",
"androidtv[async]==0.0.70",
"pure-python-adb[async]==0.3.0.dev0"
],
"codeowners": ["@JeffLIrion", "@ollo69"],

View File

@ -7,7 +7,7 @@ import voluptuous as vol
from homeassistant import auth, config_entries, core
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, dispatcher
from homeassistant.helpers import config_validation as cv, dispatcher, instance_id
from homeassistant.helpers.network import NoURLAvailableError, get_url
from homeassistant.helpers.service import async_register_admin_service
@ -49,10 +49,13 @@ async def async_setup_ha_cast(
except NoURLAvailableError as err:
raise HomeAssistantError(NO_URL_AVAILABLE_ERROR) from err
hass_uuid = await instance_id.async_get(hass)
controller = HomeAssistantController(
# If you are developing Home Assistant Cast, uncomment and set to your dev app id.
# app_id="5FE44367",
hass_url=hass_url,
hass_uuid=hass_uuid,
client_id=None,
refresh_token=refresh_token.token,
)

View File

@ -3,7 +3,7 @@
"name": "Google Cast",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/cast",
"requirements": ["pychromecast==13.0.1"],
"requirements": ["pychromecast==13.0.2"],
"after_dependencies": [
"cloud",
"http",

View File

@ -164,7 +164,8 @@ class FibaroThermostat(FibaroDevice, ClimateEntity):
):
self._target_temp_device = FibaroDevice(device)
self._attr_supported_features |= ClimateEntityFeature.TARGET_TEMPERATURE
tempunit = device.properties.unit
if "unit" in device.properties:
tempunit = device.properties.unit
if any(action for action in OP_MODE_ACTIONS if action in device.actions):
self._op_mode_device = FibaroDevice(device)

View File

@ -669,6 +669,9 @@ class AvmWrapper(FritzBoxTools):
def wrap_external_ipv6() -> str:
return str(self.fritz_status.external_ipv6)
if not self.device_is_router:
return False
return bool(await self.hass.async_add_executor_job(wrap_external_ipv6))
async def async_get_connection_info(self) -> ConnectionInfo:

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
from xml.etree.ElementTree import ParseError
from pyfritzhome import Fritzhome, FritzhomeDevice, LoginError
from pyfritzhome.devicetypes import FritzhomeTemplate
@ -34,6 +35,13 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
self.entry = entry
self.fritz: Fritzhome = hass.data[DOMAIN][self.entry.entry_id][CONF_CONNECTIONS]
self.configuration_url = self.fritz.get_prefixed_host()
self.has_templates = True
try:
hass.async_add_executor_job(self.fritz.update_templates)
except ParseError:
LOGGER.info("Disable smarthome templates")
self.has_templates = False
super().__init__(
hass,
LOGGER,
@ -45,7 +53,8 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
"""Update all fritzbox device data."""
try:
self.fritz.update_devices()
self.fritz.update_templates()
if self.has_templates:
self.fritz.update_templates()
except requests.exceptions.ConnectionError as ex:
raise UpdateFailed from ex
except requests.exceptions.HTTPError:
@ -55,7 +64,8 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
except LoginError as ex:
raise ConfigEntryAuthFailed from ex
self.fritz.update_devices()
self.fritz.update_templates()
if self.has_templates:
self.fritz.update_templates()
devices = self.fritz.get_devices()
device_data = {}
@ -75,10 +85,11 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
device_data[device.ain] = device
templates = self.fritz.get_templates()
template_data = {}
for template in templates:
template_data[template.ain] = template
if self.has_templates:
templates = self.fritz.get_templates()
for template in templates:
template_data[template.ain] = template
return FritzboxCoordinatorData(devices=device_data, templates=template_data)

View File

@ -5,7 +5,7 @@
"documentation": "https://www.home-assistant.io/integrations/lifx",
"requirements": [
"aiolifx==0.8.7",
"aiolifx_effects==0.3.0",
"aiolifx_effects==0.3.1",
"aiolifx_themes==0.2.0"
],
"quality_scale": "platinum",

View File

@ -3,7 +3,7 @@
"name": "Risco",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/risco",
"requirements": ["pyrisco==0.5.6"],
"requirements": ["pyrisco==0.5.7"],
"codeowners": ["@OnFreund"],
"quality_scale": "platinum",
"iot_class": "local_push",

View File

@ -61,7 +61,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
load_coroutines: list[Coroutine[Any, Any, None]] = []
for resource_config in scrape_config:
rest = create_rest_data_from_config(hass, resource_config)
scan_interval: timedelta = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
scan_interval: timedelta = resource_config.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
)
coordinator = ScrapeCoordinator(hass, rest, scan_interval)
sensors: list[ConfigType] = resource_config.get(SENSOR_DOMAIN, [])

View File

@ -143,6 +143,7 @@ CONDITION_SCHEMA = vol.All(
CONF_IS_PRESSURE,
CONF_IS_REACTIVE_POWER,
CONF_IS_SIGNAL_STRENGTH,
CONF_IS_SPEED,
CONF_IS_SULPHUR_DIOXIDE,
CONF_IS_TEMPERATURE,
CONF_IS_VOLATILE_ORGANIC_COMPOUNDS,

View File

@ -143,6 +143,7 @@ TRIGGER_SCHEMA = vol.All(
CONF_PRESSURE,
CONF_REACTIVE_POWER,
CONF_SIGNAL_STRENGTH,
CONF_SPEED,
CONF_SULPHUR_DIOXIDE,
CONF_TEMPERATURE,
CONF_VOLATILE_ORGANIC_COMPOUNDS,

View File

@ -3,7 +3,7 @@
"name": "Shelly",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/shelly",
"requirements": ["aioshelly==5.1.0"],
"requirements": ["aioshelly==5.1.1"],
"dependencies": ["bluetooth", "http"],
"zeroconf": [
{

View File

@ -772,20 +772,29 @@ class ProtectEventSensor(EventEntityMixin, SensorEntity):
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
# do not call ProtectDeviceSensor method since we want event to get value here
EventEntityMixin._async_update_device_from_protect(self, device)
if (
is_on = self.entity_description.get_is_on(device)
is_license_plate = (
self.entity_description.ufp_smart_type
== SmartDetectObjectType.LICENSE_PLATE
)
if (
not is_on
or self._event is None
or (
is_license_plate
and (
self._event.metadata is None
or self._event.metadata.license_plate is None
)
)
):
if (
self._event is None
or self._event.metadata is None
or self._event.metadata.license_plate is None
):
self._attr_native_value = OBJECT_TYPE_NONE
else:
self._attr_native_value = self._event.metadata.license_plate.name
self._attr_native_value = OBJECT_TYPE_NONE
self._event = None
self._attr_extra_state_attributes = {}
return
if is_license_plate:
# type verified above
self._attr_native_value = self._event.metadata.license_plate.name # type: ignore[union-attr]
else:
if self._event is None:
self._attr_native_value = OBJECT_TYPE_NONE
else:
self._attr_native_value = self._event.smart_detect_types[0].value
self._attr_native_value = self._event.smart_detect_types[0].value

View File

@ -1,7 +1,6 @@
"""Config flow for Yale Access Bluetooth integration."""
from __future__ import annotations
import asyncio
import logging
from typing import Any
@ -27,7 +26,7 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.typing import DiscoveryInfoType
from .const import CONF_KEY, CONF_LOCAL_NAME, CONF_SLOT, DOMAIN
from .util import async_get_service_info, human_readable_name
from .util import async_find_existing_service_info, human_readable_name
_LOGGER = logging.getLogger(__name__)
@ -110,11 +109,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
)
raise AbortFlow(reason="already_configured")
try:
self._discovery_info = await async_get_service_info(
hass, local_name, address
)
except asyncio.TimeoutError:
self._discovery_info = async_find_existing_service_info(
hass, local_name, address
)
if not self._discovery_info:
return self.async_abort(reason="no_devices_found")
# Integration discovery should abort other flows unless they

View File

@ -6,10 +6,8 @@ import platform
from yalexs_ble import local_name_is_unique
from homeassistant.components.bluetooth import (
BluetoothScanningMode,
BluetoothServiceInfoBleak,
async_discovered_service_info,
async_process_advertisements,
)
from homeassistant.components.bluetooth.match import (
ADDRESS,
@ -18,8 +16,6 @@ from homeassistant.components.bluetooth.match import (
)
from homeassistant.core import HomeAssistant, callback
from .const import DEVICE_TIMEOUT
def bluetooth_callback_matcher(
local_name: str, address: str
@ -51,21 +47,6 @@ def async_find_existing_service_info(
return None
async def async_get_service_info(
hass: HomeAssistant, local_name: str, address: str
) -> BluetoothServiceInfoBleak:
"""Wait for the service info for the given local_name and address."""
if service_info := async_find_existing_service_info(hass, local_name, address):
return service_info
return await async_process_advertisements(
hass,
lambda service_info: True,
bluetooth_callback_matcher(local_name, address),
BluetoothScanningMode.ACTIVE,
DEVICE_TIMEOUT,
)
def short_address(address: str) -> str:
"""Convert a Bluetooth address to a short address."""
split_address = address.replace("-", ":").split(":")

View File

@ -8,7 +8,7 @@ from .backports.enum import StrEnum
APPLICATION_NAME: Final = "HomeAssistant"
MAJOR_VERSION: Final = 2022
MINOR_VERSION: Final = 12
PATCH_VERSION: Final = "1"
PATCH_VERSION: Final = "2"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "homeassistant"
version = "2022.12.1"
version = "2022.12.2"
license = {text = "Apache-2.0"}
description = "Open-source home automation platform running on Python 3."
readme = "README.rst"

View File

@ -196,7 +196,7 @@ aiokef==0.2.16
aiolifx==0.8.7
# homeassistant.components.lifx
aiolifx_effects==0.3.0
aiolifx_effects==0.3.1
# homeassistant.components.lifx
aiolifx_themes==0.2.0
@ -261,7 +261,7 @@ aiosenseme==0.6.1
aiosenz==1.0.0
# homeassistant.components.shelly
aioshelly==5.1.0
aioshelly==5.1.1
# homeassistant.components.skybell
aioskybell==22.7.0
@ -321,7 +321,7 @@ ambiclimate==0.2.1
amcrest==1.9.7
# homeassistant.components.androidtv
androidtv[async]==0.0.69
androidtv[async]==0.0.70
# homeassistant.components.anel_pwrctrl
anel_pwrctrl-homeassistant==0.0.1.dev2
@ -1504,7 +1504,7 @@ pycfdns==2.0.1
pychannels==1.2.3
# homeassistant.components.cast
pychromecast==13.0.1
pychromecast==13.0.2
# homeassistant.components.pocketcasts
pycketcasts==1.0.1
@ -1866,7 +1866,7 @@ pyrecswitch==1.0.2
pyrepetierng==0.1.0
# homeassistant.components.risco
pyrisco==0.5.6
pyrisco==0.5.7
# homeassistant.components.rituals_perfume_genie
pyrituals==0.0.6

View File

@ -174,7 +174,7 @@ aiokafka==0.7.2
aiolifx==0.8.7
# homeassistant.components.lifx
aiolifx_effects==0.3.0
aiolifx_effects==0.3.1
# homeassistant.components.lifx
aiolifx_themes==0.2.0
@ -236,7 +236,7 @@ aiosenseme==0.6.1
aiosenz==1.0.0
# homeassistant.components.shelly
aioshelly==5.1.0
aioshelly==5.1.1
# homeassistant.components.skybell
aioskybell==22.7.0
@ -290,7 +290,7 @@ amberelectric==1.0.4
ambiclimate==0.2.1
# homeassistant.components.androidtv
androidtv[async]==0.0.69
androidtv[async]==0.0.70
# homeassistant.components.anthemav
anthemav==1.4.1
@ -1077,7 +1077,7 @@ pybravia==0.2.3
pycfdns==2.0.1
# homeassistant.components.cast
pychromecast==13.0.1
pychromecast==13.0.2
# homeassistant.components.comfoconnect
pycomfoconnect==0.4
@ -1322,7 +1322,7 @@ pyps4-2ndscreen==1.3.1
pyqwikswitch==0.93
# homeassistant.components.risco
pyrisco==0.5.6
pyrisco==0.5.7
# homeassistant.components.rituals_perfume_genie
pyrituals==0.0.6

View File

@ -2,6 +2,7 @@
from __future__ import annotations
from unittest.mock import Mock, call, patch
from xml.etree.ElementTree import ParseError
from pyfritzhome import LoginError
import pytest
@ -167,7 +168,7 @@ async def test_coordinator_update_after_reboot(hass: HomeAssistant, fritz: Mock)
assert await hass.config_entries.async_setup(entry.entry_id)
assert fritz().update_devices.call_count == 2
assert fritz().update_templates.call_count == 1
assert fritz().update_templates.call_count == 2
assert fritz().get_devices.call_count == 1
assert fritz().get_templates.call_count == 1
assert fritz().login.call_count == 2
@ -265,3 +266,17 @@ async def test_raise_config_entry_not_ready_when_offline(hass: HomeAssistant):
entries = hass.config_entries.async_entries()
config_entry = entries[0]
assert config_entry.state is ConfigEntryState.SETUP_ERROR
async def test_disable_smarthome_templates(hass: HomeAssistant, fritz: Mock):
"""Test smarthome templates are disabled."""
entry = MockConfigEntry(
domain=FB_DOMAIN,
data=MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0],
unique_id="any",
)
entry.add_to_hass(hass)
fritz().update_templates.side_effect = [ParseError(), ""]
assert await hass.config_entries.async_setup(entry.entry_id)
assert fritz().update_templates.call_count == 1

View File

@ -400,8 +400,8 @@ async def test_bluetooth_step_success(hass: HomeAssistant) -> None:
async def test_integration_discovery_success(hass: HomeAssistant) -> None:
"""Test integration discovery step success path."""
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=YALE_ACCESS_LOCK_DISCOVERY_INFO,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[YALE_ACCESS_LOCK_DISCOVERY_INFO],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -443,8 +443,8 @@ async def test_integration_discovery_success(hass: HomeAssistant) -> None:
async def test_integration_discovery_device_not_found(hass: HomeAssistant) -> None:
"""Test integration discovery when the device is not found."""
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
side_effect=asyncio.TimeoutError,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -483,8 +483,8 @@ async def test_integration_discovery_takes_precedence_over_bluetooth(
assert flows[0]["context"]["local_name"] == YALE_ACCESS_LOCK_DISCOVERY_INFO.name
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=YALE_ACCESS_LOCK_DISCOVERY_INFO,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[YALE_ACCESS_LOCK_DISCOVERY_INFO],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -558,8 +558,8 @@ async def test_integration_discovery_updates_key_unique_local_name(
entry.add_to_hass(hass)
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=LOCK_DISCOVERY_INFO_UUID_ADDRESS,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[LOCK_DISCOVERY_INFO_UUID_ADDRESS],
), patch(
"homeassistant.components.yalexs_ble.async_setup_entry",
return_value=True,
@ -600,8 +600,8 @@ async def test_integration_discovery_updates_key_without_unique_local_name(
entry.add_to_hass(hass)
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=LOCK_DISCOVERY_INFO_UUID_ADDRESS,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[LOCK_DISCOVERY_INFO_UUID_ADDRESS],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -649,8 +649,8 @@ async def test_integration_discovery_updates_key_duplicate_local_name(
entry2.add_to_hass(hass)
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=LOCK_DISCOVERY_INFO_UUID_ADDRESS,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[LOCK_DISCOVERY_INFO_UUID_ADDRESS],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -695,8 +695,8 @@ async def test_integration_discovery_takes_precedence_over_bluetooth_uuid_addres
assert flows[0]["context"]["local_name"] == LOCK_DISCOVERY_INFO_UUID_ADDRESS.name
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=LOCK_DISCOVERY_INFO_UUID_ADDRESS,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[LOCK_DISCOVERY_INFO_UUID_ADDRESS],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -775,8 +775,8 @@ async def test_integration_discovery_takes_precedence_over_bluetooth_non_unique_
assert flows[0]["context"]["local_name"] == OLD_FIRMWARE_LOCK_DISCOVERY_INFO.name
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=OLD_FIRMWARE_LOCK_DISCOVERY_INFO,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[OLD_FIRMWARE_LOCK_DISCOVERY_INFO],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -851,8 +851,8 @@ async def test_user_is_setting_up_lock_and_discovery_happens_in_the_middle(
await valdidate_started.wait()
with patch(
"homeassistant.components.yalexs_ble.util.async_process_advertisements",
return_value=LOCK_DISCOVERY_INFO_UUID_ADDRESS,
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
return_value=[LOCK_DISCOVERY_INFO_UUID_ADDRESS],
):
discovery_result = await hass.config_entries.flow.async_init(
DOMAIN,