File: /volume1/docker/homeassistant2025/custom_components/xiaomi_miot/alarm_control_panel.py
"""Support alarm_control_panel entity for Xiaomi Miot."""
import logging
from homeassistant.components.alarm_control_panel import (
DOMAIN as ENTITY_DOMAIN,
AlarmControlPanelEntity,
AlarmControlPanelEntityFeature, # v2022.5
)
from . import (
DOMAIN,
CONF_MODEL,
XIAOMI_CONFIG_SCHEMA as PLATFORM_SCHEMA, # noqa: F401
HassEntry,
MiotEntity,
async_setup_config_entry,
bind_services_to_entries,
)
from .core.miot_spec import (
MiotSpec,
MiotService,
)
from .core.const import AlarmControlPanelState
_LOGGER = logging.getLogger(__name__)
DATA_KEY = f'{ENTITY_DOMAIN}.{DOMAIN}'
SERVICE_TO_METHOD = {}
async def async_setup_entry(hass, config_entry, async_add_entities):
HassEntry.init(hass, config_entry).new_adder(ENTITY_DOMAIN, async_add_entities)
await async_setup_config_entry(hass, config_entry, async_setup_platform, async_add_entities, ENTITY_DOMAIN)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
hass.data.setdefault(DATA_KEY, {})
hass.data[DOMAIN]['add_entities'][ENTITY_DOMAIN] = async_add_entities
config['hass'] = hass
model = str(config.get(CONF_MODEL) or '')
spec = hass.data[DOMAIN]['miot_specs'].get(model)
entities = []
if isinstance(spec, MiotSpec):
for srv in spec.get_services('arming'):
if not srv.get_property('arming_mode'):
continue
entities.append(MiotAlarmEntity(config, srv))
for entity in entities:
hass.data[DOMAIN]['entities'][entity.unique_id] = entity
async_add_entities(entities, update_before_add=True)
bind_services_to_entries(hass, SERVICE_TO_METHOD)
class MiotAlarmEntity(MiotEntity, AlarmControlPanelEntity):
def __init__(self, config, miot_service: MiotService):
super().__init__(miot_service, config=config, logger=_LOGGER)
self._attr_code_arm_required = False
self._is_mgl03 = self.model == 'lumi.gateway.mgl03'
self._prop_mode = miot_service.get_property('arming_mode')
if self._prop_mode:
if self._prop_mode.list_value('home_arming') is not None:
self._supported_features |= AlarmControlPanelEntityFeature.ARM_HOME
if self._prop_mode.list_value('away_arming') is not None:
self._supported_features |= AlarmControlPanelEntityFeature.ARM_AWAY
if self._prop_mode.list_value('sleep_arming') is not None:
self._supported_features |= AlarmControlPanelEntityFeature.ARM_NIGHT
if self._is_mgl03:
self._supported_features |= AlarmControlPanelEntityFeature.TRIGGER
async def async_update(self):
await super().async_update()
if not self._available:
return
self.update_state()
def update_state(self):
sta = None
if self._prop_mode:
val = self._prop_mode.from_device(self.device)
des = self._prop_mode.list_description(val) if val is not None else None
if des is not None:
des = f'{des}'.lower()
if 'basic' in des:
sta = AlarmControlPanelState.DISARMED
elif 'home' in des:
sta = AlarmControlPanelState.ARMED_HOME
elif 'away' in des:
sta = AlarmControlPanelState.ARMED_AWAY
elif 'sleep' in des:
sta = AlarmControlPanelState.ARMED_NIGHT
if self._is_mgl03:
if self.device.props.get('arming.alarm'):
sta = AlarmControlPanelState.TRIGGERED
if hasattr(self, '_attr_alarm_state'):
self._attr_alarm_state = sta
else:
self._attr_state = sta
async def async_set_arm_mode(self, mode):
ret = False
val = self._prop_mode.list_value(mode)
if val is not None:
ret = await self.async_set_property(self._prop_mode, val)
if ret:
self.update_state()
return ret
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
return await self.async_set_arm_mode('basic_arming')
async def async_alarm_arm_home(self, code=None):
"""Send arm home command."""
return await self.async_set_arm_mode('home_arming')
async def async_alarm_arm_away(self, code=None):
"""Send arm away command."""
return await self.async_set_arm_mode('away_arming')
async def async_alarm_arm_night(self, code=None):
"""Send arm night command."""
return await self.async_set_arm_mode('sleep_arming')
def alarm_arm_vacation(self, code=None):
"""Send arm vacation command."""
raise NotImplementedError()
async def async_alarm_trigger(self, code=None):
"""Send alarm trigger command."""
if self._is_mgl03:
return await self.async_set_miot_property(3, 22, 1)
raise NotImplementedError()
def alarm_arm_custom_bypass(self, code=None):
"""Send arm custom bypass command."""
raise NotImplementedError()