diff --git a/homeassistant/components/androidtv_remote/manifest.json b/homeassistant/components/androidtv_remote/manifest.json index cb7a969379e..f45dee34afe 100644 --- a/homeassistant/components/androidtv_remote/manifest.json +++ b/homeassistant/components/androidtv_remote/manifest.json @@ -8,6 +8,6 @@ "iot_class": "local_push", "loggers": ["androidtvremote2"], "quality_scale": "platinum", - "requirements": ["androidtvremote2==0.0.13"], + "requirements": ["androidtvremote2==0.0.14"], "zeroconf": ["_androidtvremote2._tcp.local."] } diff --git a/homeassistant/components/freebox/router.py b/homeassistant/components/freebox/router.py index 122242f1959..f5aa51983c6 100644 --- a/homeassistant/components/freebox/router.py +++ b/homeassistant/components/freebox/router.py @@ -72,6 +72,7 @@ class FreeboxRouter: self.devices: dict[str, dict[str, Any]] = {} self.disks: dict[int, dict[str, Any]] = {} + self.supports_raid = True self.raids: dict[int, dict[str, Any]] = {} self.sensors_temperature: dict[str, int] = {} self.sensors_connection: dict[str, float] = {} @@ -160,14 +161,21 @@ class FreeboxRouter: async def _update_raids_sensors(self) -> None: """Update Freebox raids.""" - # None at first request + if not self.supports_raid: + return + try: fbx_raids: list[dict[str, Any]] = await self._api.storage.get_raids() or [] except HttpRequestError: - _LOGGER.warning("Unable to enumerate raid disks") - else: - for fbx_raid in fbx_raids: - self.raids[fbx_raid["id"]] = fbx_raid + self.supports_raid = False + _LOGGER.info( + "Router %s API does not support RAID", + self.name, + ) + return + + for fbx_raid in fbx_raids: + self.raids[fbx_raid["id"]] = fbx_raid async def update_home_devices(self) -> None: """Update Home devices (alarm, light, sensor, switch, remote ...).""" diff --git a/homeassistant/components/litterrobot/manifest.json b/homeassistant/components/litterrobot/manifest.json index 2a4a3447eb6..9a3334cbaac 100644 --- a/homeassistant/components/litterrobot/manifest.json +++ b/homeassistant/components/litterrobot/manifest.json @@ -12,5 +12,5 @@ "integration_type": "hub", "iot_class": "cloud_push", "loggers": ["pylitterbot"], - "requirements": ["pylitterbot==2023.4.2"] + "requirements": ["pylitterbot==2023.4.5"] } diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index 44ad596b520..4f3f4a1c8a1 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -65,7 +65,6 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: name = config[CONF_NAME] structure = config.get(CONF_STRUCTURE) slave_count = config.get(CONF_SLAVE_COUNT, 0) + 1 - slave = config.get(CONF_SLAVE, 0) swap_type = config.get(CONF_SWAP, CONF_SWAP_NONE) if ( slave_count > 1 @@ -79,7 +78,7 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: error = f"{name} structure: cannot be mixed with {data_type}" if config[CONF_DATA_TYPE] == DataType.CUSTOM: - if slave or slave_count > 1: + if slave_count > 1: error = f"{name}: `{CONF_STRUCTURE}` illegal with `{CONF_SLAVE_COUNT}` / `{CONF_SLAVE}`" raise vol.Invalid(error) if swap_type != CONF_SWAP_NONE: @@ -125,8 +124,7 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: if count < regs_needed or (count % regs_needed) != 0: raise vol.Invalid( f"Error in sensor {name} swap({swap_type}) " - "not possible due to the registers " - f"count: {count}, needed: {regs_needed}" + f"impossible because datatype({data_type}) is too small" ) structure = f">{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" if slave_count > 1: diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index 70156703155..48b18a61782 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -1144,11 +1144,8 @@ class MqttEntity( ) elif (device_name := config[CONF_DEVICE][CONF_NAME]) == entity_name: self._attr_name = None - self._issue_key = ( - "entity_name_is_device_name_discovery" - if self._discovery - else "entity_name_is_device_name_yaml" - ) + if not self._discovery: + self._issue_key = "entity_name_is_device_name_yaml" _LOGGER.warning( "MQTT device name is equal to entity name in your config %s, " "this is not expected. Please correct your configuration. " @@ -1162,11 +1159,8 @@ class MqttEntity( if device_name[:1].isupper(): # Ensure a capital if the device name first char is a capital new_entity_name = new_entity_name[:1].upper() + new_entity_name[1:] - self._issue_key = ( - "entity_name_startswith_device_name_discovery" - if self._discovery - else "entity_name_startswith_device_name_yaml" - ) + if not self._discovery: + self._issue_key = "entity_name_startswith_device_name_yaml" _LOGGER.warning( "MQTT entity name starts with the device name in your config %s, " "this is not expected. Please correct your configuration. " diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 55677798a08..ae6033de5f9 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -14,15 +14,7 @@ }, "entity_name_startswith_device_name_yaml": { "title": "Manual configured MQTT entities with a name that starts with the device name", - "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped of the entity name as a work-a-round. Please update your configuration and restart Home Assistant to fix this issue. \n\nList of affected entities:\n\n{config}" - }, - "entity_name_is_device_name_discovery": { - "title": "Discovered MQTT entities with a name that is equal to the device name", - "description": "Some MQTT entities have an entity name equal to the device name. This is not expected. The entity name is set to `null` as a work-a-round to avoid a duplicate name. Please inform the maintainer of the software application that supplies the affected entities to fix this issue.\n\nList of affected entities:\n\n{config}" - }, - "entity_name_startswith_device_name_discovery": { - "title": "Discovered entities with a name that starts with the device name", - "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped of the entity name as a work-a-round. Please inform the maintainer of the software application that supplies the affected entities to fix this issue. \n\nList of affected entities:\n\n{config}" + "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped off the entity name as a work-a-round. Please update your configuration and restart Home Assistant to fix this issue. \n\nList of affected entities:\n\n{config}" } }, "config": { diff --git a/homeassistant/components/octoprint/__init__.py b/homeassistant/components/octoprint/__init__.py index dd6ab5794fc..790b332dbfd 100644 --- a/homeassistant/components/octoprint/__init__.py +++ b/homeassistant/components/octoprint/__init__.py @@ -5,6 +5,7 @@ from datetime import timedelta import logging from typing import cast +import aiohttp from pyoctoprintapi import ApiError, OctoprintClient, PrinterOffline from pyoctoprintapi.exceptions import UnauthorizedException import voluptuous as vol @@ -22,11 +23,11 @@ from homeassistant.const import ( CONF_SENSORS, CONF_SSL, CONF_VERIFY_SSL, + EVENT_HOMEASSISTANT_STOP, Platform, ) -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryAuthFailed -from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.typing import ConfigType @@ -163,14 +164,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: data = {**entry.data, CONF_VERIFY_SSL: True} hass.config_entries.async_update_entry(entry, data=data) - verify_ssl = entry.data[CONF_VERIFY_SSL] - websession = async_get_clientsession(hass, verify_ssl=verify_ssl) + connector = aiohttp.TCPConnector( + force_close=True, + ssl=False if not entry.data[CONF_VERIFY_SSL] else None, + ) + session = aiohttp.ClientSession(connector=connector) + + @callback + def _async_close_websession(event: Event) -> None: + """Close websession.""" + session.detach() + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_close_websession) + client = OctoprintClient( - entry.data[CONF_HOST], - websession, - entry.data[CONF_PORT], - entry.data[CONF_SSL], - entry.data[CONF_PATH], + host=entry.data[CONF_HOST], + session=session, + port=entry.data[CONF_PORT], + ssl=entry.data[CONF_SSL], + path=entry.data[CONF_PATH], ) client.set_api_key(entry.data[CONF_API_KEY]) diff --git a/homeassistant/components/octoprint/config_flow.py b/homeassistant/components/octoprint/config_flow.py index 33aaff8976e..09ac53ecf5b 100644 --- a/homeassistant/components/octoprint/config_flow.py +++ b/homeassistant/components/octoprint/config_flow.py @@ -6,6 +6,7 @@ from collections.abc import Mapping import logging from typing import Any +import aiohttp from pyoctoprintapi import ApiError, OctoprintClient, OctoprintException import voluptuous as vol from yarl import URL @@ -22,7 +23,6 @@ from homeassistant.const import ( CONF_VERIFY_SSL, ) from homeassistant.data_entry_flow import FlowResult -from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv from .const import DOMAIN @@ -58,6 +58,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for OctoPrint.""" self.discovery_schema = None self._user_input = None + self._sessions: list[aiohttp.ClientSession] = [] async def async_step_user(self, user_input=None): """Handle the initial step.""" @@ -260,14 +261,26 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): def _get_octoprint_client(self, user_input: dict) -> OctoprintClient: """Build an octoprint client from the user_input.""" verify_ssl = user_input.get(CONF_VERIFY_SSL, True) - session = async_get_clientsession(self.hass, verify_ssl=verify_ssl) - return OctoprintClient( - user_input[CONF_HOST], - session, - user_input[CONF_PORT], - user_input[CONF_SSL], - user_input[CONF_PATH], + + connector = aiohttp.TCPConnector( + force_close=True, + ssl=False if not verify_ssl else None, ) + session = aiohttp.ClientSession(connector=connector) + self._sessions.append(session) + + return OctoprintClient( + host=user_input[CONF_HOST], + session=session, + port=user_input[CONF_PORT], + ssl=user_input[CONF_SSL], + path=user_input[CONF_PATH], + ) + + def async_remove(self): + """Detach the session.""" + for session in self._sessions: + session.detach() class CannotConnect(exceptions.HomeAssistantError): diff --git a/homeassistant/components/octoprint/manifest.json b/homeassistant/components/octoprint/manifest.json index e4bc70e5d86..005cf5305d9 100644 --- a/homeassistant/components/octoprint/manifest.json +++ b/homeassistant/components/octoprint/manifest.json @@ -6,7 +6,7 @@ "documentation": "https://www.home-assistant.io/integrations/octoprint", "iot_class": "local_polling", "loggers": ["pyoctoprintapi"], - "requirements": ["pyoctoprintapi==0.1.11"], + "requirements": ["pyoctoprintapi==0.1.12"], "ssdp": [ { "manufacturer": "The OctoPrint Project", diff --git a/homeassistant/components/opower/manifest.json b/homeassistant/components/opower/manifest.json index 31929df5bf6..2de5b268999 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.29"] + "requirements": ["opower==0.0.31"] } diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index f350bb4f948..3ff25d1e7a0 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -18,5 +18,5 @@ "documentation": "https://www.home-assistant.io/integrations/reolink", "iot_class": "local_push", "loggers": ["reolink_aio"], - "requirements": ["reolink-aio==0.7.7"] + "requirements": ["reolink-aio==0.7.8"] } diff --git a/homeassistant/const.py b/homeassistant/const.py index db28d072aa5..f803a673265 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from typing import Final APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "3" +PATCH_VERSION: Final = "4" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0) diff --git a/pyproject.toml b/pyproject.toml index d3e2f065e1c..06b9c965cbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.8.3" +version = "2023.8.4" 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 a95ebbc09ed..34d6b48c0db 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -399,7 +399,7 @@ amcrest==1.9.7 androidtv[async]==0.0.70 # homeassistant.components.androidtv_remote -androidtvremote2==0.0.13 +androidtvremote2==0.0.14 # homeassistant.components.anel_pwrctrl anel-pwrctrl-homeassistant==0.0.1.dev2 @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.29 +opower==0.0.31 # homeassistant.components.oralb oralb-ble==0.17.6 @@ -1809,7 +1809,7 @@ pylibrespot-java==0.1.1 pylitejet==0.5.0 # homeassistant.components.litterrobot -pylitterbot==2023.4.2 +pylitterbot==2023.4.5 # homeassistant.components.lutron_caseta pylutron-caseta==0.18.1 @@ -1884,7 +1884,7 @@ pynzbgetapi==0.2.0 pyobihai==1.4.2 # homeassistant.components.octoprint -pyoctoprintapi==0.1.11 +pyoctoprintapi==0.1.12 # homeassistant.components.ombi pyombi==0.1.10 @@ -2278,7 +2278,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.7 +reolink-aio==0.7.8 # homeassistant.components.idteck_prox rfk101py==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0178acea600..1000c01a2d2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -368,7 +368,7 @@ amberelectric==1.0.4 androidtv[async]==0.0.70 # homeassistant.components.androidtv_remote -androidtvremote2==0.0.13 +androidtvremote2==0.0.14 # homeassistant.components.anova anova-wifi==0.10.0 @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.29 +opower==0.0.31 # homeassistant.components.oralb oralb-ble==0.17.6 @@ -1340,7 +1340,7 @@ pylibrespot-java==0.1.1 pylitejet==0.5.0 # homeassistant.components.litterrobot -pylitterbot==2023.4.2 +pylitterbot==2023.4.5 # homeassistant.components.lutron_caseta pylutron-caseta==0.18.1 @@ -1400,7 +1400,7 @@ pynzbgetapi==0.2.0 pyobihai==1.4.2 # homeassistant.components.octoprint -pyoctoprintapi==0.1.11 +pyoctoprintapi==0.1.12 # homeassistant.components.openuv pyopenuv==2023.02.0 @@ -1674,7 +1674,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.7 +reolink-aio==0.7.8 # homeassistant.components.rflink rflink==0.0.65