Home Assistant Unofficial Reference 2024.12.1
camera.py
Go to the documentation of this file.
1 """Support for loading picture from Neato."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 from typing import Any
8 
9 from pybotvac.exceptions import NeatoRobotException
10 from pybotvac.robot import Robot
11 from urllib3.response import HTTPResponse
12 
13 from homeassistant.components.camera import Camera
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.core import HomeAssistant
16 from homeassistant.helpers.entity_platform import AddEntitiesCallback
17 
18 from .const import NEATO_LOGIN, NEATO_MAP_DATA, NEATO_ROBOTS, SCAN_INTERVAL_MINUTES
19 from .entity import NeatoEntity
20 from .hub import NeatoHub
21 
22 _LOGGER = logging.getLogger(__name__)
23 
24 SCAN_INTERVAL = timedelta(minutes=SCAN_INTERVAL_MINUTES)
25 ATTR_GENERATED_AT = "generated_at"
26 
27 
29  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
30 ) -> None:
31  """Set up Neato camera with config entry."""
32  neato: NeatoHub = hass.data[NEATO_LOGIN]
33  mapdata: dict[str, Any] | None = hass.data.get(NEATO_MAP_DATA)
34  dev = [
35  NeatoCleaningMap(neato, robot, mapdata)
36  for robot in hass.data[NEATO_ROBOTS]
37  if "maps" in robot.traits
38  ]
39 
40  if not dev:
41  return
42 
43  _LOGGER.debug("Adding robots for cleaning maps %s", dev)
44  async_add_entities(dev, True)
45 
46 
48  """Neato cleaning map for last clean."""
49 
50  _attr_translation_key = "cleaning_map"
51 
52  def __init__(
53  self, neato: NeatoHub, robot: Robot, mapdata: dict[str, Any] | None
54  ) -> None:
55  """Initialize Neato cleaning map."""
56  super().__init__(robot)
57  Camera.__init__(self)
58  self.neatoneato = neato
59  self._mapdata_mapdata = mapdata
60  self._available_available = neato is not None
61  self._robot_serial: str = self.robotrobot.serial
62  self._attr_unique_id_attr_unique_id = self.robotrobot.serial
63  self._generated_at_generated_at: str | None = None
64  self._image_url_image_url: str | None = None
65  self._image_image: bytes | None = None
66 
68  self, width: int | None = None, height: int | None = None
69  ) -> bytes | None:
70  """Return image response."""
71  self.updateupdate()
72  return self._image_image
73 
74  def update(self) -> None:
75  """Check the contents of the map list."""
76 
77  _LOGGER.debug("Running camera update for '%s'", self.entity_identity_id)
78  try:
79  self.neatoneato.update_robots()
80  except NeatoRobotException as ex:
81  if self._available_available: # Print only once when available
82  _LOGGER.error(
83  "Neato camera connection error for '%s': %s", self.entity_identity_id, ex
84  )
85  self._image_image = None
86  self._image_url_image_url = None
87  self._available_available = False
88  return
89 
90  if self._mapdata_mapdata:
91  map_data: dict[str, Any] = self._mapdata_mapdata[self._robot_serial]["maps"][0]
92  if (image_url := map_data["url"]) == self._image_url_image_url:
93  _LOGGER.debug(
94  "The map image_url for '%s' is the same as old", self.entity_identity_id
95  )
96  return
97 
98  try:
99  image: HTTPResponse = self.neatoneato.download_map(image_url)
100  except NeatoRobotException as ex:
101  if self._available_available: # Print only once when available
102  _LOGGER.error(
103  "Neato camera connection error for '%s': %s", self.entity_identity_id, ex
104  )
105  self._image_image = None
106  self._image_url_image_url = None
107  self._available_available = False
108  return
109 
110  self._image_image = image.read()
111  self._image_url_image_url = image_url
112  self._generated_at_generated_at = map_data.get("generated_at")
113  self._available_available = True
114 
115  @property
116  def available(self) -> bool:
117  """Return if the robot is available."""
118  return self._available_available
119 
120  @property
121  def extra_state_attributes(self) -> dict[str, Any]:
122  """Return the state attributes of the vacuum cleaner."""
123  data: dict[str, Any] = {}
124 
125  if self._generated_at_generated_at is not None:
126  data[ATTR_GENERATED_AT] = self._generated_at_generated_at
127 
128  return data
None __init__(self, NeatoHub neato, Robot robot, dict[str, Any]|None mapdata)
Definition: camera.py:54
bytes|None camera_image(self, int|None width=None, int|None height=None)
Definition: camera.py:69
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: camera.py:30