diff --git a/homeassistant/components/roborock/__init__.py b/homeassistant/components/roborock/__init__.py index 141770e733d..b72fec5a8e1 100644 --- a/homeassistant/components/roborock/__init__.py +++ b/homeassistant/components/roborock/__init__.py @@ -9,8 +9,8 @@ import logging from typing import Any from roborock import HomeDataRoom, RoborockException, RoborockInvalidCredentials -from roborock.cloud_api import RoborockMqttClient from roborock.containers import DeviceData, HomeDataDevice, HomeDataProduct, UserData +from roborock.version_1_apis.roborock_mqtt_client_v1 import RoborockMqttClientV1 from roborock.web_api import RoborockApiClient from homeassistant.config_entries import ConfigEntry @@ -75,7 +75,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: translation_key="no_coordinators", ) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { - coordinator.roborock_device_info.device.duid: coordinator + coordinator.api.device_info.device.duid: coordinator for coordinator in valid_coordinators } await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) @@ -107,7 +107,7 @@ async def setup_device( home_data_rooms: list[HomeDataRoom], ) -> RoborockDataUpdateCoordinator | None: """Set up a device Coordinator.""" - mqtt_client = RoborockMqttClient(user_data, DeviceData(device, product_info.name)) + mqtt_client = RoborockMqttClientV1(user_data, DeviceData(device, product_info.name)) try: networking = await mqtt_client.get_networking() if networking is None: @@ -138,7 +138,7 @@ async def setup_device( await coordinator.async_config_entry_first_refresh() except ConfigEntryNotReady as ex: await coordinator.release() - if isinstance(coordinator.api, RoborockMqttClient): + if isinstance(coordinator.api, RoborockMqttClientV1): _LOGGER.warning( "Not setting up %s because the we failed to get data for the first time using the online client. " "Please ensure your Home Assistant instance can communicate with this device. " diff --git a/homeassistant/components/roborock/coordinator.py b/homeassistant/components/roborock/coordinator.py index c5fd0c09c46..293415360bd 100644 --- a/homeassistant/components/roborock/coordinator.py +++ b/homeassistant/components/roborock/coordinator.py @@ -7,11 +7,11 @@ from datetime import timedelta import logging from roborock import HomeDataRoom -from roborock.cloud_api import RoborockMqttClient from roborock.containers import DeviceData, HomeDataDevice, HomeDataProduct, NetworkInfo from roborock.exceptions import RoborockException -from roborock.local_api import RoborockLocalClient from roborock.roborock_typing import DeviceProp +from roborock.version_1_apis.roborock_local_client_v1 import RoborockLocalClientV1 +from roborock.version_1_apis.roborock_mqtt_client_v1 import RoborockMqttClientV1 from homeassistant.const import ATTR_CONNECTIONS from homeassistant.core import HomeAssistant @@ -36,7 +36,7 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]): device: HomeDataDevice, device_networking: NetworkInfo, product_info: HomeDataProduct, - cloud_api: RoborockMqttClient, + cloud_api: RoborockMqttClientV1, home_data_rooms: list[HomeDataRoom], ) -> None: """Initialize.""" @@ -48,7 +48,7 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]): DeviceProp(), ) device_data = DeviceData(device, product_info.model, device_networking.ip) - self.api: RoborockLocalClient | RoborockMqttClient = RoborockLocalClient( + self.api: RoborockLocalClientV1 | RoborockMqttClientV1 = RoborockLocalClientV1( device_data ) self.cloud_api = cloud_api @@ -69,7 +69,7 @@ class RoborockDataUpdateCoordinator(DataUpdateCoordinator[DeviceProp]): async def verify_api(self) -> None: """Verify that the api is reachable. If it is not, switch clients.""" - if isinstance(self.api, RoborockLocalClient): + if isinstance(self.api, RoborockLocalClientV1): try: await self.api.ping() except RoborockException: diff --git a/homeassistant/components/roborock/device.py b/homeassistant/components/roborock/device.py index 7affaa396e6..69384d6e23a 100644 --- a/homeassistant/components/roborock/device.py +++ b/homeassistant/components/roborock/device.py @@ -2,21 +2,21 @@ from typing import Any -from roborock.api import AttributeCache, RoborockClient -from roborock.cloud_api import RoborockMqttClient from roborock.command_cache import CacheableAttribute from roborock.containers import Consumable, Status from roborock.exceptions import RoborockException from roborock.roborock_message import RoborockDataProtocol from roborock.roborock_typing import RoborockCommand +from roborock.version_1_apis.roborock_client_v1 import AttributeCache, RoborockClientV1 +from roborock.version_1_apis.roborock_mqtt_client_v1 import RoborockMqttClientV1 from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity import Entity from homeassistant.helpers.update_coordinator import CoordinatorEntity -from . import RoborockDataUpdateCoordinator from .const import DOMAIN +from .coordinator import RoborockDataUpdateCoordinator class RoborockEntity(Entity): @@ -28,7 +28,7 @@ class RoborockEntity(Entity): self, unique_id: str, device_info: DeviceInfo, - api: RoborockClient, + api: RoborockClientV1, ) -> None: """Initialize the coordinated Roborock Device.""" self._attr_unique_id = unique_id @@ -36,7 +36,7 @@ class RoborockEntity(Entity): self._api = api @property - def api(self) -> RoborockClient: + def api(self) -> RoborockClientV1: """Returns the api.""" return self._api @@ -116,7 +116,7 @@ class RoborockCoordinatedEntity( return data.status @property - def cloud_api(self) -> RoborockMqttClient: + def cloud_api(self) -> RoborockMqttClientV1: """Return the cloud api.""" return self.coordinator.cloud_api diff --git a/homeassistant/components/roborock/manifest.json b/homeassistant/components/roborock/manifest.json index a7a7fe01d23..711da78de31 100644 --- a/homeassistant/components/roborock/manifest.json +++ b/homeassistant/components/roborock/manifest.json @@ -7,7 +7,7 @@ "iot_class": "local_polling", "loggers": ["roborock"], "requirements": [ - "python-roborock==0.40.0", + "python-roborock==1.0.0", "vacuum-map-parser-roborock==0.1.1" ] } diff --git a/homeassistant/components/roborock/number.py b/homeassistant/components/roborock/number.py index 09030ef8500..0a7abf5a090 100644 --- a/homeassistant/components/roborock/number.py +++ b/homeassistant/components/roborock/number.py @@ -6,9 +6,9 @@ from dataclasses import dataclass import logging from typing import Any -from roborock.api import AttributeCache from roborock.command_cache import CacheableAttribute from roborock.exceptions import RoborockException +from roborock.version_1_apis.roborock_client_v1 import AttributeCache from homeassistant.components.number import NumberEntity, NumberEntityDescription from homeassistant.config_entries import ConfigEntry diff --git a/homeassistant/components/roborock/switch.py b/homeassistant/components/roborock/switch.py index 9c7ca3cdcae..090c3219fd3 100644 --- a/homeassistant/components/roborock/switch.py +++ b/homeassistant/components/roborock/switch.py @@ -8,8 +8,8 @@ from dataclasses import dataclass import logging from typing import Any -from roborock.api import AttributeCache from roborock.command_cache import CacheableAttribute +from roborock.version_1_apis.roborock_client_v1 import AttributeCache from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.config_entries import ConfigEntry diff --git a/homeassistant/components/roborock/time.py b/homeassistant/components/roborock/time.py index 9a3cac86425..c90fc7fa438 100644 --- a/homeassistant/components/roborock/time.py +++ b/homeassistant/components/roborock/time.py @@ -8,9 +8,9 @@ from datetime import time import logging from typing import Any -from roborock.api import AttributeCache from roborock.command_cache import CacheableAttribute from roborock.exceptions import RoborockException +from roborock.version_1_apis.roborock_client_v1 import AttributeCache from homeassistant.components.time import TimeEntity, TimeEntityDescription from homeassistant.config_entries import ConfigEntry diff --git a/requirements_all.txt b/requirements_all.txt index 9143631cffc..2bcc0be7f31 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2294,7 +2294,7 @@ python-rabbitair==0.0.8 python-ripple-api==0.0.3 # homeassistant.components.roborock -python-roborock==0.40.0 +python-roborock==1.0.0 # homeassistant.components.smarttub python-smarttub==0.0.36 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 002bc5132c6..80bce7f87f7 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1773,7 +1773,7 @@ python-qbittorrent==0.4.3 python-rabbitair==0.0.8 # homeassistant.components.roborock -python-roborock==0.40.0 +python-roborock==1.0.0 # homeassistant.components.smarttub python-smarttub==0.0.36 diff --git a/tests/components/roborock/conftest.py b/tests/components/roborock/conftest.py index 2910fa38995..0f3689da161 100644 --- a/tests/components/roborock/conftest.py +++ b/tests/components/roborock/conftest.py @@ -32,26 +32,26 @@ from tests.common import MockConfigEntry def bypass_api_fixture() -> None: """Skip calls to the API.""" with ( - patch("homeassistant.components.roborock.RoborockMqttClient.async_connect"), - patch("homeassistant.components.roborock.RoborockMqttClient._send_command"), + patch("homeassistant.components.roborock.RoborockMqttClientV1.async_connect"), + patch("homeassistant.components.roborock.RoborockMqttClientV1._send_command"), patch( "homeassistant.components.roborock.RoborockApiClient.get_home_data", return_value=HOME_DATA, ), patch( - "homeassistant.components.roborock.RoborockMqttClient.get_networking", + "homeassistant.components.roborock.RoborockMqttClientV1.get_networking", return_value=NETWORK_INFO, ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", return_value=PROP, ), patch( - "homeassistant.components.roborock.coordinator.RoborockMqttClient.get_multi_maps_list", + "homeassistant.components.roborock.coordinator.RoborockMqttClientV1.get_multi_maps_list", return_value=MULTI_MAP_LIST, ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_multi_maps_list", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_multi_maps_list", return_value=MULTI_MAP_LIST, ), patch( @@ -59,24 +59,24 @@ def bypass_api_fixture() -> None: return_value=MAP_DATA, ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_message" ), - patch("homeassistant.components.roborock.RoborockMqttClient._wait_response"), + patch("homeassistant.components.roborock.RoborockMqttClientV1._wait_response"), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient._wait_response" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1._wait_response" ), patch( - "roborock.api.AttributeCache.async_value", + "roborock.version_1_apis.AttributeCache.async_value", ), patch( - "roborock.api.AttributeCache.value", + "roborock.version_1_apis.AttributeCache.value", ), patch( "homeassistant.components.roborock.image.MAP_SLEEP", 0, ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_room_mapping", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_room_mapping", return_value=[ RoomMapping(16, "2362048"), RoomMapping(17, "2362044"), @@ -84,7 +84,7 @@ def bypass_api_fixture() -> None: ], ), patch( - "homeassistant.components.roborock.coordinator.RoborockMqttClient.get_room_mapping", + "homeassistant.components.roborock.coordinator.RoborockMqttClientV1.get_room_mapping", return_value=[ RoomMapping(16, "2362048"), RoomMapping(17, "2362044"), diff --git a/tests/components/roborock/test_button.py b/tests/components/roborock/test_button.py index 5654dac9218..88cf5beab15 100644 --- a/tests/components/roborock/test_button.py +++ b/tests/components/roborock/test_button.py @@ -31,7 +31,7 @@ async def test_update_success( # Ensure that the entity exist, as these test can pass even if there is no entity. assert hass.states.get(entity_id).state == "unknown" with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_message" ) as mock_send_message: await hass.services.async_call( "button", diff --git a/tests/components/roborock/test_image.py b/tests/components/roborock/test_image.py index 77829e5aaa6..445f90f4a05 100644 --- a/tests/components/roborock/test_image.py +++ b/tests/components/roborock/test_image.py @@ -37,7 +37,7 @@ async def test_floorplan_image( prop.status.in_cleaning = 1 with ( patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", return_value=prop, ), patch( @@ -72,7 +72,7 @@ async def test_floorplan_image_failed_parse( return_value=map_data, ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", return_value=prop, ), patch( diff --git a/tests/components/roborock/test_init.py b/tests/components/roborock/test_init.py index 08a3afe6c5e..de858ef7cb2 100644 --- a/tests/components/roborock/test_init.py +++ b/tests/components/roborock/test_init.py @@ -19,7 +19,7 @@ async def test_unload_entry( assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert setup_entry.state is ConfigEntryState.LOADED with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.async_release" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.async_release" ) as mock_disconnect: assert await hass.config_entries.async_unload(setup_entry.entry_id) await hass.async_block_till_done() @@ -37,7 +37,7 @@ async def test_config_entry_not_ready( "homeassistant.components.roborock.RoborockApiClient.get_home_data", ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", side_effect=RoborockException(), ), ): @@ -55,7 +55,7 @@ async def test_config_entry_not_ready_home_data( side_effect=RoborockException(), ), patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", side_effect=RoborockException(), ), ): @@ -68,7 +68,7 @@ async def test_get_networking_fails( ) -> None: """Test that when networking fails, we attempt to retry.""" with patch( - "homeassistant.components.roborock.RoborockMqttClient.get_networking", + "homeassistant.components.roborock.RoborockMqttClientV1.get_networking", side_effect=RoborockException(), ): await async_setup_component(hass, DOMAIN, {}) @@ -80,7 +80,7 @@ async def test_get_networking_fails_none( ) -> None: """Test that when networking returns None, we attempt to retry.""" with patch( - "homeassistant.components.roborock.RoborockMqttClient.get_networking", + "homeassistant.components.roborock.RoborockMqttClientV1.get_networking", return_value=None, ): await async_setup_component(hass, DOMAIN, {}) @@ -93,11 +93,11 @@ async def test_cloud_client_fails_props( """Test that if networking succeeds, but we can't communicate with the vacuum, we can't get props, fail.""" with ( patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.ping", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.ping", side_effect=RoborockException(), ), patch( - "homeassistant.components.roborock.coordinator.RoborockMqttClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockMqttClientV1.get_prop", side_effect=RoborockException(), ), ): @@ -110,7 +110,7 @@ async def test_local_client_fails_props( ) -> None: """Test that if networking succeeds, but we can't communicate locally with the vacuum, we can't get props, fail.""" with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", side_effect=RoborockException(), ): await async_setup_component(hass, DOMAIN, {}) @@ -122,7 +122,7 @@ async def test_fails_maps_continue( ) -> None: """Test that if we fail to get the maps, we still setup.""" with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_multi_maps_list", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_multi_maps_list", side_effect=RoborockException(), ): await async_setup_component(hass, DOMAIN, {}) diff --git a/tests/components/roborock/test_number.py b/tests/components/roborock/test_number.py index 1c20a93cace..3291dd2a7dc 100644 --- a/tests/components/roborock/test_number.py +++ b/tests/components/roborock/test_number.py @@ -27,7 +27,7 @@ async def test_update_success( # Ensure that the entity exist, as these test can pass even if there is no entity. assert hass.states.get(entity_id) is not None with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_message" ) as mock_send_message: await hass.services.async_call( "number", diff --git a/tests/components/roborock/test_select.py b/tests/components/roborock/test_select.py index 9310d4e2e9a..c8626818749 100644 --- a/tests/components/roborock/test_select.py +++ b/tests/components/roborock/test_select.py @@ -30,7 +30,7 @@ async def test_update_success( # Ensure that the entity exist, as these test can pass even if there is no entity. assert hass.states.get(entity_id) is not None with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_message" ) as mock_send_message: await hass.services.async_call( "select", @@ -50,7 +50,7 @@ async def test_update_failure( """Test that changing a value will raise a homeassistanterror when it fails.""" with ( patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_message", side_effect=RoborockException(), ), pytest.raises(HomeAssistantError), diff --git a/tests/components/roborock/test_sensor.py b/tests/components/roborock/test_sensor.py index a5f4164eee1..23d16f643b2 100644 --- a/tests/components/roborock/test_sensor.py +++ b/tests/components/roborock/test_sensor.py @@ -3,7 +3,6 @@ from unittest.mock import patch from roborock import DeviceData, HomeDataDevice -from roborock.cloud_api import RoborockMqttClient from roborock.const import ( FILTER_REPLACE_TIME, MAIN_BRUSH_REPLACE_TIME, @@ -11,6 +10,7 @@ from roborock.const import ( SIDE_BRUSH_REPLACE_TIME, ) from roborock.roborock_message import RoborockMessage, RoborockMessageProtocol +from roborock.version_1_apis import RoborockMqttClientV1 from homeassistant.core import HomeAssistant @@ -62,11 +62,11 @@ async def test_listener_update( """Test that when we receive a mqtt topic, we successfully update the entity.""" assert hass.states.get("sensor.roborock_s7_maxv_status").state == "charging" # Listeners are global based on uuid - so this is okay - client = RoborockMqttClient( + client = RoborockMqttClientV1( USER_DATA, DeviceData(device=HomeDataDevice("abc123", "", "", "", ""), model="") ) # Test Status - with patch("roborock.api.AttributeCache.value", STATUS.as_dict()): + with patch("roborock.version_1_apis.AttributeCache.value", STATUS.as_dict()): # Symbolizes a mqtt message coming in client.on_message_received( [ @@ -80,7 +80,7 @@ async def test_listener_update( assert hass.states.get("sensor.roborock_s7_maxv_filter_time_left").state == str( FILTER_REPLACE_TIME - 74382 ) - with patch("roborock.api.AttributeCache.value", CONSUMABLE.as_dict()): + with patch("roborock.version_1_apis.AttributeCache.value", CONSUMABLE.as_dict()): client.on_message_received( [ RoborockMessage( diff --git a/tests/components/roborock/test_switch.py b/tests/components/roborock/test_switch.py index 42a5e92f32a..3afa72b319d 100644 --- a/tests/components/roborock/test_switch.py +++ b/tests/components/roborock/test_switch.py @@ -28,7 +28,7 @@ async def test_update_success( # Ensure that the entity exist, as these test can pass even if there is no entity. assert hass.states.get(entity_id) is not None with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient._send_command" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1._send_command" ) as mock_send_message: await hass.services.async_call( "switch", @@ -39,7 +39,7 @@ async def test_update_success( ) assert mock_send_message.assert_called_once with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_message" ) as mock_send_message: await hass.services.async_call( "switch", diff --git a/tests/components/roborock/test_time.py b/tests/components/roborock/test_time.py index 378c642b2f4..ca6507f887b 100644 --- a/tests/components/roborock/test_time.py +++ b/tests/components/roborock/test_time.py @@ -28,7 +28,7 @@ async def test_update_success( # Ensure that the entity exist, as these test can pass even if there is no entity. assert hass.states.get(entity_id) is not None with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient._send_command" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1._send_command" ) as mock_send_message: await hass.services.async_call( "time", diff --git a/tests/components/roborock/test_vacuum.py b/tests/components/roborock/test_vacuum.py index cc01acc29fd..437c9847e21 100644 --- a/tests/components/roborock/test_vacuum.py +++ b/tests/components/roborock/test_vacuum.py @@ -82,7 +82,7 @@ async def test_commands( data = {ATTR_ENTITY_ID: ENTITY_ID, **(service_params or {})} with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_command" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_command" ) as mock_send_command: await hass.services.async_call( Platform.VACUUM, @@ -115,7 +115,7 @@ async def test_resume_cleaning( prop = copy.deepcopy(PROP) prop.status.in_cleaning = in_cleaning_int with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.get_prop", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.get_prop", return_value=prop, ): await async_setup_component(hass, DOMAIN, {}) @@ -124,7 +124,7 @@ async def test_resume_cleaning( data = {ATTR_ENTITY_ID: ENTITY_ID} with patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_command" + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_command" ) as mock_send_command: await hass.services.async_call( Platform.VACUUM, @@ -145,7 +145,7 @@ async def test_failed_user_command( data = {ATTR_ENTITY_ID: ENTITY_ID, "command": "fake_command"} with ( patch( - "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_command", + "homeassistant.components.roborock.coordinator.RoborockLocalClientV1.send_command", side_effect=RoborockException(), ), pytest.raises(HomeAssistantError, match="Error while calling fake_command"),