From b0bb91ec08918636a6bf693489890cc963992915 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 4 Nov 2023 17:08:06 +0000 Subject: [PATCH 01/33] Don't assume that the `sleep` value is a dictionary in Tractive integration (#103138) * Sleep value can be null * Catch TypeError --- homeassistant/components/tractive/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/tractive/__init__.py b/homeassistant/components/tractive/__init__.py index f2853e0032c..300d7ebafc7 100644 --- a/homeassistant/components/tractive/__init__.py +++ b/homeassistant/components/tractive/__init__.py @@ -240,7 +240,7 @@ class TractiveClient: self._config_entry.data[CONF_EMAIL], ) return - except KeyError as error: + except (KeyError, TypeError) as error: _LOGGER.error("Error while listening for events: %s", error) continue except aiotractive.exceptions.TractiveError: @@ -284,11 +284,16 @@ class TractiveClient: ) def _send_wellness_update(self, event: dict[str, Any]) -> None: + sleep_day = None + sleep_night = None + if isinstance(event["sleep"], dict): + sleep_day = event["sleep"]["minutes_day_sleep"] + sleep_night = event["sleep"]["minutes_night_sleep"] payload = { ATTR_ACTIVITY_LABEL: event["wellness"].get("activity_label"), ATTR_CALORIES: event["activity"]["calories"], - ATTR_MINUTES_DAY_SLEEP: event["sleep"]["minutes_day_sleep"], - ATTR_MINUTES_NIGHT_SLEEP: event["sleep"]["minutes_night_sleep"], + ATTR_MINUTES_DAY_SLEEP: sleep_day, + ATTR_MINUTES_NIGHT_SLEEP: sleep_night, ATTR_MINUTES_REST: event["activity"]["minutes_rest"], ATTR_SLEEP_LABEL: event["wellness"].get("sleep_label"), } From aa623cc15c51a2004cc35a9b323d37335072bfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 2 Nov 2023 20:53:26 +0100 Subject: [PATCH 02/33] Update aioairzone-cloud to v0.3.2 (#103258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Álvaro Fernández Rojas --- homeassistant/components/airzone_cloud/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/airzone_cloud/manifest.json b/homeassistant/components/airzone_cloud/manifest.json index eb959342122..bbc8a84a3dc 100644 --- a/homeassistant/components/airzone_cloud/manifest.json +++ b/homeassistant/components/airzone_cloud/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/airzone_cloud", "iot_class": "cloud_polling", "loggers": ["aioairzone_cloud"], - "requirements": ["aioairzone-cloud==0.3.1"] + "requirements": ["aioairzone-cloud==0.3.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index c005a86cac3..0e9c7378b8d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -192,7 +192,7 @@ aio-georss-gdacs==0.8 aioairq==0.2.4 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.3.1 +aioairzone-cloud==0.3.2 # homeassistant.components.airzone aioairzone==0.6.9 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b41909be078..ce384b2e248 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -173,7 +173,7 @@ aio-georss-gdacs==0.8 aioairq==0.2.4 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.3.1 +aioairzone-cloud==0.3.2 # homeassistant.components.airzone aioairzone==0.6.9 From 2b36befe959e8843173a792ab8e252cf7db7f8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sun, 5 Nov 2023 14:09:29 +0100 Subject: [PATCH 03/33] Update aioairzone-cloud to v0.3.5 (#103315) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update aioairzone-cloud to v0.3.3 Signed-off-by: Álvaro Fernández Rojas * Update aioairzone-cloud to v0.3.4 Reverts accidental TaskGroup changes. Signed-off-by: Álvaro Fernández Rojas * Update aioairzone-cloud to v0.3.5 Signed-off-by: Álvaro Fernández Rojas * Trigger Github CI --------- Signed-off-by: Álvaro Fernández Rojas Co-authored-by: J. Nick Koston --- homeassistant/components/airzone_cloud/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/airzone_cloud/manifest.json b/homeassistant/components/airzone_cloud/manifest.json index bbc8a84a3dc..ea22487f4a2 100644 --- a/homeassistant/components/airzone_cloud/manifest.json +++ b/homeassistant/components/airzone_cloud/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/airzone_cloud", "iot_class": "cloud_polling", "loggers": ["aioairzone_cloud"], - "requirements": ["aioairzone-cloud==0.3.2"] + "requirements": ["aioairzone-cloud==0.3.5"] } diff --git a/requirements_all.txt b/requirements_all.txt index 0e9c7378b8d..1e388942667 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -192,7 +192,7 @@ aio-georss-gdacs==0.8 aioairq==0.2.4 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.3.2 +aioairzone-cloud==0.3.5 # homeassistant.components.airzone aioairzone==0.6.9 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ce384b2e248..62ac01261a0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -173,7 +173,7 @@ aio-georss-gdacs==0.8 aioairq==0.2.4 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.3.2 +aioairzone-cloud==0.3.5 # homeassistant.components.airzone aioairzone==0.6.9 From 412fa4c65a301af4772b95ff5c958fce0bd0280c Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Mon, 6 Nov 2023 06:48:00 -0700 Subject: [PATCH 04/33] Handle null data in WeatherFlow sensors (#103349) Co-authored-by: J. Nick Koston --- homeassistant/components/weatherflow/sensor.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/weatherflow/sensor.py b/homeassistant/components/weatherflow/sensor.py index bc5d38e99e5..f3e5b8744e6 100644 --- a/homeassistant/components/weatherflow/sensor.py +++ b/homeassistant/components/weatherflow/sensor.py @@ -71,7 +71,8 @@ class WeatherFlowSensorEntityDescription( def get_native_value(self, device: WeatherFlowDevice) -> datetime | StateType: """Return the parsed sensor value.""" - raw_sensor_data = getattr(device, self.key) + if (raw_sensor_data := getattr(device, self.key)) is None: + return None return self.raw_data_conv_fn(raw_sensor_data) @@ -371,14 +372,17 @@ class WeatherFlowSensorEntity(SensorEntity): return self.device.last_report return None - @property - def native_value(self) -> datetime | StateType: - """Return the state of the sensor.""" - return self.entity_description.get_native_value(self.device) + def _async_update_state(self) -> None: + """Update entity state.""" + value = self.entity_description.get_native_value(self.device) + self._attr_available = value is not None + self._attr_native_value = value + self.async_write_ha_state() async def async_added_to_hass(self) -> None: """Subscribe to events.""" + self._async_update_state() for event in self.entity_description.event_subscriptions: self.async_on_remove( - self.device.on(event, lambda _: self.async_write_ha_state()) + self.device.on(event, lambda _: self._async_update_state()) ) From 334a02bc2be14ab45acf3534d8141f78dd3e45cf Mon Sep 17 00:00:00 2001 From: Matt Zimmerman Date: Sun, 5 Nov 2023 19:11:50 -0800 Subject: [PATCH 05/33] Handle smarttub sensor values being None (#103385) * [smarttub] handle sensor values being None * empty commit to rerun CI * lint * use const in test * reorder checks * use None instead of STATE_UNKNOWN * empty commit to rerun CI * check for STATE_UNKNOWN in test * empty commit to rerun CI --- .../components/smarttub/manifest.json | 2 +- homeassistant/components/smarttub/sensor.py | 6 ++++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/smarttub/test_sensor.py | 22 +++++++++++++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/smarttub/manifest.json b/homeassistant/components/smarttub/manifest.json index 3b8b727015b..e8db096f31d 100644 --- a/homeassistant/components/smarttub/manifest.json +++ b/homeassistant/components/smarttub/manifest.json @@ -7,5 +7,5 @@ "iot_class": "cloud_polling", "loggers": ["smarttub"], "quality_scale": "platinum", - "requirements": ["python-smarttub==0.0.33"] + "requirements": ["python-smarttub==0.0.35"] } diff --git a/homeassistant/components/smarttub/sensor.py b/homeassistant/components/smarttub/sensor.py index a72555962eb..c362e1ea8f0 100644 --- a/homeassistant/components/smarttub/sensor.py +++ b/homeassistant/components/smarttub/sensor.py @@ -89,10 +89,14 @@ class SmartTubSensor(SmartTubSensorBase, SensorEntity): """Generic class for SmartTub status sensors.""" @property - def native_value(self) -> str: + def native_value(self) -> str | None: """Return the current state of the sensor.""" + if self._state is None: + return None + if isinstance(self._state, Enum): return self._state.name.lower() + return self._state.lower() diff --git a/requirements_all.txt b/requirements_all.txt index 1e388942667..7baa4592aec 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2184,7 +2184,7 @@ python-ripple-api==0.0.3 python-roborock==0.35.0 # homeassistant.components.smarttub -python-smarttub==0.0.33 +python-smarttub==0.0.35 # homeassistant.components.songpal python-songpal==0.15.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 62ac01261a0..bfcae4f5396 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1628,7 +1628,7 @@ python-qbittorrent==0.4.3 python-roborock==0.35.0 # homeassistant.components.smarttub -python-smarttub==0.0.33 +python-smarttub==0.0.35 # homeassistant.components.songpal python-songpal==0.15.2 diff --git a/tests/components/smarttub/test_sensor.py b/tests/components/smarttub/test_sensor.py index 5c5359df381..5e476dcaaa5 100644 --- a/tests/components/smarttub/test_sensor.py +++ b/tests/components/smarttub/test_sensor.py @@ -2,6 +2,7 @@ import pytest import smarttub +from homeassistant.const import STATE_UNKNOWN from homeassistant.core import HomeAssistant @@ -27,6 +28,27 @@ async def test_sensor( assert state.state == expected_state +# https://github.com/home-assistant/core/issues/102339 +async def test_null_blowoutcycle( + spa, + spa_state, + config_entry, + hass: HomeAssistant, +) -> None: + """Test blowoutCycle having null value.""" + + spa_state.blowout_cycle = None + + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + entity_id = f"sensor.{spa.brand}_{spa.model}_blowout_cycle" + state = hass.states.get(entity_id) + assert state is not None + assert state.state == STATE_UNKNOWN + + async def test_primary_filtration( spa, spa_state, setup_entry, hass: HomeAssistant ) -> None: From 050f1085d037b6dab1b92797c799a7003c7fa6df Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 4 Nov 2023 18:38:28 -0500 Subject: [PATCH 06/33] Pin jaraco.functools to fix builds and CI (#103406) --- homeassistant/components/abode/manifest.json | 2 +- requirements_all.txt | 3 +++ requirements_test_all.txt | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/abode/manifest.json b/homeassistant/components/abode/manifest.json index d27def55251..c7d51c7ea1f 100644 --- a/homeassistant/components/abode/manifest.json +++ b/homeassistant/components/abode/manifest.json @@ -9,5 +9,5 @@ }, "iot_class": "cloud_push", "loggers": ["jaraco.abode", "lomond"], - "requirements": ["jaraco.abode==3.3.0"] + "requirements": ["jaraco.abode==3.3.0", "jaraco.functools==3.9.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 7baa4592aec..7568d76b55e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1094,6 +1094,9 @@ janus==1.0.0 # homeassistant.components.abode jaraco.abode==3.3.0 +# homeassistant.components.abode +jaraco.functools==3.9.0 + # homeassistant.components.jellyfin jellyfin-apiclient-python==1.9.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index bfcae4f5396..06fd96dfe82 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -862,6 +862,9 @@ janus==1.0.0 # homeassistant.components.abode jaraco.abode==3.3.0 +# homeassistant.components.abode +jaraco.functools==3.9.0 + # homeassistant.components.jellyfin jellyfin-apiclient-python==1.9.2 From 7e2c12b0a9c69dee0fe3856b8ac21e06de604233 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Mon, 6 Nov 2023 11:12:33 +0100 Subject: [PATCH 07/33] Update tailscale to 0.6.0 (#103409) --- .../components/tailscale/diagnostics.py | 2 +- .../components/tailscale/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/tailscale/conftest.py | 4 +- .../tailscale/snapshots/test_diagnostics.ambr | 87 +++++++++++++++++ .../components/tailscale/test_diagnostics.py | 95 ++----------------- 7 files changed, 99 insertions(+), 95 deletions(-) create mode 100644 tests/components/tailscale/snapshots/test_diagnostics.ambr diff --git a/homeassistant/components/tailscale/diagnostics.py b/homeassistant/components/tailscale/diagnostics.py index 0fd69a12825..687cee7741f 100644 --- a/homeassistant/components/tailscale/diagnostics.py +++ b/homeassistant/components/tailscale/diagnostics.py @@ -32,5 +32,5 @@ async def async_get_config_entry_diagnostics( """Return diagnostics for a config entry.""" coordinator: TailscaleDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] # Round-trip via JSON to trigger serialization - devices = [json.loads(device.json()) for device in coordinator.data.values()] + devices = [json.loads(device.to_json()) for device in coordinator.data.values()] return async_redact_data({"devices": devices}, TO_REDACT) diff --git a/homeassistant/components/tailscale/manifest.json b/homeassistant/components/tailscale/manifest.json index 088389060f5..14f4206f44f 100644 --- a/homeassistant/components/tailscale/manifest.json +++ b/homeassistant/components/tailscale/manifest.json @@ -7,5 +7,5 @@ "integration_type": "hub", "iot_class": "cloud_polling", "quality_scale": "platinum", - "requirements": ["tailscale==0.2.0"] + "requirements": ["tailscale==0.6.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 7568d76b55e..b1927de3b45 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2536,7 +2536,7 @@ synology-srm==0.2.0 systembridgeconnector==3.8.4 # homeassistant.components.tailscale -tailscale==0.2.0 +tailscale==0.6.0 # homeassistant.components.tank_utility tank-utility==1.5.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 06fd96dfe82..a21b1a9cd70 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1890,7 +1890,7 @@ switchbot-api==1.2.1 systembridgeconnector==3.8.4 # homeassistant.components.tailscale -tailscale==0.2.0 +tailscale==0.6.0 # homeassistant.components.tellduslive tellduslive==0.10.11 diff --git a/tests/components/tailscale/conftest.py b/tests/components/tailscale/conftest.py index 12f11a5656d..ec3b6afa139 100644 --- a/tests/components/tailscale/conftest.py +++ b/tests/components/tailscale/conftest.py @@ -41,7 +41,7 @@ def mock_tailscale_config_flow() -> Generator[None, MagicMock, None]: "homeassistant.components.tailscale.config_flow.Tailscale", autospec=True ) as tailscale_mock: tailscale = tailscale_mock.return_value - tailscale.devices.return_value = Devices.parse_raw( + tailscale.devices.return_value = Devices.from_json( load_fixture("tailscale/devices.json") ).devices yield tailscale @@ -54,7 +54,7 @@ def mock_tailscale(request: pytest.FixtureRequest) -> Generator[None, MagicMock, if hasattr(request, "param") and request.param: fixture = request.param - devices = Devices.parse_raw(load_fixture(fixture)).devices + devices = Devices.from_json(load_fixture(fixture)).devices with patch( "homeassistant.components.tailscale.coordinator.Tailscale", autospec=True ) as tailscale_mock: diff --git a/tests/components/tailscale/snapshots/test_diagnostics.ambr b/tests/components/tailscale/snapshots/test_diagnostics.ambr new file mode 100644 index 00000000000..eba8d9bd145 --- /dev/null +++ b/tests/components/tailscale/snapshots/test_diagnostics.ambr @@ -0,0 +1,87 @@ +# serializer version: 1 +# name: test_diagnostics + dict({ + 'devices': list([ + dict({ + 'addresses': '**REDACTED**', + 'advertised_routes': list([ + ]), + 'authorized': True, + 'blocks_incoming_connections': False, + 'client_connectivity': dict({ + 'client_supports': dict({ + 'hair_pinning': False, + 'ipv6': False, + 'pcp': False, + 'pmp': False, + 'udp': True, + 'upnp': False, + }), + 'endpoints': '**REDACTED**', + 'mapping_varies_by_dest_ip': False, + }), + 'client_version': '1.12.3-td91ea7286-ge1bbbd90c', + 'created': '2021-08-19T09:25:22+00:00', + 'device_id': '**REDACTED**', + 'enabled_routes': list([ + ]), + 'expires': '2022-02-15T09:25:22+00:00', + 'hostname': '**REDACTED**', + 'is_external': False, + 'key_expiry_disabled': False, + 'last_seen': '2021-09-16T06:11:23+00:00', + 'machine_key': '**REDACTED**', + 'name': '**REDACTED**', + 'node_key': '**REDACTED**', + 'os': 'iOS', + 'tags': list([ + ]), + 'update_available': True, + 'user': '**REDACTED**', + }), + dict({ + 'addresses': '**REDACTED**', + 'advertised_routes': list([ + '0.0.0.0/0', + '10.10.10.0/23', + '::/0', + ]), + 'authorized': True, + 'blocks_incoming_connections': False, + 'client_connectivity': dict({ + 'client_supports': dict({ + 'hair_pinning': True, + 'ipv6': False, + 'pcp': False, + 'pmp': False, + 'udp': True, + 'upnp': False, + }), + 'endpoints': '**REDACTED**', + 'mapping_varies_by_dest_ip': False, + }), + 'client_version': '1.14.0-t5cff36945-g809e87bba', + 'created': '2021-08-29T09:49:06+00:00', + 'device_id': '**REDACTED**', + 'enabled_routes': list([ + '0.0.0.0/0', + '10.10.10.0/23', + '::/0', + ]), + 'expires': '2022-02-25T09:49:06+00:00', + 'hostname': '**REDACTED**', + 'is_external': False, + 'key_expiry_disabled': False, + 'last_seen': '2021-11-15T20:37:03+00:00', + 'machine_key': '**REDACTED**', + 'name': '**REDACTED**', + 'node_key': '**REDACTED**', + 'os': 'linux', + 'tags': list([ + ]), + 'update_available': True, + 'user': '**REDACTED**', + }), + ]), + }) +# --- diff --git a/tests/components/tailscale/test_diagnostics.py b/tests/components/tailscale/test_diagnostics.py index a6b892dbc86..4f900db7401 100644 --- a/tests/components/tailscale/test_diagnostics.py +++ b/tests/components/tailscale/test_diagnostics.py @@ -1,6 +1,6 @@ """Tests for the diagnostics data provided by the Tailscale integration.""" +from syrupy import SnapshotAssertion -from homeassistant.components.diagnostics import REDACTED from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry @@ -12,93 +12,10 @@ async def test_diagnostics( hass: HomeAssistant, hass_client: ClientSessionGenerator, init_integration: MockConfigEntry, + snapshot: SnapshotAssertion, ) -> None: """Test diagnostics.""" - assert await get_diagnostics_for_config_entry( - hass, hass_client, init_integration - ) == { - "devices": [ - { - "addresses": REDACTED, - "device_id": REDACTED, - "user": REDACTED, - "name": REDACTED, - "hostname": REDACTED, - "client_version": "1.12.3-td91ea7286-ge1bbbd90c", - "update_available": True, - "os": "iOS", - "created": "2021-08-19T09:25:22+00:00", - "last_seen": "2021-09-16T06:11:23+00:00", - "key_expiry_disabled": False, - "expires": "2022-02-15T09:25:22+00:00", - "authorized": True, - "is_external": False, - "machine_key": REDACTED, - "node_key": REDACTED, - "blocks_incoming_connections": False, - "enabled_routes": [], - "advertised_routes": [], - "client_connectivity": { - "endpoints": REDACTED, - "derp": "", - "mapping_varies_by_dest_ip": False, - "latency": {}, - "client_supports": { - "hair_pinning": False, - "ipv6": False, - "pcp": False, - "pmp": False, - "udp": True, - "upnp": False, - }, - }, - }, - { - "addresses": REDACTED, - "device_id": REDACTED, - "user": REDACTED, - "name": REDACTED, - "hostname": REDACTED, - "client_version": "1.14.0-t5cff36945-g809e87bba", - "update_available": True, - "os": "linux", - "created": "2021-08-29T09:49:06+00:00", - "last_seen": "2021-11-15T20:37:03+00:00", - "key_expiry_disabled": False, - "expires": "2022-02-25T09:49:06+00:00", - "authorized": True, - "is_external": False, - "machine_key": REDACTED, - "node_key": REDACTED, - "blocks_incoming_connections": False, - "enabled_routes": ["0.0.0.0/0", "10.10.10.0/23", "::/0"], - "advertised_routes": ["0.0.0.0/0", "10.10.10.0/23", "::/0"], - "client_connectivity": { - "endpoints": REDACTED, - "derp": "", - "mapping_varies_by_dest_ip": False, - "latency": { - "Bangalore": {"latencyMs": 143.42505599999998}, - "Chicago": {"latencyMs": 101.123646}, - "Dallas": {"latencyMs": 136.85886}, - "Frankfurt": {"latencyMs": 18.968314}, - "London": {"preferred": True, "latencyMs": 14.314574}, - "New York City": {"latencyMs": 83.078912}, - "San Francisco": {"latencyMs": 148.215522}, - "Seattle": {"latencyMs": 181.553595}, - "Singapore": {"latencyMs": 164.566539}, - "São Paulo": {"latencyMs": 207.250179}, - "Tokyo": {"latencyMs": 226.90714300000002}, - }, - "client_supports": { - "hair_pinning": True, - "ipv6": False, - "pcp": False, - "pmp": False, - "udp": True, - "upnp": False, - }, - }, - }, - ] - } + assert ( + await get_diagnostics_for_config_entry(hass, hass_client, init_integration) + == snapshot + ) From f45114371e3513c2b6e6c555beaf2e6d416a9f1b Mon Sep 17 00:00:00 2001 From: Tobias Sauerwein Date: Sun, 5 Nov 2023 21:13:45 +0100 Subject: [PATCH 08/33] Bump pyatmo to v7.6.0 (#103410) Signed-off-by: Tobias Sauerwein --- homeassistant/components/netatmo/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/netatmo/snapshots/test_diagnostics.ambr | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/netatmo/manifest.json b/homeassistant/components/netatmo/manifest.json index 7fe1f9b8c04..d031632ed75 100644 --- a/homeassistant/components/netatmo/manifest.json +++ b/homeassistant/components/netatmo/manifest.json @@ -12,5 +12,5 @@ "integration_type": "hub", "iot_class": "cloud_polling", "loggers": ["pyatmo"], - "requirements": ["pyatmo==7.5.0"] + "requirements": ["pyatmo==7.6.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index b1927de3b45..0e7821f82d9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1600,7 +1600,7 @@ pyairvisual==2023.08.1 pyatag==0.3.5.3 # homeassistant.components.netatmo -pyatmo==7.5.0 +pyatmo==7.6.0 # homeassistant.components.apple_tv pyatv==0.14.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a21b1a9cd70..d0bc7b85dcd 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1218,7 +1218,7 @@ pyairvisual==2023.08.1 pyatag==0.3.5.3 # homeassistant.components.netatmo -pyatmo==7.5.0 +pyatmo==7.6.0 # homeassistant.components.apple_tv pyatv==0.14.3 diff --git a/tests/components/netatmo/snapshots/test_diagnostics.ambr b/tests/components/netatmo/snapshots/test_diagnostics.ambr index 228fc7563e0..bd9005bd389 100644 --- a/tests/components/netatmo/snapshots/test_diagnostics.ambr +++ b/tests/components/netatmo/snapshots/test_diagnostics.ambr @@ -572,6 +572,7 @@ 'read_smokedetector', 'read_station', 'read_thermostat', + 'read_mhs1', 'write_bubendorff', 'write_camera', 'write_magellan', @@ -579,6 +580,7 @@ 'write_presence', 'write_smarther', 'write_thermostat', + 'write_mhs1', ]), 'type': 'Bearer', }), From e56e75114a419b2013aa71afaa7b4f9d5d262a45 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Sun, 5 Nov 2023 12:41:15 +0100 Subject: [PATCH 09/33] Fix serial in Flo device information (#103427) --- homeassistant/components/flo/device.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/flo/device.py b/homeassistant/components/flo/device.py index 99e86d4b6b5..bcc52f512a1 100644 --- a/homeassistant/components/flo/device.py +++ b/homeassistant/components/flo/device.py @@ -139,9 +139,9 @@ class FloDeviceDataUpdateCoordinator(DataUpdateCoordinator): return self._device_information["fwVersion"] @property - def serial_number(self) -> str: + def serial_number(self) -> str | None: """Return the serial number for the device.""" - return self._device_information["serialNumber"] + return self._device_information.get("serialNumber") @property def pending_info_alerts_count(self) -> int: From 9327c51115b0e7b95debe83587ea36e11fbb6515 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Mon, 6 Nov 2023 07:52:15 +0100 Subject: [PATCH 10/33] modbus Allow swap: byte for datatype: string. (#103441) --- homeassistant/components/modbus/validators.py | 6 +++--- tests/components/modbus/test_sensor.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index bef58b3fa56..5fa314d589c 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -63,8 +63,8 @@ PARM_IS_LEGAL = namedtuple( ], ) # PARM_IS_LEGAL defines if the keywords: -# count: .. -# structure: .. +# count: +# structure: # swap: byte # swap: word # swap: word_byte (identical to swap: word) @@ -84,7 +84,7 @@ DEFAULT_STRUCT_FORMAT = { DataType.INT64: ENTRY("q", 4, PARM_IS_LEGAL(False, False, True, True, True)), DataType.UINT64: ENTRY("Q", 4, PARM_IS_LEGAL(False, False, True, True, True)), DataType.FLOAT64: ENTRY("d", 4, PARM_IS_LEGAL(False, False, True, True, True)), - DataType.STRING: ENTRY("s", -1, PARM_IS_LEGAL(True, False, False, False, False)), + DataType.STRING: ENTRY("s", -1, PARM_IS_LEGAL(True, False, False, True, False)), DataType.CUSTOM: ENTRY("?", 0, PARM_IS_LEGAL(True, True, False, False, False)), } diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py index 0f79a125c86..72aebbd396f 100644 --- a/tests/components/modbus/test_sensor.py +++ b/tests/components/modbus/test_sensor.py @@ -513,6 +513,20 @@ async def test_config_wrong_struct_sensor( False, "07-05-2020 14:35", ), + ( + { + CONF_COUNT: 8, + CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_DATA_TYPE: DataType.STRING, + CONF_SWAP: CONF_SWAP_BYTE, + CONF_SCALE: 1, + CONF_OFFSET: 0, + CONF_PRECISION: 0, + }, + [0x3730, 0x302D, 0x2D35, 0x3032, 0x3032, 0x3120, 0x3A34, 0x3533], + False, + "07-05-2020 14:35", + ), ( { CONF_COUNT: 8, From 9a37868244d2ee030be0eac7cf83380b55fdde78 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Sun, 5 Nov 2023 20:20:13 +0100 Subject: [PATCH 11/33] Modbus set device_class in slaves (#103442) --- homeassistant/components/modbus/sensor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index d7a6b4cca0f..52aa37535d6 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -168,6 +168,7 @@ class SlaveSensor( self._attr_unique_id = f"{self._attr_unique_id}_{idx}" self._attr_native_unit_of_measurement = entry.get(CONF_UNIT_OF_MEASUREMENT) self._attr_state_class = entry.get(CONF_STATE_CLASS) + self._attr_device_class = entry.get(CONF_DEVICE_CLASS) self._attr_available = False super().__init__(coordinator) From 6fd8973a0059b12d36fe0f0565efb43f86530d2b Mon Sep 17 00:00:00 2001 From: Matthias Alphart Date: Mon, 6 Nov 2023 08:39:40 +0100 Subject: [PATCH 12/33] Fix KNX expose default value when attribute is `None` (#103446) Fix KNX expose default value when attribute is `null` --- homeassistant/components/knx/expose.py | 10 +++++----- tests/components/knx/test_expose.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/knx/expose.py b/homeassistant/components/knx/expose.py index e14ee501d7b..d5c871d59ba 100644 --- a/homeassistant/components/knx/expose.py +++ b/homeassistant/components/knx/expose.py @@ -122,12 +122,12 @@ class KNXExposeSensor: """Extract value from state.""" if state is None or state.state in (STATE_UNKNOWN, STATE_UNAVAILABLE): value = self.expose_default + elif self.expose_attribute is not None: + _attr = state.attributes.get(self.expose_attribute) + value = _attr if _attr is not None else self.expose_default else: - value = ( - state.state - if self.expose_attribute is None - else state.attributes.get(self.expose_attribute, self.expose_default) - ) + value = state.state + if self.expose_type == "binary": if value in (1, STATE_ON, "True"): return True diff --git a/tests/components/knx/test_expose.py b/tests/components/knx/test_expose.py index ca3fc5c7f58..4359c54164a 100644 --- a/tests/components/knx/test_expose.py +++ b/tests/components/knx/test_expose.py @@ -85,6 +85,14 @@ async def test_expose_attribute(hass: HomeAssistant, knx: KNXTestKit) -> None: hass.states.async_set(entity_id, "off", {}) await knx.assert_telegram_count(0) + # Change attribute; keep state + hass.states.async_set(entity_id, "on", {attribute: 1}) + await knx.assert_write("1/1/8", (1,)) + + # Change state to "off"; null attribute + hass.states.async_set(entity_id, "off", {attribute: None}) + await knx.assert_telegram_count(0) + async def test_expose_attribute_with_default( hass: HomeAssistant, knx: KNXTestKit @@ -132,6 +140,14 @@ async def test_expose_attribute_with_default( hass.states.async_set(entity_id, "off", {}) await knx.assert_write("1/1/8", (0,)) + # Change state and attribute + hass.states.async_set(entity_id, "on", {attribute: 1}) + await knx.assert_write("1/1/8", (1,)) + + # Change state to "off"; null attribute + hass.states.async_set(entity_id, "off", {attribute: None}) + await knx.assert_write("1/1/8", (0,)) + async def test_expose_string(hass: HomeAssistant, knx: KNXTestKit) -> None: """Test an expose to send string values of up to 14 bytes only.""" From e2270a305dd37763f71e607694bde60ea76eee46 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Mon, 6 Nov 2023 07:58:13 +0100 Subject: [PATCH 13/33] Sort Withings sleep data on end date (#103454) * Sort Withings sleep data on end date * Sort Withings sleep data on end date --- .../components/withings/coordinator.py | 5 +- .../withings/fixtures/sleep_summaries.json | 78 +++++++++---------- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/homeassistant/components/withings/coordinator.py b/homeassistant/components/withings/coordinator.py index 35eeb6e62b6..7dec48a3489 100644 --- a/homeassistant/components/withings/coordinator.py +++ b/homeassistant/components/withings/coordinator.py @@ -147,7 +147,10 @@ class WithingsSleepDataUpdateCoordinator( ) if not response: return None - return response[0] + + return sorted( + response, key=lambda sleep_summary: sleep_summary.end_date, reverse=True + )[0] class WithingsBedPresenceDataUpdateCoordinator(WithingsDataUpdateCoordinator[None]): diff --git a/tests/components/withings/fixtures/sleep_summaries.json b/tests/components/withings/fixtures/sleep_summaries.json index 1bcfcfcc1d2..4e7f05142d3 100644 --- a/tests/components/withings/fixtures/sleep_summaries.json +++ b/tests/components/withings/fixtures/sleep_summaries.json @@ -1,43 +1,4 @@ [ - { - "id": 2081804182, - "timezone": "Europe/Paris", - "model": 32, - "model_id": 63, - "hash_deviceid": "201d0b9a0556d6b755166b2cf8d22d3bdf0487ee", - "startdate": 1618691453, - "enddate": 1618713173, - "date": "2021-04-18", - "data": { - "wakeupduration": 3060, - "wakeupcount": 1, - "durationtosleep": 540, - "remsleepduration": 2400, - "durationtowakeup": 1140, - "total_sleep_time": 18660, - "sleep_efficiency": 0.86, - "sleep_latency": 540, - "wakeup_latency": 1140, - "waso": 1380, - "nb_rem_episodes": 1, - "out_of_bed_count": 0, - "lightsleepduration": 10440, - "deepsleepduration": 5820, - "hr_average": 103, - "hr_min": 70, - "hr_max": 120, - "rr_average": 14, - "rr_min": 10, - "rr_max": 20, - "breathing_disturbances_intensity": 9, - "snoring": 1080, - "snoringepisodecount": 18, - "sleep_score": 37, - "apnea_hypopnea_index": 9 - }, - "created": 1620237476, - "modified": 1620237476 - }, { "id": 2081804265, "timezone": "Europe/Paris", @@ -77,6 +38,45 @@ "created": 1620237480, "modified": 1620237479 }, + { + "id": 2081804182, + "timezone": "Europe/Paris", + "model": 32, + "model_id": 63, + "hash_deviceid": "201d0b9a0556d6b755166b2cf8d22d3bdf0487ee", + "startdate": 1618691453, + "enddate": 1618713173, + "date": "2021-04-18", + "data": { + "wakeupduration": 3060, + "wakeupcount": 1, + "durationtosleep": 540, + "remsleepduration": 2400, + "durationtowakeup": 1140, + "total_sleep_time": 18660, + "sleep_efficiency": 0.86, + "sleep_latency": 540, + "wakeup_latency": 1140, + "waso": 1380, + "nb_rem_episodes": 1, + "out_of_bed_count": 0, + "lightsleepduration": 10440, + "deepsleepduration": 5820, + "hr_average": 103, + "hr_min": 70, + "hr_max": 120, + "rr_average": 14, + "rr_min": 10, + "rr_max": 20, + "breathing_disturbances_intensity": 9, + "snoring": 1080, + "snoringepisodecount": 18, + "sleep_score": 37, + "apnea_hypopnea_index": 9 + }, + "created": 1620237476, + "modified": 1620237476 + }, { "id": 2081804358, "timezone": "Europe/Paris", From 27d8d1011e9d62fd2edfdbd657d551a978abab5e Mon Sep 17 00:00:00 2001 From: dupondje Date: Mon, 6 Nov 2023 14:19:47 +0100 Subject: [PATCH 14/33] Use right equipment identifier in DSMR setup (#103494) --- homeassistant/components/dsmr/config_flow.py | 2 + tests/components/dsmr/conftest.py | 10 +++++ tests/components/dsmr/test_config_flow.py | 44 ++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/homeassistant/components/dsmr/config_flow.py b/homeassistant/components/dsmr/config_flow.py index c7b9ab4e380..3b32d354766 100644 --- a/homeassistant/components/dsmr/config_flow.py +++ b/homeassistant/components/dsmr/config_flow.py @@ -53,6 +53,8 @@ class DSMRConnection: self._protocol = protocol self._telegram: dict[str, DSMRObject] = {} self._equipment_identifier = obis_ref.EQUIPMENT_IDENTIFIER + if dsmr_version == "5B": + self._equipment_identifier = obis_ref.BELGIUM_EQUIPMENT_IDENTIFIER if dsmr_version == "5L": self._equipment_identifier = obis_ref.LUXEMBOURG_EQUIPMENT_IDENTIFIER if dsmr_version == "Q3D": diff --git a/tests/components/dsmr/conftest.py b/tests/components/dsmr/conftest.py index 67e8b724a97..01aff5ae48e 100644 --- a/tests/components/dsmr/conftest.py +++ b/tests/components/dsmr/conftest.py @@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch from dsmr_parser.clients.protocol import DSMRProtocol from dsmr_parser.clients.rfxtrx_protocol import RFXtrxDSMRProtocol from dsmr_parser.obis_references import ( + BELGIUM_EQUIPMENT_IDENTIFIER, EQUIPMENT_IDENTIFIER, EQUIPMENT_IDENTIFIER_GAS, LUXEMBOURG_EQUIPMENT_IDENTIFIER, @@ -81,6 +82,15 @@ async def dsmr_connection_send_validate_fixture(hass): async def connection_factory(*args, **kwargs): """Return mocked out Asyncio classes.""" + if args[1] == "5B": + protocol.telegram = { + BELGIUM_EQUIPMENT_IDENTIFIER: CosemObject( + BELGIUM_EQUIPMENT_IDENTIFIER, [{"value": "12345678", "unit": ""}] + ), + EQUIPMENT_IDENTIFIER_GAS: CosemObject( + EQUIPMENT_IDENTIFIER_GAS, [{"value": "123456789", "unit": ""}] + ), + } if args[1] == "5L": protocol.telegram = { LUXEMBOURG_EQUIPMENT_IDENTIFIER: CosemObject( diff --git a/tests/components/dsmr/test_config_flow.py b/tests/components/dsmr/test_config_flow.py index 8ad7c7214a3..c4bbe9a7086 100644 --- a/tests/components/dsmr/test_config_flow.py +++ b/tests/components/dsmr/test_config_flow.py @@ -215,6 +215,50 @@ async def test_setup_serial_rfxtrx( assert result["data"] == {**entry_data, **SERIAL_DATA} +@patch("serial.tools.list_ports.comports", return_value=[com_port()]) +async def test_setup_5B( + com_mock, hass: HomeAssistant, dsmr_connection_send_validate_fixture +) -> None: + """Test we can setup serial.""" + port = com_port() + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + assert result["type"] == "form" + assert result["step_id"] == "user" + assert result["errors"] is None + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {"type": "Serial"}, + ) + + assert result["type"] == "form" + assert result["step_id"] == "setup_serial" + assert result["errors"] == {} + + with patch("homeassistant.components.dsmr.async_setup_entry", return_value=True): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + {"port": port.device, "dsmr_version": "5B"}, + ) + await hass.async_block_till_done() + + entry_data = { + "port": port.device, + "dsmr_version": "5B", + "protocol": "dsmr_protocol", + "serial_id": "12345678", + "serial_id_gas": "123456789", + } + + assert result["type"] == "create_entry" + assert result["title"] == port.device + assert result["data"] == entry_data + + @patch("serial.tools.list_ports.comports", return_value=[com_port()]) async def test_setup_5L( com_mock, hass: HomeAssistant, dsmr_connection_send_validate_fixture From c17def27fc8045cb244a88a5bbc5d43770492191 Mon Sep 17 00:00:00 2001 From: Matt Zimmerman Date: Sun, 5 Nov 2023 09:42:07 -0800 Subject: [PATCH 15/33] Fix litterrobot test failure due to time zone dependence (#103444) * fix litterrobot test * use a date in northern hemisehpere summer --- tests/components/litterrobot/test_time.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/components/litterrobot/test_time.py b/tests/components/litterrobot/test_time.py index 6532f2a3bc7..53f254008e7 100644 --- a/tests/components/litterrobot/test_time.py +++ b/tests/components/litterrobot/test_time.py @@ -1,10 +1,11 @@ """Test the Litter-Robot time entity.""" from __future__ import annotations -from datetime import time +from datetime import datetime, time from unittest.mock import MagicMock from pylitterbot import LitterRobot3 +import pytest from homeassistant.components.time import DOMAIN as PLATFORM_DOMAIN from homeassistant.const import ATTR_ENTITY_ID @@ -15,6 +16,7 @@ from .conftest import setup_integration SLEEP_START_TIME_ENTITY_ID = "time.test_sleep_mode_start_time" +@pytest.mark.freeze_time(datetime(2023, 7, 1, 12)) async def test_sleep_mode_start_time( hass: HomeAssistant, mock_account: MagicMock ) -> None: From 8f684ab102d583f777f74fb6e3ea6433dc057621 Mon Sep 17 00:00:00 2001 From: Robert Resch Date: Mon, 6 Nov 2023 17:56:53 +0100 Subject: [PATCH 16/33] Revert binary_sensor part of #103210 (#103499) --- homeassistant/components/mqtt/binary_sensor.py | 10 ++-------- tests/components/mqtt/test_init.py | 9 --------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/mqtt/binary_sensor.py b/homeassistant/components/mqtt/binary_sensor.py index a89fb8a22fc..7ab2e9ebf90 100644 --- a/homeassistant/components/mqtt/binary_sensor.py +++ b/homeassistant/components/mqtt/binary_sensor.py @@ -42,7 +42,6 @@ from .mixins import ( MqttAvailability, MqttEntity, async_setup_entity_entry_helper, - validate_sensor_entity_category, write_state_on_attr_change, ) from .models import MqttValueTemplate, ReceiveMessage @@ -56,7 +55,7 @@ DEFAULT_PAYLOAD_ON = "ON" DEFAULT_FORCE_UPDATE = False CONF_EXPIRE_AFTER = "expire_after" -_PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend( +PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend( { vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None), vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int, @@ -68,12 +67,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend( } ).extend(MQTT_ENTITY_COMMON_SCHEMA.schema) -DISCOVERY_SCHEMA = vol.All( - validate_sensor_entity_category, - _PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA), -) - -PLATFORM_SCHEMA_MODERN = vol.All(validate_sensor_entity_category, _PLATFORM_SCHEMA_BASE) +DISCOVERY_SCHEMA = PLATFORM_SCHEMA_MODERN.extend({}, extra=vol.REMOVE_EXTRA) async def async_setup_entry( diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 93d73094885..8112a289e62 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -2163,15 +2163,6 @@ async def test_setup_manual_mqtt_with_invalid_config( } } }, - { - mqtt.DOMAIN: { - "binary_sensor": { - "name": "test", - "state_topic": "test-topic", - "entity_category": "config", - } - } - }, ], ) @patch( From d019045199c589fb60ecacd819bcbb04767b8276 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 26 Oct 2023 20:19:31 +1300 Subject: [PATCH 17/33] ESPHome: Add suggested_area from device info (#102834) --- homeassistant/components/esphome/manager.py | 5 +++++ homeassistant/components/esphome/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/esphome/manager.py b/homeassistant/components/esphome/manager.py index 812cf430d09..d2eca7d39f9 100644 --- a/homeassistant/components/esphome/manager.py +++ b/homeassistant/components/esphome/manager.py @@ -596,6 +596,10 @@ def _async_setup_device_registry( model = project_name[1] hw_version = device_info.project_version + suggested_area = None + if device_info.suggested_area: + suggested_area = device_info.suggested_area + device_registry = dr.async_get(hass) device_entry = device_registry.async_get_or_create( config_entry_id=entry.entry_id, @@ -606,6 +610,7 @@ def _async_setup_device_registry( model=model, sw_version=sw_version, hw_version=hw_version, + suggested_area=suggested_area, ) return device_entry.id diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 702f75b166e..8968fa7da4f 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -16,7 +16,7 @@ "loggers": ["aioesphomeapi", "noiseprotocol"], "requirements": [ "async-interrupt==1.1.1", - "aioesphomeapi==18.1.0", + "aioesphomeapi==18.2.0", "bluetooth-data-tools==1.13.0", "esphome-dashboard-api==1.2.3" ], diff --git a/requirements_all.txt b/requirements_all.txt index 0e7821f82d9..74339e7a29b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -237,7 +237,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==18.1.0 +aioesphomeapi==18.2.0 # homeassistant.components.flo aioflo==2021.11.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d0bc7b85dcd..f92b787a6ef 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -218,7 +218,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==18.1.0 +aioesphomeapi==18.2.0 # homeassistant.components.flo aioflo==2021.11.0 From 3cac87cf30a7377108c985781619c278e71fede0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 1 Nov 2023 02:56:48 -0500 Subject: [PATCH 18/33] Bump aioesphomeapi to 18.2.1 (#103156) --- homeassistant/components/esphome/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 8968fa7da4f..4619ffef4c5 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -16,7 +16,7 @@ "loggers": ["aioesphomeapi", "noiseprotocol"], "requirements": [ "async-interrupt==1.1.1", - "aioesphomeapi==18.2.0", + "aioesphomeapi==18.2.1", "bluetooth-data-tools==1.13.0", "esphome-dashboard-api==1.2.3" ], diff --git a/requirements_all.txt b/requirements_all.txt index 74339e7a29b..930ade42cc4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -237,7 +237,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==18.2.0 +aioesphomeapi==18.2.1 # homeassistant.components.flo aioflo==2021.11.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f92b787a6ef..0b45c9579b8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -218,7 +218,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==18.2.0 +aioesphomeapi==18.2.1 # homeassistant.components.flo aioflo==2021.11.0 From dbdd9d74cf8c15a52238b1092eeaafeea0c23a58 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 5 Nov 2023 07:07:44 -0600 Subject: [PATCH 19/33] Bump bluetooth-data-tools to 0.14.0 (#103413) changelog: https://github.com/Bluetooth-Devices/bluetooth-data-tools/compare/v1.13.0...v1.14.0 --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/components/esphome/manifest.json | 2 +- homeassistant/components/ld2410_ble/manifest.json | 2 +- homeassistant/components/led_ble/manifest.json | 2 +- homeassistant/components/private_ble_device/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 06e7d34e68d..813bc900900 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -18,7 +18,7 @@ "bleak-retry-connector==3.3.0", "bluetooth-adapters==0.16.1", "bluetooth-auto-recovery==1.2.3", - "bluetooth-data-tools==1.13.0", + "bluetooth-data-tools==1.14.0", "dbus-fast==2.12.0" ] } diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 4619ffef4c5..4e8d3c8dde4 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -17,7 +17,7 @@ "requirements": [ "async-interrupt==1.1.1", "aioesphomeapi==18.2.1", - "bluetooth-data-tools==1.13.0", + "bluetooth-data-tools==1.14.0", "esphome-dashboard-api==1.2.3" ], "zeroconf": ["_esphomelib._tcp.local."] diff --git a/homeassistant/components/ld2410_ble/manifest.json b/homeassistant/components/ld2410_ble/manifest.json index f82b2fff62b..7996376b6ac 100644 --- a/homeassistant/components/ld2410_ble/manifest.json +++ b/homeassistant/components/ld2410_ble/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/ld2410_ble", "integration_type": "device", "iot_class": "local_push", - "requirements": ["bluetooth-data-tools==1.13.0", "ld2410-ble==0.1.1"] + "requirements": ["bluetooth-data-tools==1.14.0", "ld2410-ble==0.1.1"] } diff --git a/homeassistant/components/led_ble/manifest.json b/homeassistant/components/led_ble/manifest.json index a0f7685a2ec..21543ad6788 100644 --- a/homeassistant/components/led_ble/manifest.json +++ b/homeassistant/components/led_ble/manifest.json @@ -32,5 +32,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/led_ble", "iot_class": "local_polling", - "requirements": ["bluetooth-data-tools==1.13.0", "led-ble==1.0.1"] + "requirements": ["bluetooth-data-tools==1.14.0", "led-ble==1.0.1"] } diff --git a/homeassistant/components/private_ble_device/manifest.json b/homeassistant/components/private_ble_device/manifest.json index 91ef843a864..663461ceaa1 100644 --- a/homeassistant/components/private_ble_device/manifest.json +++ b/homeassistant/components/private_ble_device/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/private_ble_device", "iot_class": "local_push", - "requirements": ["bluetooth-data-tools==1.13.0"] + "requirements": ["bluetooth-data-tools==1.14.0"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index a70bcf4524a..12b1c6a4d0a 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -12,7 +12,7 @@ bleak-retry-connector==3.3.0 bleak==0.21.1 bluetooth-adapters==0.16.1 bluetooth-auto-recovery==1.2.3 -bluetooth-data-tools==1.13.0 +bluetooth-data-tools==1.14.0 certifi>=2021.5.30 ciso8601==2.3.0 cryptography==41.0.4 diff --git a/requirements_all.txt b/requirements_all.txt index 930ade42cc4..e02ddb809e2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -562,7 +562,7 @@ bluetooth-auto-recovery==1.2.3 # homeassistant.components.ld2410_ble # homeassistant.components.led_ble # homeassistant.components.private_ble_device -bluetooth-data-tools==1.13.0 +bluetooth-data-tools==1.14.0 # homeassistant.components.bond bond-async==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0b45c9579b8..28f515c826d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -476,7 +476,7 @@ bluetooth-auto-recovery==1.2.3 # homeassistant.components.ld2410_ble # homeassistant.components.led_ble # homeassistant.components.private_ble_device -bluetooth-data-tools==1.13.0 +bluetooth-data-tools==1.14.0 # homeassistant.components.bond bond-async==0.2.1 From 93a0bd351a199871353e3c8795b2f6c71fcf54b7 Mon Sep 17 00:00:00 2001 From: mkmer Date: Tue, 7 Nov 2023 18:04:23 -0500 Subject: [PATCH 20/33] Bump blinkpy to 0.22.3 (#103438) --- 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 54f36ec6e2e..bb8fd4a5a51 100644 --- a/homeassistant/components/blink/manifest.json +++ b/homeassistant/components/blink/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/blink", "iot_class": "cloud_polling", "loggers": ["blinkpy"], - "requirements": ["blinkpy==0.22.2"] + "requirements": ["blinkpy==0.22.3"] } diff --git a/requirements_all.txt b/requirements_all.txt index e02ddb809e2..c6c465e7f9d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -539,7 +539,7 @@ bleak==0.21.1 blebox-uniapi==2.2.0 # homeassistant.components.blink -blinkpy==0.22.2 +blinkpy==0.22.3 # homeassistant.components.bitcoin blockchain==1.4.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 28f515c826d..3c22bbb9a05 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -460,7 +460,7 @@ bleak==0.21.1 blebox-uniapi==2.2.0 # homeassistant.components.blink -blinkpy==0.22.2 +blinkpy==0.22.3 # homeassistant.components.bluemaestro bluemaestro-ble==0.2.3 From 35c0c9958d64ba5fce2af996323beea29de7f8f0 Mon Sep 17 00:00:00 2001 From: dupondje Date: Wed, 8 Nov 2023 09:13:51 +0100 Subject: [PATCH 21/33] Fix 5B Gas meter in dsmr (#103506) * Fix 5B Gas meter in dsmr In commit 1b73219 the gas meter broke for 5B. As the change can't be reverted easily without removing the peak usage sensors, we implement a workaround. The first MBUS_METER_READING2 value will contain the gas meter data just like the previous BELGIUM_5MIN_GAS_METER_READING did. But this without the need to touch dsmr_parser (version). Fixes: #103306, #103293 * Use parametrize * Apply suggestions from code review Co-authored-by: Jan Bouwhuis * Add additional tests + typo fix --------- Co-authored-by: Jan Bouwhuis --- homeassistant/components/dsmr/const.py | 3 - homeassistant/components/dsmr/sensor.py | 42 +++++-- tests/components/dsmr/test_sensor.py | 152 +++++++++++++++++++++++- 3 files changed, 179 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/dsmr/const.py b/homeassistant/components/dsmr/const.py index 7bc0247aea6..5e1a54aedc4 100644 --- a/homeassistant/components/dsmr/const.py +++ b/homeassistant/components/dsmr/const.py @@ -34,6 +34,3 @@ DSMR_VERSIONS = {"2.2", "4", "5", "5B", "5L", "5S", "Q3D"} DSMR_PROTOCOL = "dsmr_protocol" RFXTRX_DSMR_PROTOCOL = "rfxtrx_dsmr_protocol" - -# Temp obis until sensors replaced by mbus variants -BELGIUM_5MIN_GAS_METER_READING = r"\d-\d:24\.2\.3.+?\r\n" diff --git a/homeassistant/components/dsmr/sensor.py b/homeassistant/components/dsmr/sensor.py index 99af30b8111..fa58bd8c5a6 100644 --- a/homeassistant/components/dsmr/sensor.py +++ b/homeassistant/components/dsmr/sensor.py @@ -44,7 +44,6 @@ from homeassistant.helpers.typing import StateType from homeassistant.util import Throttle from .const import ( - BELGIUM_5MIN_GAS_METER_READING, CONF_DSMR_VERSION, CONF_PRECISION, CONF_PROTOCOL, @@ -382,16 +381,6 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = ( device_class=SensorDeviceClass.GAS, state_class=SensorStateClass.TOTAL_INCREASING, ), - DSMRSensorEntityDescription( - key="belgium_5min_gas_meter_reading", - translation_key="gas_meter_reading", - obis_reference=BELGIUM_5MIN_GAS_METER_READING, - dsmr_versions={"5B"}, - is_gas=True, - force_update=True, - device_class=SensorDeviceClass.GAS, - state_class=SensorStateClass.TOTAL_INCREASING, - ), DSMRSensorEntityDescription( key="gas_meter_reading", translation_key="gas_meter_reading", @@ -405,6 +394,31 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = ( ) +def add_gas_sensor_5B(telegram: dict[str, DSMRObject]) -> DSMRSensorEntityDescription: + """Return correct entity for 5B Gas meter.""" + ref = None + if obis_references.BELGIUM_MBUS1_METER_READING2 in telegram: + ref = obis_references.BELGIUM_MBUS1_METER_READING2 + elif obis_references.BELGIUM_MBUS2_METER_READING2 in telegram: + ref = obis_references.BELGIUM_MBUS2_METER_READING2 + elif obis_references.BELGIUM_MBUS3_METER_READING2 in telegram: + ref = obis_references.BELGIUM_MBUS3_METER_READING2 + elif obis_references.BELGIUM_MBUS4_METER_READING2 in telegram: + ref = obis_references.BELGIUM_MBUS4_METER_READING2 + elif ref is None: + ref = obis_references.BELGIUM_MBUS1_METER_READING2 + return DSMRSensorEntityDescription( + key="belgium_5min_gas_meter_reading", + translation_key="gas_meter_reading", + obis_reference=ref, + dsmr_versions={"5B"}, + is_gas=True, + force_update=True, + device_class=SensorDeviceClass.GAS, + state_class=SensorStateClass.TOTAL_INCREASING, + ) + + async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: @@ -438,6 +452,10 @@ async def async_setup_entry( return (entity_description.device_class, UNIT_CONVERSION[uom]) return (entity_description.device_class, uom) + all_sensors = SENSORS + if dsmr_version == "5B": + all_sensors += (add_gas_sensor_5B(telegram),) + entities.extend( [ DSMREntity( @@ -448,7 +466,7 @@ async def async_setup_entry( telegram, description ), # type: ignore[arg-type] ) - for description in SENSORS + for description in all_sensors if ( description.dsmr_versions is None or dsmr_version in description.dsmr_versions diff --git a/tests/components/dsmr/test_sensor.py b/tests/components/dsmr/test_sensor.py index 9c8c4e6fc70..e7f0e715f59 100644 --- a/tests/components/dsmr/test_sensor.py +++ b/tests/components/dsmr/test_sensor.py @@ -8,10 +8,22 @@ import asyncio import datetime from decimal import Decimal from itertools import chain, repeat +from typing import Literal from unittest.mock import DEFAULT, MagicMock +from dsmr_parser.obis_references import ( + BELGIUM_MBUS1_METER_READING1, + BELGIUM_MBUS1_METER_READING2, + BELGIUM_MBUS2_METER_READING1, + BELGIUM_MBUS2_METER_READING2, + BELGIUM_MBUS3_METER_READING1, + BELGIUM_MBUS3_METER_READING2, + BELGIUM_MBUS4_METER_READING1, + BELGIUM_MBUS4_METER_READING2, +) +import pytest + from homeassistant import config_entries -from homeassistant.components.dsmr.const import BELGIUM_5MIN_GAS_METER_READING from homeassistant.components.sensor import ( ATTR_OPTIONS, ATTR_STATE_CLASS, @@ -483,6 +495,10 @@ async def test_belgian_meter(hass: HomeAssistant, dsmr_connection_fixture) -> No from dsmr_parser.obis_references import ( BELGIUM_CURRENT_AVERAGE_DEMAND, BELGIUM_MAXIMUM_DEMAND_MONTH, + BELGIUM_MBUS1_METER_READING2, + BELGIUM_MBUS2_METER_READING2, + BELGIUM_MBUS3_METER_READING2, + BELGIUM_MBUS4_METER_READING2, ELECTRICITY_ACTIVE_TARIFF, ) from dsmr_parser.objects import CosemObject, MBusObject @@ -500,13 +516,34 @@ async def test_belgian_meter(hass: HomeAssistant, dsmr_connection_fixture) -> No } telegram = { - BELGIUM_5MIN_GAS_METER_READING: MBusObject( - BELGIUM_5MIN_GAS_METER_READING, + BELGIUM_MBUS1_METER_READING2: MBusObject( + BELGIUM_MBUS1_METER_READING2, [ {"value": datetime.datetime.fromtimestamp(1551642213)}, {"value": Decimal(745.695), "unit": "m3"}, ], ), + BELGIUM_MBUS2_METER_READING2: MBusObject( + BELGIUM_MBUS2_METER_READING2, + [ + {"value": datetime.datetime.fromtimestamp(1551642214)}, + {"value": Decimal(745.696), "unit": "m3"}, + ], + ), + BELGIUM_MBUS3_METER_READING2: MBusObject( + BELGIUM_MBUS3_METER_READING2, + [ + {"value": datetime.datetime.fromtimestamp(1551642215)}, + {"value": Decimal(745.697), "unit": "m3"}, + ], + ), + BELGIUM_MBUS4_METER_READING2: MBusObject( + BELGIUM_MBUS4_METER_READING2, + [ + {"value": datetime.datetime.fromtimestamp(1551642216)}, + {"value": Decimal(745.698), "unit": "m3"}, + ], + ), BELGIUM_CURRENT_AVERAGE_DEMAND: CosemObject( BELGIUM_CURRENT_AVERAGE_DEMAND, [{"value": Decimal(1.75), "unit": "kW"}], @@ -577,6 +614,115 @@ async def test_belgian_meter(hass: HomeAssistant, dsmr_connection_fixture) -> No ) +@pytest.mark.parametrize( + ("key1", "key2", "key3", "gas_value"), + [ + ( + BELGIUM_MBUS1_METER_READING1, + BELGIUM_MBUS2_METER_READING2, + BELGIUM_MBUS3_METER_READING1, + "745.696", + ), + ( + BELGIUM_MBUS1_METER_READING2, + BELGIUM_MBUS2_METER_READING1, + BELGIUM_MBUS3_METER_READING2, + "745.695", + ), + ( + BELGIUM_MBUS4_METER_READING2, + BELGIUM_MBUS2_METER_READING1, + BELGIUM_MBUS3_METER_READING1, + "745.695", + ), + ( + BELGIUM_MBUS4_METER_READING1, + BELGIUM_MBUS2_METER_READING1, + BELGIUM_MBUS3_METER_READING2, + "745.697", + ), + ], +) +async def test_belgian_meter_alt( + hass: HomeAssistant, + dsmr_connection_fixture, + key1: Literal, + key2: Literal, + key3: Literal, + gas_value: str, +) -> None: + """Test if Belgian meter is correctly parsed.""" + (connection_factory, transport, protocol) = dsmr_connection_fixture + + from dsmr_parser.objects import MBusObject + + entry_data = { + "port": "/dev/ttyUSB0", + "dsmr_version": "5B", + "precision": 4, + "reconnect_interval": 30, + "serial_id": "1234", + "serial_id_gas": "5678", + } + entry_options = { + "time_between_update": 0, + } + + telegram = { + key1: MBusObject( + key1, + [ + {"value": datetime.datetime.fromtimestamp(1551642213)}, + {"value": Decimal(745.695), "unit": "m3"}, + ], + ), + key2: MBusObject( + key2, + [ + {"value": datetime.datetime.fromtimestamp(1551642214)}, + {"value": Decimal(745.696), "unit": "m3"}, + ], + ), + key3: MBusObject( + key3, + [ + {"value": datetime.datetime.fromtimestamp(1551642215)}, + {"value": Decimal(745.697), "unit": "m3"}, + ], + ), + } + + mock_entry = MockConfigEntry( + domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options + ) + + mock_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(mock_entry.entry_id) + await hass.async_block_till_done() + + telegram_callback = connection_factory.call_args_list[0][0][2] + + # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser + telegram_callback(telegram) + + # after receiving telegram entities need to have the chance to be created + await hass.async_block_till_done() + + # check if gas consumption is parsed correctly + gas_consumption = hass.states.get("sensor.gas_meter_gas_consumption") + assert gas_consumption.state == gas_value + assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.GAS + assert ( + gas_consumption.attributes.get(ATTR_STATE_CLASS) + == SensorStateClass.TOTAL_INCREASING + ) + assert ( + gas_consumption.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + == UnitOfVolume.CUBIC_METERS + ) + + async def test_belgian_meter_low(hass: HomeAssistant, dsmr_connection_fixture) -> None: """Test if Belgian meter is correctly parsed.""" (connection_factory, transport, protocol) = dsmr_connection_fixture From da1c282c1b8d937f5395793d122e3ecfcd81ac42 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Mon, 6 Nov 2023 23:43:56 +0100 Subject: [PATCH 22/33] Fix invalid MAC in samsungtv (#103512) * Fix invalid MAC in samsungtv * Also adjust __init__ --- .../components/samsungtv/__init__.py | 4 +- .../components/samsungtv/config_flow.py | 5 +- .../components/samsungtv/test_config_flow.py | 62 ++++++++++++++++--- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/samsungtv/__init__.py b/homeassistant/components/samsungtv/__init__.py index b7d400ce831..2ced868ada7 100644 --- a/homeassistant/components/samsungtv/__init__.py +++ b/homeassistant/components/samsungtv/__init__.py @@ -211,7 +211,9 @@ async def _async_create_bridge_with_updated_data( partial(getmac.get_mac_address, ip=host) ) - if mac: + if mac and mac != "none": + # Samsung sometimes returns a value of "none" for the mac address + # this should be ignored LOGGER.info("Updated mac to %s for %s", mac, host) updated_data[CONF_MAC] = mac else: diff --git a/homeassistant/components/samsungtv/config_flow.py b/homeassistant/components/samsungtv/config_flow.py index 124dab73004..f20a79cc9e6 100644 --- a/homeassistant/components/samsungtv/config_flow.py +++ b/homeassistant/components/samsungtv/config_flow.py @@ -219,7 +219,10 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self._title = f"{self._name} ({self._model})" self._udn = _strip_uuid(dev_info.get("udn", info["id"])) if mac := mac_from_device_info(info): - self._mac = mac + # Samsung sometimes returns a value of "none" for the mac address + # this should be ignored - but also shouldn't trigger getmac + if mac != "none": + self._mac = mac elif mac := await self.hass.async_add_executor_job( partial(getmac.get_mac_address, ip=self._host) ): diff --git a/tests/components/samsungtv/test_config_flow.py b/tests/components/samsungtv/test_config_flow.py index a70a0042fcd..0eacd63b42d 100644 --- a/tests/components/samsungtv/test_config_flow.py +++ b/tests/components/samsungtv/test_config_flow.py @@ -1,4 +1,5 @@ """Tests for Samsung TV config flow.""" +from copy import deepcopy from ipaddress import ip_address from unittest.mock import ANY, AsyncMock, Mock, call, patch @@ -165,14 +166,6 @@ MOCK_DEVICE_INFO = { }, "id": "123", } -MOCK_DEVICE_INFO_2 = { - "device": { - "type": "Samsung SmartTV", - "name": "fake2_name", - "modelName": "fake2_model", - }, - "id": "345", -} AUTODETECT_LEGACY = { "name": "HomeAssistant", @@ -1968,3 +1961,56 @@ async def test_no_update_incorrect_udn_not_matching_mac_from_dhcp( assert result["step_id"] == "confirm" assert entry.data[CONF_MAC] == "aa:bb:ss:ss:dd:pp" assert entry.unique_id == "0d1cef00-00dc-1000-9c80-4844f7b172de" + + +@pytest.mark.usefixtures("remotews", "remoteencws_failing") +async def test_ssdp_update_mac(hass: HomeAssistant) -> None: + """Ensure that MAC address is correctly updated from SSDP.""" + with patch( + "homeassistant.components.samsungtv.bridge.SamsungTVWSBridge.async_device_info", + return_value=MOCK_DEVICE_INFO, + ): + # entry was added + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_USER_DATA + ) + assert result["type"] == FlowResultType.CREATE_ENTRY + entry = result["result"] + assert entry.data[CONF_MANUFACTURER] == DEFAULT_MANUFACTURER + assert entry.data[CONF_MODEL] == "fake_model" + assert entry.data[CONF_MAC] is None + assert entry.unique_id == "123" + + device_info = deepcopy(MOCK_DEVICE_INFO) + device_info["device"]["wifiMac"] = "none" + with patch( + "homeassistant.components.samsungtv.bridge.SamsungTVWSBridge.async_device_info", + return_value=device_info, + ): + # Updated + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_SSDP}, data=MOCK_SSDP_DATA + ) + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == RESULT_ALREADY_CONFIGURED + + # ensure mac wasn't updated with "none" + assert entry.data[CONF_MAC] is None + assert entry.unique_id == "123" + + device_info = deepcopy(MOCK_DEVICE_INFO) + device_info["device"]["wifiMac"] = "aa:bb:cc:dd:ee:ff" + with patch( + "homeassistant.components.samsungtv.bridge.SamsungTVWSBridge.async_device_info", + return_value=device_info, + ): + # Updated + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_SSDP}, data=MOCK_SSDP_DATA + ) + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == RESULT_ALREADY_CONFIGURED + + # ensure mac was updated with new wifiMac value + assert entry.data[CONF_MAC] == "aa:bb:cc:dd:ee:ff" + assert entry.unique_id == "123" From c8d3e377f0fcbae33aa447deef944307066fbcfe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 7 Nov 2023 04:22:41 -0600 Subject: [PATCH 23/33] Bump aioesphomeapi to 18.2.4 (#103552) --- .../components/esphome/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/esphome/conftest.py | 25 +++++++++++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 4e8d3c8dde4..cb1a741c447 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -16,7 +16,7 @@ "loggers": ["aioesphomeapi", "noiseprotocol"], "requirements": [ "async-interrupt==1.1.1", - "aioesphomeapi==18.2.1", + "aioesphomeapi==18.2.4", "bluetooth-data-tools==1.14.0", "esphome-dashboard-api==1.2.3" ], diff --git a/requirements_all.txt b/requirements_all.txt index c6c465e7f9d..df1e8835288 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -237,7 +237,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==18.2.1 +aioesphomeapi==18.2.4 # homeassistant.components.flo aioflo==2021.11.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3c22bbb9a05..7d343781c60 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -218,7 +218,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==18.2.1 +aioesphomeapi==18.2.4 # homeassistant.components.flo aioflo==2021.11.0 diff --git a/tests/components/esphome/conftest.py b/tests/components/esphome/conftest.py index 4ff6b503b3c..48b0868e406 100644 --- a/tests/components/esphome/conftest.py +++ b/tests/components/esphome/conftest.py @@ -77,6 +77,17 @@ def mock_config_entry(hass) -> MockConfigEntry: return config_entry +class BaseMockReconnectLogic(ReconnectLogic): + """Mock ReconnectLogic.""" + + def stop_callback(self) -> None: + """Stop the reconnect logic.""" + # For the purposes of testing, we don't want to wait + # for the reconnect logic to finish trying to connect + self._cancel_connect("forced disconnect from test") + self._is_stopped = True + + @pytest.fixture def mock_device_info() -> DeviceInfo: """Return the default mocked device info.""" @@ -132,7 +143,10 @@ def mock_client(mock_device_info) -> APIClient: mock_client.address = "127.0.0.1" mock_client.api_version = APIVersion(99, 99) - with patch("homeassistant.components.esphome.APIClient", mock_client), patch( + with patch( + "homeassistant.components.esphome.manager.ReconnectLogic", + BaseMockReconnectLogic, + ), patch("homeassistant.components.esphome.APIClient", mock_client), patch( "homeassistant.components.esphome.config_flow.APIClient", mock_client ): yield mock_client @@ -234,7 +248,7 @@ async def _mock_generic_device_entry( try_connect_done = Event() - class MockReconnectLogic(ReconnectLogic): + class MockReconnectLogic(BaseMockReconnectLogic): """Mock ReconnectLogic.""" def __init__(self, *args, **kwargs): @@ -250,6 +264,13 @@ async def _mock_generic_device_entry( try_connect_done.set() return result + def stop_callback(self) -> None: + """Stop the reconnect logic.""" + # For the purposes of testing, we don't want to wait + # for the reconnect logic to finish trying to connect + self._cancel_connect("forced disconnect from test") + self._is_stopped = True + with patch( "homeassistant.components.esphome.manager.ReconnectLogic", MockReconnectLogic ): From 95d4254074f79bafe25ca2e8e7d92a0d3b469bdd Mon Sep 17 00:00:00 2001 From: Charles Garwood Date: Mon, 6 Nov 2023 18:53:44 -0500 Subject: [PATCH 24/33] Bump pyenphase to 1.14.2 (#103553) --- homeassistant/components/enphase_envoy/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/enphase_envoy/manifest.json b/homeassistant/components/enphase_envoy/manifest.json index 4cffcce2d5c..718c33d2811 100644 --- a/homeassistant/components/enphase_envoy/manifest.json +++ b/homeassistant/components/enphase_envoy/manifest.json @@ -6,7 +6,7 @@ "documentation": "https://www.home-assistant.io/integrations/enphase_envoy", "iot_class": "local_polling", "loggers": ["pyenphase"], - "requirements": ["pyenphase==1.14.1"], + "requirements": ["pyenphase==1.14.2"], "zeroconf": [ { "type": "_enphase-envoy._tcp.local." diff --git a/requirements_all.txt b/requirements_all.txt index df1e8835288..74d9af9953a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1696,7 +1696,7 @@ pyedimax==0.2.1 pyefergy==22.1.1 # homeassistant.components.enphase_envoy -pyenphase==1.14.1 +pyenphase==1.14.2 # homeassistant.components.envisalink pyenvisalink==4.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7d343781c60..4c356309f24 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1278,7 +1278,7 @@ pyeconet==0.1.22 pyefergy==22.1.1 # homeassistant.components.enphase_envoy -pyenphase==1.14.1 +pyenphase==1.14.2 # homeassistant.components.everlights pyeverlights==0.1.0 From 70f0ee81c9885e1dae0eb2fbfc05515315e9f090 Mon Sep 17 00:00:00 2001 From: dupondje Date: Tue, 7 Nov 2023 10:38:37 +0100 Subject: [PATCH 25/33] Update dsmr-parser to 1.3.1 to fix parsing issues (#103572) --- homeassistant/components/dsmr/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/dsmr/manifest.json b/homeassistant/components/dsmr/manifest.json index b3f59a15b80..90fd2d6cdce 100644 --- a/homeassistant/components/dsmr/manifest.json +++ b/homeassistant/components/dsmr/manifest.json @@ -7,5 +7,5 @@ "integration_type": "hub", "iot_class": "local_push", "loggers": ["dsmr_parser"], - "requirements": ["dsmr-parser==1.3.0"] + "requirements": ["dsmr-parser==1.3.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index 74d9af9953a..8a6230bb9d7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -701,7 +701,7 @@ dovado==0.4.1 dremel3dpy==2.1.1 # homeassistant.components.dsmr -dsmr-parser==1.3.0 +dsmr-parser==1.3.1 # homeassistant.components.dwd_weather_warnings dwdwfsapi==1.0.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4c356309f24..77ab2e7e38f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -572,7 +572,7 @@ discovery30303==0.2.1 dremel3dpy==2.1.1 # homeassistant.components.dsmr -dsmr-parser==1.3.0 +dsmr-parser==1.3.1 # homeassistant.components.dwd_weather_warnings dwdwfsapi==1.0.6 From f9c70fd3c85859c81ccd8c0f042dd901115e5d77 Mon Sep 17 00:00:00 2001 From: suaveolent <2163625+suaveolent@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:46:02 +0100 Subject: [PATCH 26/33] fix: get_devices only checks for the first type (#103583) --- homeassistant/components/lupusec/switch.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/lupusec/switch.py b/homeassistant/components/lupusec/switch.py index b4294216003..981a2a8633a 100644 --- a/homeassistant/components/lupusec/switch.py +++ b/homeassistant/components/lupusec/switch.py @@ -28,9 +28,10 @@ def setup_platform( data = hass.data[LUPUSEC_DOMAIN] - devices = [] + device_types = [CONST.TYPE_SWITCH] - for device in data.lupusec.get_devices(generic_type=CONST.TYPE_SWITCH): + devices = [] + for device in data.lupusec.get_devices(generic_type=device_types): devices.append(LupusecSwitch(data, device)) add_entities(devices) From d1a3a5895b4de08344140f229ff2f8c4dcb83577 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 7 Nov 2023 16:33:46 +0100 Subject: [PATCH 27/33] Raise exception when data can't be fetched in Opensky (#103596) --- homeassistant/components/opensky/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/opensky/__init__.py b/homeassistant/components/opensky/__init__.py index cb9c6173694..6e60c2ec4f1 100644 --- a/homeassistant/components/opensky/__init__.py +++ b/homeassistant/components/opensky/__init__.py @@ -3,7 +3,7 @@ from __future__ import annotations from aiohttp import BasicAuth from python_opensky import OpenSky -from python_opensky.exceptions import OpenSkyUnauthenticatedError +from python_opensky.exceptions import OpenSkyError from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME @@ -28,7 +28,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ), contributing_user=entry.options.get(CONF_CONTRIBUTING_USER, False), ) - except OpenSkyUnauthenticatedError as exc: + except OpenSkyError as exc: raise ConfigEntryNotReady from exc coordinator = OpenSkyDataUpdateCoordinator(hass, client) From 0ffc1bae7644a67e40fc7ec7ba33b891f4f1548f Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 7 Nov 2023 22:50:09 +0100 Subject: [PATCH 28/33] Bump yt-dlp to 2023.10.13 (#103616) --- homeassistant/components/media_extractor/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/media_extractor/manifest.json b/homeassistant/components/media_extractor/manifest.json index 37a8a0d6773..d16439800a9 100644 --- a/homeassistant/components/media_extractor/manifest.json +++ b/homeassistant/components/media_extractor/manifest.json @@ -7,5 +7,5 @@ "iot_class": "calculated", "loggers": ["yt_dlp"], "quality_scale": "internal", - "requirements": ["yt-dlp==2023.9.24"] + "requirements": ["yt-dlp==2023.10.13"] } diff --git a/requirements_all.txt b/requirements_all.txt index 8a6230bb9d7..f48915d5629 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2782,7 +2782,7 @@ youless-api==1.0.1 youtubeaio==1.1.5 # homeassistant.components.media_extractor -yt-dlp==2023.9.24 +yt-dlp==2023.10.13 # homeassistant.components.zamg zamg==0.3.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 77ab2e7e38f..ad95793bfee 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2079,7 +2079,7 @@ youless-api==1.0.1 youtubeaio==1.1.5 # homeassistant.components.media_extractor -yt-dlp==2023.9.24 +yt-dlp==2023.10.13 # homeassistant.components.zamg zamg==0.3.0 From f946ed9e16409f58a8bedee158c2775056aceb8e Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Nov 2023 09:27:33 +0100 Subject: [PATCH 29/33] Fix Reolink DHCP IP update (#103654) --- .../components/reolink/config_flow.py | 4 ++- tests/components/reolink/conftest.py | 16 ++++++++--- tests/components/reolink/test_config_flow.py | 27 +++++++++++++++++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/reolink/config_flow.py b/homeassistant/components/reolink/config_flow.py index 59fbdc22747..a27c84b9593 100644 --- a/homeassistant/components/reolink/config_flow.py +++ b/homeassistant/components/reolink/config_flow.py @@ -113,7 +113,9 @@ class ReolinkFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): raise AbortFlow("already_configured") # check if the camera is reachable at the new IP - host = ReolinkHost(self.hass, existing_entry.data, existing_entry.options) + new_config = dict(existing_entry.data) + new_config[CONF_HOST] = discovery_info.ip + host = ReolinkHost(self.hass, new_config, existing_entry.options) try: await host.api.get_state("GetLocalLink") await host.api.logout() diff --git a/tests/components/reolink/conftest.py b/tests/components/reolink/conftest.py index 25719c4cff7..3efc1e481df 100644 --- a/tests/components/reolink/conftest.py +++ b/tests/components/reolink/conftest.py @@ -34,8 +34,10 @@ def mock_setup_entry() -> Generator[AsyncMock, None, None]: @pytest.fixture -def reolink_connect(mock_get_source_ip: None) -> Generator[MagicMock, None, None]: - """Mock reolink connection.""" +def reolink_connect_class( + mock_get_source_ip: None, +) -> Generator[MagicMock, None, None]: + """Mock reolink connection and return both the host_mock and host_mock_class.""" with patch( "homeassistant.components.reolink.host.webhook.async_register", return_value=True, @@ -65,7 +67,15 @@ def reolink_connect(mock_get_source_ip: None) -> Generator[MagicMock, None, None host_mock.session_active = True host_mock.timeout = 60 host_mock.renewtimer.return_value = 600 - yield host_mock + yield host_mock_class + + +@pytest.fixture +def reolink_connect( + reolink_connect_class: MagicMock, +) -> Generator[MagicMock, None, None]: + """Mock reolink connection.""" + return reolink_connect_class.return_value @pytest.fixture diff --git a/tests/components/reolink/test_config_flow.py b/tests/components/reolink/test_config_flow.py index 1a4bf999cce..9b449d4b851 100644 --- a/tests/components/reolink/test_config_flow.py +++ b/tests/components/reolink/test_config_flow.py @@ -2,7 +2,7 @@ from datetime import timedelta import json from typing import Any -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import AsyncMock, MagicMock, call import pytest from reolink_aio.exceptions import ApiError, CredentialsInvalidError, ReolinkError @@ -12,6 +12,7 @@ from homeassistant.components import dhcp from homeassistant.components.reolink import DEVICE_UPDATE_INTERVAL, const from homeassistant.components.reolink.config_flow import DEFAULT_PROTOCOL from homeassistant.components.reolink.exceptions import ReolinkWebhookException +from homeassistant.components.reolink.host import DEFAULT_TIMEOUT from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME from homeassistant.core import HomeAssistant @@ -380,41 +381,47 @@ async def test_dhcp_flow(hass: HomeAssistant, mock_setup_entry: MagicMock) -> No @pytest.mark.parametrize( - ("last_update_success", "attr", "value", "expected"), + ("last_update_success", "attr", "value", "expected", "host_call_list"), [ ( False, None, None, TEST_HOST2, + [TEST_HOST, TEST_HOST2], ), ( True, None, None, TEST_HOST, + [TEST_HOST], ), ( False, "get_state", AsyncMock(side_effect=ReolinkError("Test error")), TEST_HOST, + [TEST_HOST, TEST_HOST2], ), ( False, "mac_address", "aa:aa:aa:aa:aa:aa", TEST_HOST, + [TEST_HOST, TEST_HOST2], ), ], ) async def test_dhcp_ip_update( hass: HomeAssistant, + reolink_connect_class: MagicMock, reolink_connect: MagicMock, last_update_success: bool, attr: str, value: Any, expected: str, + host_call_list: list[str], ) -> None: """Test dhcp discovery aborts if already configured where the IP is updated if appropriate.""" config_entry = MockConfigEntry( @@ -459,6 +466,22 @@ async def test_dhcp_ip_update( const.DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=dhcp_data ) + expected_calls = [] + for host in host_call_list: + expected_calls.append( + call( + host, + TEST_USERNAME, + TEST_PASSWORD, + port=TEST_PORT, + use_https=TEST_USE_HTTPS, + protocol=DEFAULT_PROTOCOL, + timeout=DEFAULT_TIMEOUT, + ) + ) + + assert reolink_connect_class.call_args_list == expected_calls + assert result["type"] is data_entry_flow.FlowResultType.ABORT assert result["reason"] == "already_configured" From 8ce746972f147e3cce547fcb23ed1a7d8eb087af Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 8 Nov 2023 18:13:11 -0600 Subject: [PATCH 30/33] Incease tplink setup timeout (#103671) It can take longer than 5s to do the first update of the device especially when the device is overloaded as seen in #103668 Wait 10 seconds for the discovery since when the power strips are loaded they cannot respond in time --- homeassistant/components/tplink/__init__.py | 2 +- tests/components/tplink/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tplink/__init__.py b/homeassistant/components/tplink/__init__.py index d8285cbed70..f2a1e682304 100644 --- a/homeassistant/components/tplink/__init__.py +++ b/homeassistant/components/tplink/__init__.py @@ -87,7 +87,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up TPLink from a config entry.""" host = entry.data[CONF_HOST] try: - device: SmartDevice = await Discover.discover_single(host) + device: SmartDevice = await Discover.discover_single(host, timeout=10) except SmartDeviceException as ex: raise ConfigEntryNotReady from ex diff --git a/tests/components/tplink/__init__.py b/tests/components/tplink/__init__.py index 816251ae3bb..9006a058c57 100644 --- a/tests/components/tplink/__init__.py +++ b/tests/components/tplink/__init__.py @@ -202,7 +202,7 @@ def _patch_discovery(device=None, no_device=False): def _patch_single_discovery(device=None, no_device=False): - async def _discover_single(*_): + async def _discover_single(*args, **kwargs): if no_device: raise SmartDeviceException return device if device else _mocked_bulb() From 30dc05cdd729ae18171a7219ad79317c98e7a598 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 9 Nov 2023 12:44:50 +0100 Subject: [PATCH 31/33] Add name to Withings coordinator (#103692) --- homeassistant/components/withings/coordinator.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/withings/coordinator.py b/homeassistant/components/withings/coordinator.py index 7dec48a3489..2639ccccf7d 100644 --- a/homeassistant/components/withings/coordinator.py +++ b/homeassistant/components/withings/coordinator.py @@ -37,11 +37,15 @@ class WithingsDataUpdateCoordinator(DataUpdateCoordinator[_T]): _default_update_interval: timedelta | None = UPDATE_INTERVAL _last_valid_update: datetime | None = None webhooks_connected: bool = False + coordinator_name: str = "" def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None: """Initialize the Withings data coordinator.""" super().__init__( - hass, LOGGER, name="Withings", update_interval=self._default_update_interval + hass, + LOGGER, + name=f"Withings {self.coordinator_name}", + update_interval=self._default_update_interval, ) self._client = client self.notification_categories: set[NotificationCategory] = set() @@ -77,6 +81,8 @@ class WithingsMeasurementDataUpdateCoordinator( ): """Withings measurement coordinator.""" + coordinator_name: str = "measurements" + def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None: """Initialize the Withings data coordinator.""" super().__init__(hass, client) @@ -109,6 +115,8 @@ class WithingsSleepDataUpdateCoordinator( ): """Withings sleep coordinator.""" + coordinator_name: str = "sleep" + def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None: """Initialize the Withings data coordinator.""" super().__init__(hass, client) @@ -156,6 +164,7 @@ class WithingsSleepDataUpdateCoordinator( class WithingsBedPresenceDataUpdateCoordinator(WithingsDataUpdateCoordinator[None]): """Withings bed presence coordinator.""" + coordinator_name: str = "bed presence" in_bed: bool | None = None _default_update_interval = None @@ -181,6 +190,7 @@ class WithingsBedPresenceDataUpdateCoordinator(WithingsDataUpdateCoordinator[Non class WithingsGoalsDataUpdateCoordinator(WithingsDataUpdateCoordinator[Goals]): """Withings goals coordinator.""" + coordinator_name: str = "goals" _default_update_interval = timedelta(hours=1) def webhook_subscription_listener(self, connected: bool) -> None: @@ -197,6 +207,7 @@ class WithingsActivityDataUpdateCoordinator( ): """Withings activity coordinator.""" + coordinator_name: str = "activity" _previous_data: Activity | None = None def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None: @@ -235,6 +246,7 @@ class WithingsWorkoutDataUpdateCoordinator( ): """Withings workout coordinator.""" + coordinator_name: str = "workout" _previous_data: Workout | None = None def __init__(self, hass: HomeAssistant, client: WithingsClient) -> None: From f12055875097db1de9bffd43cfcbe6effc136d70 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 10 Nov 2023 09:04:33 +0100 Subject: [PATCH 32/33] Update frontend to 20231030.2 (#103706) --- 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 6fffc0e8acd..469deab23e1 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/frontend", "integration_type": "system", "quality_scale": "internal", - "requirements": ["home-assistant-frontend==20231030.1"] + "requirements": ["home-assistant-frontend==20231030.2"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 12b1c6a4d0a..67050e43eeb 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -22,7 +22,7 @@ ha-av==10.1.1 hass-nabucasa==0.74.0 hassil==1.2.5 home-assistant-bluetooth==1.10.4 -home-assistant-frontend==20231030.1 +home-assistant-frontend==20231030.2 home-assistant-intents==2023.10.16 httpx==0.25.0 ifaddr==0.2.0 diff --git a/requirements_all.txt b/requirements_all.txt index f48915d5629..ab4afc4dfa9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1007,7 +1007,7 @@ hole==0.8.0 holidays==0.35 # homeassistant.components.frontend -home-assistant-frontend==20231030.1 +home-assistant-frontend==20231030.2 # homeassistant.components.conversation home-assistant-intents==2023.10.16 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ad95793bfee..798a6851b62 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -796,7 +796,7 @@ hole==0.8.0 holidays==0.35 # homeassistant.components.frontend -home-assistant-frontend==20231030.1 +home-assistant-frontend==20231030.2 # homeassistant.components.conversation home-assistant-intents==2023.10.16 From eaf711335d9675099586d68e862cec2aab7bfd72 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 10 Nov 2023 10:04:50 +0100 Subject: [PATCH 33/33] Bumped version to 2023.11.2 --- 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 99c1312dc98..479bfcbac6e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from typing import Final APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 11 -PATCH_VERSION: Final = "1" +PATCH_VERSION: Final = "2" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0) diff --git a/pyproject.toml b/pyproject.toml index 616dd219baf..55dd7a81a37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.11.1" +version = "2023.11.2" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"