From f7fd781a27209d8d0a1c3bc9f32b39b25802b3f0 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Fri, 18 Mar 2022 09:26:19 +0100 Subject: [PATCH 01/13] Fix TypeError in SamsungTV (#68235) Co-authored-by: epenet --- homeassistant/components/samsungtv/bridge.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/samsungtv/bridge.py b/homeassistant/components/samsungtv/bridge.py index 481d3588bb7..616820aec26 100644 --- a/homeassistant/components/samsungtv/bridge.py +++ b/homeassistant/components/samsungtv/bridge.py @@ -319,8 +319,9 @@ class SamsungTVWSBridge(SamsungTVBridge): def _get_app_list(self) -> dict[str, str] | None: """Get installed app list.""" if self._app_list is None and (remote := self._get_remote()): - with contextlib.suppress(WebSocketTimeoutException): + with contextlib.suppress(TypeError, WebSocketTimeoutException): raw_app_list: list[dict[str, str]] = remote.app_list() + LOGGER.debug("Received app list: %s", raw_app_list) self._app_list = { app["name"]: app["appId"] for app in sorted(raw_app_list, key=lambda app: app["name"]) From 9352ed1286f7c9fa05f6971256399176526d489e Mon Sep 17 00:00:00 2001 From: Numa Perez <41305393+nprez83@users.noreply.github.com> Date: Tue, 15 Mar 2022 05:59:18 -0400 Subject: [PATCH 02/13] Fix lyric climate (#67018) * Fixed the issues related to auto mode I was having the same issues as described in #63403, specifically, the error stating that Mode 7 is not valid, only Heat, Cool, Off when trying to do anything while the thermostat is set to Auto. This error originates with the way the Lyric API handles the modes. Basically, when one queries the changeableValues dict, you get a mode=Auto, as well as a heatCoolMode, which is set to either Heat, Cool, Off. Per the documentation, heatCoolMode contains the "heat cool mode when system switch is in Auto mode". It would make sense that when changing the thermostat settings, mode=Auto should be valid, but it's not. The way the API understands that the mode should be set to Auto when changing the thermostat settings is by setting the autoChangeoverActive variable to true, not the mode itself. This require changes in the async_set_hvac_mode, async_set_temperature, and async_set_preset_mode functions. Related to this issue, I got rid of the references to hasDualSetpointStatus, as it seems that it always remains false in the API, even when the mode is set to auto, so again, the key variable for this is autoChangeoverActive. While I was working on this I also noticed another issue. The support flag SUPPORT_TARGET_TEMPERATURE_RANGE had not been included, which did not allow for the temperature range to be available, thus invalidating the target_temperature_low and target_temperature_high functions. I added this flag and sorted out which set point (heat vs cool) should be called for each of them so things work as expected in Lovelace. I have tested all of these functionalities and they all work great on my end, so I thought I'd share. * Update climate.py * Update climate.py Fixed two additional issues: 1) When the system is turned off from Auto, the heatCoolMode variable becomes 'Off', so when you try to restart the system back to Auto, nothing happens. 2) I now prevent the async_set_temperature function from being called with a new set point when the system is Off. All changes tested and functional. * Update climate.py * Update climate.py Return SUPPORT_PRESET_MODE flag only for LCC models (i.e. they have the "thermostatSetpointStatus" variable defined). TCC models do not support this feature * Update climate.py After playing with the official Honeywell API, I realized it doesn't like to received commands with missing data, i.e., it always wants to get a mode, coolSetpoint, heatSetpoint, and autoChangeoverActive variables. This was causing some random issues with changing modes, especially from coming from off, so I modified the async_set_temperature, and async_set_hvac_mode fuctions to always send all pertinent variables. * Update climate.py * Update climate.py * Update climate.py * Update climate.py * Clean code and test everything Alright, sorry for the multiple commits, fixing this properly took a fair bit of testing. I went ahead and cleaned up the code and made the following big picture changes: 1) The integration now supports the Auto mode appropriately, to include the temperature range. 2) There's a bug that actually manifests when using the native app. When the system is 'Off' and you try to turn it on to 'Auto', it will turn on briefly but will go back to 'Off' after a few seconds. When checking the web api, this appears to be related to the fact that the heatCoolMode variable seems to continue to store 'Off', even if the mode accurately displays 'Auto', and the autoChangeoverActive=True. So to overcome that inherent limitation, when the system is 'Off' and the user turns it to 'Auto', I first turn it to Heat, wait 3 seconds, and then turn it to 'Auto', which seems to work well. * Update climate.py * Fixed errors * Fixed comments that were resulting in error. * Update climate.py * Update homeassistant/components/lyric/climate.py Co-authored-by: Martin Hjelmare * Update homeassistant/components/lyric/climate.py Co-authored-by: Martin Hjelmare * Update climate.py I removed a blank line in 268 and another one at the end of the document. I also fixed the outdents of await commands after the _LOGGER.error calls, not sure what else may be driving the flake8 and black errors. Any guidance is much appreciated @MartinHjelmare * Update climate.py * Update climate.py corrected some indents that I think were the culprit of the flake8 errors * Update climate.py I used VS Code to fix locate the flake8 errors. I ran black on it, so I'm hoping that will fix the last lingering black error. Co-authored-by: Martin Hjelmare --- homeassistant/components/lyric/climate.py | 94 ++++++++++++++++++----- 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/lyric/climate.py b/homeassistant/components/lyric/climate.py index e798aca5831..dfe88048ba4 100644 --- a/homeassistant/components/lyric/climate.py +++ b/homeassistant/components/lyric/climate.py @@ -1,6 +1,7 @@ """Support for Honeywell Lyric climate platform.""" from __future__ import annotations +import asyncio import logging from time import localtime, strftime, time @@ -22,6 +23,7 @@ from homeassistant.components.climate.const import ( HVAC_MODE_OFF, SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, + SUPPORT_TARGET_TEMPERATURE_RANGE, ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_TEMPERATURE @@ -45,7 +47,11 @@ from .const import ( _LOGGER = logging.getLogger(__name__) -SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE +# Only LCC models support presets +SUPPORT_FLAGS_LCC = ( + SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE | SUPPORT_TARGET_TEMPERATURE_RANGE +) +SUPPORT_FLAGS_TCC = SUPPORT_TARGET_TEMPERATURE | SUPPORT_TARGET_TEMPERATURE_RANGE LYRIC_HVAC_ACTION_OFF = "EquipmentOff" LYRIC_HVAC_ACTION_HEAT = "Heat" @@ -166,7 +172,11 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): @property def supported_features(self) -> int: """Return the list of supported features.""" - return SUPPORT_FLAGS + if self.device.changeableValues.thermostatSetpointStatus: + support_flags = SUPPORT_FLAGS_LCC + else: + support_flags = SUPPORT_FLAGS_TCC + return support_flags @property def temperature_unit(self) -> str: @@ -200,25 +210,28 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): def target_temperature(self) -> float | None: """Return the temperature we try to reach.""" device = self.device - if not device.hasDualSetpointStatus: + if ( + not device.changeableValues.autoChangeoverActive + and HVAC_MODES[device.changeableValues.mode] != HVAC_MODE_OFF + ): if self.hvac_mode == HVAC_MODE_COOL: return device.changeableValues.coolSetpoint return device.changeableValues.heatSetpoint return None @property - def target_temperature_low(self) -> float | None: - """Return the upper bound temperature we try to reach.""" + def target_temperature_high(self) -> float | None: + """Return the highbound target temperature we try to reach.""" device = self.device - if device.hasDualSetpointStatus: + if device.changeableValues.autoChangeoverActive: return device.changeableValues.coolSetpoint return None @property - def target_temperature_high(self) -> float | None: - """Return the upper bound temperature we try to reach.""" + def target_temperature_low(self) -> float | None: + """Return the lowbound target temperature we try to reach.""" device = self.device - if device.hasDualSetpointStatus: + if device.changeableValues.autoChangeoverActive: return device.changeableValues.heatSetpoint return None @@ -256,11 +269,11 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): async def async_set_temperature(self, **kwargs) -> None: """Set new target temperature.""" + device = self.device target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW) target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) - device = self.device - if device.hasDualSetpointStatus: + if device.changeableValues.autoChangeoverActive: if target_temp_low is None or target_temp_high is None: raise HomeAssistantError( "Could not find target_temp_low and/or target_temp_high in arguments" @@ -270,11 +283,13 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): await self._update_thermostat( self.location, device, - coolSetpoint=target_temp_low, - heatSetpoint=target_temp_high, + coolSetpoint=target_temp_high, + heatSetpoint=target_temp_low, + mode=HVAC_MODES[device.changeableValues.heatCoolMode], ) except LYRIC_EXCEPTIONS as exception: _LOGGER.error(exception) + await self.coordinator.async_refresh() else: temp = kwargs.get(ATTR_TEMPERATURE) _LOGGER.debug("Set temperature: %s", temp) @@ -289,15 +304,58 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): ) except LYRIC_EXCEPTIONS as exception: _LOGGER.error(exception) - await self.coordinator.async_refresh() + await self.coordinator.async_refresh() async def async_set_hvac_mode(self, hvac_mode: str) -> None: """Set hvac mode.""" - _LOGGER.debug("Set hvac mode: %s", hvac_mode) + _LOGGER.debug("HVAC mode: %s", hvac_mode) try: - await self._update_thermostat( - self.location, self.device, mode=LYRIC_HVAC_MODES[hvac_mode] - ) + if LYRIC_HVAC_MODES[hvac_mode] == LYRIC_HVAC_MODE_HEAT_COOL: + # If the system is off, turn it to Heat first then to Auto, otherwise it turns to + # Auto briefly and then reverts to Off (perhaps related to heatCoolMode). This is the + # behavior that happens with the native app as well, so likely a bug in the api itself + + if HVAC_MODES[self.device.changeableValues.mode] == HVAC_MODE_OFF: + _LOGGER.debug( + "HVAC mode passed to lyric: %s", + HVAC_MODES[LYRIC_HVAC_MODE_COOL], + ) + await self._update_thermostat( + self.location, + self.device, + mode=HVAC_MODES[LYRIC_HVAC_MODE_HEAT], + autoChangeoverActive=False, + ) + # Sleep 3 seconds before proceeding + await asyncio.sleep(3) + _LOGGER.debug( + "HVAC mode passed to lyric: %s", + HVAC_MODES[LYRIC_HVAC_MODE_HEAT], + ) + await self._update_thermostat( + self.location, + self.device, + mode=HVAC_MODES[LYRIC_HVAC_MODE_HEAT], + autoChangeoverActive=True, + ) + else: + _LOGGER.debug( + "HVAC mode passed to lyric: %s", + HVAC_MODES[self.device.changeableValues.mode], + ) + await self._update_thermostat( + self.location, self.device, autoChangeoverActive=True + ) + else: + _LOGGER.debug( + "HVAC mode passed to lyric: %s", LYRIC_HVAC_MODES[hvac_mode] + ) + await self._update_thermostat( + self.location, + self.device, + mode=LYRIC_HVAC_MODES[hvac_mode], + autoChangeoverActive=False, + ) except LYRIC_EXCEPTIONS as exception: _LOGGER.error(exception) await self.coordinator.async_refresh() From bc1438531759ff6965badafc545f41a5ec75e57b Mon Sep 17 00:00:00 2001 From: Antonio Larrosa Date: Tue, 15 Mar 2022 22:33:59 +0100 Subject: [PATCH 03/13] Fix finding matrix room that is already joined (#67967) After some debugging, it seems room.canonical_alias contains the room alias that matches the room_id_or_alias value but is not contained in room.aliases (which is empty). As a result, the matrix component thought the room wasn't alread joined, joins again, and this replaces the previous room which had the listener. This resulted in the component callback not being called for new messages in the room. This fixes #66372 --- homeassistant/components/matrix/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/matrix/__init__.py b/homeassistant/components/matrix/__init__.py index 76e2630b26e..03772630a9e 100644 --- a/homeassistant/components/matrix/__init__.py +++ b/homeassistant/components/matrix/__init__.py @@ -243,7 +243,10 @@ class MatrixBot: room.update_aliases() self._aliases_fetched_for.add(room.room_id) - if room_id_or_alias in room.aliases: + if ( + room_id_or_alias in room.aliases + or room_id_or_alias == room.canonical_alias + ): _LOGGER.debug( "Already in room %s (known as %s)", room.room_id, room_id_or_alias ) From 774f2b9b8265f05b358129213312b3151a7d1063 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Tue, 22 Mar 2022 04:40:33 +0100 Subject: [PATCH 04/13] Respect disable_new_entities for new device_tracker entities (#68148) --- .../components/device_tracker/config_entry.py | 12 ++++++- .../device_tracker/test_config_entry.py | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/config_entry.py b/homeassistant/components/device_tracker/config_entry.py index adabd297c55..c9b8534c2bc 100644 --- a/homeassistant/components/device_tracker/config_entry.py +++ b/homeassistant/components/device_tracker/config_entry.py @@ -149,9 +149,19 @@ def _async_register_mac( return # Make sure entity has a config entry and was disabled by the - # default disable logic in the integration. + # default disable logic in the integration and new entities + # are allowed to be added. if ( entity_entry.config_entry_id is None + or ( + ( + config_entry := hass.config_entries.async_get_entry( + entity_entry.config_entry_id + ) + ) + is not None + and config_entry.pref_disable_new_entities + ) or entity_entry.disabled_by != er.RegistryEntryDisabler.INTEGRATION ): return diff --git a/tests/components/device_tracker/test_config_entry.py b/tests/components/device_tracker/test_config_entry.py index 5134123074e..73b07d31026 100644 --- a/tests/components/device_tracker/test_config_entry.py +++ b/tests/components/device_tracker/test_config_entry.py @@ -137,6 +137,39 @@ async def test_register_mac(hass): assert entity_entry_1.disabled_by is None +async def test_register_mac_ignored(hass): + """Test ignoring registering a mac.""" + dev_reg = dr.async_get(hass) + ent_reg = er.async_get(hass) + + config_entry = MockConfigEntry(domain="test", pref_disable_new_entities=True) + config_entry.add_to_hass(hass) + + mac1 = "12:34:56:AB:CD:EF" + + entity_entry_1 = ent_reg.async_get_or_create( + "device_tracker", + "test", + mac1 + "yo1", + original_name="name 1", + config_entry=config_entry, + disabled_by=er.RegistryEntryDisabler.INTEGRATION, + ) + + ce._async_register_mac(hass, "test", mac1, mac1 + "yo1") + + dev_reg.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, mac1)}, + ) + + await hass.async_block_till_done() + + entity_entry_1 = ent_reg.async_get(entity_entry_1.entity_id) + + assert entity_entry_1.disabled_by == er.RegistryEntryDisabler.INTEGRATION + + async def test_connected_device_registered(hass): """Test dispatch on connected device being registered.""" From 54b7f13a548495b7014c455d2fa62c93193225fa Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 15 Mar 2022 15:57:36 +0100 Subject: [PATCH 05/13] Add missing await [velbus] (#68153) --- homeassistant/components/velbus/cover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/velbus/cover.py b/homeassistant/components/velbus/cover.py index 2e2ceb761a9..4afe02f4637 100644 --- a/homeassistant/components/velbus/cover.py +++ b/homeassistant/components/velbus/cover.py @@ -78,4 +78,4 @@ class VelbusCover(VelbusEntity, CoverEntity): async def async_set_cover_position(self, **kwargs: Any) -> None: """Move the cover to a specific position.""" - self._channel.set_position(100 - kwargs[ATTR_POSITION]) + await self._channel.set_position(100 - kwargs[ATTR_POSITION]) From 7dd9bfa92f39d716da7a78add950f4503da6d46e Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 15 Mar 2022 15:56:08 +0100 Subject: [PATCH 06/13] Fix point by adding authlib constraint (#68176) * Fix point by pinning authlib * Use constraint --- homeassistant/components/point/__init__.py | 2 ++ homeassistant/package_constraints.txt | 4 ++++ script/gen_requirements_all.py | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/homeassistant/components/point/__init__.py b/homeassistant/components/point/__init__.py index 288c16df14a..99108323187 100644 --- a/homeassistant/components/point/__init__.py +++ b/homeassistant/components/point/__init__.py @@ -97,6 +97,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: token_saver=token_saver, ) try: + # pylint: disable-next=fixme + # TODO Remove authlib constraint when refactoring this code await session.ensure_active_token() except ConnectTimeout as err: _LOGGER.debug("Connection Timeout") diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 20b3c5badd3..8ec6f3cc67d 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -95,3 +95,7 @@ python-socketio>=4.6.0,<5.0 # Constrain multidict to avoid typing issues # https://github.com/home-assistant/core/pull/67046 multidict>=6.0.2 + +# Required for compatibility with point integration - ensure_active_token +# https://github.com/home-assistant/core/pull/68176 +authlib<1.0 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index fe8962e4f1e..a8d1d40a7d5 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -124,6 +124,10 @@ python-socketio>=4.6.0,<5.0 # Constrain multidict to avoid typing issues # https://github.com/home-assistant/core/pull/67046 multidict>=6.0.2 + +# Required for compatibility with point integration - ensure_active_token +# https://github.com/home-assistant/core/pull/68176 +authlib<1.0 """ IGNORE_PRE_COMMIT_HOOK_ID = ( From 38eb007f6332dab2ddb9ffadf7e8171025bc2078 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 15 Mar 2022 18:14:07 +0100 Subject: [PATCH 07/13] Update opensensemap-api to 0.2.0 (#68193) --- homeassistant/components/opensensemap/air_quality.py | 2 +- homeassistant/components/opensensemap/manifest.json | 2 +- requirements_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opensensemap/air_quality.py b/homeassistant/components/opensensemap/air_quality.py index b8028431796..5999eb91580 100644 --- a/homeassistant/components/opensensemap/air_quality.py +++ b/homeassistant/components/opensensemap/air_quality.py @@ -43,7 +43,7 @@ async def async_setup_platform( station_id = config[CONF_STATION_ID] session = async_get_clientsession(hass) - osm_api = OpenSenseMapData(OpenSenseMap(station_id, hass.loop, session)) + osm_api = OpenSenseMapData(OpenSenseMap(station_id, session)) await osm_api.async_update() diff --git a/homeassistant/components/opensensemap/manifest.json b/homeassistant/components/opensensemap/manifest.json index 513cb5ac3da..baf62985448 100644 --- a/homeassistant/components/opensensemap/manifest.json +++ b/homeassistant/components/opensensemap/manifest.json @@ -2,7 +2,7 @@ "domain": "opensensemap", "name": "openSenseMap", "documentation": "https://www.home-assistant.io/integrations/opensensemap", - "requirements": ["opensensemap-api==0.1.5"], + "requirements": ["opensensemap-api==0.2.0"], "codeowners": [], "iot_class": "cloud_polling", "loggers": ["opensensemap_api"] diff --git a/requirements_all.txt b/requirements_all.txt index 565cdcae1a3..e9879102828 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1180,7 +1180,7 @@ openevsewifi==1.1.0 openhomedevice==2.0.1 # homeassistant.components.opensensemap -opensensemap-api==0.1.5 +opensensemap-api==0.2.0 # homeassistant.components.enigma2 openwebifpy==3.2.7 From df5c09e4830b1e8894e55c7a24dd1d21193bcd93 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Thu, 17 Mar 2022 08:51:03 +0100 Subject: [PATCH 08/13] Bump renault-api to 0.1.10 (#68260) Co-authored-by: epenet --- homeassistant/components/renault/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/renault/manifest.json b/homeassistant/components/renault/manifest.json index 71e2e7d64b8..d41686f0c1f 100644 --- a/homeassistant/components/renault/manifest.json +++ b/homeassistant/components/renault/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/renault", "requirements": [ - "renault-api==0.1.9" + "renault-api==0.1.10" ], "codeowners": [ "@epenet" diff --git a/requirements_all.txt b/requirements_all.txt index e9879102828..df63a7159c7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2097,7 +2097,7 @@ raspyrfm-client==1.2.8 regenmaschine==2022.01.0 # homeassistant.components.renault -renault-api==0.1.9 +renault-api==0.1.10 # homeassistant.components.python_script restrictedpython==5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0ec2c864424..6550c353e05 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1301,7 +1301,7 @@ radios==0.1.1 regenmaschine==2022.01.0 # homeassistant.components.renault -renault-api==0.1.9 +renault-api==0.1.10 # homeassistant.components.python_script restrictedpython==5.2 From caee432901788c0817d805d671d153c2ede3849c Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 19 Mar 2022 21:27:04 +0100 Subject: [PATCH 09/13] Hue integration: update errors that should be supressed (#68337) --- homeassistant/components/hue/v2/group.py | 8 ++++++++ homeassistant/components/hue/v2/light.py | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/homeassistant/components/hue/v2/group.py b/homeassistant/components/hue/v2/group.py index 31c5a502853..948609f4c13 100644 --- a/homeassistant/components/hue/v2/group.py +++ b/homeassistant/components/hue/v2/group.py @@ -42,6 +42,14 @@ ALLOWED_ERRORS = [ 'device (groupedLight) is "soft off", command (on) may not have effect', "device (light) has communication issues, command (on) may not have effect", 'device (light) is "soft off", command (on) may not have effect', + "device (grouped_light) has communication issues, command (.on) may not have effect", + 'device (grouped_light) is "soft off", command (.on) may not have effect' + "device (grouped_light) has communication issues, command (.on.on) may not have effect", + 'device (grouped_light) is "soft off", command (.on.on) may not have effect' + "device (light) has communication issues, command (.on) may not have effect", + 'device (light) is "soft off", command (.on) may not have effect', + "device (light) has communication issues, command (.on.on) may not have effect", + 'device (light) is "soft off", command (.on.on) may not have effect', ] diff --git a/homeassistant/components/hue/v2/light.py b/homeassistant/components/hue/v2/light.py index ee40222b083..5b4574c717c 100644 --- a/homeassistant/components/hue/v2/light.py +++ b/homeassistant/components/hue/v2/light.py @@ -39,6 +39,10 @@ from .helpers import ( ALLOWED_ERRORS = [ "device (light) has communication issues, command (on) may not have effect", 'device (light) is "soft off", command (on) may not have effect', + "device (light) has communication issues, command (.on) may not have effect", + 'device (light) is "soft off", command (.on) may not have effect', + "device (light) has communication issues, command (.on.on) may not have effect", + 'device (light) is "soft off", command (.on.on) may not have effect', ] From a8e1f57058c7a7dd7f39470ef672ae5def40ff40 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 19 Mar 2022 10:40:00 -1000 Subject: [PATCH 10/13] Filter IPv6 addreses from enphase_envoy discovery (#68362) --- .../components/enphase_envoy/config_flow.py | 3 ++ .../enphase_envoy/translations/en.json | 3 +- .../enphase_envoy/test_config_flow.py | 41 ++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/enphase_envoy/config_flow.py b/homeassistant/components/enphase_envoy/config_flow.py index fa43cb61ffe..88310579e72 100644 --- a/homeassistant/components/enphase_envoy/config_flow.py +++ b/homeassistant/components/enphase_envoy/config_flow.py @@ -16,6 +16,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.httpx_client import get_async_client +from homeassistant.util.network import is_ipv4_address from .const import DOMAIN @@ -86,6 +87,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self, discovery_info: zeroconf.ZeroconfServiceInfo ) -> FlowResult: """Handle a flow initialized by zeroconf discovery.""" + if not is_ipv4_address(discovery_info.host): + return self.async_abort(reason="not_ipv4_address") serial = discovery_info.properties["serialnum"] await self.async_set_unique_id(serial) self.ip_address = discovery_info.host diff --git a/homeassistant/components/enphase_envoy/translations/en.json b/homeassistant/components/enphase_envoy/translations/en.json index 5d4617ed9fa..ff600fea454 100644 --- a/homeassistant/components/enphase_envoy/translations/en.json +++ b/homeassistant/components/enphase_envoy/translations/en.json @@ -2,7 +2,8 @@ "config": { "abort": { "already_configured": "Device is already configured", - "reauth_successful": "Re-authentication was successful" + "reauth_successful": "Re-authentication was successful", + "not_ipv4_address": "Only IPv4 addresess are supported" }, "error": { "cannot_connect": "Failed to connect", diff --git a/tests/components/enphase_envoy/test_config_flow.py b/tests/components/enphase_envoy/test_config_flow.py index 76179c02e22..caba2296927 100644 --- a/tests/components/enphase_envoy/test_config_flow.py +++ b/tests/components/enphase_envoy/test_config_flow.py @@ -6,6 +6,7 @@ import httpx from homeassistant import config_entries from homeassistant.components import zeroconf from homeassistant.components.enphase_envoy.const import DOMAIN +from homeassistant.const import CONF_HOST from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry @@ -312,8 +313,8 @@ async def test_zeroconf_serial_already_exists(hass: HomeAssistant) -> None: DOMAIN, context={"source": config_entries.SOURCE_ZEROCONF}, data=zeroconf.ZeroconfServiceInfo( - host="1.1.1.1", - addresses=["1.1.1.1"], + host="4.4.4.4", + addresses=["4.4.4.4"], hostname="mock_hostname", name="mock_name", port=None, @@ -324,6 +325,42 @@ async def test_zeroconf_serial_already_exists(hass: HomeAssistant) -> None: assert result["type"] == "abort" assert result["reason"] == "already_configured" + assert config_entry.data[CONF_HOST] == "4.4.4.4" + + +async def test_zeroconf_serial_already_exists_ignores_ipv6(hass: HomeAssistant) -> None: + """Test serial number already exists from zeroconf but the discovery is ipv6.""" + + config_entry = MockConfigEntry( + domain=DOMAIN, + data={ + "host": "1.1.1.1", + "name": "Envoy", + "username": "test-username", + "password": "test-password", + }, + unique_id="1234", + title="Envoy", + ) + config_entry.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_ZEROCONF}, + data=zeroconf.ZeroconfServiceInfo( + host="fd00::b27c:63bb:cc85:4ea0", + addresses=["fd00::b27c:63bb:cc85:4ea0"], + hostname="mock_hostname", + name="mock_name", + port=None, + properties={"serialnum": "1234"}, + type="mock_type", + ), + ) + + assert result["type"] == "abort" + assert result["reason"] == "not_ipv4_address" + assert config_entry.data[CONF_HOST] == "1.1.1.1" async def test_zeroconf_host_already_exists(hass: HomeAssistant) -> None: From 23e9aa6ad246b0818a1d6e83b67b49ed1fa6623c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 19 Mar 2022 14:28:16 -0700 Subject: [PATCH 11/13] Handle Hue discovery errors (#68392) --- homeassistant/components/hue/config_flow.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/hue/config_flow.py b/homeassistant/components/hue/config_flow.py index 0901d9a1e2c..265777814a8 100644 --- a/homeassistant/components/hue/config_flow.py +++ b/homeassistant/components/hue/config_flow.py @@ -6,6 +6,7 @@ import logging from typing import Any from urllib.parse import urlparse +import aiohttp from aiohue import LinkButtonNotPressed, create_app_key from aiohue.discovery import DiscoveredHueBridge, discover_bridge, discover_nupnp from aiohue.util import normalize_bridge_id @@ -70,9 +71,12 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): self, host: str, bridge_id: str | None = None ) -> DiscoveredHueBridge: """Return a DiscoveredHueBridge object.""" - bridge = await discover_bridge( - host, websession=aiohttp_client.async_get_clientsession(self.hass) - ) + try: + bridge = await discover_bridge( + host, websession=aiohttp_client.async_get_clientsession(self.hass) + ) + except aiohttp.ClientError: + return None if bridge_id is not None: bridge_id = normalize_bridge_id(bridge_id) assert bridge_id == bridge.id From 3bf0a64e21f436a0b44822a401a390e9e663fcc4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 21 Mar 2022 12:41:15 -1000 Subject: [PATCH 12/13] Fix tplink color temp conversion (#68484) --- homeassistant/components/tplink/light.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/tplink/light.py b/homeassistant/components/tplink/light.py index 6efabe537f7..182bef586ee 100644 --- a/homeassistant/components/tplink/light.py +++ b/homeassistant/components/tplink/light.py @@ -88,7 +88,10 @@ class TPLinkSmartBulb(CoordinatedTPLinkEntity, LightEntity): # Handle turning to temp mode if ATTR_COLOR_TEMP in kwargs: - color_tmp = mired_to_kelvin(int(kwargs[ATTR_COLOR_TEMP])) + # Handle temp conversion mireds -> kelvin being slightly outside of valid range + kelvin = mired_to_kelvin(int(kwargs[ATTR_COLOR_TEMP])) + kelvin_range = self.device.valid_temperature_range + color_tmp = max(kelvin_range.min, min(kelvin_range.max, kelvin)) _LOGGER.debug("Changing color temp to %s", color_tmp) await self.device.set_color_temp( color_tmp, brightness=brightness, transition=transition From 2be9798fb8ccce629d736ba1b7b239706be972cd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 21 Mar 2022 20:42:13 -0700 Subject: [PATCH 13/13] Bumped version to 2022.3.6 --- homeassistant/const.py | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 36f5c21b279..224bf89b0e2 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 3 -PATCH_VERSION: Final = "5" +PATCH_VERSION: Final = "6" __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/setup.cfg b/setup.cfg index 5e229a0da9d..c4e7a968cc2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = homeassistant -version = 2022.3.5 +version = 2022.3.6 author = The Home Assistant Authors author_email = hello@home-assistant.io license = Apache-2.0