Home Assistant Unofficial Reference 2024.12.1
camera.py
Go to the documentation of this file.
1 """Support for Agent camera streaming."""
2 
3 from datetime import timedelta
4 import logging
5 
6 from agent import AgentError
7 
8 from homeassistant.components.camera import CameraEntityFeature
9 from homeassistant.components.mjpeg import MjpegCamera, filter_urllib3_logging
10 from homeassistant.core import HomeAssistant
11 from homeassistant.helpers.device_registry import DeviceInfo
13  AddEntitiesCallback,
14  async_get_current_platform,
15 )
16 
17 from . import AgentDVRConfigEntry
18 from .const import ATTRIBUTION, CAMERA_SCAN_INTERVAL_SECS, DOMAIN as AGENT_DOMAIN
19 
20 SCAN_INTERVAL = timedelta(seconds=CAMERA_SCAN_INTERVAL_SECS)
21 
22 _LOGGER = logging.getLogger(__name__)
23 
24 _DEV_EN_ALT = "enable_alerts"
25 _DEV_DS_ALT = "disable_alerts"
26 _DEV_EN_REC = "start_recording"
27 _DEV_DS_REC = "stop_recording"
28 _DEV_SNAP = "snapshot"
29 
30 CAMERA_SERVICES = {
31  _DEV_EN_ALT: "async_enable_alerts",
32  _DEV_DS_ALT: "async_disable_alerts",
33  _DEV_EN_REC: "async_start_recording",
34  _DEV_DS_REC: "async_stop_recording",
35  _DEV_SNAP: "async_snapshot",
36 }
37 
38 
40  hass: HomeAssistant,
41  config_entry: AgentDVRConfigEntry,
42  async_add_entities: AddEntitiesCallback,
43 ) -> None:
44  """Set up the Agent cameras."""
46  cameras = []
47 
48  server = config_entry.runtime_data
49  if not server.devices:
50  _LOGGER.warning("Could not fetch cameras from Agent server")
51  return
52 
53  for device in server.devices:
54  if device.typeID == 2:
55  camera = AgentCamera(device)
56  cameras.append(camera)
57 
58  async_add_entities(cameras)
59 
60  platform = async_get_current_platform()
61  for service, method in CAMERA_SERVICES.items():
62  platform.async_register_entity_service(service, None, method)
63 
64 
65 class AgentCamera(MjpegCamera):
66  """Representation of an Agent Device Stream."""
67 
68  _attr_attribution = ATTRIBUTION
69  _attr_should_poll = True # Cameras default to False
70  _attr_supported_features = CameraEntityFeature.ON_OFF
71  _attr_has_entity_name = True
72  _attr_name = None
73 
74  def __init__(self, device):
75  """Initialize as a subclass of MjpegCamera."""
76  self.devicedevice = device
77  self._removed_removed = False
78  self._attr_unique_id_attr_unique_id = f"{device.client.unique}_{device.typeID}_{device.id}"
79  super().__init__(
80  name=device.name,
81  mjpeg_url=f"{device.client._server_url}{device.mjpeg_image_url}&size={device.mjpegStreamWidth}x{device.mjpegStreamHeight}", # noqa: SLF001
82  still_image_url=f"{device.client._server_url}{device.still_image_url}&size={device.mjpegStreamWidth}x{device.mjpegStreamHeight}", # noqa: SLF001
83  )
84  self._attr_device_info_attr_device_info = DeviceInfo(
85  identifiers={(AGENT_DOMAIN, self.unique_id)},
86  manufacturer="Agent",
87  model="Camera",
88  name=f"{device.client.name} {device.name}",
89  sw_version=device.client.version,
90  )
91 
92  async def async_update(self) -> None:
93  """Update our state from the Agent API."""
94  try:
95  await self.devicedevice.update()
96  if self._removed_removed:
97  _LOGGER.debug("%s reacquired", self.name)
98  self._removed_removed = False
99  except AgentError:
100  # server still available - camera error
101  if self.devicedevice.client.is_available and not self._removed_removed:
102  _LOGGER.error("%s lost", self.name)
103  self._removed_removed = True
104  self._attr_icon_attr_icon = "mdi:camcorder-off"
105  if self.is_onis_on:
106  self._attr_icon_attr_icon = "mdi:camcorder"
107  self._attr_available_attr_available = self.devicedevice.client.is_available
108  self._attr_extra_state_attributes_attr_extra_state_attributes = {
109  "editable": False,
110  "enabled": self.is_onis_on,
111  "connected": self.connectedconnected,
112  "detected": self.is_detectedis_detected,
113  "alerted": self.is_alertedis_alerted,
114  "has_ptz": self.devicedevice.has_ptz,
115  "alerts_enabled": self.devicedevice.alerts_active,
116  }
117 
118  @property
119  def is_recording(self) -> bool:
120  """Return whether the monitor is recording."""
121  return self.devicedevice.recording
122 
123  @property
124  def is_alerted(self) -> bool:
125  """Return whether the monitor has alerted."""
126  return self.devicedevice.alerted
127 
128  @property
129  def is_detected(self) -> bool:
130  """Return whether the monitor has alerted."""
131  return self.devicedevice.detected
132 
133  @property
134  def connected(self) -> bool:
135  """Return True if entity is connected."""
136  return self.devicedevice.connected
137 
138  @property
139  def is_on(self) -> bool:
140  """Return true if on."""
141  return self.devicedevice.online
142 
143  @property
144  def motion_detection_enabled(self) -> bool:
145  """Return the camera motion detection status."""
146  return self.devicedevice.detector_active
147 
148  async def async_enable_alerts(self):
149  """Enable alerts."""
150  await self.devicedevice.alerts_on()
151 
152  async def async_disable_alerts(self):
153  """Disable alerts."""
154  await self.devicedevice.alerts_off()
155 
156  async def async_enable_motion_detection(self) -> None:
157  """Enable motion detection."""
158  await self.devicedevice.detector_on()
159 
160  async def async_disable_motion_detection(self) -> None:
161  """Disable motion detection."""
162  await self.devicedevice.detector_off()
163 
164  async def async_start_recording(self):
165  """Start recording."""
166  await self.devicedevice.record()
167 
168  async def async_stop_recording(self):
169  """Stop recording."""
170  await self.devicedevice.record_stop()
171 
172  async def async_turn_on(self) -> None:
173  """Enable the camera."""
174  await self.devicedevice.enable()
175 
176  async def async_snapshot(self):
177  """Take a snapshot."""
178  await self.devicedevice.snapshot()
179 
180  async def async_turn_off(self) -> None:
181  """Disable the camera."""
182  await self.devicedevice.disable()
None async_setup_entry(HomeAssistant hass, AgentDVRConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: camera.py:43
IssData update(pyiss.ISS iss)
Definition: __init__.py:33