Tuya Alarm Initial commit (#60080)
parent
09986436a1
commit
8b216db885
|
@ -1174,6 +1174,7 @@ omit =
|
||||||
homeassistant/components/transmission/errors.py
|
homeassistant/components/transmission/errors.py
|
||||||
homeassistant/components/travisci/sensor.py
|
homeassistant/components/travisci/sensor.py
|
||||||
homeassistant/components/tuya/__init__.py
|
homeassistant/components/tuya/__init__.py
|
||||||
|
homeassistant/components/tuya/alarm_control_panel.py
|
||||||
homeassistant/components/tuya/base.py
|
homeassistant/components/tuya/base.py
|
||||||
homeassistant/components/tuya/binary_sensor.py
|
homeassistant/components/tuya/binary_sensor.py
|
||||||
homeassistant/components/tuya/button.py
|
homeassistant/components/tuya/button.py
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
"""Support for Tuya Alarm."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from tuya_iot import TuyaDevice, TuyaDeviceManager
|
||||||
|
|
||||||
|
from homeassistant.backports.enum import StrEnum
|
||||||
|
from homeassistant.components.alarm_control_panel import (
|
||||||
|
SUPPORT_ALARM_ARM_AWAY,
|
||||||
|
SUPPORT_ALARM_ARM_HOME,
|
||||||
|
SUPPORT_ALARM_TRIGGER,
|
||||||
|
AlarmControlPanelEntity,
|
||||||
|
AlarmControlPanelEntityDescription,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import (
|
||||||
|
STATE_ALARM_ARMED_AWAY,
|
||||||
|
STATE_ALARM_ARMED_HOME,
|
||||||
|
STATE_ALARM_DISARMED,
|
||||||
|
STATE_ALARM_TRIGGERED,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from . import HomeAssistantTuyaData
|
||||||
|
from .base import EnumTypeData, TuyaEntity
|
||||||
|
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode
|
||||||
|
|
||||||
|
|
||||||
|
class Mode(StrEnum):
|
||||||
|
"""Alarm modes."""
|
||||||
|
|
||||||
|
ARM = "arm"
|
||||||
|
DISARMED = "disarmed"
|
||||||
|
HOME = "home"
|
||||||
|
SOS = "sos"
|
||||||
|
|
||||||
|
|
||||||
|
STATE_MAPPING: dict[str, str] = {
|
||||||
|
Mode.DISARMED: STATE_ALARM_DISARMED,
|
||||||
|
Mode.ARM: STATE_ALARM_ARMED_AWAY,
|
||||||
|
Mode.HOME: STATE_ALARM_ARMED_HOME,
|
||||||
|
Mode.SOS: STATE_ALARM_TRIGGERED,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# All descriptions can be found here:
|
||||||
|
# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
|
||||||
|
ALARM: dict[str, tuple[AlarmControlPanelEntityDescription, ...]] = {
|
||||||
|
# Alarm Host
|
||||||
|
# https://developer.tuya.com/en/docs/iot/categorymal?id=Kaiuz33clqxaf
|
||||||
|
"mal": (
|
||||||
|
AlarmControlPanelEntityDescription(
|
||||||
|
key=DPCode.MASTER_MODE,
|
||||||
|
name="Alarm",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
|
) -> None:
|
||||||
|
"""Set up Tuya alarm dynamically through Tuya discovery."""
|
||||||
|
hass_data: HomeAssistantTuyaData = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_discover_device(device_ids: list[str]) -> None:
|
||||||
|
"""Discover and add a discovered Tuya siren."""
|
||||||
|
entities: list[TuyaAlarmEntity] = []
|
||||||
|
for device_id in device_ids:
|
||||||
|
device = hass_data.device_manager.device_map[device_id]
|
||||||
|
if descriptions := ALARM.get(device.category):
|
||||||
|
for description in descriptions:
|
||||||
|
if description.key in device.status:
|
||||||
|
entities.append(
|
||||||
|
TuyaAlarmEntity(
|
||||||
|
device, hass_data.device_manager, description
|
||||||
|
)
|
||||||
|
)
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
async_discover_device([*hass_data.device_manager.device_map])
|
||||||
|
|
||||||
|
entry.async_on_unload(
|
||||||
|
async_dispatcher_connect(hass, TUYA_DISCOVERY_NEW, async_discover_device)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TuyaAlarmEntity(TuyaEntity, AlarmControlPanelEntity):
|
||||||
|
"""Tuya Alarm Entity."""
|
||||||
|
|
||||||
|
_attr_icon = "mdi:security"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: TuyaDevice,
|
||||||
|
device_manager: TuyaDeviceManager,
|
||||||
|
description: AlarmControlPanelEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Init Tuya Alarm."""
|
||||||
|
self._attr_supported_features = 0
|
||||||
|
super().__init__(device, device_manager)
|
||||||
|
self.entity_description = description
|
||||||
|
self._attr_unique_id = f"{super().unique_id}{description.key}"
|
||||||
|
|
||||||
|
# Determine supported modes
|
||||||
|
supported_mode = EnumTypeData.from_json(
|
||||||
|
device.function[DPCode.MASTER_MODE].values
|
||||||
|
).range
|
||||||
|
|
||||||
|
if Mode.HOME in supported_mode:
|
||||||
|
self._attr_supported_features |= SUPPORT_ALARM_ARM_HOME
|
||||||
|
|
||||||
|
if Mode.ARM in supported_mode:
|
||||||
|
self._attr_supported_features |= SUPPORT_ALARM_ARM_AWAY
|
||||||
|
|
||||||
|
if Mode.SOS in supported_mode:
|
||||||
|
self._attr_supported_features |= SUPPORT_ALARM_TRIGGER
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self):
|
||||||
|
"""Return the state of the device."""
|
||||||
|
return STATE_MAPPING.get(self.device.status.get(DPCode.MASTER_MODE))
|
||||||
|
|
||||||
|
def alarm_disarm(self, code: str | None = None) -> None:
|
||||||
|
"""Send Disarm command."""
|
||||||
|
self._send_command([{"code": DPCode.MASTER_MODE, "value": Mode.DISARMED}])
|
||||||
|
|
||||||
|
def alarm_arm_home(self, code: str | None = None) -> None:
|
||||||
|
"""Send Home command."""
|
||||||
|
self._send_command([{"code": DPCode.MASTER_MODE, "value": Mode.HOME}])
|
||||||
|
|
||||||
|
def alarm_arm_away(self, code: str | None = None) -> None:
|
||||||
|
"""Send Arm command."""
|
||||||
|
self._send_command([{"code": DPCode.MASTER_MODE, "value": Mode.ARM}])
|
||||||
|
|
||||||
|
def alarm_trigger(self, code: str | None = None) -> None:
|
||||||
|
"""Send SOS command."""
|
||||||
|
self._send_command([{"code": DPCode.MASTER_MODE, "value": Mode.SOS}])
|
|
@ -80,6 +80,7 @@ TUYA_SMART_APP = "tuyaSmart"
|
||||||
SMARTLIFE_APP = "smartlife"
|
SMARTLIFE_APP = "smartlife"
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
|
Platform.ALARM_CONTROL_PANEL,
|
||||||
Platform.BINARY_SENSOR,
|
Platform.BINARY_SENSOR,
|
||||||
Platform.BUTTON,
|
Platform.BUTTON,
|
||||||
Platform.CAMERA,
|
Platform.CAMERA,
|
||||||
|
@ -210,6 +211,7 @@ class DPCode(StrEnum):
|
||||||
LIGHT = "light" # Light
|
LIGHT = "light" # Light
|
||||||
LIGHT_MODE = "light_mode"
|
LIGHT_MODE = "light_mode"
|
||||||
LOCK = "lock" # Lock / Child lock
|
LOCK = "lock" # Lock / Child lock
|
||||||
|
MASTER_MODE = "master_mode" # alarm mode
|
||||||
MACH_OPERATE = "mach_operate"
|
MACH_OPERATE = "mach_operate"
|
||||||
MANUAL_FEED = "manual_feed"
|
MANUAL_FEED = "manual_feed"
|
||||||
MATERIAL = "material" # Material
|
MATERIAL = "material" # Material
|
||||||
|
|
Loading…
Reference in New Issue