mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Add missing exception translations to LCN (#147723)
This commit is contained in:
parent
cb8e076703
commit
f77e6cc8fc
@ -104,7 +104,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: LcnConfigEntry) -
|
|||||||
) as ex:
|
) as ex:
|
||||||
await lcn_connection.async_close()
|
await lcn_connection.async_close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"Unable to connect to {config_entry.title}: {ex}"
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="cannot_connect",
|
||||||
|
translation_placeholders={
|
||||||
|
"config_entry_title": config_entry.title,
|
||||||
|
},
|
||||||
) from ex
|
) from ex
|
||||||
|
|
||||||
_LOGGER.info('LCN connected to "%s"', config_entry.title)
|
_LOGGER.info('LCN connected to "%s"', config_entry.title)
|
||||||
|
@ -26,6 +26,7 @@ from homeassistant.const import (
|
|||||||
CONF_SWITCHES,
|
CONF_SWITCHES,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
@ -100,7 +101,11 @@ def get_resource(domain_name: str, domain_data: ConfigType) -> str:
|
|||||||
return cast(str, domain_data["setpoint"])
|
return cast(str, domain_data["setpoint"])
|
||||||
if domain_name == "scene":
|
if domain_name == "scene":
|
||||||
return f"{domain_data['register']}{domain_data['scene']}"
|
return f"{domain_data['register']}{domain_data['scene']}"
|
||||||
raise ValueError("Unknown domain")
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="invalid_domain",
|
||||||
|
translation_placeholders={CONF_DOMAIN: domain_name},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def generate_unique_id(
|
def generate_unique_id(
|
||||||
@ -304,6 +309,8 @@ def get_device_config(
|
|||||||
def is_states_string(states_string: str) -> list[str]:
|
def is_states_string(states_string: str) -> list[str]:
|
||||||
"""Validate the given states string and return states list."""
|
"""Validate the given states string and return states list."""
|
||||||
if len(states_string) != 8:
|
if len(states_string) != 8:
|
||||||
raise ValueError("Invalid length of states string")
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN, translation_key="invalid_length_of_states_string"
|
||||||
|
)
|
||||||
states = {"1": "ON", "0": "OFF", "T": "TOGGLE", "-": "NOCHANGE"}
|
states = {"1": "ON", "0": "OFF", "T": "TOGGLE", "-": "NOCHANGE"}
|
||||||
return [states[state_string] for state_string in states_string]
|
return [states[state_string] for state_string in states_string]
|
||||||
|
@ -19,7 +19,7 @@ rules:
|
|||||||
test-before-setup: done
|
test-before-setup: done
|
||||||
unique-config-entry: done
|
unique-config-entry: done
|
||||||
# Silver
|
# Silver
|
||||||
action-exceptions: todo
|
action-exceptions: done
|
||||||
config-entry-unloading: done
|
config-entry-unloading: done
|
||||||
docs-configuration-parameters:
|
docs-configuration-parameters:
|
||||||
status: exempt
|
status: exempt
|
||||||
|
@ -330,8 +330,9 @@ class SendKeys(LcnServiceCall):
|
|||||||
if (delay_time := service.data[CONF_TIME]) != 0:
|
if (delay_time := service.data[CONF_TIME]) != 0:
|
||||||
hit = pypck.lcn_defs.SendKeyCommand.HIT
|
hit = pypck.lcn_defs.SendKeyCommand.HIT
|
||||||
if pypck.lcn_defs.SendKeyCommand[service.data[CONF_STATE]] != hit:
|
if pypck.lcn_defs.SendKeyCommand[service.data[CONF_STATE]] != hit:
|
||||||
raise ValueError(
|
raise ServiceValidationError(
|
||||||
"Only hit command is allowed when sending deferred keys."
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="invalid_send_keys_action",
|
||||||
)
|
)
|
||||||
delay_unit = pypck.lcn_defs.TimeUnit.parse(service.data[CONF_TIME_UNIT])
|
delay_unit = pypck.lcn_defs.TimeUnit.parse(service.data[CONF_TIME_UNIT])
|
||||||
await device_connection.send_keys_hit_deferred(keys, delay_time, delay_unit)
|
await device_connection.send_keys_hit_deferred(keys, delay_time, delay_unit)
|
||||||
@ -368,8 +369,9 @@ class LockKeys(LcnServiceCall):
|
|||||||
|
|
||||||
if (delay_time := service.data[CONF_TIME]) != 0:
|
if (delay_time := service.data[CONF_TIME]) != 0:
|
||||||
if table_id != 0:
|
if table_id != 0:
|
||||||
raise ValueError(
|
raise ServiceValidationError(
|
||||||
"Only table A is allowed when locking keys for a specific time."
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="invalid_lock_keys_table",
|
||||||
)
|
)
|
||||||
delay_unit = pypck.lcn_defs.TimeUnit.parse(service.data[CONF_TIME_UNIT])
|
delay_unit = pypck.lcn_defs.TimeUnit.parse(service.data[CONF_TIME_UNIT])
|
||||||
await device_connection.lock_keys_tab_a_temporary(
|
await device_connection.lock_keys_tab_a_temporary(
|
||||||
|
@ -414,11 +414,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exceptions": {
|
"exceptions": {
|
||||||
"invalid_address": {
|
"cannot_connect": {
|
||||||
"message": "LCN device for given address has not been configured."
|
"message": "Unable to connect to {config_entry_title}."
|
||||||
},
|
},
|
||||||
"invalid_device_id": {
|
"invalid_device_id": {
|
||||||
"message": "LCN device for given device ID has not been configured."
|
"message": "LCN device for given device ID {device_id} has not been configured."
|
||||||
|
},
|
||||||
|
"invalid_domain": {
|
||||||
|
"message": "Invalid domain {domain}."
|
||||||
|
},
|
||||||
|
"invalid_send_keys_action": {
|
||||||
|
"message": "Invalid state for sending keys. Only 'hit' allowed for deferred sending."
|
||||||
|
},
|
||||||
|
"invalid_lock_keys_table": {
|
||||||
|
"message": "Invalid table for locking keys. Only table A allowed when locking for a specific time."
|
||||||
|
},
|
||||||
|
"invalid_length_of_states_string": {
|
||||||
|
"message": "Invalid length of states string. Expected 8 characters."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ from homeassistant.const import (
|
|||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
@ -134,6 +135,23 @@ async def test_service_relays(
|
|||||||
|
|
||||||
control_relays.assert_awaited_with(relay_states)
|
control_relays.assert_awaited_with(relay_states)
|
||||||
|
|
||||||
|
# wrong states string
|
||||||
|
with (
|
||||||
|
patch.object(MockModuleConnection, "control_relays") as control_relays,
|
||||||
|
pytest.raises(HomeAssistantError) as exc_info,
|
||||||
|
):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
LcnService.RELAYS,
|
||||||
|
{
|
||||||
|
CONF_DEVICE_ID: get_device(hass, entry, (0, 7, False)).id,
|
||||||
|
CONF_STATE: "0011TT--00",
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert exc_info.value.translation_domain == DOMAIN
|
||||||
|
assert exc_info.value.translation_key == "invalid_length_of_states_string"
|
||||||
|
|
||||||
|
|
||||||
async def test_service_led(
|
async def test_service_led(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -328,7 +346,7 @@ async def test_service_send_keys_hit_deferred(
|
|||||||
patch.object(
|
patch.object(
|
||||||
MockModuleConnection, "send_keys_hit_deferred"
|
MockModuleConnection, "send_keys_hit_deferred"
|
||||||
) as send_keys_hit_deferred,
|
) as send_keys_hit_deferred,
|
||||||
pytest.raises(ValueError),
|
pytest.raises(ServiceValidationError) as exc_info,
|
||||||
):
|
):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -342,6 +360,8 @@ async def test_service_send_keys_hit_deferred(
|
|||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
assert exc_info.value.translation_domain == DOMAIN
|
||||||
|
assert exc_info.value.translation_key == "invalid_send_keys_action"
|
||||||
|
|
||||||
|
|
||||||
async def test_service_lock_keys(
|
async def test_service_lock_keys(
|
||||||
@ -369,6 +389,24 @@ async def test_service_lock_keys(
|
|||||||
|
|
||||||
lock_keys.assert_awaited_with(0, lock_states)
|
lock_keys.assert_awaited_with(0, lock_states)
|
||||||
|
|
||||||
|
# wrong states string
|
||||||
|
with (
|
||||||
|
patch.object(MockModuleConnection, "lock_keys") as lock_keys,
|
||||||
|
pytest.raises(HomeAssistantError) as exc_info,
|
||||||
|
):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
LcnService.LOCK_KEYS,
|
||||||
|
{
|
||||||
|
CONF_DEVICE_ID: get_device(hass, entry, (0, 7, False)).id,
|
||||||
|
CONF_TABLE: "a",
|
||||||
|
CONF_STATE: "0011TT--00",
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert exc_info.value.translation_domain == DOMAIN
|
||||||
|
assert exc_info.value.translation_key == "invalid_length_of_states_string"
|
||||||
|
|
||||||
|
|
||||||
async def test_service_lock_keys_tab_a_temporary(
|
async def test_service_lock_keys_tab_a_temporary(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -406,7 +444,7 @@ async def test_service_lock_keys_tab_a_temporary(
|
|||||||
patch.object(
|
patch.object(
|
||||||
MockModuleConnection, "lock_keys_tab_a_temporary"
|
MockModuleConnection, "lock_keys_tab_a_temporary"
|
||||||
) as lock_keys_tab_a_temporary,
|
) as lock_keys_tab_a_temporary,
|
||||||
pytest.raises(ValueError),
|
pytest.raises(ServiceValidationError) as exc_info,
|
||||||
):
|
):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -420,6 +458,8 @@ async def test_service_lock_keys_tab_a_temporary(
|
|||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
assert exc_info.value.translation_domain == DOMAIN
|
||||||
|
assert exc_info.value.translation_key == "invalid_lock_keys_table"
|
||||||
|
|
||||||
|
|
||||||
async def test_service_dyn_text(
|
async def test_service_dyn_text(
|
||||||
|
@ -192,6 +192,16 @@ async def test_lcn_entities_add_command(
|
|||||||
|
|
||||||
assert entity_config in entry.data[CONF_ENTITIES]
|
assert entity_config in entry.data[CONF_ENTITIES]
|
||||||
|
|
||||||
|
# invalid domain
|
||||||
|
await client.send_json_auto_id(
|
||||||
|
{**ENTITIES_ADD_PAYLOAD, "entry_id": entry.entry_id, CONF_DOMAIN: "invalid"}
|
||||||
|
)
|
||||||
|
|
||||||
|
res = await client.receive_json()
|
||||||
|
assert not res["success"]
|
||||||
|
assert res["error"]["code"] == "home_assistant_error"
|
||||||
|
assert res["error"]["translation_key"] == "invalid_domain"
|
||||||
|
|
||||||
|
|
||||||
async def test_lcn_entities_delete_command(
|
async def test_lcn_entities_delete_command(
|
||||||
hass: HomeAssistant, hass_ws_client: WebSocketGenerator, entry: MockConfigEntry
|
hass: HomeAssistant, hass_ws_client: WebSocketGenerator, entry: MockConfigEntry
|
||||||
|
Loading…
x
Reference in New Issue
Block a user