core/homeassistant/components/neato/camera.py

137 lines
4.0 KiB
Python
Raw Normal View History

"""Support for loading picture from Neato."""
from datetime import timedelta
import logging
from pybotvac.exceptions import NeatoRobotException
from homeassistant.components.camera import Camera
from .const import (
NEATO_DOMAIN,
NEATO_LOGIN,
NEATO_MAP_DATA,
NEATO_ROBOTS,
SCAN_INTERVAL_MINUTES,
)
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(minutes=SCAN_INTERVAL_MINUTES)
ATTR_GENERATED_AT = "generated_at"
async def async_setup_entry(hass, entry, async_add_entities):
"""Set up Neato camera with config entry."""
dev = []
neato = hass.data.get(NEATO_LOGIN)
mapdata = hass.data.get(NEATO_MAP_DATA)
for robot in hass.data[NEATO_ROBOTS]:
2019-07-31 19:25:30 +00:00
if "maps" in robot.traits:
dev.append(NeatoCleaningMap(neato, robot, mapdata))
if not dev:
return
_LOGGER.debug("Adding robots for cleaning maps %s", dev)
async_add_entities(dev, True)
class NeatoCleaningMap(Camera):
"""Neato cleaning map for last clean."""
def __init__(self, neato, robot, mapdata):
"""Initialize Neato cleaning map."""
super().__init__()
self.robot = robot
self.neato = neato
self._mapdata = mapdata
self._available = self.neato.logged_in if self.neato is not None else False
self._robot_name = f"{self.robot.name} Cleaning Map"
self._robot_serial = self.robot.serial
self._generated_at = None
self._image_url = None
self._image = None
def camera_image(self):
"""Return image response."""
self.update()
return self._image
def update(self):
"""Check the contents of the map list."""
if self.neato is None:
_LOGGER.error("Error while updating '%s'", self.entity_id)
self._image = None
self._image_url = None
self._available = False
return
_LOGGER.debug("Running camera update for '%s'", self.entity_id)
try:
self.neato.update_robots()
except NeatoRobotException as ex:
if self._available: # Print only once when available
_LOGGER.error(
"Neato camera connection error for '%s': %s", self.entity_id, ex
)
self._image = None
self._image_url = None
self._available = False
return
image_url = None
map_data = self._mapdata[self._robot_serial]["maps"][0]
image_url = map_data["url"]
if image_url == self._image_url:
_LOGGER.debug(
"The map image_url for '%s' is the same as old", self.entity_id
)
return
try:
image = self.neato.download_map(image_url)
except NeatoRobotException as ex:
if self._available: # Print only once when available
_LOGGER.error(
"Neato camera connection error for '%s': %s", self.entity_id, ex
)
self._image = None
self._image_url = None
self._available = False
return
self._image = image.read()
self._image_url = image_url
self._generated_at = (map_data["generated_at"].strip("Z")).replace("T", " ")
self._available = True
@property
def name(self):
"""Return the name of this camera."""
return self._robot_name
@property
def unique_id(self):
"""Return unique ID."""
return self._robot_serial
@property
def available(self):
"""Return if the robot is available."""
return self._available
@property
def device_info(self):
"""Device info for neato robot."""
return {"identifiers": {(NEATO_DOMAIN, self._robot_serial)}}
@property
def device_state_attributes(self):
"""Return the state attributes of the vacuum cleaner."""
data = {}
if self._generated_at is not None:
data[ATTR_GENERATED_AT] = self._generated_at
return data