From 07f8236e6f2920ab8bd9c531b81bf2735331ed87 Mon Sep 17 00:00:00 2001 From: Oscar Calvo <2091582+ocalvo@users.noreply.github.com> Date: Fri, 6 Aug 2021 03:18:29 -0700 Subject: [PATCH 1/6] Gracefully handle additional GSM errors (#54114) --- homeassistant/components/sms/gateway.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/homeassistant/components/sms/gateway.py b/homeassistant/components/sms/gateway.py index 51667ef8f77..5003f7019ca 100644 --- a/homeassistant/components/sms/gateway.py +++ b/homeassistant/components/sms/gateway.py @@ -25,6 +25,10 @@ class Gateway: await self._worker.set_incoming_sms_async() except gammu.ERR_NOTSUPPORTED: _LOGGER.warning("Your phone does not support incoming SMS notifications!") + except gammu.GSMError: + _LOGGER.warning( + "GSM error, your phone does not support incoming SMS notifications!" + ) else: await self._worker.set_incoming_callback_async(self.sms_callback) From 93a2e2849c57cd4223620dd70cc9693b6b655fc4 Mon Sep 17 00:00:00 2001 From: Niccolo Zapponi Date: Fri, 6 Aug 2021 17:34:42 +0100 Subject: [PATCH 2/6] Handle software version being None when setting up HomeKit accessories (#54130) * Convert all HomeKit service info to string prior to checking for max length * Added check for None software version * Added test case for numeric version number * Update tests/components/homekit/test_accessories.py Co-authored-by: J. Nick Koston * Fix style & none version test * Fix test * revert other change since it should be covered by the format_sw_version fix Co-authored-by: J. Nick Koston --- .../components/homekit/accessories.py | 3 +- tests/components/homekit/test_accessories.py | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index 772143e7c1f..836221ac7e9 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -238,9 +238,10 @@ class HomeAccessory(Accessory): model = self.config[ATTR_MODEL] else: model = domain.title() + sw_version = None if self.config.get(ATTR_SOFTWARE_VERSION) is not None: sw_version = format_sw_version(self.config[ATTR_SOFTWARE_VERSION]) - else: + if sw_version is None: sw_version = __version__ self.set_info_service( diff --git a/tests/components/homekit/test_accessories.py b/tests/components/homekit/test_accessories.py index 00e894b91cb..0584ee4c0ff 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -133,6 +133,39 @@ async def test_home_accessory(hass, hk_driver): ) assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == "0.4.3" + acc4 = HomeAccessory( + hass, + hk_driver, + "Home Accessory that exceeds the maximum maximum maximum maximum maximum maximum length", + entity_id2, + 3, + { + ATTR_MODEL: "Awesome Model that exceeds the maximum maximum maximum maximum maximum maximum length", + ATTR_MANUFACTURER: "Lux Brands that exceeds the maximum maximum maximum maximum maximum maximum length", + ATTR_SOFTWARE_VERSION: "will_not_match_regex", + ATTR_INTEGRATION: "luxe that exceeds the maximum maximum maximum maximum maximum maximum length", + }, + ) + assert acc4.available is False + serv = acc4.services[0] # SERV_ACCESSORY_INFO + assert ( + serv.get_characteristic(CHAR_NAME).value + == "Home Accessory that exceeds the maximum maximum maximum maximum " + ) + assert ( + serv.get_characteristic(CHAR_MANUFACTURER).value + == "Lux Brands that exceeds the maximum maximum maximum maximum maxi" + ) + assert ( + serv.get_characteristic(CHAR_MODEL).value + == "Awesome Model that exceeds the maximum maximum maximum maximum m" + ) + assert ( + serv.get_characteristic(CHAR_SERIAL_NUMBER).value + == "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum" + ) + assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == hass_version + hass.states.async_set(entity_id, "on") await hass.async_block_till_done() with patch( From 15e9310a01cfe699caf33b7dad21bf983fb5d86e Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Fri, 6 Aug 2021 14:59:00 +0200 Subject: [PATCH 3/6] Fix sensor PLATFORM_SCHEMA for ebox and enphase_envoy (#54142) * Fix sensor PLATFORM_SCHEMA * fix pylint --- homeassistant/components/ebox/sensor.py | 4 +++- homeassistant/components/enphase_envoy/sensor.py | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ebox/sensor.py b/homeassistant/components/ebox/sensor.py index e27c6fe0772..e98dea45929 100644 --- a/homeassistant/components/ebox/sensor.py +++ b/homeassistant/components/ebox/sensor.py @@ -122,10 +122,12 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( ), ) +SENSOR_TYPE_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES] + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_MONITORED_VARIABLES): vol.All( - cv.ensure_list, [vol.In(SENSOR_TYPES)] + cv.ensure_list, [vol.In(SENSOR_TYPE_KEYS)] ), vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, diff --git a/homeassistant/components/enphase_envoy/sensor.py b/homeassistant/components/enphase_envoy/sensor.py index 29d273401f4..3af5cd1ec0c 100644 --- a/homeassistant/components/enphase_envoy/sensor.py +++ b/homeassistant/components/enphase_envoy/sensor.py @@ -1,4 +1,5 @@ """Support for Enphase Envoy solar energy monitor.""" +from __future__ import annotations import logging @@ -22,14 +23,15 @@ ICON = "mdi:flash" CONST_DEFAULT_HOST = "envoy" _LOGGER = logging.getLogger(__name__) +SENSOR_KEYS: list[str] = [desc.key for desc in SENSORS] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Optional(CONF_IP_ADDRESS, default=CONST_DEFAULT_HOST): cv.string, vol.Optional(CONF_USERNAME, default="envoy"): cv.string, vol.Optional(CONF_PASSWORD, default=""): cv.string, - vol.Optional(CONF_MONITORED_CONDITIONS, default=list(SENSORS)): vol.All( - cv.ensure_list, [vol.In(list(SENSORS))] + vol.Optional(CONF_MONITORED_CONDITIONS, default=SENSOR_KEYS): vol.All( + cv.ensure_list, [vol.In(SENSOR_KEYS)] ), vol.Optional(CONF_NAME, default=""): cv.string, } From d580036dfbd48e208fb25889def73fa306d97b72 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 6 Aug 2021 11:15:35 -0500 Subject: [PATCH 4/6] Fetch interface index from network integration instead of socket.if_nametoindex in zeroconf (#54152) --- homeassistant/components/network/models.py | 1 + homeassistant/components/network/util.py | 1 + homeassistant/components/zeroconf/__init__.py | 5 ++- tests/components/network/test_init.py | 32 +++++++++++++++++++ tests/components/zeroconf/test_init.py | 4 +++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/network/models.py b/homeassistant/components/network/models.py index a007eb8636d..d3fbc824489 100644 --- a/homeassistant/components/network/models.py +++ b/homeassistant/components/network/models.py @@ -24,6 +24,7 @@ class Adapter(TypedDict): """Configured network adapters.""" name: str + index: int enabled: bool auto: bool default: bool diff --git a/homeassistant/components/network/util.py b/homeassistant/components/network/util.py index eece4b38548..f8b33b3df90 100644 --- a/homeassistant/components/network/util.py +++ b/homeassistant/components/network/util.py @@ -116,6 +116,7 @@ def _ifaddr_adapter_to_ha( return { "name": adapter.nice_name, + "index": adapter.index, "enabled": False, "auto": auto, "default": default, diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index 4c4c81aff32..cdb46318578 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -155,9 +155,8 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool: for ipv4 in ipv4s if not ipaddress.ip_address(ipv4["address"]).is_loopback ) - if adapter["ipv6"]: - ifi = socket.if_nametoindex(adapter["name"]) - interfaces.append(ifi) + if adapter["ipv6"] and adapter["index"] not in interfaces: + interfaces.append(adapter["index"]) ipv6 = True if not any(adapter["enabled"] and adapter["ipv6"] for adapter in adapters): diff --git a/tests/components/network/test_init.py b/tests/components/network/test_init.py index bc4c543842f..6a85f5ea9e8 100644 --- a/tests/components/network/test_init.py +++ b/tests/components/network/test_init.py @@ -21,15 +21,19 @@ def _generate_mock_adapters(): mock_lo0 = Mock(spec=ifaddr.Adapter) mock_lo0.nice_name = "lo0" mock_lo0.ips = [ifaddr.IP("127.0.0.1", 8, "lo0")] + mock_lo0.index = 0 mock_eth0 = Mock(spec=ifaddr.Adapter) mock_eth0.nice_name = "eth0" mock_eth0.ips = [ifaddr.IP(("2001:db8::", 1, 1), 8, "eth0")] + mock_eth0.index = 1 mock_eth1 = Mock(spec=ifaddr.Adapter) mock_eth1.nice_name = "eth1" mock_eth1.ips = [ifaddr.IP("192.168.1.5", 23, "eth1")] + mock_eth1.index = 2 mock_vtun0 = Mock(spec=ifaddr.Adapter) mock_vtun0.nice_name = "vtun0" mock_vtun0.ips = [ifaddr.IP("169.254.3.2", 16, "vtun0")] + mock_vtun0.index = 3 return [mock_eth0, mock_lo0, mock_eth1, mock_vtun0] @@ -51,6 +55,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto assert network_obj.adapters == [ { "auto": False, + "index": 1, "default": False, "enabled": False, "ipv4": [], @@ -65,6 +70,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto "name": "eth0", }, { + "index": 0, "auto": False, "default": False, "enabled": False, @@ -73,6 +79,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto "name": "lo0", }, { + "index": 2, "auto": True, "default": True, "enabled": True, @@ -81,6 +88,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route(hass, hass_sto "name": "eth1", }, { + "index": 3, "auto": False, "default": False, "enabled": False, @@ -107,6 +115,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage assert network_obj.configured_adapters == [] assert network_obj.adapters == [ { + "index": 1, "auto": True, "default": False, "enabled": True, @@ -122,6 +131,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage "name": "eth0", }, { + "index": 0, "auto": False, "default": True, "enabled": False, @@ -130,6 +140,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage "name": "lo0", }, { + "index": 2, "auto": True, "default": False, "enabled": True, @@ -138,6 +149,7 @@ async def test_async_detect_interfaces_setting_loopback_route(hass, hass_storage "name": "eth1", }, { + "index": 3, "auto": False, "default": False, "enabled": False, @@ -165,6 +177,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): assert network_obj.adapters == [ { "auto": True, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -180,6 +193,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -188,6 +202,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): }, { "auto": True, + "index": 2, "default": False, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -196,6 +211,7 @@ async def test_async_detect_interfaces_setting_empty_route(hass, hass_storage): }, { "auto": False, + "index": 3, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -222,6 +238,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): assert network_obj.adapters == [ { "auto": True, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -237,6 +254,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -245,6 +263,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): }, { "auto": True, + "index": 2, "default": False, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -253,6 +272,7 @@ async def test_async_detect_interfaces_setting_exception(hass, hass_storage): }, { "auto": False, + "index": 3, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -285,6 +305,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): assert network_obj.adapters == [ { "auto": False, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -300,6 +321,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -308,6 +330,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): }, { "auto": True, + "index": 2, "default": True, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -316,6 +339,7 @@ async def test_interfaces_configured_from_storage(hass, hass_storage): }, { "auto": False, + "index": 3, "default": False, "enabled": True, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -356,6 +380,7 @@ async def test_interfaces_configured_from_storage_websocket_update( assert response["result"][ATTR_ADAPTERS] == [ { "auto": False, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -371,6 +396,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -379,6 +405,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": True, + "index": 2, "default": True, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -387,6 +414,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 3, "default": False, "enabled": True, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], @@ -407,6 +435,7 @@ async def test_interfaces_configured_from_storage_websocket_update( assert response["result"][ATTR_ADAPTERS] == [ { "auto": False, + "index": 1, "default": False, "enabled": False, "ipv4": [], @@ -422,6 +451,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 0, "default": False, "enabled": False, "ipv4": [{"address": "127.0.0.1", "network_prefix": 8}], @@ -430,6 +460,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": True, + "index": 2, "default": True, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -438,6 +469,7 @@ async def test_interfaces_configured_from_storage_websocket_update( }, { "auto": False, + "index": 3, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], diff --git a/tests/components/zeroconf/test_init.py b/tests/components/zeroconf/test_init.py index 3b8cf883a13..e1e346621fe 100644 --- a/tests/components/zeroconf/test_init.py +++ b/tests/components/zeroconf/test_init.py @@ -725,6 +725,7 @@ async def test_async_detect_interfaces_setting_non_loopback_route( _ADAPTERS_WITH_MANUAL_CONFIG = [ { "auto": True, + "index": 1, "default": False, "enabled": True, "ipv4": [], @@ -746,6 +747,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ }, { "auto": True, + "index": 2, "default": False, "enabled": True, "ipv4": [{"address": "192.168.1.5", "network_prefix": 23}], @@ -754,6 +756,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ }, { "auto": True, + "index": 3, "default": False, "enabled": True, "ipv4": [{"address": "172.16.1.5", "network_prefix": 23}], @@ -769,6 +772,7 @@ _ADAPTERS_WITH_MANUAL_CONFIG = [ }, { "auto": False, + "index": 4, "default": False, "enabled": False, "ipv4": [{"address": "169.254.3.2", "network_prefix": 16}], From 011cda5fc4ff9c030a8b4ca972f4dc0d9cc51f45 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 6 Aug 2021 14:48:00 -0500 Subject: [PATCH 5/6] Bump zeroconf to 0.33.4 to ensure zeroconf can startup when ipv6 is disabled (#54165) Changelog: https://github.com/jstasiak/python-zeroconf/compare/0.33.3...0.33.4 --- homeassistant/components/zeroconf/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/zeroconf/manifest.json b/homeassistant/components/zeroconf/manifest.json index 7b3cfa1fefd..1847a1c806b 100644 --- a/homeassistant/components/zeroconf/manifest.json +++ b/homeassistant/components/zeroconf/manifest.json @@ -2,7 +2,7 @@ "domain": "zeroconf", "name": "Zero-configuration networking (zeroconf)", "documentation": "https://www.home-assistant.io/integrations/zeroconf", - "requirements": ["zeroconf==0.33.3"], + "requirements": ["zeroconf==0.33.4"], "dependencies": ["network", "api"], "codeowners": ["@bdraco"], "quality_scale": "internal", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index d435f165f61..617a057743b 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -33,7 +33,7 @@ sqlalchemy==1.4.17 voluptuous-serialize==2.4.0 voluptuous==0.12.1 yarl==1.6.3 -zeroconf==0.33.3 +zeroconf==0.33.4 pycryptodome>=3.6.6 diff --git a/requirements_all.txt b/requirements_all.txt index 248a33ee293..8c936677ba2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2439,7 +2439,7 @@ zeep[async]==4.0.0 zengge==0.2 # homeassistant.components.zeroconf -zeroconf==0.33.3 +zeroconf==0.33.4 # homeassistant.components.zha zha-quirks==0.0.59 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0ec7f8b25f4..f9fbc43d789 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1341,7 +1341,7 @@ youless-api==0.10 zeep[async]==4.0.0 # homeassistant.components.zeroconf -zeroconf==0.33.3 +zeroconf==0.33.4 # homeassistant.components.zha zha-quirks==0.0.59 From cb775029e0ae74ebb7daa0e2cbecb66a18aa5db6 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 6 Aug 2021 12:55:59 -0700 Subject: [PATCH 6/6] Bumped version to 2021.8.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index b8134905927..d4a79d3a8bb 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -5,7 +5,7 @@ from typing import Final MAJOR_VERSION: Final = 2021 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "2" +PATCH_VERSION: Final = "3" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)