mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Add camera platform to Tuya (#57865)
This commit is contained in:
parent
2fa08ae6ab
commit
d64f210b67
@ -1112,6 +1112,7 @@ omit =
|
|||||||
homeassistant/components/tuya/__init__.py
|
homeassistant/components/tuya/__init__.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/camera.py
|
||||||
homeassistant/components/tuya/climate.py
|
homeassistant/components/tuya/climate.py
|
||||||
homeassistant/components/tuya/const.py
|
homeassistant/components/tuya/const.py
|
||||||
homeassistant/components/tuya/fan.py
|
homeassistant/components/tuya/fan.py
|
||||||
|
130
homeassistant/components/tuya/camera.py
Normal file
130
homeassistant/components/tuya/camera.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
"""Support for Tuya cameras."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from tuya_iot import TuyaDevice, TuyaDeviceManager
|
||||||
|
|
||||||
|
from homeassistant.components import ffmpeg
|
||||||
|
from homeassistant.components.camera import SUPPORT_STREAM, Camera as CameraEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
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 TuyaEntity
|
||||||
|
from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode
|
||||||
|
|
||||||
|
# All descriptions can be found here:
|
||||||
|
# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
|
||||||
|
CAMERAS: tuple[str, ...] = (
|
||||||
|
# Smart Camera (including doorbells)
|
||||||
|
# https://developer.tuya.com/en/docs/iot/categorysgbj?id=Kaiuz37tlpbnu
|
||||||
|
"sp",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
|
) -> None:
|
||||||
|
"""Set up Tuya cameras 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 camera."""
|
||||||
|
entities: list[TuyaCameraEntity] = []
|
||||||
|
for device_id in device_ids:
|
||||||
|
device = hass_data.device_manager.device_map[device_id]
|
||||||
|
if device.category in CAMERAS:
|
||||||
|
entities.append(TuyaCameraEntity(device, hass_data.device_manager))
|
||||||
|
|
||||||
|
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 TuyaCameraEntity(TuyaEntity, CameraEntity):
|
||||||
|
"""Tuya Camera Entity."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
device: TuyaDevice,
|
||||||
|
device_manager: TuyaDeviceManager,
|
||||||
|
) -> None:
|
||||||
|
"""Init Tuya Camera."""
|
||||||
|
super().__init__(device, device_manager)
|
||||||
|
CameraEntity.__init__(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self) -> int:
|
||||||
|
"""Flag supported features."""
|
||||||
|
return SUPPORT_STREAM
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_recording(self) -> bool:
|
||||||
|
"""Return true if the device is recording."""
|
||||||
|
return self.device.status.get(DPCode.RECORD_SWITCH, False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def brand(self) -> str | None:
|
||||||
|
"""Return the camera brand."""
|
||||||
|
return "Tuya"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def motion_detection_enabled(self) -> bool:
|
||||||
|
"""Return the camera motion detection status."""
|
||||||
|
return self.device.status.get(DPCode.MOTION_SWITCH, False)
|
||||||
|
|
||||||
|
async def stream_source(self) -> str | None:
|
||||||
|
"""Return the source of the stream."""
|
||||||
|
|
||||||
|
def _stream_source() -> str | None:
|
||||||
|
# This method can be replaced by the following snippet, once
|
||||||
|
# upstream changes have been merged.
|
||||||
|
#
|
||||||
|
# return self.device_manager.get_device_stream_allocate(
|
||||||
|
# self.device.id, stream_type="rtsp"
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# https://github.com/tuya/tuya-iot-python-sdk/pull/28
|
||||||
|
|
||||||
|
response = self.device_manager.api.post(
|
||||||
|
f"/v1.0/devices/{self.device.id}/stream/actions/allocate",
|
||||||
|
{"type": "rtsp"},
|
||||||
|
)
|
||||||
|
if response["success"]:
|
||||||
|
return response["result"]["url"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
return await self.hass.async_add_executor_job(_stream_source)
|
||||||
|
|
||||||
|
async def async_camera_image(
|
||||||
|
self, width: int | None = None, height: int | None = None
|
||||||
|
) -> bytes | None:
|
||||||
|
"""Return a still image response from the camera."""
|
||||||
|
stream_source = await self.stream_source()
|
||||||
|
if not stream_source:
|
||||||
|
return None
|
||||||
|
return await ffmpeg.async_get_image(
|
||||||
|
self.hass,
|
||||||
|
stream_source,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def model(self) -> str | None:
|
||||||
|
"""Return the camera model."""
|
||||||
|
return self.device.product_name
|
||||||
|
|
||||||
|
def enable_motion_detection(self) -> None:
|
||||||
|
"""Enable motion detection in the camera."""
|
||||||
|
self._send_command([{"code": DPCode.MOTION_SWITCH, "value": True}])
|
||||||
|
|
||||||
|
def disable_motion_detection(self) -> None:
|
||||||
|
"""Disable motion detection in camera."""
|
||||||
|
self._send_command([{"code": DPCode.MOTION_SWITCH, "value": False}])
|
@ -46,8 +46,9 @@ TUYA_SUPPORTED_PRODUCT_CATEGORIES = (
|
|||||||
"pc", # Power Strip
|
"pc", # Power Strip
|
||||||
"pir", # PIR Detector
|
"pir", # PIR Detector
|
||||||
"qn", # Heater
|
"qn", # Heater
|
||||||
"sos", # SOS Button
|
|
||||||
"sgbj", # Siren Alarm
|
"sgbj", # Siren Alarm
|
||||||
|
"sos", # SOS Button
|
||||||
|
"sp", # Smart Camera
|
||||||
"wk", # Thermostat
|
"wk", # Thermostat
|
||||||
"xdd", # Ceiling Light
|
"xdd", # Ceiling Light
|
||||||
"xxj", # Diffuser
|
"xxj", # Diffuser
|
||||||
@ -58,6 +59,7 @@ SMARTLIFE_APP = "smartlife"
|
|||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
"binary_sensor",
|
"binary_sensor",
|
||||||
|
"camera",
|
||||||
"climate",
|
"climate",
|
||||||
"fan",
|
"fan",
|
||||||
"light",
|
"light",
|
||||||
@ -106,10 +108,12 @@ class DPCode(str, Enum):
|
|||||||
LOCK = "lock" # Lock / Child lock
|
LOCK = "lock" # Lock / Child lock
|
||||||
MATERIAL = "material" # Material
|
MATERIAL = "material" # Material
|
||||||
MODE = "mode" # Working mode / Mode
|
MODE = "mode" # Working mode / Mode
|
||||||
|
MOTION_SWITCH = "motion_switch" # Motion switch
|
||||||
MUFFLING = "muffling" # Muffling
|
MUFFLING = "muffling" # Muffling
|
||||||
PIR = "pir" # Motion sensor
|
PIR = "pir" # Motion sensor
|
||||||
POWDER_SET = "powder_set" # Powder
|
POWDER_SET = "powder_set" # Powder
|
||||||
PUMP_RESET = "pump_reset" # Water pump reset
|
PUMP_RESET = "pump_reset" # Water pump reset
|
||||||
|
RECORD_SWITCH = "record_switch" # Recording switch
|
||||||
SHAKE = "shake" # Oscillating
|
SHAKE = "shake" # Oscillating
|
||||||
SOS = "sos" # Emergency State
|
SOS = "sos" # Emergency State
|
||||||
SOS_STATE = "sos_state" # Emergency mode
|
SOS_STATE = "sos_state" # Emergency mode
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"name": "Tuya",
|
"name": "Tuya",
|
||||||
"documentation": "https://github.com/tuya/tuya-home-assistant",
|
"documentation": "https://github.com/tuya/tuya-home-assistant",
|
||||||
"requirements": ["tuya-iot-py-sdk==0.5.0"],
|
"requirements": ["tuya-iot-py-sdk==0.5.0"],
|
||||||
|
"dependencies": ["ffmpeg"],
|
||||||
"codeowners": ["@Tuya", "@zlinoliver", "@METISU", "@frenck"],
|
"codeowners": ["@Tuya", "@zlinoliver", "@METISU", "@frenck"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"iot_class": "cloud_push",
|
"iot_class": "cloud_push",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user