Home Assistant Unofficial Reference 2024.12.1
camera.py
Go to the documentation of this file.
1 """Support for Vivotek IP Cameras."""
2 
3 from __future__ import annotations
4 
5 from libpyvivotek import VivotekCamera
6 import voluptuous as vol
7 
9  PLATFORM_SCHEMA as CAMERA_PLATFORM_SCHEMA,
10  Camera,
11  CameraEntityFeature,
12 )
13 from homeassistant.const import (
14  CONF_AUTHENTICATION,
15  CONF_IP_ADDRESS,
16  CONF_NAME,
17  CONF_PASSWORD,
18  CONF_SSL,
19  CONF_USERNAME,
20  CONF_VERIFY_SSL,
21  HTTP_BASIC_AUTHENTICATION,
22  HTTP_DIGEST_AUTHENTICATION,
23 )
24 from homeassistant.core import HomeAssistant
25 from homeassistant.helpers import config_validation as cv
26 from homeassistant.helpers.entity_platform import AddEntitiesCallback
27 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
28 
29 CONF_FRAMERATE = "framerate"
30 CONF_SECURITY_LEVEL = "security_level"
31 CONF_STREAM_PATH = "stream_path"
32 
33 DEFAULT_CAMERA_BRAND = "VIVOTEK"
34 DEFAULT_NAME = "VIVOTEK Camera"
35 DEFAULT_EVENT_0_KEY = "event_i0_enable"
36 DEFAULT_SECURITY_LEVEL = "admin"
37 DEFAULT_STREAM_SOURCE = "live.sdp"
38 
39 PLATFORM_SCHEMA = CAMERA_PLATFORM_SCHEMA.extend(
40  {
41  vol.Required(CONF_IP_ADDRESS): cv.string,
42  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
43  vol.Required(CONF_PASSWORD): cv.string,
44  vol.Required(CONF_USERNAME): cv.string,
45  vol.Optional(CONF_AUTHENTICATION, default=HTTP_BASIC_AUTHENTICATION): vol.In(
46  [HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION]
47  ),
48  vol.Optional(CONF_SSL, default=False): cv.boolean,
49  vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
50  vol.Optional(CONF_FRAMERATE, default=2): cv.positive_int,
51  vol.Optional(CONF_SECURITY_LEVEL, default=DEFAULT_SECURITY_LEVEL): cv.string,
52  vol.Optional(CONF_STREAM_PATH, default=DEFAULT_STREAM_SOURCE): cv.string,
53  }
54 )
55 
56 
58  hass: HomeAssistant,
59  config: ConfigType,
60  add_entities: AddEntitiesCallback,
61  discovery_info: DiscoveryInfoType | None = None,
62 ) -> None:
63  """Set up a Vivotek IP Camera."""
64  creds = f"{config[CONF_USERNAME]}:{config[CONF_PASSWORD]}"
65  args = {
66  "config": config,
67  "cam": VivotekCamera(
68  host=config[CONF_IP_ADDRESS],
69  port=(443 if config[CONF_SSL] else 80),
70  verify_ssl=config[CONF_VERIFY_SSL],
71  usr=config[CONF_USERNAME],
72  pwd=config[CONF_PASSWORD],
73  digest_auth=config[CONF_AUTHENTICATION] == HTTP_DIGEST_AUTHENTICATION,
74  sec_lvl=config[CONF_SECURITY_LEVEL],
75  ),
76  "stream_source": (
77  f"rtsp://{creds}@{config[CONF_IP_ADDRESS]}:554/{config[CONF_STREAM_PATH]}"
78  ),
79  }
80  add_entities([VivotekCam(**args)], True)
81 
82 
84  """A Vivotek IP camera."""
85 
86  _attr_supported_features = CameraEntityFeature.STREAM
87 
88  def __init__(self, config, cam, stream_source):
89  """Initialize a Vivotek camera."""
90  super().__init__()
91 
92  self._cam_cam = cam
93  self._frame_interval_frame_interval = 1 / config[CONF_FRAMERATE]
94  self._motion_detection_enabled_motion_detection_enabled = False
95  self._model_name_model_name = None
96  self._name_name = config[CONF_NAME]
97  self._stream_source_stream_source = stream_source
98 
99  @property
100  def frame_interval(self):
101  """Return the interval between frames of the mjpeg stream."""
102  return self._frame_interval_frame_interval
103 
105  self, width: int | None = None, height: int | None = None
106  ) -> bytes | None:
107  """Return bytes of camera image."""
108  return self._cam_cam.snapshot()
109 
110  @property
111  def name(self):
112  """Return the name of this device."""
113  return self._name_name
114 
115  async def stream_source(self):
116  """Return the source of the stream."""
117  return self._stream_source_stream_source
118 
119  @property
121  """Return the camera motion detection status."""
122  return self._motion_detection_enabled_motion_detection_enabled
123 
124  def disable_motion_detection(self) -> None:
125  """Disable motion detection in camera."""
126  response = self._cam_cam.set_param(DEFAULT_EVENT_0_KEY, 0)
127  self._motion_detection_enabled_motion_detection_enabled = int(response) == 1
128 
129  def enable_motion_detection(self) -> None:
130  """Enable motion detection in camera."""
131  response = self._cam_cam.set_param(DEFAULT_EVENT_0_KEY, 1)
132  self._motion_detection_enabled_motion_detection_enabled = int(response) == 1
133 
134  @property
135  def brand(self):
136  """Return the camera brand."""
137  return DEFAULT_CAMERA_BRAND
138 
139  @property
140  def model(self):
141  """Return the camera model."""
142  return self._model_name_model_name
143 
144  def update(self) -> None:
145  """Update entity status."""
146  self._model_name_model_name = self._cam_cam.model_name
bytes|None camera_image(self, int|None width=None, int|None height=None)
Definition: camera.py:106
def __init__(self, config, cam, stream_source)
Definition: camera.py:88
None add_entities(HomeAssistant hass, FreeboxRouter router, AddEntitiesCallback async_add_entities, set[str] tracked)
Definition: camera.py:54
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: camera.py:62