Raise ServiceValidationError for missing code in arming actions for Satel Integra (#180996)

This commit is contained in:
Tom Matheussen
2026-09-01 20:24:03 +02:00
committed by GitHub
parent 7bddee43e8
commit 1c79a02b47
3 changed files with 39 additions and 12 deletions
@@ -1,7 +1,6 @@
"""Support for Satel Integra alarm, using ETHM module."""
import asyncio
import logging
from typing import override
from satel_integra import AlarmState
@@ -14,9 +13,15 @@ from homeassistant.components.alarm_control_panel import (
)
from homeassistant.config_entries import ConfigSubentry
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import CONF_ARM_HOME_MODE, CONF_PARTITION_NUMBER, SUBENTRY_TYPE_PARTITION
from .const import (
CONF_ARM_HOME_MODE,
CONF_PARTITION_NUMBER,
DOMAIN,
SUBENTRY_TYPE_PARTITION,
)
from .coordinator import SatelConfigEntry, SatelIntegraPartitionsCoordinator
from .entity import SatelIntegraEntity
@@ -32,8 +37,6 @@ ALARM_STATE_MAP = {
AlarmState.EXIT_COUNTDOWN_UNDER_10: AlarmControlPanelState.ARMING,
}
_LOGGER = logging.getLogger(__name__)
PARALLEL_UPDATES = 0
@@ -118,8 +121,10 @@ class SatelIntegraAlarmPanel(
async def async_alarm_disarm(self, code: str | None = None) -> None:
"""Send disarm command."""
if not code:
_LOGGER.debug("Code was empty or None")
return
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="missing_alarm_access_code",
)
clear_alarm_necessary = (
self._attr_alarm_state == AlarmControlPanelState.TRIGGERED
@@ -135,13 +140,9 @@ class SatelIntegraAlarmPanel(
@override
async def async_alarm_arm_away(self, code: str | None = None) -> None:
"""Send arm away command."""
if code:
await self._controller.arm(code, [self._device_number])
await self._controller.arm(code, [self._device_number])
@override
async def async_alarm_arm_home(self, code: str | None = None) -> None:
"""Send arm home command."""
if code:
await self._controller.arm(code, [self._device_number], self._arm_home_mode)
await self._controller.arm(code, [self._device_number], self._arm_home_mode)
@@ -203,6 +203,9 @@
"connection_initialization_failed": {
"message": "[%key:component::satel_integra::config::error::connection_initialization_failed%]"
},
"missing_alarm_access_code": {
"message": "Cannot disarm the alarm panel because no user code was provided."
},
"missing_output_access_code": {
"message": "Cannot control switchable outputs because no user code is configured for this Satel Integra entry. Configure a code in the integration options to enable output control."
},
@@ -22,6 +22,7 @@ from homeassistant.const import (
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers.device_registry import DeviceRegistry
from homeassistant.helpers.entity_registry import EntityRegistry
@@ -225,6 +226,28 @@ async def test_alarm_control_panel_disarming(
mock_satel.clear_alarm.assert_awaited_once_with(MOCK_CODE, [1])
async def test_alarm_control_panel_disarming_requires_code(
hass: HomeAssistant,
mock_satel: AsyncMock,
mock_config_entry_with_subentries: MockConfigEntry,
) -> None:
"""Test disarming fails when the access code is missing."""
await setup_integration(hass, mock_config_entry_with_subentries)
with pytest.raises(ServiceValidationError) as exc_info:
await hass.services.async_call(
ALARM_DOMAIN,
SERVICE_ALARM_DISARM,
{ATTR_ENTITY_ID: "alarm_control_panel.home"},
blocking=True,
)
assert exc_info.value.translation_domain == DOMAIN
assert exc_info.value.translation_key == "missing_alarm_access_code"
mock_satel.disarm.assert_not_awaited()
mock_satel.clear_alarm.assert_not_awaited()
async def test_alarm_panel_last_reported(
hass: HomeAssistant,
mock_satel: AsyncMock,