Add error handling for all zwave_js service calls (#93846)
* Add error handling for all service calls * Switch siren to use internal function * Remove failing checks * Revert change to poll service, add comments, and add additional error handling * Add error handling for ping and refresh + review comment + add tests * Add test for statistics entity refresh
This commit is contained in:
parent
927b59fe5a
commit
bd8c88f51b
18 changed files with 191 additions and 69 deletions
|
@ -5,6 +5,7 @@ from zwave_js_server.const.command_class.thermostat import (
|
|||
THERMOSTAT_OPERATING_STATE_PROPERTY,
|
||||
)
|
||||
from zwave_js_server.event import Event
|
||||
from zwave_js_server.exceptions import FailedZWaveCommand
|
||||
from zwave_js_server.model.node import Node
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
|
@ -30,6 +31,7 @@ from homeassistant.components.climate import (
|
|||
HVACMode,
|
||||
)
|
||||
from homeassistant.components.zwave_js.climate import ATTR_FAN_STATE
|
||||
from homeassistant.components.zwave_js.const import DOMAIN, SERVICE_REFRESH_VALUE
|
||||
from homeassistant.components.zwave_js.helpers import ZwaveValueMatcher
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
|
@ -49,7 +51,11 @@ from .common import (
|
|||
|
||||
|
||||
async def test_thermostat_v2(
|
||||
hass: HomeAssistant, client, climate_radio_thermostat_ct100_plus, integration
|
||||
hass: HomeAssistant,
|
||||
client,
|
||||
climate_radio_thermostat_ct100_plus,
|
||||
integration,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test a thermostat v2 command class entity."""
|
||||
node = climate_radio_thermostat_ct100_plus
|
||||
|
@ -280,6 +286,20 @@ async def test_thermostat_v2(
|
|||
blocking=True,
|
||||
)
|
||||
|
||||
# Refresh value should log an error when there is an issue
|
||||
client.async_send_command.reset_mock()
|
||||
client.async_send_command.side_effect = FailedZWaveCommand("test", 1, "test")
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_REFRESH_VALUE,
|
||||
{
|
||||
ATTR_ENTITY_ID: CLIMATE_RADIO_THERMOSTAT_ENTITY,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert "Error while refreshing value" in caplog.text
|
||||
|
||||
|
||||
async def test_thermostat_different_endpoints(
|
||||
hass: HomeAssistant,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Test the Z-Wave JS lock platform."""
|
||||
import pytest
|
||||
from zwave_js_server.const import CommandClass
|
||||
from zwave_js_server.const.command_class.lock import (
|
||||
ATTR_CODE_SLOT,
|
||||
|
@ -6,6 +7,7 @@ from zwave_js_server.const.command_class.lock import (
|
|||
CURRENT_MODE_PROPERTY,
|
||||
)
|
||||
from zwave_js_server.event import Event
|
||||
from zwave_js_server.exceptions import FailedZWaveCommand
|
||||
from zwave_js_server.model.node import Node, NodeStatus
|
||||
|
||||
from homeassistant.components.lock import (
|
||||
|
@ -27,6 +29,7 @@ from homeassistant.const import (
|
|||
STATE_UNLOCKED,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
from .common import SCHLAGE_BE469_LOCK_ENTITY, replace_value_of_zwave_value
|
||||
|
||||
|
@ -153,6 +156,33 @@ async def test_door_lock(
|
|||
}
|
||||
assert args["value"] == 0
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
client.async_send_command.side_effect = FailedZWaveCommand("test", 1, "test")
|
||||
# Test set usercode service error handling
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
ZWAVE_JS_DOMAIN,
|
||||
SERVICE_SET_LOCK_USERCODE,
|
||||
{
|
||||
ATTR_ENTITY_ID: SCHLAGE_BE469_LOCK_ENTITY,
|
||||
ATTR_CODE_SLOT: 1,
|
||||
ATTR_USERCODE: "1234",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Test clear usercode service error handling
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
ZWAVE_JS_DOMAIN,
|
||||
SERVICE_CLEAR_LOCK_USERCODE,
|
||||
{ATTR_ENTITY_ID: SCHLAGE_BE469_LOCK_ENTITY, ATTR_CODE_SLOT: 1},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
|
||||
event = Event(
|
||||
type="dead",
|
||||
data={
|
||||
|
|
|
@ -4,6 +4,7 @@ import copy
|
|||
import pytest
|
||||
from zwave_js_server.const.command_class.meter import MeterType
|
||||
from zwave_js_server.event import Event
|
||||
from zwave_js_server.exceptions import FailedZWaveCommand
|
||||
from zwave_js_server.model.node import Node
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
|
@ -39,6 +40,7 @@ from homeassistant.const import (
|
|||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .common import (
|
||||
|
@ -420,6 +422,18 @@ async def test_reset_meter(
|
|||
|
||||
client.async_send_command_no_wait.reset_mock()
|
||||
|
||||
client.async_send_command_no_wait.side_effect = FailedZWaveCommand(
|
||||
"test", 1, "test"
|
||||
)
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_RESET_METER,
|
||||
{ATTR_ENTITY_ID: METER_ENERGY_SENSOR},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_meter_attributes(
|
||||
hass: HomeAssistant,
|
||||
|
@ -609,7 +623,7 @@ NODE_STATISTICS_SUFFIXES_UNKNOWN = {
|
|||
|
||||
|
||||
async def test_statistics_sensors(
|
||||
hass: HomeAssistant, zp3111, client, integration
|
||||
hass: HomeAssistant, zp3111, client, integration, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test statistics sensors."""
|
||||
ent_reg = er.async_get(hass)
|
||||
|
@ -730,10 +744,27 @@ async def test_statistics_sensors(
|
|||
(NODE_STATISTICS_ENTITY_PREFIX, NODE_STATISTICS_SUFFIXES_UNKNOWN),
|
||||
):
|
||||
for suffix_key, val in suffixes.items():
|
||||
state = hass.states.get(f"{prefix}{suffix_key}")
|
||||
entity_id = f"{prefix}{suffix_key}"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == str(val)
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_REFRESH_VALUE,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert caplog.text.count("There is no value to refresh for this entity") == len(
|
||||
[
|
||||
*CONTROLLER_STATISTICS_SUFFIXES,
|
||||
*CONTROLLER_STATISTICS_SUFFIXES_UNKNOWN,
|
||||
*NODE_STATISTICS_SUFFIXES,
|
||||
*NODE_STATISTICS_SUFFIXES_UNKNOWN,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
ENERGY_PRODUCTION_ENTITY_MAP = {
|
||||
"energy_production_power": {
|
||||
|
|
|
@ -1539,6 +1539,18 @@ async def test_ping(
|
|||
blocking=True,
|
||||
)
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
client.async_send_command.side_effect = FailedZWaveCommand("test", 1, "test")
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_PING,
|
||||
{
|
||||
ATTR_ENTITY_ID: CLIMATE_RADIO_THERMOSTAT_ENTITY,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
async def test_invoke_cc_api(
|
||||
hass: HomeAssistant,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue