Add Translation for Roborock exceptions (#105427)

* add translations to exceptions

* Make errors more user understandable

* make command not ternary operator

* removed non-user facing exceptions

* Add user facing exceptions and code coverage

* add match

* fix linting

* Apply suggestions from code review

Co-authored-by: Franck Nijhof <frenck@frenck.nl>

---------

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
Luke Lashley 2024-01-16 15:00:20 -05:00 committed by GitHub
parent 639f06843b
commit fa5af8f187
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 69 additions and 6 deletions

View File

@ -35,9 +35,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
try:
home_data = await api_client.get_home_data(user_data)
except RoborockInvalidCredentials as err:
raise ConfigEntryAuthFailed("Invalid credentials.") from err
raise ConfigEntryAuthFailed(
"Invalid credentials",
translation_domain=DOMAIN,
translation_key="invalid_credentials",
) from err
except RoborockException as err:
raise ConfigEntryNotReady("Failed getting Roborock home_data.") from err
raise ConfigEntryNotReady(
"Failed to get Roborock home data",
translation_domain=DOMAIN,
translation_key="home_data_fail",
) from err
_LOGGER.debug("Got home data %s", home_data)
device_map: dict[str, HomeDataDevice] = {
device.duid: device for device in home_data.devices + home_data.received_devices
@ -57,7 +65,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if isinstance(coord, RoborockDataUpdateCoordinator)
]
if len(valid_coordinators) == 0:
raise ConfigEntryNotReady("No coordinators were able to successfully setup.")
raise ConfigEntryNotReady(
"No devices were able to successfully setup",
translation_domain=DOMAIN,
translation_key="no_coordinators",
)
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
coordinator.roborock_device_info.device.duid: coordinator
for coordinator in valid_coordinators

View File

@ -15,6 +15,7 @@ from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import RoborockDataUpdateCoordinator
from .const import DOMAIN
class RoborockEntity(Entity):
@ -48,10 +49,18 @@ class RoborockEntity(Entity):
try:
response: dict = await self._api.send_command(command, params)
except RoborockException as err:
if isinstance(command, RoborockCommand):
command_name = command.name
else:
command_name = command
raise HomeAssistantError(
f"Error while calling {command.name if isinstance(command, RoborockCommand) else command} with {params}"
f"Error while calling {command}",
translation_domain=DOMAIN,
translation_key="command_failed",
translation_placeholders={
"command": command_name,
},
) from err
return response

View File

@ -109,7 +109,11 @@ class RoborockMap(RoborockCoordinatedEntity, ImageEntity):
"""Create an image using the map parser."""
parsed_map = self.parser.parse(map_bytes)
if parsed_map.image is None:
raise HomeAssistantError("Something went wrong creating the map.")
raise HomeAssistantError(
"Something went wrong creating the map",
translation_domain=DOMAIN,
translation_key="map_failure",
)
img_byte_arr = io.BytesIO()
parsed_map.image.data.save(img_byte_arr, format="PNG")
return img_byte_arr.getvalue()

View File

@ -276,5 +276,22 @@
}
}
}
},
"exceptions": {
"command_failed": {
"message": "Error while calling {command}"
},
"home_data_fail": {
"message": "Failed to get Roborock home data"
},
"invalid_credentials": {
"message": "Invalid credentials."
},
"map_failure": {
"message": "Something went wrong creating the map"
},
"no_coordinators": {
"message": "No devices were able to successfully setup"
}
}
}

View File

@ -5,6 +5,7 @@ from typing import Any
from unittest.mock import patch
import pytest
from roborock import RoborockException
from roborock.roborock_typing import RoborockCommand
from homeassistant.components.vacuum import (
@ -19,6 +20,7 @@ from homeassistant.components.vacuum import (
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry
@ -86,3 +88,22 @@ async def test_commands(
assert mock_send_command.call_count == 1
assert mock_send_command.call_args[0][0] == command
assert mock_send_command.call_args[0][1] == called_params
async def test_failed_user_command(
hass: HomeAssistant,
bypass_api_fixture,
setup_entry: MockConfigEntry,
) -> None:
"""Test that when a user sends an invalid command, we raise HomeAssistantError."""
data = {ATTR_ENTITY_ID: ENTITY_ID, **{"command": "fake_command"}}
with patch(
"homeassistant.components.roborock.coordinator.RoborockLocalClient.send_command",
side_effect=RoborockException(),
), pytest.raises(HomeAssistantError, match="Error while calling fake_command"):
await hass.services.async_call(
Platform.VACUUM,
SERVICE_SEND_COMMAND,
data,
blocking=True,
)