From f18ab504a552a93c8e59e65c2cb6cba350576701 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 2 Sep 2022 03:33:55 +0200 Subject: [PATCH 01/34] Move up setup of service to make it more robust when running multiple instances of deCONZ (#77621) --- homeassistant/components/deconz/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index cb4715f3c28..4750c40fab2 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -43,6 +43,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b except AuthenticationRequired as err: raise ConfigEntryAuthFailed from err + if not hass.data[DOMAIN]: + async_setup_services(hass) + gateway = hass.data[DOMAIN][config_entry.entry_id] = DeconzGateway( hass, config_entry, api ) @@ -53,9 +56,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b await async_setup_events(gateway) await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) - if len(hass.data[DOMAIN]) == 1: - async_setup_services(hass) - api.start() config_entry.async_on_unload( From 184a1c95f0aa312fd64b29ddd9af25eb9567fe9c Mon Sep 17 00:00:00 2001 From: Yevhenii Vaskivskyi Date: Tue, 13 Sep 2022 16:46:31 +0200 Subject: [PATCH 02/34] Bump blinkpy to 0.19.2 (#78097) --- homeassistant/components/blink/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/blink/manifest.json b/homeassistant/components/blink/manifest.json index c302f2dab6c..aa3cad317ac 100644 --- a/homeassistant/components/blink/manifest.json +++ b/homeassistant/components/blink/manifest.json @@ -2,7 +2,7 @@ "domain": "blink", "name": "Blink", "documentation": "https://www.home-assistant.io/integrations/blink", - "requirements": ["blinkpy==0.19.0"], + "requirements": ["blinkpy==0.19.2"], "codeowners": ["@fronzbot"], "dhcp": [ { diff --git a/requirements_all.txt b/requirements_all.txt index 4038e1863f4..0e1af72f066 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -414,7 +414,7 @@ bleak==0.16.0 blebox_uniapi==2.0.2 # homeassistant.components.blink -blinkpy==0.19.0 +blinkpy==0.19.2 # homeassistant.components.blinksticklight blinkstick==1.2.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3f072512375..3cded1bf00c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -335,7 +335,7 @@ bleak==0.16.0 blebox_uniapi==2.0.2 # homeassistant.components.blink -blinkpy==0.19.0 +blinkpy==0.19.2 # homeassistant.components.bluemaestro bluemaestro-ble==0.2.0 From 3129114d07af35800d3b77806859f582f93d6f0c Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Tue, 13 Sep 2022 13:01:13 +0200 Subject: [PATCH 03/34] Bump PyViCare==2.17.0 (#78232) --- homeassistant/components/vicare/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/vicare/manifest.json b/homeassistant/components/vicare/manifest.json index 575ca35729b..c770f1b2382 100644 --- a/homeassistant/components/vicare/manifest.json +++ b/homeassistant/components/vicare/manifest.json @@ -3,7 +3,7 @@ "name": "Viessmann ViCare", "documentation": "https://www.home-assistant.io/integrations/vicare", "codeowners": ["@oischinger"], - "requirements": ["PyViCare==2.16.2"], + "requirements": ["PyViCare==2.17.0"], "iot_class": "cloud_polling", "config_flow": true, "dhcp": [ diff --git a/requirements_all.txt b/requirements_all.txt index 0e1af72f066..09448308a01 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -47,7 +47,7 @@ PyTransportNSW==0.1.1 PyTurboJPEG==1.6.7 # homeassistant.components.vicare -PyViCare==2.16.2 +PyViCare==2.17.0 # homeassistant.components.xiaomi_aqara PyXiaomiGateway==0.13.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3cded1bf00c..6d3e863708a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -43,7 +43,7 @@ PyTransportNSW==0.1.1 PyTurboJPEG==1.6.7 # homeassistant.components.vicare -PyViCare==2.16.2 +PyViCare==2.17.0 # homeassistant.components.xiaomi_aqara PyXiaomiGateway==0.13.4 From 9640553b529442594a5850d83c8442abc94543d9 Mon Sep 17 00:00:00 2001 From: d-walsh Date: Mon, 12 Sep 2022 19:03:07 -0400 Subject: [PATCH 04/34] Fix missing dependency for dbus_next (#78235) --- homeassistant/components/bluetooth/manifest.json | 3 ++- homeassistant/package_constraints.txt | 1 + requirements_all.txt | 3 +++ requirements_test_all.txt | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 3c9ef7a85b7..55a7e610e76 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -7,7 +7,8 @@ "requirements": [ "bleak==0.16.0", "bluetooth-adapters==0.4.1", - "bluetooth-auto-recovery==0.3.2" + "bluetooth-auto-recovery==0.3.2", + "dbus_next==0.2.3" ], "codeowners": ["@bdraco"], "config_flow": true, diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 4f41518361f..1e4a0975a1a 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -16,6 +16,7 @@ bluetooth-auto-recovery==0.3.2 certifi>=2021.5.30 ciso8601==2.2.0 cryptography==37.0.4 +dbus_next==0.2.3 fnvhash==0.1.0 hass-nabucasa==0.55.0 home-assistant-bluetooth==1.3.0 diff --git a/requirements_all.txt b/requirements_all.txt index 09448308a01..6e49b75c0dd 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -534,6 +534,9 @@ datadog==0.15.0 # homeassistant.components.metoffice datapoint==0.9.8 +# homeassistant.components.bluetooth +dbus_next==0.2.3 + # homeassistant.components.debugpy debugpy==1.6.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6d3e863708a..cd195516a73 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -411,6 +411,9 @@ datadog==0.15.0 # homeassistant.components.metoffice datapoint==0.9.8 +# homeassistant.components.bluetooth +dbus_next==0.2.3 + # homeassistant.components.debugpy debugpy==1.6.3 From f6d26476b571c7996b2aa4537916b54fb0b7c866 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Sep 2022 19:16:46 -0500 Subject: [PATCH 05/34] Bump bluetooth-auto-recovery to 0.3.3 (#78245) Downgrades a few more loggers to debug since the only reason we check them is to give a better error message when the bluetooth adapter is blocked by rfkill. https://github.com/Bluetooth-Devices/bluetooth-auto-recovery/compare/v0.3.2...v0.3.3 closes #78211 --- homeassistant/components/bluetooth/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/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 55a7e610e76..434b4c1127e 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -7,7 +7,7 @@ "requirements": [ "bleak==0.16.0", "bluetooth-adapters==0.4.1", - "bluetooth-auto-recovery==0.3.2", + "bluetooth-auto-recovery==0.3.3", "dbus_next==0.2.3" ], "codeowners": ["@bdraco"], diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 1e4a0975a1a..f9c92c8fdea 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -12,7 +12,7 @@ awesomeversion==22.8.0 bcrypt==3.1.7 bleak==0.16.0 bluetooth-adapters==0.4.1 -bluetooth-auto-recovery==0.3.2 +bluetooth-auto-recovery==0.3.3 certifi>=2021.5.30 ciso8601==2.2.0 cryptography==37.0.4 diff --git a/requirements_all.txt b/requirements_all.txt index 6e49b75c0dd..1ac6009d871 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -433,7 +433,7 @@ bluemaestro-ble==0.2.0 bluetooth-adapters==0.4.1 # homeassistant.components.bluetooth -bluetooth-auto-recovery==0.3.2 +bluetooth-auto-recovery==0.3.3 # homeassistant.components.bond bond-async==0.1.22 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index cd195516a73..6215cd68cb5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -344,7 +344,7 @@ bluemaestro-ble==0.2.0 bluetooth-adapters==0.4.1 # homeassistant.components.bluetooth -bluetooth-auto-recovery==0.3.2 +bluetooth-auto-recovery==0.3.3 # homeassistant.components.bond bond-async==0.1.22 From 95a89448e043c54269213ca60d44c300b4d1cd5e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Sep 2022 05:19:45 -0500 Subject: [PATCH 06/34] Bump aiodiscover to 1.4.13 (#78253) --- homeassistant/components/dhcp/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/dhcp/manifest.json b/homeassistant/components/dhcp/manifest.json index fea7772f72d..f3f44f6dc9b 100644 --- a/homeassistant/components/dhcp/manifest.json +++ b/homeassistant/components/dhcp/manifest.json @@ -2,7 +2,7 @@ "domain": "dhcp", "name": "DHCP Discovery", "documentation": "https://www.home-assistant.io/integrations/dhcp", - "requirements": ["scapy==2.4.5", "aiodiscover==1.4.11"], + "requirements": ["scapy==2.4.5", "aiodiscover==1.4.13"], "codeowners": ["@bdraco"], "quality_scale": "internal", "iot_class": "local_push", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index f9c92c8fdea..dbbfda9d6db 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -1,6 +1,6 @@ PyJWT==2.4.0 PyNaCl==1.5.0 -aiodiscover==1.4.11 +aiodiscover==1.4.13 aiohttp==3.8.1 aiohttp_cors==0.7.0 astral==2.2 diff --git a/requirements_all.txt b/requirements_all.txt index 1ac6009d871..6d00afceb36 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -134,7 +134,7 @@ aiobafi6==0.7.2 aiobotocore==2.1.0 # homeassistant.components.dhcp -aiodiscover==1.4.11 +aiodiscover==1.4.13 # homeassistant.components.dnsip # homeassistant.components.minecraft_server diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6215cd68cb5..2780b516ce4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -121,7 +121,7 @@ aiobafi6==0.7.2 aiobotocore==2.1.0 # homeassistant.components.dhcp -aiodiscover==1.4.11 +aiodiscover==1.4.13 # homeassistant.components.dnsip # homeassistant.components.minecraft_server From d6bf1a8caa10b3af52ee2cbf5df34b82be508619 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Sep 2022 14:18:26 -0500 Subject: [PATCH 07/34] Bump pySwitchbot to 0.19.6 (#78304) No longer swallows exceptions from bleak connection errors which was hiding the root cause of problems. This was the original behavior from a long time ago which does not make sense anymore since we retry a few times anyways https://github.com/Danielhiversen/pySwitchbot/compare/0.19.5...0.19.6 --- homeassistant/components/switchbot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index e1e832f854a..b2a5b68deae 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.19.5"], + "requirements": ["PySwitchbot==0.19.6"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/requirements_all.txt b/requirements_all.txt index 6d00afceb36..d2b6f6ef853 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,7 +37,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.19.5 +PySwitchbot==0.19.6 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2780b516ce4..b1069836313 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -33,7 +33,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.19.5 +PySwitchbot==0.19.6 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From a90b6d37bf34c9738cc11c578d6e4a81eb92a3c4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 05:38:01 -0500 Subject: [PATCH 08/34] Make yalexs_ble matcher more specific (#78307) --- homeassistant/components/yalexs_ble/manifest.json | 7 ++++++- homeassistant/generated/bluetooth.py | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/yalexs_ble/manifest.json b/homeassistant/components/yalexs_ble/manifest.json index a685d750077..f3a9cc798e6 100644 --- a/homeassistant/components/yalexs_ble/manifest.json +++ b/homeassistant/components/yalexs_ble/manifest.json @@ -6,7 +6,12 @@ "requirements": ["yalexs-ble==1.8.1"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], - "bluetooth": [{ "manufacturer_id": 465 }], + "bluetooth": [ + { + "manufacturer_id": 465, + "service_uuid": "0000fe24-0000-1000-8000-00805f9b34fb" + } + ], "iot_class": "local_push", "supported_brands": { "august_ble": "August Bluetooth" diff --git a/homeassistant/generated/bluetooth.py b/homeassistant/generated/bluetooth.py index b2400f733da..59f10767e0d 100644 --- a/homeassistant/generated/bluetooth.py +++ b/homeassistant/generated/bluetooth.py @@ -281,6 +281,7 @@ BLUETOOTH: list[dict[str, bool | str | int | list[int]]] = [ }, { "domain": "yalexs_ble", - "manufacturer_id": 465 + "manufacturer_id": 465, + "service_uuid": "0000fe24-0000-1000-8000-00805f9b34fb" } ] From 0aa2685e0c4657492fbaede5786b4769b45df989 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Mon, 12 Sep 2022 15:37:11 -0400 Subject: [PATCH 09/34] Fix sengled bulbs in ZHA (#78315) * Fix sengled bulbs in ZHA * fix tests * update discovery data --- homeassistant/components/zha/light.py | 2 +- tests/components/zha/test_light.py | 2 +- tests/components/zha/zha_devices_list.py | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index 9858c6803f9..5b2df6d11cf 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -84,7 +84,7 @@ PARALLEL_UPDATES = 0 SIGNAL_LIGHT_GROUP_STATE_CHANGED = "zha_light_group_state_changed" SIGNAL_LIGHT_GROUP_TRANSITION_START = "zha_light_group_transition_start" SIGNAL_LIGHT_GROUP_TRANSITION_FINISHED = "zha_light_group_transition_finished" -DEFAULT_MIN_TRANSITION_MANUFACTURERS = {"Sengled"} +DEFAULT_MIN_TRANSITION_MANUFACTURERS = {"sengled"} COLOR_MODES_GROUP_LIGHT = {ColorMode.COLOR_TEMP, ColorMode.XY} SUPPORT_GROUP_LIGHT = ( diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py index 16678393f52..bc907e4252f 100644 --- a/tests/components/zha/test_light.py +++ b/tests/components/zha/test_light.py @@ -178,7 +178,7 @@ async def device_light_2(hass, zigpy_device_mock, zha_device_joined): } }, ieee=IEEE_GROUPABLE_DEVICE2, - manufacturer="Sengled", + manufacturer="sengled", nwk=0xC79E, ) color_cluster = zigpy_device.endpoints[1].light_color diff --git a/tests/components/zha/zha_devices_list.py b/tests/components/zha/zha_devices_list.py index 4cea8eb8f66..2d15f9335db 100644 --- a/tests/components/zha/zha_devices_list.py +++ b/tests/components/zha/zha_devices_list.py @@ -5493,7 +5493,7 @@ DEVICES = [ DEV_SIG_EVT_CHANNELS: ["1:0x0019"], DEV_SIG_ENTITIES: [ "button.sengled_e11_g13_identifybutton", - "light.sengled_e11_g13_light", + "light.sengled_e11_g13_mintransitionlight", "sensor.sengled_e11_g13_smartenergymetering", "sensor.sengled_e11_g13_smartenergysummation", "sensor.sengled_e11_g13_rssi", @@ -5502,8 +5502,8 @@ DEVICES = [ DEV_SIG_ENT_MAP: { ("light", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CHANNELS: ["on_off", "level"], - DEV_SIG_ENT_MAP_CLASS: "Light", - DEV_SIG_ENT_MAP_ID: "light.sengled_e11_g13_light", + DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", + DEV_SIG_ENT_MAP_ID: "light.sengled_e11_g13_mintransitionlight", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CHANNELS: ["identify"], @@ -5549,7 +5549,7 @@ DEVICES = [ DEV_SIG_EVT_CHANNELS: ["1:0x0019"], DEV_SIG_ENTITIES: [ "button.sengled_e12_n14_identifybutton", - "light.sengled_e12_n14_light", + "light.sengled_e12_n14_mintransitionlight", "sensor.sengled_e12_n14_smartenergymetering", "sensor.sengled_e12_n14_smartenergysummation", "sensor.sengled_e12_n14_rssi", @@ -5558,8 +5558,8 @@ DEVICES = [ DEV_SIG_ENT_MAP: { ("light", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CHANNELS: ["on_off", "level"], - DEV_SIG_ENT_MAP_CLASS: "Light", - DEV_SIG_ENT_MAP_ID: "light.sengled_e12_n14_light", + DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", + DEV_SIG_ENT_MAP_ID: "light.sengled_e12_n14_mintransitionlight", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CHANNELS: ["identify"], @@ -5605,7 +5605,7 @@ DEVICES = [ DEV_SIG_EVT_CHANNELS: ["1:0x0019"], DEV_SIG_ENTITIES: [ "button.sengled_z01_a19nae26_identifybutton", - "light.sengled_z01_a19nae26_light", + "light.sengled_z01_a19nae26_mintransitionlight", "sensor.sengled_z01_a19nae26_smartenergymetering", "sensor.sengled_z01_a19nae26_smartenergysummation", "sensor.sengled_z01_a19nae26_rssi", @@ -5614,8 +5614,8 @@ DEVICES = [ DEV_SIG_ENT_MAP: { ("light", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CHANNELS: ["on_off", "level", "light_color"], - DEV_SIG_ENT_MAP_CLASS: "Light", - DEV_SIG_ENT_MAP_ID: "light.sengled_z01_a19nae26_light", + DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", + DEV_SIG_ENT_MAP_ID: "light.sengled_z01_a19nae26_mintransitionlight", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CHANNELS: ["identify"], From 9acf74d78313a95d6902ca7c57099286dfc1a0e9 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 03:24:49 +0200 Subject: [PATCH 10/34] Fix calculating gas cost for gas measured in ft3 (#78327) --- homeassistant/components/energy/sensor.py | 3 ++- tests/components/energy/test_sensor.py | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/energy/sensor.py b/homeassistant/components/energy/sensor.py index 4002f6c416d..602fc09f602 100644 --- a/homeassistant/components/energy/sensor.py +++ b/homeassistant/components/energy/sensor.py @@ -20,6 +20,7 @@ from homeassistant.const import ( ENERGY_KILO_WATT_HOUR, ENERGY_MEGA_WATT_HOUR, ENERGY_WATT_HOUR, + VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS, ) from homeassistant.core import ( @@ -44,7 +45,7 @@ SUPPORTED_STATE_CLASSES = [ SensorStateClass.TOTAL_INCREASING, ] VALID_ENERGY_UNITS = [ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR, ENERGY_MEGA_WATT_HOUR] -VALID_ENERGY_UNITS_GAS = [VOLUME_CUBIC_METERS] + VALID_ENERGY_UNITS +VALID_ENERGY_UNITS_GAS = [VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS] + VALID_ENERGY_UNITS _LOGGER = logging.getLogger(__name__) diff --git a/tests/components/energy/test_sensor.py b/tests/components/energy/test_sensor.py index 997f60a8899..9fa82ead2a1 100644 --- a/tests/components/energy/test_sensor.py +++ b/tests/components/energy/test_sensor.py @@ -20,6 +20,7 @@ from homeassistant.const import ( ENERGY_MEGA_WATT_HOUR, ENERGY_WATT_HOUR, STATE_UNKNOWN, + VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS, ) from homeassistant.helpers import entity_registry as er @@ -841,10 +842,13 @@ async def test_cost_sensor_handle_price_units( assert state.state == "20.0" -async def test_cost_sensor_handle_gas(hass, hass_storage, setup_integration) -> None: +@pytest.mark.parametrize("unit", (VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS)) +async def test_cost_sensor_handle_gas( + hass, hass_storage, setup_integration, unit +) -> None: """Test gas cost price from sensor entity.""" energy_attributes = { - ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS, + ATTR_UNIT_OF_MEASUREMENT: unit, ATTR_STATE_CLASS: SensorStateClass.TOTAL_INCREASING, } energy_data = data.EnergyManager.default_preferences() From 47f6be77cc53053bc23b905c0fac3df7cdd0f5b2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 14:31:34 +0200 Subject: [PATCH 11/34] Bump bleak to 0.17.0 (#78333) --- homeassistant/components/bluetooth/manifest.json | 5 +++-- homeassistant/components/bluetooth/scanner.py | 2 +- homeassistant/package_constraints.txt | 5 +++-- requirements_all.txt | 7 +++++-- requirements_test_all.txt | 7 +++++-- tests/components/bluetooth/test_scanner.py | 2 +- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 434b4c1127e..acc8a6977e3 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -5,10 +5,11 @@ "dependencies": ["usb"], "quality_scale": "internal", "requirements": [ - "bleak==0.16.0", + "bleak==0.17.0", + "bleak-retry-connector==1.15.1", "bluetooth-adapters==0.4.1", "bluetooth-auto-recovery==0.3.3", - "dbus_next==0.2.3" + "dbus-fast==1.4.0" ], "codeowners": ["@bdraco"], "config_flow": true, diff --git a/homeassistant/components/bluetooth/scanner.py b/homeassistant/components/bluetooth/scanner.py index 78979198e5c..184e8775f07 100644 --- a/homeassistant/components/bluetooth/scanner.py +++ b/homeassistant/components/bluetooth/scanner.py @@ -17,7 +17,7 @@ from bleak.backends.bluezdbus.advertisement_monitor import OrPattern from bleak.backends.bluezdbus.scanner import BlueZScannerArgs from bleak.backends.device import BLEDevice from bleak.backends.scanner import AdvertisementData -from dbus_next import InvalidMessageError +from dbus_fast import InvalidMessageError from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.core import ( diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index dbbfda9d6db..b511248a602 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -10,13 +10,14 @@ atomicwrites-homeassistant==1.4.1 attrs==21.2.0 awesomeversion==22.8.0 bcrypt==3.1.7 -bleak==0.16.0 +bleak-retry-connector==1.15.1 +bleak==0.17.0 bluetooth-adapters==0.4.1 bluetooth-auto-recovery==0.3.3 certifi>=2021.5.30 ciso8601==2.2.0 cryptography==37.0.4 -dbus_next==0.2.3 +dbus-fast==1.4.0 fnvhash==0.1.0 hass-nabucasa==0.55.0 home-assistant-bluetooth==1.3.0 diff --git a/requirements_all.txt b/requirements_all.txt index d2b6f6ef853..85cea15f0e9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -408,7 +408,10 @@ bimmer_connected==0.10.2 bizkaibus==0.1.1 # homeassistant.components.bluetooth -bleak==0.16.0 +bleak-retry-connector==1.15.1 + +# homeassistant.components.bluetooth +bleak==0.17.0 # homeassistant.components.blebox blebox_uniapi==2.0.2 @@ -535,7 +538,7 @@ datadog==0.15.0 datapoint==0.9.8 # homeassistant.components.bluetooth -dbus_next==0.2.3 +dbus-fast==1.4.0 # homeassistant.components.debugpy debugpy==1.6.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b1069836313..df34b95ff56 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -329,7 +329,10 @@ bellows==0.33.1 bimmer_connected==0.10.2 # homeassistant.components.bluetooth -bleak==0.16.0 +bleak-retry-connector==1.15.1 + +# homeassistant.components.bluetooth +bleak==0.17.0 # homeassistant.components.blebox blebox_uniapi==2.0.2 @@ -412,7 +415,7 @@ datadog==0.15.0 datapoint==0.9.8 # homeassistant.components.bluetooth -dbus_next==0.2.3 +dbus-fast==1.4.0 # homeassistant.components.debugpy debugpy==1.6.3 diff --git a/tests/components/bluetooth/test_scanner.py b/tests/components/bluetooth/test_scanner.py index 26e949ad2e3..2c1810d8338 100644 --- a/tests/components/bluetooth/test_scanner.py +++ b/tests/components/bluetooth/test_scanner.py @@ -7,7 +7,7 @@ from bleak.backends.scanner import ( AdvertisementDataCallback, BLEDevice, ) -from dbus_next import InvalidMessageError +from dbus_fast import InvalidMessageError import pytest from homeassistant.components import bluetooth From 12edfb39293884f0830700e8c6aeb6fc227bdf04 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 14:39:05 +0200 Subject: [PATCH 12/34] Drop initial when loading input_number from storage (#78354) --- .../components/input_number/__init__.py | 16 ++++++++++++++++ tests/components/input_number/test_init.py | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/input_number/__init__.py b/homeassistant/components/input_number/__init__.py index ff01bd124b6..0e56c1df15b 100644 --- a/homeassistant/components/input_number/__init__.py +++ b/homeassistant/components/input_number/__init__.py @@ -196,6 +196,22 @@ class NumberStorageCollection(collection.StorageCollection): """Suggest an ID based on the config.""" return info[CONF_NAME] + async def _async_load_data(self) -> dict | None: + """Load the data. + + A past bug caused frontend to add initial value to all input numbers. + This drops that. + """ + data = await super()._async_load_data() + + if data is None: + return data + + for number in data["items"]: + number.pop(CONF_INITIAL, None) + + return data + async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" update_data = self.UPDATE_SCHEMA(update_data) diff --git a/tests/components/input_number/test_init.py b/tests/components/input_number/test_init.py index 4149627720b..bec05d3f344 100644 --- a/tests/components/input_number/test_init.py +++ b/tests/components/input_number/test_init.py @@ -416,7 +416,7 @@ async def test_load_from_storage(hass, storage_setup): """Test set up from storage.""" assert await storage_setup() state = hass.states.get(f"{DOMAIN}.from_storage") - assert float(state.state) == 10 + assert float(state.state) == 0 # initial is not supported when loading from storage assert state.attributes.get(ATTR_FRIENDLY_NAME) == "from storage" assert state.attributes.get(ATTR_EDITABLE) @@ -438,7 +438,7 @@ async def test_editable_state_attribute(hass, storage_setup): ) state = hass.states.get(f"{DOMAIN}.from_storage") - assert float(state.state) == 10 + assert float(state.state) == 0 assert state.attributes.get(ATTR_FRIENDLY_NAME) == "from storage" assert state.attributes.get(ATTR_EDITABLE) From ad396f0538bd6f15340d0eb626e8d713f8737dca Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:54:52 +0200 Subject: [PATCH 13/34] Don't allow partial update of input_number settings (#78356) --- .../components/input_number/__init__.py | 24 ++++---------- tests/components/input_number/test_init.py | 32 +++++++++++-------- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/input_number/__init__.py b/homeassistant/components/input_number/__init__.py index 0e56c1df15b..00aeca2ab34 100644 --- a/homeassistant/components/input_number/__init__.py +++ b/homeassistant/components/input_number/__init__.py @@ -65,7 +65,7 @@ def _cv_input_number(cfg): return cfg -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), vol.Required(CONF_MIN): vol.Coerce(float), vol.Required(CONF_MAX): vol.Coerce(float), @@ -76,17 +76,6 @@ CREATE_FIELDS = { vol.Optional(CONF_MODE, default=MODE_SLIDER): vol.In([MODE_BOX, MODE_SLIDER]), } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_MIN): vol.Coerce(float), - vol.Optional(CONF_MAX): vol.Coerce(float), - vol.Optional(CONF_INITIAL): vol.Coerce(float), - vol.Optional(CONF_STEP): vol.All(vol.Coerce(float), vol.Range(min=1e-9)), - vol.Optional(CONF_ICON): cv.icon, - vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, - vol.Optional(CONF_MODE): vol.In([MODE_BOX, MODE_SLIDER]), -} - CONFIG_SCHEMA = vol.Schema( { DOMAIN: cv.schema_with_slug_keys( @@ -148,7 +137,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: @@ -184,12 +173,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class NumberStorageCollection(collection.StorageCollection): """Input storage based collection.""" - CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, _cv_input_number)) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_number)) async def _process_create_data(self, data: dict) -> dict: """Validate the config is valid.""" - return self.CREATE_SCHEMA(data) + return self.SCHEMA(data) @callback def _get_suggested_id(self, info: dict) -> str: @@ -214,8 +202,8 @@ class NumberStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return _cv_input_number({**data, **update_data}) + update_data = self.SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data class InputNumber(RestoreEntity): diff --git a/tests/components/input_number/test_init.py b/tests/components/input_number/test_init.py index bec05d3f344..7ba7489f644 100644 --- a/tests/components/input_number/test_init.py +++ b/tests/components/input_number/test_init.py @@ -507,16 +507,14 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup): async def test_update_min_max(hass, hass_ws_client, storage_setup): """Test updating min/max updates the state.""" - items = [ - { - "id": "from_storage", - "name": "from storage", - "max": 100, - "min": 0, - "step": 1, - "mode": "slider", - } - ] + settings = { + "name": "from storage", + "max": 100, + "min": 0, + "step": 1, + "mode": "slider", + } + items = [{"id": "from_storage"} | settings] assert await storage_setup(items) input_id = "from_storage" @@ -530,26 +528,34 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup): client = await hass_ws_client(hass) + updated_settings = settings | {"min": 9} await client.send_json( - {"id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", "min": 9} + { + "id": 6, + "type": f"{DOMAIN}/update", + f"{DOMAIN}_id": f"{input_id}", + **updated_settings, + } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert float(state.state) == 9 + updated_settings = settings | {"max": 5} await client.send_json( { "id": 7, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "max": 5, - "min": 0, + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert float(state.state) == 5 From bfcb9402ef4d2f36465d572b6fce46b075e26995 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 22:11:44 +0200 Subject: [PATCH 14/34] Bump PySwitchbot to 0.19.8 (#78361) * Bump PySwitchbot to 0.19.7 Changes for bleak 0.17 https://github.com/Danielhiversen/pySwitchbot/compare/0.19.6...0.19.7 * bump again to fix some more stale state bugs --- homeassistant/components/switchbot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index b2a5b68deae..41b3f5aa61b 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.19.6"], + "requirements": ["PySwitchbot==0.19.8"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/requirements_all.txt b/requirements_all.txt index 85cea15f0e9..5da2446c36b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,7 +37,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.19.6 +PySwitchbot==0.19.8 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index df34b95ff56..f9ee981b1a9 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -33,7 +33,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.19.6 +PySwitchbot==0.19.8 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From b21a37cad51ed0c53795f0e3830f72a9e9eebeda Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 22:14:53 +0200 Subject: [PATCH 15/34] Bump yalexs-ble to 1.9.0 (#78362) --- homeassistant/components/yalexs_ble/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/yalexs_ble/manifest.json b/homeassistant/components/yalexs_ble/manifest.json index f3a9cc798e6..673521f9e06 100644 --- a/homeassistant/components/yalexs_ble/manifest.json +++ b/homeassistant/components/yalexs_ble/manifest.json @@ -3,7 +3,7 @@ "name": "Yale Access Bluetooth", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/yalexs_ble", - "requirements": ["yalexs-ble==1.8.1"], + "requirements": ["yalexs-ble==1.9.0"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], "bluetooth": [ diff --git a/requirements_all.txt b/requirements_all.txt index 5da2446c36b..a46bc7c3193 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2548,7 +2548,7 @@ xs1-api-client==3.0.0 yalesmartalarmclient==0.3.9 # homeassistant.components.yalexs_ble -yalexs-ble==1.8.1 +yalexs-ble==1.9.0 # homeassistant.components.august yalexs==1.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f9ee981b1a9..82508fd7cb3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1752,7 +1752,7 @@ xmltodict==0.13.0 yalesmartalarmclient==0.3.9 # homeassistant.components.yalexs_ble -yalexs-ble==1.8.1 +yalexs-ble==1.9.0 # homeassistant.components.august yalexs==1.2.1 From cd7f65bb6aefc45066e7b16833b1a7fcde5b997e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Sep 2022 16:54:20 -0500 Subject: [PATCH 16/34] Bump xiaomi-ble to 0.9.3 (#78301) --- .../components/xiaomi_ble/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- .../xiaomi_ble/test_binary_sensor.py | 8 +- .../components/xiaomi_ble/test_config_flow.py | 38 ++++---- tests/components/xiaomi_ble/test_sensor.py | 95 ++++++++----------- 6 files changed, 66 insertions(+), 81 deletions(-) diff --git a/homeassistant/components/xiaomi_ble/manifest.json b/homeassistant/components/xiaomi_ble/manifest.json index c01f0846234..de8e61ad8ce 100644 --- a/homeassistant/components/xiaomi_ble/manifest.json +++ b/homeassistant/components/xiaomi_ble/manifest.json @@ -9,7 +9,7 @@ "service_data_uuid": "0000fe95-0000-1000-8000-00805f9b34fb" } ], - "requirements": ["xiaomi-ble==0.9.0"], + "requirements": ["xiaomi-ble==0.9.3"], "dependencies": ["bluetooth"], "codeowners": ["@Jc2k", "@Ernst79"], "iot_class": "local_push" diff --git a/requirements_all.txt b/requirements_all.txt index a46bc7c3193..6ba52832cba 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2528,7 +2528,7 @@ xbox-webapi==2.0.11 xboxapi==2.0.1 # homeassistant.components.xiaomi_ble -xiaomi-ble==0.9.0 +xiaomi-ble==0.9.3 # homeassistant.components.knx xknx==1.0.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 82508fd7cb3..f5452a9140c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1735,7 +1735,7 @@ wolf_smartset==0.1.11 xbox-webapi==2.0.11 # homeassistant.components.xiaomi_ble -xiaomi-ble==0.9.0 +xiaomi-ble==0.9.3 # homeassistant.components.knx xknx==1.0.2 diff --git a/tests/components/xiaomi_ble/test_binary_sensor.py b/tests/components/xiaomi_ble/test_binary_sensor.py index 390c8d4b579..dd49b4d181d 100644 --- a/tests/components/xiaomi_ble/test_binary_sensor.py +++ b/tests/components/xiaomi_ble/test_binary_sensor.py @@ -45,10 +45,10 @@ async def test_smoke_sensor(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 - smoke_sensor = hass.states.get("binary_sensor.thermometer_e39cbc_smoke") + smoke_sensor = hass.states.get("binary_sensor.thermometer_9cbc_smoke") smoke_sensor_attribtes = smoke_sensor.attributes assert smoke_sensor.state == "on" - assert smoke_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Thermometer E39CBC Smoke" + assert smoke_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Thermometer 9CBC Smoke" assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() @@ -90,10 +90,10 @@ async def test_moisture(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 - sensor = hass.states.get("binary_sensor.smart_flower_pot_6a3e7a_moisture") + sensor = hass.states.get("binary_sensor.smart_flower_pot_3e7a_moisture") sensor_attr = sensor.attributes assert sensor.state == "on" - assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Moisture" + assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Moisture" assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() diff --git a/tests/components/xiaomi_ble/test_config_flow.py b/tests/components/xiaomi_ble/test_config_flow.py index 6a1c9c8e435..a884e5cbefa 100644 --- a/tests/components/xiaomi_ble/test_config_flow.py +++ b/tests/components/xiaomi_ble/test_config_flow.py @@ -39,7 +39,7 @@ async def test_async_step_bluetooth_valid_device(hass): result["flow_id"], user_input={} ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Baby Thermometer DD6FC1 (MMC-T201-1)" + assert result2["title"] == "Baby Thermometer 6FC1 (MMC-T201-1)" assert result2["data"] == {} assert result2["result"].unique_id == "00:81:F9:DD:6F:C1" @@ -65,7 +65,7 @@ async def test_async_step_bluetooth_valid_device_but_missing_payload(hass): result["flow_id"], user_input={} ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Temperature/Humidity Sensor 565384 (LYWSD03MMC)" + assert result2["title"] == "Temperature/Humidity Sensor 5384 (LYWSD03MMC)" assert result2["data"] == {} assert result2["result"].unique_id == "A4:C1:38:56:53:84" @@ -123,7 +123,7 @@ async def test_async_step_bluetooth_during_onboarding(hass): ) assert result["type"] == FlowResultType.CREATE_ENTRY - assert result["title"] == "Baby Thermometer DD6FC1 (MMC-T201-1)" + assert result["title"] == "Baby Thermometer 6FC1 (MMC-T201-1)" assert result["data"] == {} assert result["result"].unique_id == "00:81:F9:DD:6F:C1" assert len(mock_setup_entry.mock_calls) == 1 @@ -148,7 +148,7 @@ async def test_async_step_bluetooth_valid_device_legacy_encryption(hass): user_input={"bindkey": "b853075158487ca39a5b5ea9"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)" + assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)" assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"} assert result2["result"].unique_id == "F8:24:41:C5:98:8B" @@ -180,7 +180,7 @@ async def test_async_step_bluetooth_valid_device_legacy_encryption_wrong_key(has user_input={"bindkey": "b853075158487ca39a5b5ea9"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)" + assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)" assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"} assert result2["result"].unique_id == "F8:24:41:C5:98:8B" @@ -214,7 +214,7 @@ async def test_async_step_bluetooth_valid_device_legacy_encryption_wrong_key_len user_input={"bindkey": "b853075158487ca39a5b5ea9"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)" + assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)" assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"} assert result2["result"].unique_id == "F8:24:41:C5:98:8B" @@ -238,7 +238,7 @@ async def test_async_step_bluetooth_valid_device_v4_encryption(hass): ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)" + assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)" assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"} assert result2["result"].unique_id == "54:EF:44:E3:9C:BC" @@ -272,7 +272,7 @@ async def test_async_step_bluetooth_valid_device_v4_encryption_wrong_key(hass): ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)" + assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)" assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"} assert result2["result"].unique_id == "54:EF:44:E3:9C:BC" @@ -306,7 +306,7 @@ async def test_async_step_bluetooth_valid_device_v4_encryption_wrong_key_length( ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)" + assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)" assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"} assert result2["result"].unique_id == "54:EF:44:E3:9C:BC" @@ -370,7 +370,7 @@ async def test_async_step_user_with_found_devices(hass): user_input={"address": "58:2D:34:35:93:21"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Temperature/Humidity Sensor 359321 (LYWSDCGQ)" + assert result2["title"] == "Temperature/Humidity Sensor 9321 (LYWSDCGQ)" assert result2["data"] == {} assert result2["result"].unique_id == "58:2D:34:35:93:21" @@ -405,7 +405,7 @@ async def test_async_step_user_short_payload(hass): result["flow_id"], user_input={} ) assert result3["type"] == FlowResultType.CREATE_ENTRY - assert result3["title"] == "Temperature/Humidity Sensor 565384 (LYWSD03MMC)" + assert result3["title"] == "Temperature/Humidity Sensor 5384 (LYWSD03MMC)" assert result3["data"] == {} assert result3["result"].unique_id == "A4:C1:38:56:53:84" @@ -453,7 +453,7 @@ async def test_async_step_user_short_payload_then_full(hass): ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Temperature/Humidity Sensor 565384 (LYWSD03MMC)" + assert result2["title"] == "Temperature/Humidity Sensor 5384 (LYWSD03MMC)" assert result2["data"] == {"bindkey": "a115210eed7a88e50ad52662e732a9fb"} @@ -486,7 +486,7 @@ async def test_async_step_user_with_found_devices_v4_encryption(hass): ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)" + assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)" assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"} assert result2["result"].unique_id == "54:EF:44:E3:9C:BC" @@ -532,7 +532,7 @@ async def test_async_step_user_with_found_devices_v4_encryption_wrong_key(hass): ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)" + assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)" assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"} assert result2["result"].unique_id == "54:EF:44:E3:9C:BC" @@ -580,7 +580,7 @@ async def test_async_step_user_with_found_devices_v4_encryption_wrong_key_length ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Thermometer E39CBC (JTYJGD03MI)" + assert result2["title"] == "Thermometer 9CBC (JTYJGD03MI)" assert result2["data"] == {"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"} assert result2["result"].unique_id == "54:EF:44:E3:9C:BC" @@ -613,7 +613,7 @@ async def test_async_step_user_with_found_devices_legacy_encryption(hass): user_input={"bindkey": "b853075158487ca39a5b5ea9"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)" + assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)" assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"} assert result2["result"].unique_id == "F8:24:41:C5:98:8B" @@ -658,7 +658,7 @@ async def test_async_step_user_with_found_devices_legacy_encryption_wrong_key( user_input={"bindkey": "b853075158487ca39a5b5ea9"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)" + assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)" assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"} assert result2["result"].unique_id == "F8:24:41:C5:98:8B" @@ -703,7 +703,7 @@ async def test_async_step_user_with_found_devices_legacy_encryption_wrong_key_le user_input={"bindkey": "b853075158487ca39a5b5ea9"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Dimmer Switch C5988B (YLKG07YL/YLKG08YL)" + assert result2["title"] == "Dimmer Switch 988B (YLKG07YL/YLKG08YL)" assert result2["data"] == {"bindkey": "b853075158487ca39a5b5ea9"} assert result2["result"].unique_id == "F8:24:41:C5:98:8B" @@ -822,7 +822,7 @@ async def test_async_step_user_takes_precedence_over_discovery(hass): user_input={"address": "00:81:F9:DD:6F:C1"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "Baby Thermometer DD6FC1 (MMC-T201-1)" + assert result2["title"] == "Baby Thermometer 6FC1 (MMC-T201-1)" assert result2["data"] == {} assert result2["result"].unique_id == "00:81:F9:DD:6F:C1" diff --git a/tests/components/xiaomi_ble/test_sensor.py b/tests/components/xiaomi_ble/test_sensor.py index c4052d36bf4..25c118bed49 100644 --- a/tests/components/xiaomi_ble/test_sensor.py +++ b/tests/components/xiaomi_ble/test_sensor.py @@ -42,12 +42,11 @@ async def test_sensors(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 2 - temp_sensor = hass.states.get("sensor.baby_thermometer_dd6fc1_temperature") + temp_sensor = hass.states.get("sensor.baby_thermometer_6fc1_temperature") temp_sensor_attribtes = temp_sensor.attributes assert temp_sensor.state == "36.8719980616822" assert ( - temp_sensor_attribtes[ATTR_FRIENDLY_NAME] - == "Baby Thermometer DD6FC1 Temperature" + temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Baby Thermometer 6FC1 Temperature" ) assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C" assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" @@ -92,10 +91,10 @@ async def test_xiaomi_formaldeyhde(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 - sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_formaldehyde") + sensor = hass.states.get("sensor.smart_flower_pot_3e7a_formaldehyde") sensor_attr = sensor.attributes assert sensor.state == "2.44" - assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Formaldehyde" + assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Formaldehyde" assert sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "mg/m³" assert sensor_attr[ATTR_STATE_CLASS] == "measurement" @@ -139,10 +138,10 @@ async def test_xiaomi_consumable(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 - sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_consumable") + sensor = hass.states.get("sensor.smart_flower_pot_3e7a_consumable") sensor_attr = sensor.attributes assert sensor.state == "96" - assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Consumable" + assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Consumable" assert sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%" assert sensor_attr[ATTR_STATE_CLASS] == "measurement" @@ -186,17 +185,17 @@ async def test_xiaomi_battery_voltage(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 2 - volt_sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_voltage") + volt_sensor = hass.states.get("sensor.smart_flower_pot_3e7a_voltage") volt_sensor_attr = volt_sensor.attributes assert volt_sensor.state == "3.1" - assert volt_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Voltage" + assert volt_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Voltage" assert volt_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "V" assert volt_sensor_attr[ATTR_STATE_CLASS] == "measurement" - bat_sensor = hass.states.get("sensor.smart_flower_pot_6a3e7a_battery") + bat_sensor = hass.states.get("sensor.smart_flower_pot_3e7a_battery") bat_sensor_attr = bat_sensor.attributes assert bat_sensor.state == "100" - assert bat_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 6A3E7A Battery" + assert bat_sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Flower Pot 3E7A Battery" assert bat_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%" assert bat_sensor_attr[ATTR_STATE_CLASS] == "measurement" @@ -254,42 +253,38 @@ async def test_xiaomi_HHCCJCY01(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 5 - illum_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_illuminance") + illum_sensor = hass.states.get("sensor.plant_sensor_3e7a_illuminance") illum_sensor_attr = illum_sensor.attributes assert illum_sensor.state == "0" - assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Illuminance" + assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Illuminance" assert illum_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx" assert illum_sensor_attr[ATTR_STATE_CLASS] == "measurement" - cond_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_conductivity") + cond_sensor = hass.states.get("sensor.plant_sensor_3e7a_conductivity") cond_sensor_attribtes = cond_sensor.attributes assert cond_sensor.state == "599" - assert ( - cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Conductivity" - ) + assert cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Conductivity" assert cond_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm" assert cond_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - moist_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_moisture") + moist_sensor = hass.states.get("sensor.plant_sensor_3e7a_moisture") moist_sensor_attribtes = moist_sensor.attributes assert moist_sensor.state == "64" - assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Moisture" + assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Moisture" assert moist_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%" assert moist_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - temp_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_temperature") + temp_sensor = hass.states.get("sensor.plant_sensor_3e7a_temperature") temp_sensor_attribtes = temp_sensor.attributes assert temp_sensor.state == "24.4" - assert ( - temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Temperature" - ) + assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Temperature" assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C" assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - batt_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_battery") + batt_sensor = hass.states.get("sensor.plant_sensor_3e7a_battery") batt_sensor_attribtes = batt_sensor.attributes assert batt_sensor.state == "5" - assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Battery" + assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Battery" assert batt_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%" assert batt_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" @@ -355,35 +350,31 @@ async def test_xiaomi_HHCCJCY01_not_connectable(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 4 - illum_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_illuminance") + illum_sensor = hass.states.get("sensor.plant_sensor_3e7a_illuminance") illum_sensor_attr = illum_sensor.attributes assert illum_sensor.state == "0" - assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Illuminance" + assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Illuminance" assert illum_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx" assert illum_sensor_attr[ATTR_STATE_CLASS] == "measurement" - cond_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_conductivity") + cond_sensor = hass.states.get("sensor.plant_sensor_3e7a_conductivity") cond_sensor_attribtes = cond_sensor.attributes assert cond_sensor.state == "599" - assert ( - cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Conductivity" - ) + assert cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Conductivity" assert cond_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm" assert cond_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - moist_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_moisture") + moist_sensor = hass.states.get("sensor.plant_sensor_3e7a_moisture") moist_sensor_attribtes = moist_sensor.attributes assert moist_sensor.state == "64" - assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Moisture" + assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Moisture" assert moist_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%" assert moist_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - temp_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_temperature") + temp_sensor = hass.states.get("sensor.plant_sensor_3e7a_temperature") temp_sensor_attribtes = temp_sensor.attributes assert temp_sensor.state == "24.4" - assert ( - temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Temperature" - ) + assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Temperature" assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C" assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" @@ -438,42 +429,38 @@ async def test_xiaomi_HHCCJCY01_only_some_sources_connectable(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 5 - illum_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_illuminance") + illum_sensor = hass.states.get("sensor.plant_sensor_3e7a_illuminance") illum_sensor_attr = illum_sensor.attributes assert illum_sensor.state == "0" - assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Illuminance" + assert illum_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Illuminance" assert illum_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx" assert illum_sensor_attr[ATTR_STATE_CLASS] == "measurement" - cond_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_conductivity") + cond_sensor = hass.states.get("sensor.plant_sensor_3e7a_conductivity") cond_sensor_attribtes = cond_sensor.attributes assert cond_sensor.state == "599" - assert ( - cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Conductivity" - ) + assert cond_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Conductivity" assert cond_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm" assert cond_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - moist_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_moisture") + moist_sensor = hass.states.get("sensor.plant_sensor_3e7a_moisture") moist_sensor_attribtes = moist_sensor.attributes assert moist_sensor.state == "64" - assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Moisture" + assert moist_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Moisture" assert moist_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%" assert moist_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - temp_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_temperature") + temp_sensor = hass.states.get("sensor.plant_sensor_3e7a_temperature") temp_sensor_attribtes = temp_sensor.attributes assert temp_sensor.state == "24.4" - assert ( - temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Temperature" - ) + assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Temperature" assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C" assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" - batt_sensor = hass.states.get("sensor.plant_sensor_6a3e7a_battery") + batt_sensor = hass.states.get("sensor.plant_sensor_3e7a_battery") batt_sensor_attribtes = batt_sensor.attributes assert batt_sensor.state == "5" - assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 6A3E7A Battery" + assert batt_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Plant Sensor 3E7A Battery" assert batt_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%" assert batt_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" @@ -515,14 +502,12 @@ async def test_xiaomi_CGDK2(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 - temp_sensor = hass.states.get( - "sensor.temperature_humidity_sensor_122089_temperature" - ) + temp_sensor = hass.states.get("sensor.temperature_humidity_sensor_2089_temperature") temp_sensor_attribtes = temp_sensor.attributes assert temp_sensor.state == "22.6" assert ( temp_sensor_attribtes[ATTR_FRIENDLY_NAME] - == "Temperature/Humidity Sensor 122089 Temperature" + == "Temperature/Humidity Sensor 2089 Temperature" ) assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "°C" assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" From 7cdac3ee8c6ccc320a4f37ee00f5d180f74f533d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 21:06:17 +0200 Subject: [PATCH 17/34] Bump xiaomi-ble to 0.10.0 (#78365) --- homeassistant/components/xiaomi_ble/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/xiaomi_ble/manifest.json b/homeassistant/components/xiaomi_ble/manifest.json index de8e61ad8ce..56efd9e966a 100644 --- a/homeassistant/components/xiaomi_ble/manifest.json +++ b/homeassistant/components/xiaomi_ble/manifest.json @@ -9,7 +9,7 @@ "service_data_uuid": "0000fe95-0000-1000-8000-00805f9b34fb" } ], - "requirements": ["xiaomi-ble==0.9.3"], + "requirements": ["xiaomi-ble==0.10.0"], "dependencies": ["bluetooth"], "codeowners": ["@Jc2k", "@Ernst79"], "iot_class": "local_push" diff --git a/requirements_all.txt b/requirements_all.txt index 6ba52832cba..855c924b0f9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2528,7 +2528,7 @@ xbox-webapi==2.0.11 xboxapi==2.0.1 # homeassistant.components.xiaomi_ble -xiaomi-ble==0.9.3 +xiaomi-ble==0.10.0 # homeassistant.components.knx xknx==1.0.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f5452a9140c..eafa9d219d0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1735,7 +1735,7 @@ wolf_smartset==0.1.11 xbox-webapi==2.0.11 # homeassistant.components.xiaomi_ble -xiaomi-ble==0.9.3 +xiaomi-ble==0.10.0 # homeassistant.components.knx xknx==1.0.2 From dd007cd765de3023d8553ec8a5a984990072035f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 22:15:30 +0200 Subject: [PATCH 18/34] Bump led-ble to 0.10.0 (#78367) --- homeassistant/components/led_ble/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/led_ble/manifest.json b/homeassistant/components/led_ble/manifest.json index 1f27837b89e..89b4fdb26af 100644 --- a/homeassistant/components/led_ble/manifest.json +++ b/homeassistant/components/led_ble/manifest.json @@ -3,7 +3,7 @@ "name": "LED BLE", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/ble_ble", - "requirements": ["led-ble==0.9.1"], + "requirements": ["led-ble==0.10.0"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], "bluetooth": [ diff --git a/requirements_all.txt b/requirements_all.txt index 855c924b0f9..5ebb0a5a56c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -974,7 +974,7 @@ lakeside==0.12 laundrify_aio==1.1.2 # homeassistant.components.led_ble -led-ble==0.9.1 +led-ble==0.10.0 # homeassistant.components.foscam libpyfoscam==1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index eafa9d219d0..3aaa5cb2fea 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -712,7 +712,7 @@ lacrosse-view==0.0.9 laundrify_aio==1.1.2 # homeassistant.components.led_ble -led-ble==0.9.1 +led-ble==0.10.0 # homeassistant.components.foscam libpyfoscam==1.0 From f0753f7a97af808664fa1a6b26c64a7db65b61ab Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 21:00:45 +0200 Subject: [PATCH 19/34] Bump aiohomekit to 1.5.7 (#78369) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index a4cbbc227d9..0b67f80bac5 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -3,7 +3,7 @@ "name": "HomeKit Controller", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/homekit_controller", - "requirements": ["aiohomekit==1.5.6"], + "requirements": ["aiohomekit==1.5.7"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."], "bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }], "dependencies": ["bluetooth", "zeroconf"], diff --git a/requirements_all.txt b/requirements_all.txt index 5ebb0a5a56c..b7ab218a461 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -171,7 +171,7 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.5.6 +aiohomekit==1.5.7 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3aaa5cb2fea..e52ccf0a359 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -155,7 +155,7 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.5.6 +aiohomekit==1.5.7 # homeassistant.components.emulated_hue # homeassistant.components.http From 3beed135865bb6f43dac3d7e11fa2f41cd14fa7f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:55:06 +0200 Subject: [PATCH 20/34] Don't allow partial update of counter settings (#78371) --- homeassistant/components/counter/__init__.py | 23 ++++--------- tests/components/counter/test_init.py | 36 ++++++++++---------- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/homeassistant/components/counter/__init__.py b/homeassistant/components/counter/__init__.py index a16d891af54..83d307f69d3 100644 --- a/homeassistant/components/counter/__init__.py +++ b/homeassistant/components/counter/__init__.py @@ -47,7 +47,7 @@ SERVICE_CONFIGURE = "configure" STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Optional(CONF_ICON): cv.icon, vol.Optional(CONF_INITIAL, default=DEFAULT_INITIAL): cv.positive_int, vol.Required(CONF_NAME): vol.All(cv.string, vol.Length(min=1)), @@ -57,16 +57,6 @@ CREATE_FIELDS = { vol.Optional(CONF_STEP, default=DEFAULT_STEP): cv.positive_int, } -UPDATE_FIELDS = { - vol.Optional(CONF_ICON): cv.icon, - vol.Optional(CONF_INITIAL): cv.positive_int, - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_MAXIMUM): vol.Any(None, vol.Coerce(int)), - vol.Optional(CONF_MINIMUM): vol.Any(None, vol.Coerce(int)), - vol.Optional(CONF_RESTORE): cv.boolean, - vol.Optional(CONF_STEP): cv.positive_int, -} - def _none_to_empty_dict(value): if value is None: @@ -128,7 +118,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) component.async_register_entity_service(SERVICE_INCREMENT, {}, "async_increment") @@ -152,12 +142,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class CounterStorageCollection(collection.StorageCollection): """Input storage based collection.""" - CREATE_SCHEMA = vol.Schema(CREATE_FIELDS) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS) async def _process_create_data(self, data: dict) -> dict: """Validate the config is valid.""" - return self.CREATE_SCHEMA(data) + return self.CREATE_UPDATE_SCHEMA(data) @callback def _get_suggested_id(self, info: dict) -> str: @@ -166,8 +155,8 @@ class CounterStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return {**data, **update_data} + update_data = self.CREATE_UPDATE_SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data class Counter(RestoreEntity): diff --git a/tests/components/counter/test_init.py b/tests/components/counter/test_init.py index 107dd97924d..90885be770d 100644 --- a/tests/components/counter/test_init.py +++ b/tests/components/counter/test_init.py @@ -591,17 +591,15 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup): async def test_update_min_max(hass, hass_ws_client, storage_setup): """Test updating min/max updates the state.""" - items = [ - { - "id": "from_storage", - "initial": 15, - "name": "from storage", - "maximum": 100, - "minimum": 10, - "step": 3, - "restore": True, - } - ] + settings = { + "initial": 15, + "name": "from storage", + "maximum": 100, + "minimum": 10, + "step": 3, + "restore": True, + } + items = [{"id": "from_storage"} | settings] assert await storage_setup(items) input_id = "from_storage" @@ -618,16 +616,18 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup): client = await hass_ws_client(hass) + updated_settings = settings | {"minimum": 19} await client.send_json( { "id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "minimum": 19, + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert int(state.state) == 19 @@ -635,18 +635,18 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup): assert state.attributes[ATTR_MAXIMUM] == 100 assert state.attributes[ATTR_STEP] == 3 + updated_settings = settings | {"maximum": 5, "minimum": 2, "step": 5} await client.send_json( { "id": 7, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "maximum": 5, - "minimum": 2, - "step": 5, + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert int(state.state) == 5 @@ -654,18 +654,18 @@ async def test_update_min_max(hass, hass_ws_client, storage_setup): assert state.attributes[ATTR_MAXIMUM] == 5 assert state.attributes[ATTR_STEP] == 5 + updated_settings = settings | {"maximum": None, "minimum": None, "step": 6} await client.send_json( { "id": 8, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "maximum": None, - "minimum": None, - "step": 6, + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert int(state.state) == 5 From ee07ca8caa9ef03a2d449da2068994ef7ff8d3e5 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:55:24 +0200 Subject: [PATCH 21/34] Don't allow partial update of input_boolean settings (#78372) --- .../components/input_boolean/__init__.py | 32 ++++--- tests/components/input_boolean/test_init.py | 89 ++++++++++++++++++- 2 files changed, 106 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/input_boolean/__init__.py b/homeassistant/components/input_boolean/__init__.py index 7dee3614ad5..a43b132a0e2 100644 --- a/homeassistant/components/input_boolean/__init__.py +++ b/homeassistant/components/input_boolean/__init__.py @@ -37,20 +37,25 @@ _LOGGER = logging.getLogger(__name__) CONF_INITIAL = "initial" -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), vol.Optional(CONF_INITIAL): cv.boolean, vol.Optional(CONF_ICON): cv.icon, } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_INITIAL): cv.boolean, - vol.Optional(CONF_ICON): cv.icon, -} - CONFIG_SCHEMA = vol.Schema( - {DOMAIN: cv.schema_with_slug_keys(vol.Any(UPDATE_FIELDS, None))}, + { + DOMAIN: cv.schema_with_slug_keys( + vol.Any( + { + vol.Optional(CONF_NAME): cv.string, + vol.Optional(CONF_INITIAL): cv.boolean, + vol.Optional(CONF_ICON): cv.icon, + }, + None, + ) + ) + }, extra=vol.ALLOW_EXTRA, ) @@ -62,12 +67,11 @@ STORAGE_VERSION = 1 class InputBooleanStorageCollection(collection.StorageCollection): """Input boolean collection stored in storage.""" - CREATE_SCHEMA = vol.Schema(CREATE_FIELDS) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS) async def _process_create_data(self, data: dict) -> dict: """Validate the config is valid.""" - return self.CREATE_SCHEMA(data) + return self.CREATE_UPDATE_SCHEMA(data) @callback def _get_suggested_id(self, info: dict) -> str: @@ -76,8 +80,8 @@ class InputBooleanStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return {**data, **update_data} + update_data = self.CREATE_UPDATE_SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data @bind_hass @@ -118,7 +122,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: diff --git a/tests/components/input_boolean/test_init.py b/tests/components/input_boolean/test_init.py index 2b7a1f88ef1..2e044c7a90f 100644 --- a/tests/components/input_boolean/test_init.py +++ b/tests/components/input_boolean/test_init.py @@ -40,7 +40,11 @@ def storage_setup(hass, hass_storage): "data": {"items": [{"id": "from_storage", "name": "from storage"}]}, } else: - hass_storage[DOMAIN] = items + hass_storage[DOMAIN] = { + "key": DOMAIN, + "version": 1, + "data": {"items": items}, + } if config is None: config = {DOMAIN: {}} return await async_setup_component(hass, DOMAIN, config) @@ -332,6 +336,89 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup): assert ent_reg.async_get_entity_id(DOMAIN, DOMAIN, input_id) is None +async def test_ws_update(hass, hass_ws_client, storage_setup): + """Test update WS.""" + + settings = { + "name": "from storage", + } + items = [{"id": "from_storage"} | settings] + assert await storage_setup(items) + + input_id = "from_storage" + input_entity_id = f"{DOMAIN}.{input_id}" + ent_reg = er.async_get(hass) + + state = hass.states.get(input_entity_id) + assert state is not None + assert state.state + assert ent_reg.async_get_entity_id(DOMAIN, DOMAIN, input_id) is not None + + client = await hass_ws_client(hass) + + updated_settings = settings | {"name": "new_name", "icon": "mdi:blah"} + await client.send_json( + { + "id": 6, + "type": f"{DOMAIN}/update", + f"{DOMAIN}_id": f"{input_id}", + **updated_settings, + } + ) + resp = await client.receive_json() + assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings + + state = hass.states.get(input_entity_id) + assert state.attributes["icon"] == "mdi:blah" + assert state.attributes["friendly_name"] == "new_name" + + updated_settings = settings | {"name": "new_name_2"} + await client.send_json( + { + "id": 7, + "type": f"{DOMAIN}/update", + f"{DOMAIN}_id": f"{input_id}", + **updated_settings, + } + ) + resp = await client.receive_json() + assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings + + state = hass.states.get(input_entity_id) + assert "icon" not in state.attributes + assert state.attributes["friendly_name"] == "new_name_2" + + +async def test_ws_create(hass, hass_ws_client, storage_setup): + """Test create WS.""" + assert await storage_setup(items=[]) + + input_id = "new_input" + input_entity_id = f"{DOMAIN}.{input_id}" + ent_reg = er.async_get(hass) + + state = hass.states.get(input_entity_id) + assert state is None + assert ent_reg.async_get_entity_id(DOMAIN, DOMAIN, input_id) is None + + client = await hass_ws_client(hass) + + await client.send_json( + { + "id": 6, + "type": f"{DOMAIN}/create", + "name": "New Input", + } + ) + resp = await client.receive_json() + assert resp["success"] + + state = hass.states.get(input_entity_id) + assert state.state + + async def test_setup_no_config(hass, hass_admin_user): """Test component setup with no config.""" count_start = len(hass.states.async_entity_ids()) From 9459af30b0e6392219fac410c9fa176f434a3ca3 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:56:40 +0200 Subject: [PATCH 22/34] Don't allow partial update of input_datetime settings (#78373) --- .../components/input_datetime/__init__.py | 20 ++++++------------- tests/components/input_datetime/test_init.py | 10 ++++++++-- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/input_datetime/__init__.py b/homeassistant/components/input_datetime/__init__.py index bda5572081c..daedfd251b0 100644 --- a/homeassistant/components/input_datetime/__init__.py +++ b/homeassistant/components/input_datetime/__init__.py @@ -61,20 +61,13 @@ def validate_set_datetime_attrs(config): STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), vol.Optional(CONF_HAS_DATE, default=False): cv.boolean, vol.Optional(CONF_HAS_TIME, default=False): cv.boolean, vol.Optional(CONF_ICON): cv.icon, vol.Optional(CONF_INITIAL): cv.string, } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_HAS_DATE): cv.boolean, - vol.Optional(CONF_HAS_TIME): cv.boolean, - vol.Optional(CONF_ICON): cv.icon, - vol.Optional(CONF_INITIAL): cv.string, -} def has_date_or_time(conf): @@ -167,7 +160,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: @@ -213,12 +206,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class DateTimeStorageCollection(collection.StorageCollection): """Input storage based collection.""" - CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, has_date_or_time)) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, has_date_or_time)) async def _process_create_data(self, data: dict) -> dict: """Validate the config is valid.""" - return self.CREATE_SCHEMA(data) + return self.CREATE_UPDATE_SCHEMA(data) @callback def _get_suggested_id(self, info: dict) -> str: @@ -227,8 +219,8 @@ class DateTimeStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return has_date_or_time({**data, **update_data}) + update_data = self.CREATE_UPDATE_SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data class InputDatetime(RestoreEntity): diff --git a/tests/components/input_datetime/test_init.py b/tests/components/input_datetime/test_init.py index 28ca2ab02bd..9e694488797 100644 --- a/tests/components/input_datetime/test_init.py +++ b/tests/components/input_datetime/test_init.py @@ -583,17 +583,23 @@ async def test_update(hass, hass_ws_client, storage_setup): client = await hass_ws_client(hass) + updated_settings = { + CONF_NAME: "even newer name", + CONF_HAS_DATE: False, + CONF_HAS_TIME: True, + CONF_INITIAL: INITIAL_DATETIME, + } await client.send_json( { "id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - ATTR_NAME: "even newer name", - CONF_HAS_DATE: False, + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert state.state == INITIAL_TIME From 336179df6df97c7b68f04b18be12883e67edfbcc Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:56:46 +0200 Subject: [PATCH 23/34] Don't allow partial update of input_button settings (#78374) --- .../components/input_button/__init__.py | 30 +++++++++++-------- tests/components/input_button/test_init.py | 1 + 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/input_button/__init__.py b/homeassistant/components/input_button/__init__.py index 3182e36d5fc..a47e96d635d 100644 --- a/homeassistant/components/input_button/__init__.py +++ b/homeassistant/components/input_button/__init__.py @@ -30,18 +30,23 @@ DOMAIN = "input_button" _LOGGER = logging.getLogger(__name__) -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), vol.Optional(CONF_ICON): cv.icon, } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_ICON): cv.icon, -} - CONFIG_SCHEMA = vol.Schema( - {DOMAIN: cv.schema_with_slug_keys(vol.Any(UPDATE_FIELDS, None))}, + { + DOMAIN: cv.schema_with_slug_keys( + vol.Any( + { + vol.Optional(CONF_NAME): cv.string, + vol.Optional(CONF_ICON): cv.icon, + }, + None, + ) + ) + }, extra=vol.ALLOW_EXTRA, ) @@ -53,12 +58,11 @@ STORAGE_VERSION = 1 class InputButtonStorageCollection(collection.StorageCollection): """Input button collection stored in storage.""" - CREATE_SCHEMA = vol.Schema(CREATE_FIELDS) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS) async def _process_create_data(self, data: dict) -> vol.Schema: """Validate the config is valid.""" - return self.CREATE_SCHEMA(data) + return self.CREATE_UPDATE_SCHEMA(data) @callback def _get_suggested_id(self, info: dict) -> str: @@ -67,8 +71,8 @@ class InputButtonStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return {**data, **update_data} + update_data = self.CREATE_UPDATE_SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: @@ -103,7 +107,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: diff --git a/tests/components/input_button/test_init.py b/tests/components/input_button/test_init.py index 33342455147..eb27f277884 100644 --- a/tests/components/input_button/test_init.py +++ b/tests/components/input_button/test_init.py @@ -305,6 +305,7 @@ async def test_ws_create_update(hass, hass_ws_client, storage_setup): ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "new", "name": "newer"} state = hass.states.get(f"{DOMAIN}.new") assert state is not None From 6f9a311cec77507696590e27ac4c53f0c8c95e55 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:56:59 +0200 Subject: [PATCH 24/34] Don't allow partial update of input_select settings (#78376) --- .../components/input_select/__init__.py | 21 +++------ tests/components/input_select/test_init.py | 45 +++++++++++-------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/input_select/__init__.py b/homeassistant/components/input_select/__init__.py index 83d6684a366..5d0e356b8ee 100644 --- a/homeassistant/components/input_select/__init__.py +++ b/homeassistant/components/input_select/__init__.py @@ -56,7 +56,7 @@ def _unique(options: Any) -> Any: raise HomeAssistantError("Duplicate options are not allowed") from exc -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), vol.Required(CONF_OPTIONS): vol.All( cv.ensure_list, vol.Length(min=1), _unique, [cv.string] @@ -64,14 +64,6 @@ CREATE_FIELDS = { vol.Optional(CONF_INITIAL): cv.string, vol.Optional(CONF_ICON): cv.icon, } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_OPTIONS): vol.All( - cv.ensure_list, vol.Length(min=1), _unique, [cv.string] - ), - vol.Optional(CONF_INITIAL): cv.string, - vol.Optional(CONF_ICON): cv.icon, -} def _remove_duplicates(options: list[str], name: str | None) -> list[str]: @@ -172,7 +164,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: @@ -238,12 +230,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class InputSelectStorageCollection(collection.StorageCollection): """Input storage based collection.""" - CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, _cv_input_select)) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_select)) async def _process_create_data(self, data: dict[str, Any]) -> dict[str, Any]: """Validate the config is valid.""" - return cast(dict[str, Any], self.CREATE_SCHEMA(data)) + return cast(dict[str, Any], self.CREATE_UPDATE_SCHEMA(data)) @callback def _get_suggested_id(self, info: dict[str, Any]) -> str: @@ -254,8 +245,8 @@ class InputSelectStorageCollection(collection.StorageCollection): self, data: dict[str, Any], update_data: dict[str, Any] ) -> dict[str, Any]: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return _cv_input_select({**data, **update_data}) + update_data = self.CREATE_UPDATE_SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data class InputSelect(SelectEntity, RestoreEntity): diff --git a/tests/components/input_select/test_init.py b/tests/components/input_select/test_init.py index d65140dcbf9..1a1618d7805 100644 --- a/tests/components/input_select/test_init.py +++ b/tests/components/input_select/test_init.py @@ -628,13 +628,11 @@ async def test_ws_delete(hass, hass_ws_client, storage_setup): async def test_update(hass, hass_ws_client, storage_setup): """Test updating options updates the state.""" - items = [ - { - "id": "from_storage", - "name": "from storage", - "options": ["yaml update 1", "yaml update 2"], - } - ] + settings = { + "name": "from storage", + "options": ["yaml update 1", "yaml update 2"], + } + items = [{"id": "from_storage"} | settings] assert await storage_setup(items) input_id = "from_storage" @@ -647,28 +645,36 @@ async def test_update(hass, hass_ws_client, storage_setup): client = await hass_ws_client(hass) + updated_settings = settings | { + "options": ["new option", "newer option"], + CONF_INITIAL: "newer option", + } await client.send_json( { "id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "options": ["new option", "newer option"], - CONF_INITIAL: "newer option", + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert state.attributes[ATTR_OPTIONS] == ["new option", "newer option"] # Should fail because the initial state is now invalid + updated_settings = settings | { + "options": ["new option", "no newer option"], + CONF_INITIAL: "newer option", + } await client.send_json( { "id": 7, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "options": ["new option", "no newer option"], + **updated_settings, } ) resp = await client.receive_json() @@ -678,13 +684,11 @@ async def test_update(hass, hass_ws_client, storage_setup): async def test_update_duplicates(hass, hass_ws_client, storage_setup, caplog): """Test updating options updates the state.""" - items = [ - { - "id": "from_storage", - "name": "from storage", - "options": ["yaml update 1", "yaml update 2"], - } - ] + settings = { + "name": "from storage", + "options": ["yaml update 1", "yaml update 2"], + } + items = [{"id": "from_storage"} | settings] assert await storage_setup(items) input_id = "from_storage" @@ -697,13 +701,16 @@ async def test_update_duplicates(hass, hass_ws_client, storage_setup, caplog): client = await hass_ws_client(hass) + updated_settings = settings | { + "options": ["new option", "newer option", "newer option"], + CONF_INITIAL: "newer option", + } await client.send_json( { "id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - "options": ["new option", "newer option", "newer option"], - CONF_INITIAL: "newer option", + **updated_settings, } ) resp = await client.receive_json() From 04d6bb085b1d8bf6ae5591077c886edc38907920 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:57:14 +0200 Subject: [PATCH 25/34] Don't allow partial update of input_text settings (#78377) --- .../components/input_text/__init__.py | 23 +++++-------------- tests/components/input_text/test_init.py | 13 +++++++---- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/input_text/__init__.py b/homeassistant/components/input_text/__init__.py index 38d74f57931..211d9843996 100644 --- a/homeassistant/components/input_text/__init__.py +++ b/homeassistant/components/input_text/__init__.py @@ -51,7 +51,7 @@ SERVICE_SET_VALUE = "set_value" STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)), vol.Optional(CONF_MIN, default=CONF_MIN_VALUE): vol.Coerce(int), vol.Optional(CONF_MAX, default=CONF_MAX_VALUE): vol.Coerce(int), @@ -61,16 +61,6 @@ CREATE_FIELDS = { vol.Optional(CONF_PATTERN): cv.string, vol.Optional(CONF_MODE, default=MODE_TEXT): vol.In([MODE_TEXT, MODE_PASSWORD]), } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_MIN): vol.Coerce(int), - vol.Optional(CONF_MAX): vol.Coerce(int), - vol.Optional(CONF_INITIAL): cv.string, - vol.Optional(CONF_ICON): cv.icon, - vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, - vol.Optional(CONF_PATTERN): cv.string, - vol.Optional(CONF_MODE): vol.In([MODE_TEXT, MODE_PASSWORD]), -} def _cv_input_text(cfg): @@ -147,7 +137,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: @@ -177,12 +167,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class InputTextStorageCollection(collection.StorageCollection): """Input storage based collection.""" - CREATE_SCHEMA = vol.Schema(vol.All(CREATE_FIELDS, _cv_input_text)) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_text)) async def _process_create_data(self, data: dict) -> dict: """Validate the config is valid.""" - return self.CREATE_SCHEMA(data) + return self.CREATE_UPDATE_SCHEMA(data) @callback def _get_suggested_id(self, info: dict) -> str: @@ -191,8 +180,8 @@ class InputTextStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - update_data = self.UPDATE_SCHEMA(update_data) - return _cv_input_text({**data, **update_data}) + update_data = self.CREATE_UPDATE_SCHEMA(update_data) + return {CONF_ID: data[CONF_ID]} | update_data class InputText(RestoreEntity): diff --git a/tests/components/input_text/test_init.py b/tests/components/input_text/test_init.py index 48f9551a65b..8256d9d351f 100644 --- a/tests/components/input_text/test_init.py +++ b/tests/components/input_text/test_init.py @@ -432,19 +432,24 @@ async def test_update(hass, hass_ws_client, storage_setup): client = await hass_ws_client(hass) + updated_settings = { + ATTR_NAME: "even newer name", + CONF_INITIAL: "newer option", + ATTR_MAX: TEST_VAL_MAX, + ATTR_MIN: 6, + ATTR_MODE: "password", + } await client.send_json( { "id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{input_id}", - ATTR_NAME: "even newer name", - CONF_INITIAL: "newer option", - ATTR_MIN: 6, - ATTR_MODE: "password", + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == {"id": "from_storage"} | updated_settings state = hass.states.get(input_entity_id) assert state.state == "loaded from storage" From 859947288040aae5a64de2b596be3fda5d4bc737 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 13 Sep 2022 20:58:12 +0200 Subject: [PATCH 26/34] Don't allow partial update of timer settings (#78378) --- homeassistant/components/timer/__init__.py | 17 +++++------------ tests/components/timer/test_init.py | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/timer/__init__.py b/homeassistant/components/timer/__init__.py index e5564736c74..fea814261fe 100644 --- a/homeassistant/components/timer/__init__.py +++ b/homeassistant/components/timer/__init__.py @@ -61,18 +61,12 @@ SERVICE_FINISH = "finish" STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 -CREATE_FIELDS = { +STORAGE_FIELDS = { vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_ICON): cv.icon, vol.Optional(CONF_DURATION, default=DEFAULT_DURATION): cv.time_period, vol.Optional(CONF_RESTORE, default=DEFAULT_RESTORE): cv.boolean, } -UPDATE_FIELDS = { - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_ICON): cv.icon, - vol.Optional(CONF_DURATION): cv.time_period, - vol.Optional(CONF_RESTORE): cv.boolean, -} def _format_timedelta(delta: timedelta): @@ -137,7 +131,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await storage_collection.async_load() collection.StorageCollectionWebsocket( - storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS + storage_collection, DOMAIN, DOMAIN, STORAGE_FIELDS, STORAGE_FIELDS ).async_setup(hass) async def reload_service_handler(service_call: ServiceCall) -> None: @@ -171,12 +165,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class TimerStorageCollection(collection.StorageCollection): """Timer storage based collection.""" - CREATE_SCHEMA = vol.Schema(CREATE_FIELDS) - UPDATE_SCHEMA = vol.Schema(UPDATE_FIELDS) + CREATE_UPDATE_SCHEMA = vol.Schema(STORAGE_FIELDS) async def _process_create_data(self, data: dict) -> dict: """Validate the config is valid.""" - data = self.CREATE_SCHEMA(data) + data = self.CREATE_UPDATE_SCHEMA(data) # make duration JSON serializeable data[CONF_DURATION] = _format_timedelta(data[CONF_DURATION]) return data @@ -188,7 +181,7 @@ class TimerStorageCollection(collection.StorageCollection): async def _update_data(self, data: dict, update_data: dict) -> dict: """Return a new updated data object.""" - data = {**data, **self.UPDATE_SCHEMA(update_data)} + data = {CONF_ID: data[CONF_ID]} | self.CREATE_UPDATE_SCHEMA(update_data) # make duration JSON serializeable if CONF_DURATION in update_data: data[CONF_DURATION] = _format_timedelta(data[CONF_DURATION]) diff --git a/tests/components/timer/test_init.py b/tests/components/timer/test_init.py index 8f605d2de9f..2e9ef785b32 100644 --- a/tests/components/timer/test_init.py +++ b/tests/components/timer/test_init.py @@ -585,17 +585,27 @@ async def test_update(hass, hass_ws_client, storage_setup): client = await hass_ws_client(hass) + updated_settings = { + CONF_NAME: "timer from storage", + CONF_DURATION: 33, + CONF_RESTORE: True, + } await client.send_json( { "id": 6, "type": f"{DOMAIN}/update", f"{DOMAIN}_id": f"{timer_id}", - CONF_DURATION: 33, - CONF_RESTORE: True, + **updated_settings, } ) resp = await client.receive_json() assert resp["success"] + assert resp["result"] == { + "id": "from_storage", + CONF_DURATION: "0:00:33", + CONF_NAME: "timer from storage", + CONF_RESTORE: True, + } state = hass.states.get(timer_entity_id) assert state.attributes[ATTR_DURATION] == _format_timedelta(cv.time_period(33)) From d98ed5c6f6dbc71eda371a3f7b9b40865c9611d1 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 13 Sep 2022 20:51:04 +0200 Subject: [PATCH 27/34] Unregister EcoWitt webhook at unload (#78388) --- homeassistant/components/ecowitt/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/ecowitt/__init__.py b/homeassistant/components/ecowitt/__init__.py index ebd861c1377..567e21b4d87 100644 --- a/homeassistant/components/ecowitt/__init__.py +++ b/homeassistant/components/ecowitt/__init__.py @@ -44,6 +44,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" + webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID]) + if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): hass.data[DOMAIN].pop(entry.entry_id) From 843d5f101adb3855375985c8c4731e7c034cddcd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 22:10:50 +0200 Subject: [PATCH 28/34] Fix flapping system log test (#78391) Since we run tests with asyncio debug on, there is a chance we will get an asyncio log message instead of the one we want Fixes https://github.com/home-assistant/core/actions/runs/3045080236/jobs/4906717578 --- tests/components/system_log/test_init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/components/system_log/test_init.py b/tests/components/system_log/test_init.py index 6304e0ea7cf..96e5480acb5 100644 --- a/tests/components/system_log/test_init.py +++ b/tests/components/system_log/test_init.py @@ -41,7 +41,7 @@ def find_log(logs, level): if not isinstance(level, tuple): level = (level,) log = next( - (log for log in logs if log["level"] in level), + (log for log in logs if log["level"] in level and log["name"] != "asyncio"), None, ) assert log is not None From f07e1bc5005517870cbf64cf28d252bead87ea3d Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 13 Sep 2022 21:01:46 +0200 Subject: [PATCH 29/34] Fix CI workflow caching (#78398) --- .github/workflows/ci.yaml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 75a200402d6..80c6cbac34b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -169,7 +169,6 @@ jobs: uses: actions/setup-python@v4.1.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - cache: "pip" - name: Restore base Python virtual environment id: cache-venv uses: actions/cache@v3.0.8 @@ -484,7 +483,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ matrix.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Restore pip wheel cache if: steps.cache-venv.outputs.cache-hit != 'true' @@ -492,10 +491,10 @@ jobs: with: path: ${{ env.PIP_CACHE }} key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ matrix.python-version }}-${{ steps.generate-pip-key.outputs.key }} restore-keys: | - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-pip-${{ env.PIP_CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}- + ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ env.PIP_CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}- - name: Install additional OS dependencies if: steps.cache-venv.outputs.cache-hit != 'true' run: | @@ -542,7 +541,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -574,7 +573,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -607,7 +606,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -651,7 +650,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ env.DEFAULT_PYTHON }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -699,7 +698,7 @@ jobs: with: path: venv key: >- - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + ${{ runner.os }}-${{ matrix.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' @@ -752,7 +751,7 @@ jobs: uses: actions/cache@v3.0.8 with: path: venv - key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + key: ${{ runner.os }}-${{ matrix.python-version }}-${{ needs.info.outputs.python_cache_key }} - name: Fail job if Python cache restore failed if: steps.cache-venv.outputs.cache-hit != 'true' From 0b5953038e90327b40aec6a261e316f3bd3c06c1 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 13 Sep 2022 22:15:45 +0200 Subject: [PATCH 30/34] Update frontend to 20220907.1 (#78404) --- homeassistant/components/frontend/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/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index 07822979683..42d7dd4b0fa 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -2,7 +2,7 @@ "domain": "frontend", "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/integrations/frontend", - "requirements": ["home-assistant-frontend==20220907.0"], + "requirements": ["home-assistant-frontend==20220907.1"], "dependencies": [ "api", "auth", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index b511248a602..ef5ff53c4a4 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -21,7 +21,7 @@ dbus-fast==1.4.0 fnvhash==0.1.0 hass-nabucasa==0.55.0 home-assistant-bluetooth==1.3.0 -home-assistant-frontend==20220907.0 +home-assistant-frontend==20220907.1 httpx==0.23.0 ifaddr==0.1.7 jinja2==3.1.2 diff --git a/requirements_all.txt b/requirements_all.txt index b7ab218a461..ecbfdf8c255 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -857,7 +857,7 @@ hole==0.7.0 holidays==0.14.2 # homeassistant.components.frontend -home-assistant-frontend==20220907.0 +home-assistant-frontend==20220907.1 # homeassistant.components.home_connect homeconnect==0.7.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e52ccf0a359..097881c4b39 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -634,7 +634,7 @@ hole==0.7.0 holidays==0.14.2 # homeassistant.components.frontend -home-assistant-frontend==20220907.0 +home-assistant-frontend==20220907.1 # homeassistant.components.home_connect homeconnect==0.7.2 From 29caf06439855e78af25b73471bc1319ce6af81b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Sep 2022 22:17:09 +0200 Subject: [PATCH 31/34] Bump govee-ble to 0.17.3 (#78405) --- homeassistant/components/govee_ble/manifest.json | 7 ++++++- homeassistant/generated/bluetooth.py | 6 ++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/govee_ble/manifest.json b/homeassistant/components/govee_ble/manifest.json index 2ce68498968..537ae9c7ed5 100644 --- a/homeassistant/components/govee_ble/manifest.json +++ b/homeassistant/components/govee_ble/manifest.json @@ -17,6 +17,11 @@ "service_uuid": "00008351-0000-1000-8000-00805f9b34fb", "connectable": false }, + { + "manufacturer_id": 57391, + "service_uuid": "00008351-0000-1000-8000-00805f9b34fb", + "connectable": false + }, { "manufacturer_id": 18994, "service_uuid": "00008551-0000-1000-8000-00805f9b34fb", @@ -53,7 +58,7 @@ "connectable": false } ], - "requirements": ["govee-ble==0.17.2"], + "requirements": ["govee-ble==0.17.3"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], "iot_class": "local_push" diff --git a/homeassistant/generated/bluetooth.py b/homeassistant/generated/bluetooth.py index 59f10767e0d..22bb93d1bda 100644 --- a/homeassistant/generated/bluetooth.py +++ b/homeassistant/generated/bluetooth.py @@ -62,6 +62,12 @@ BLUETOOTH: list[dict[str, bool | str | int | list[int]]] = [ "service_uuid": "00008351-0000-1000-8000-00805f9b34fb", "connectable": False }, + { + "domain": "govee_ble", + "manufacturer_id": 57391, + "service_uuid": "00008351-0000-1000-8000-00805f9b34fb", + "connectable": False + }, { "domain": "govee_ble", "manufacturer_id": 18994, diff --git a/requirements_all.txt b/requirements_all.txt index ecbfdf8c255..fc3fd2a0f1f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -778,7 +778,7 @@ googlemaps==2.5.1 goslide-api==0.5.1 # homeassistant.components.govee_ble -govee-ble==0.17.2 +govee-ble==0.17.3 # homeassistant.components.remote_rpi_gpio gpiozero==1.6.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 097881c4b39..ece00d7d630 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -579,7 +579,7 @@ google-nest-sdm==2.0.0 googlemaps==2.5.1 # homeassistant.components.govee_ble -govee-ble==0.17.2 +govee-ble==0.17.3 # homeassistant.components.gree greeclimate==1.3.0 From 1955ff9e0de7b63b6100cc3d8c27c121bcf20756 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 13 Sep 2022 16:31:51 -0400 Subject: [PATCH 32/34] Bumped version to 2022.9.3 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index f1b41fd57e0..8b899cf0f40 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 = 9 -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, 9, 0) diff --git a/pyproject.toml b/pyproject.toml index d411a1c62bb..d926dd5bbc1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.9.2" +version = "2022.9.3" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From 6a197332c711d2f904ed6e0c6ce5bb945e7dbb1b Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Tue, 13 Sep 2022 16:16:21 -0600 Subject: [PATCH 33/34] Fix bug with RainMachine update entity (#78411) * Fix bug with RainMachine update entity * Comment --- homeassistant/components/rainmachine/update.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/rainmachine/update.py b/homeassistant/components/rainmachine/update.py index b191f2695a0..a811894a0c2 100644 --- a/homeassistant/components/rainmachine/update.py +++ b/homeassistant/components/rainmachine/update.py @@ -99,4 +99,11 @@ class RainMachineUpdateEntity(RainMachineEntity, UpdateEntity): UpdateStates.UPGRADING, UpdateStates.REBOOT, ) - self._attr_latest_version = data["packageDetails"]["newVersion"] + + # The RainMachine API docs say that multiple "packages" can be updated, but + # don't give details on what types exist (which makes it impossible to have + # update entities per update type); so, we use the first one (with the idea that + # after it succeeds, the entity will show the next update): + package_details = data["packageDetails"][0] + self._attr_latest_version = package_details["newVersion"] + self._attr_title = package_details["packageName"] From 7b83807baaa0334ee423457ba00a8cbd1dc6d0b6 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Wed, 14 Sep 2022 02:00:59 +0100 Subject: [PATCH 34/34] Retry on unavailable IPMA api (#78332) Co-authored-by: J. Nick Koston --- homeassistant/components/ipma/__init__.py | 50 +++++++++++++++++++-- homeassistant/components/ipma/const.py | 3 ++ homeassistant/components/ipma/manifest.json | 2 +- homeassistant/components/ipma/weather.py | 33 ++------------ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/ipma/test_config_flow.py | 2 +- tests/components/ipma/test_weather.py | 13 +++--- 8 files changed, 65 insertions(+), 42 deletions(-) diff --git a/homeassistant/components/ipma/__init__.py b/homeassistant/components/ipma/__init__.py index 4d675e8cc1d..315362247a2 100644 --- a/homeassistant/components/ipma/__init__.py +++ b/homeassistant/components/ipma/__init__.py @@ -1,19 +1,61 @@ """Component for the Portuguese weather service - IPMA.""" +import logging + +import async_timeout +from pyipma import IPMAException +from pyipma.api import IPMA_API +from pyipma.location import Location + from homeassistant.config_entries import ConfigEntry -from homeassistant.const import Platform +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, Platform from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryNotReady +from homeassistant.helpers.aiohttp_client import async_get_clientsession from .config_flow import IpmaFlowHandler # noqa: F401 -from .const import DOMAIN # noqa: F401 +from .const import DATA_API, DATA_LOCATION, DOMAIN DEFAULT_NAME = "ipma" PLATFORMS = [Platform.WEATHER] +_LOGGER = logging.getLogger(__name__) -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + +async def async_get_api(hass): + """Get the pyipma api object.""" + websession = async_get_clientsession(hass) + return IPMA_API(websession) + + +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up IPMA station as config entry.""" - await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + + latitude = config_entry.data[CONF_LATITUDE] + longitude = config_entry.data[CONF_LONGITUDE] + + api = await async_get_api(hass) + try: + async with async_timeout.timeout(30): + location = await Location.get(api, float(latitude), float(longitude)) + + _LOGGER.debug( + "Initializing for coordinates %s, %s -> station %s (%d, %d)", + latitude, + longitude, + location.station, + location.id_station, + location.global_id_local, + ) + except IPMAException as err: + raise ConfigEntryNotReady( + f"Could not get location for ({latitude},{longitude})" + ) from err + + hass.data.setdefault(DOMAIN, {}) + hass.data[DOMAIN][config_entry.entry_id] = {DATA_API: api, DATA_LOCATION: location} + + await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) return True diff --git a/homeassistant/components/ipma/const.py b/homeassistant/components/ipma/const.py index 47434d7f76b..60c8115a5c4 100644 --- a/homeassistant/components/ipma/const.py +++ b/homeassistant/components/ipma/const.py @@ -6,3 +6,6 @@ DOMAIN = "ipma" HOME_LOCATION_NAME = "Home" ENTITY_ID_SENSOR_FORMAT_HOME = f"{WEATHER_DOMAIN}.ipma_{HOME_LOCATION_NAME}" + +DATA_LOCATION = "location" +DATA_API = "api" diff --git a/homeassistant/components/ipma/manifest.json b/homeassistant/components/ipma/manifest.json index a391b24e3b4..23558600373 100644 --- a/homeassistant/components/ipma/manifest.json +++ b/homeassistant/components/ipma/manifest.json @@ -3,7 +3,7 @@ "name": "Instituto Portugu\u00eas do Mar e Atmosfera (IPMA)", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/ipma", - "requirements": ["pyipma==3.0.2"], + "requirements": ["pyipma==3.0.4"], "codeowners": ["@dgomes", "@abmantis"], "iot_class": "cloud_polling", "loggers": ["geopy", "pyipma"] diff --git a/homeassistant/components/ipma/weather.py b/homeassistant/components/ipma/weather.py index d20e5cb2f21..a0fe5b235b3 100644 --- a/homeassistant/components/ipma/weather.py +++ b/homeassistant/components/ipma/weather.py @@ -48,11 +48,12 @@ from homeassistant.const import ( ) from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import config_validation as cv, entity_registry -from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.sun import is_up from homeassistant.util import Throttle +from .const import DATA_API, DATA_LOCATION, DOMAIN + _LOGGER = logging.getLogger(__name__) ATTRIBUTION = "Instituto Português do Mar e Atmosfera" @@ -95,13 +96,10 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Add a weather entity from a config_entry.""" - latitude = config_entry.data[CONF_LATITUDE] - longitude = config_entry.data[CONF_LONGITUDE] + api = hass.data[DOMAIN][config_entry.entry_id][DATA_API] + location = hass.data[DOMAIN][config_entry.entry_id][DATA_LOCATION] mode = config_entry.data[CONF_MODE] - api = await async_get_api(hass) - location = await async_get_location(hass, api, latitude, longitude) - # Migrate old unique_id @callback def _async_migrator(entity_entry: entity_registry.RegistryEntry): @@ -127,29 +125,6 @@ async def async_setup_entry( async_add_entities([IPMAWeather(location, api, config_entry.data)], True) -async def async_get_api(hass): - """Get the pyipma api object.""" - websession = async_get_clientsession(hass) - return IPMA_API(websession) - - -async def async_get_location(hass, api, latitude, longitude): - """Retrieve pyipma location, location name to be used as the entity name.""" - async with async_timeout.timeout(30): - location = await Location.get(api, float(latitude), float(longitude)) - - _LOGGER.debug( - "Initializing for coordinates %s, %s -> station %s (%d, %d)", - latitude, - longitude, - location.station, - location.id_station, - location.global_id_local, - ) - - return location - - class IPMAWeather(WeatherEntity): """Representation of a weather condition.""" diff --git a/requirements_all.txt b/requirements_all.txt index fc3fd2a0f1f..8a87ad1cc6a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1614,7 +1614,7 @@ pyinsteon==1.2.0 pyintesishome==1.8.0 # homeassistant.components.ipma -pyipma==3.0.2 +pyipma==3.0.4 # homeassistant.components.ipp pyipp==0.11.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ece00d7d630..e83a56b8a28 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1127,7 +1127,7 @@ pyicloud==1.0.0 pyinsteon==1.2.0 # homeassistant.components.ipma -pyipma==3.0.2 +pyipma==3.0.4 # homeassistant.components.ipp pyipp==0.11.0 diff --git a/tests/components/ipma/test_config_flow.py b/tests/components/ipma/test_config_flow.py index c8d53f95a4a..0c17cbe7f4b 100644 --- a/tests/components/ipma/test_config_flow.py +++ b/tests/components/ipma/test_config_flow.py @@ -168,7 +168,7 @@ async def test_config_entry_migration(hass): ) with patch( - "homeassistant.components.ipma.weather.async_get_location", + "pyipma.location.Location.get", return_value=MockLocation(), ): assert await async_setup_component(hass, DOMAIN, {}) diff --git a/tests/components/ipma/test_weather.py b/tests/components/ipma/test_weather.py index 942b9654895..e129216730d 100644 --- a/tests/components/ipma/test_weather.py +++ b/tests/components/ipma/test_weather.py @@ -19,7 +19,6 @@ from homeassistant.components.weather import ( ATTR_WEATHER_TEMPERATURE, ATTR_WEATHER_WIND_BEARING, ATTR_WEATHER_WIND_SPEED, - DOMAIN as WEATHER_DOMAIN, ) from homeassistant.const import STATE_UNKNOWN @@ -181,7 +180,8 @@ async def test_setup_config_flow(hass): return_value=MockLocation(), ): entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG) - await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN) + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() state = hass.states.get("weather.hometown") @@ -203,7 +203,8 @@ async def test_daily_forecast(hass): return_value=MockLocation(), ): entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG) - await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN) + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() state = hass.states.get("weather.hometown") @@ -227,7 +228,8 @@ async def test_hourly_forecast(hass): return_value=MockLocation(), ): entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG_HOURLY) - await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN) + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() state = hass.states.get("weather.hometown") @@ -248,7 +250,8 @@ async def test_failed_get_observation_forecast(hass): return_value=MockBadLocation(), ): entry = MockConfigEntry(domain="ipma", data=TEST_CONFIG) - await hass.config_entries.async_forward_entry_setup(entry, WEATHER_DOMAIN) + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() state = hass.states.get("weather.hometown")