diff --git a/homeassistant/components/dsmr_reader/definitions.py b/homeassistant/components/dsmr_reader/definitions.py index 0721819e3128..cc0c851ebdad 100644 --- a/homeassistant/components/dsmr_reader/definitions.py +++ b/homeassistant/components/dsmr_reader/definitions.py @@ -560,8 +560,8 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = ( DSMRReaderSensorEntityDescription( key="dsmr/consumption/quarter-hour-peak-electricity/average_delivered", name="Previous quarter-hour peak usage", - device_class=SensorDeviceClass.ENERGY, - native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + device_class=SensorDeviceClass.POWER, + native_unit_of_measurement=UnitOfPower.KILO_WATT, ), DSMRReaderSensorEntityDescription( key="dsmr/consumption/quarter-hour-peak-electricity/read_at_start", diff --git a/homeassistant/components/google/manifest.json b/homeassistant/components/google/manifest.json index 100e128c8e31..9d2d96812a5a 100644 --- a/homeassistant/components/google/manifest.json +++ b/homeassistant/components/google/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "dependencies": ["application_credentials"], "documentation": "https://www.home-assistant.io/integrations/calendar.google/", - "requirements": ["gcal-sync==4.1.0", "oauth2client==4.1.3"], + "requirements": ["gcal-sync==4.1.1", "oauth2client==4.1.3"], "codeowners": ["@allenporter"], "iot_class": "cloud_polling", "loggers": ["googleapiclient"] diff --git a/homeassistant/components/hydrawise/__init__.py b/homeassistant/components/hydrawise/__init__.py index da413cce5ab2..7074f86e4a8f 100644 --- a/homeassistant/components/hydrawise/__init__.py +++ b/homeassistant/components/hydrawise/__init__.py @@ -28,7 +28,7 @@ DATA_HYDRAWISE = "hydrawise" DOMAIN = "hydrawise" DEFAULT_WATERING_TIME = 15 -SCAN_INTERVAL = timedelta(seconds=30) +SCAN_INTERVAL = timedelta(seconds=120) SIGNAL_UPDATE_HYDRAWISE = "hydrawise_update" diff --git a/homeassistant/components/life360/manifest.json b/homeassistant/components/life360/manifest.json index eb3290e41e11..9fc13b1998ed 100644 --- a/homeassistant/components/life360/manifest.json +++ b/homeassistant/components/life360/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/life360", "codeowners": ["@pnbruckner"], - "requirements": ["life360==5.3.0"], + "requirements": ["life360==5.5.0"], "iot_class": "cloud_polling", "loggers": ["life360"] } diff --git a/homeassistant/components/local_calendar/manifest.json b/homeassistant/components/local_calendar/manifest.json index b277611dfdb1..2d70700facbe 100644 --- a/homeassistant/components/local_calendar/manifest.json +++ b/homeassistant/components/local_calendar/manifest.json @@ -3,7 +3,7 @@ "name": "Local Calendar", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/local_calendar", - "requirements": ["ical==4.2.8"], + "requirements": ["ical==4.2.9"], "codeowners": ["@allenporter"], "iot_class": "local_polling", "loggers": ["ical"] diff --git a/homeassistant/components/number/__init__.py b/homeassistant/components/number/__init__.py index de2580eab75e..dfb923a8d015 100644 --- a/homeassistant/components/number/__init__.py +++ b/homeassistant/components/number/__init__.py @@ -213,7 +213,7 @@ class NumberDeviceClass(StrEnum): POWER_FACTOR = "power_factor" """Power factor. - Unit of measurement: `%` + Unit of measurement: `%`, `None` """ POWER = "power" diff --git a/homeassistant/components/philips_js/media_player.py b/homeassistant/components/philips_js/media_player.py index d9ea06c2f2c5..684dafbc750a 100644 --- a/homeassistant/components/philips_js/media_player.py +++ b/homeassistant/components/philips_js/media_player.py @@ -210,7 +210,7 @@ class PhilipsTVMediaPlayer( async def async_media_play_pause(self) -> None: """Send pause command to media player.""" if self._tv.quirk_playpause_spacebar: - await self._tv.sendUnicode(" ") + await self._tv.sendKey("Confirm") else: await self._tv.sendKey("PlayPause") await self._async_update_soon() @@ -509,6 +509,8 @@ class PhilipsTVMediaPlayer( self._media_title = self._sources.get(self._tv.source_id) self._media_channel = None + self._attr_assumed_state = True + @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index 9ea4422203b6..dfa8dfe8e6b3 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -3,7 +3,7 @@ "name": "Reolink IP NVR/camera", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/reolink", - "requirements": ["reolink-aio==0.1.2"], + "requirements": ["reolink-aio==0.1.3"], "codeowners": ["@starkillerOG"], "iot_class": "local_polling", "loggers": ["reolink-aio"] diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 7beac83f0599..5a96036f22b2 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -309,7 +309,7 @@ class SensorDeviceClass(StrEnum): POWER_FACTOR = "power_factor" """Power factor. - Unit of measurement: `%` + Unit of measurement: `%`, `None` """ POWER = "power" @@ -521,7 +521,7 @@ DEVICE_CLASS_UNITS: dict[SensorDeviceClass, set[type[StrEnum] | str | None]] = { SensorDeviceClass.PM1: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}, SensorDeviceClass.PM10: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}, SensorDeviceClass.PM25: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}, - SensorDeviceClass.POWER_FACTOR: {PERCENTAGE}, + SensorDeviceClass.POWER_FACTOR: {PERCENTAGE, None}, SensorDeviceClass.POWER: {UnitOfPower.WATT, UnitOfPower.KILO_WATT}, SensorDeviceClass.PRECIPITATION: set(UnitOfPrecipitationDepth), SensorDeviceClass.PRECIPITATION_INTENSITY: set(UnitOfVolumetricFlux), diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index c38573f82ca5..b543e7f15e7a 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -2,7 +2,7 @@ "domain": "switchbot", "name": "SwitchBot", "documentation": "https://www.home-assistant.io/integrations/switchbot", - "requirements": ["PySwitchbot==0.36.2"], + "requirements": ["PySwitchbot==0.36.3"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/homeassistant/components/switchbot/strings.json b/homeassistant/components/switchbot/strings.json index c25769bee411..d263aed3dd5d 100644 --- a/homeassistant/components/switchbot/strings.json +++ b/homeassistant/components/switchbot/strings.json @@ -24,7 +24,7 @@ } }, "lock_auth": { - "description": "Please provide your SwitchBot app username and password. This data won't be saved and only used to retrieve your locks encryption key.", + "description": "Please provide your SwitchBot app username and password. This data won't be saved and only used to retrieve your locks encryption key. Usernames and passwords are case sensitive.", "data": { "username": "[%key:common::config_flow::data::username%]", "password": "[%key:common::config_flow::data::password%]" diff --git a/homeassistant/components/switchbot/translations/en.json b/homeassistant/components/switchbot/translations/en.json index d7065138051b..fed02f12a380 100644 --- a/homeassistant/components/switchbot/translations/en.json +++ b/homeassistant/components/switchbot/translations/en.json @@ -21,7 +21,7 @@ "password": "Password", "username": "Username" }, - "description": "Please provide your SwitchBot app username and password. This data won't be saved and only used to retrieve your locks encryption key." + "description": "Please provide your SwitchBot app username and password. This data won't be saved and only used to retrieve your locks encryption key. Usernames and passwords are case sensitive." }, "lock_choose_method": { "description": "A SwitchBot lock can be set up in Home Assistant in two different ways.\n\nYou can enter the key id and encryption key yourself, or Home Assistant can import them from your SwitchBot account.", diff --git a/homeassistant/components/zha/core/gateway.py b/homeassistant/components/zha/core/gateway.py index 6a02a21781df..ffd005e8edc1 100644 --- a/homeassistant/components/zha/core/gateway.py +++ b/homeassistant/components/zha/core/gateway.py @@ -17,6 +17,7 @@ from zigpy.application import ControllerApplication from zigpy.config import CONF_DEVICE import zigpy.device import zigpy.endpoint +import zigpy.exceptions import zigpy.group from zigpy.types.named import EUI64 @@ -24,6 +25,7 @@ from homeassistant import __path__ as HOMEASSISTANT_PATH from homeassistant.components.system_log import LogEntry, _figure_out_source from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback +from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.entity import DeviceInfo @@ -172,6 +174,8 @@ class ZHAGateway: self.application_controller = await app_controller_cls.new( app_config, auto_form=True, start_radio=True ) + except zigpy.exceptions.TransientConnectionError as exc: + raise ConfigEntryNotReady from exc except Exception as exc: # pylint: disable=broad-except _LOGGER.warning( "Couldn't start %s coordinator (attempt %s of %s)", diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 7f8568f1ab3d..9adddc97720c 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -4,12 +4,12 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ - "bellows==0.34.5", + "bellows==0.34.6", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.90", "zigpy-deconz==0.19.2", - "zigpy==0.52.3", + "zigpy==0.53.0", "zigpy-xbee==0.16.2", "zigpy-zigate==0.10.3", "zigpy-znp==0.9.2" diff --git a/homeassistant/const.py b/homeassistant/const.py index 7d65c6b44a30..5aab387caa8d 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -8,7 +8,7 @@ from .backports.enum import StrEnum APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 1 -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) diff --git a/pyproject.toml b/pyproject.toml index 4bb8a5f29118..5c6450bd8e51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.1.1" +version = "2023.1.2" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" diff --git a/requirements_all.txt b/requirements_all.txt index 20c80512c2dc..d6cadbfd26ac 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -40,7 +40,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.36.2 +PySwitchbot==0.36.3 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 @@ -419,7 +419,7 @@ beautifulsoup4==4.11.1 # beewi_smartclim==0.0.10 # homeassistant.components.zha -bellows==0.34.5 +bellows==0.34.6 # homeassistant.components.bmw_connected_drive bimmer_connected==0.12.0 @@ -744,7 +744,7 @@ gTTS==2.2.4 gassist-text==0.0.7 # homeassistant.components.google -gcal-sync==4.1.0 +gcal-sync==4.1.1 # homeassistant.components.geniushub geniushub-client==0.6.30 @@ -930,7 +930,7 @@ ibm-watson==5.2.2 ibmiotf==0.3.4 # homeassistant.components.local_calendar -ical==4.2.8 +ical==4.2.9 # homeassistant.components.ping icmplib==3.0 @@ -1029,7 +1029,7 @@ librouteros==3.2.0 libsoundtouch==0.8 # homeassistant.components.life360 -life360==5.3.0 +life360==5.5.0 # homeassistant.components.osramlightify lightify==1.0.7.3 @@ -2190,7 +2190,7 @@ regenmaschine==2022.11.0 renault-api==0.1.11 # homeassistant.components.reolink -reolink-aio==0.1.2 +reolink-aio==0.1.3 # homeassistant.components.python_script restrictedpython==5.2 @@ -2668,7 +2668,7 @@ zigpy-zigate==0.10.3 zigpy-znp==0.9.2 # homeassistant.components.zha -zigpy==0.52.3 +zigpy==0.53.0 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f1bbc843baaf..315fc975e5b2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -36,7 +36,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.36.2 +PySwitchbot==0.36.3 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 @@ -346,7 +346,7 @@ base36==0.1.1 beautifulsoup4==4.11.1 # homeassistant.components.zha -bellows==0.34.5 +bellows==0.34.6 # homeassistant.components.bmw_connected_drive bimmer_connected==0.12.0 @@ -560,7 +560,7 @@ gTTS==2.2.4 gassist-text==0.0.7 # homeassistant.components.google -gcal-sync==4.1.0 +gcal-sync==4.1.1 # homeassistant.components.geocaching geocachingapi==0.2.1 @@ -695,7 +695,7 @@ iaqualink==0.5.0 ibeacon_ble==1.0.1 # homeassistant.components.local_calendar -ical==4.2.8 +ical==4.2.9 # homeassistant.components.ping icmplib==3.0 @@ -767,7 +767,7 @@ librouteros==3.2.0 libsoundtouch==0.8 # homeassistant.components.life360 -life360==5.3.0 +life360==5.5.0 # homeassistant.components.logi_circle logi_circle==0.2.3 @@ -1529,7 +1529,7 @@ regenmaschine==2022.11.0 renault-api==0.1.11 # homeassistant.components.reolink -reolink-aio==0.1.2 +reolink-aio==0.1.3 # homeassistant.components.python_script restrictedpython==5.2 @@ -1869,7 +1869,7 @@ zigpy-zigate==0.10.3 zigpy-znp==0.9.2 # homeassistant.components.zha -zigpy==0.52.3 +zigpy==0.53.0 # homeassistant.components.zwave_js zwave-js-server-python==0.44.0 diff --git a/tests/components/zha/common.py b/tests/components/zha/common.py index a6a533acc71e..53935caa4359 100644 --- a/tests/components/zha/common.py +++ b/tests/components/zha/common.py @@ -77,7 +77,7 @@ def update_attribute_cache(cluster): attrid = zigpy.types.uint16_t(attrid) attrs.append(make_attribute(attrid, value)) - hdr = make_zcl_header(zcl_f.Command.Report_Attributes) + hdr = make_zcl_header(zcl_f.GeneralCommand.Report_Attributes) hdr.frame_control.disable_default_response = True msg = zcl_f.GENERAL_COMMANDS[zcl_f.GeneralCommand.Report_Attributes].schema( attribute_reports=attrs diff --git a/tests/components/zha/test_gateway.py b/tests/components/zha/test_gateway.py index bc49b04d86af..4eb95a8441bc 100644 --- a/tests/components/zha/test_gateway.py +++ b/tests/components/zha/test_gateway.py @@ -3,12 +3,14 @@ import asyncio from unittest.mock import AsyncMock, MagicMock, patch import pytest +import zigpy.exceptions import zigpy.profiles.zha as zha import zigpy.zcl.clusters.general as general import zigpy.zcl.clusters.lighting as lighting from homeassistant.components.zha.core.group import GroupMember from homeassistant.const import Platform +from homeassistant.exceptions import ConfigEntryNotReady from .common import async_find_group_entity_id, get_zha_gateway from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE @@ -259,3 +261,20 @@ async def test_gateway_initialize_failure(hass, device_light_1, coordinator): await zha_gateway.async_initialize() assert mock_new.call_count == 3 + + +@patch("homeassistant.components.zha.core.gateway.STARTUP_FAILURE_DELAY_S", 0.01) +async def test_gateway_initialize_failure_transient(hass, device_light_1, coordinator): + """Test ZHA failing to initialize the gateway but with a transient error.""" + zha_gateway = get_zha_gateway(hass) + assert zha_gateway is not None + + with patch( + "bellows.zigbee.application.ControllerApplication.new", + side_effect=[RuntimeError(), zigpy.exceptions.TransientConnectionError()], + ) as mock_new: + with pytest.raises(ConfigEntryNotReady): + await zha_gateway.async_initialize() + + # Initialization immediately stops and is retried after TransientConnectionError + assert mock_new.call_count == 2