core/homeassistant/components/netatmo/light.py

146 lines
4.4 KiB
Python
Raw Normal View History

Add Netatmo data handler (#35571) * Fix webhook registration * Only load camera platform with valid scope * Add initial data handler and netatmo base class * Update camera to use data handler * Update init * Parallelize API calls * Remove cruft * Minor tweaks * Refactor data handler * Update climate to use data handler * Fix pylint error * Fix climate update not getting fresh data * Update climate data * update to pyatmo 4.0.0 * Refactor for pyatmo 4.0.0 * Exclude from coverage until tests are written * Fix typo * Reduce parallel calls * Add heating request attr * Async get_entities * Undo parallel updates * Fix camera issue * Introduce individual scan interval per device class * Some cleanup * Add basic webhook support for climate to improve responsiveness * Replace ClimateDevice by ClimateEntity * Add support for turning camera on/off * Update camera state upon webhook events * Guard data class registration with lock * Capture errors * Add light platform * Add dis-/connect handling * Fix set schedule service * Remove extra calls * Add service to set person(s) home/away * Add service descriptions * Improve service descriptions * Use LightEntity instead of Light * Add guard if no data is retrieved * Make services entity based * Only raise platform not ready if there is a NOC * Register webhook even during runtime * Fix turning off event * Fix linter error * Fix linter error * Exclude light platform from coverage * Change log level * Refactor public weather sensor to use data handler * Prevent too short coordinates * Ignore modules without _id * Code cleanup * Fix test * Exit early if no home data is retrieved * Prevent discovery if already active * Add services to (un-)register webhook * Fix tests * Not actually a coroutine * Move methods to base class * Address pylint comment * Address pylint complaints * Address comments * Address more comments * Add docstring * Use single instance allowed * Extract method * Remove cruft * Write state directly * Fix test * Add file to coverage * Move nested function * Move nested function * Update docstring * Clean up code * Fix webhook bug * Clean up listeners * Use deque * Clean up prints * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/camera.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/camera.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/camera.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/camera.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/camera.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update homeassistant/components/netatmo/camera.py Co-authored-by: J. Nick Koston <nick@koston.org> * Rename data_class variable * Break when match * Extract method * Extract methods * Rename variable * Improve comment * Some refinements * Extra * Extract method * Simplify code * Improve reability * Code simplification * Simplify code * Simplify code * Code cleanup * Fix import * Clean up * Clean up magic strings * Replace data_class_name with CAMERA_DATA_CLASS_NAME * Replace data_class_name with CAMERA_DATA_CLASS_NAME * Replace data_class_name with HOMEDATA_DATA_CLASS_NAME * Replace data_class_name in public weather sensor * Clean up * Remove deprecated config options * Schedule immediate update on camera reconnect * Use UUID to clearly identify public weather areas * Use subscription mode * Move clean up of temporary data classes * Delay data class removal * Fix linter complaints * Adjust test * Only setup lights if webhook are registered * Prevent crash with old config entries * Don't cache home ids * Remove stale code * Fix coordinates if entered mixed up by the user * Move nested function * Add test case for swapped coordinates * Only wait for discovery entries * Only use what I need * Bring stuff closer to where it's used * Auto clean up setup data classes * Code cleanup * Remove unneccessary lock * Update homeassistant/components/netatmo/sensor.py Co-authored-by: J. Nick Koston <nick@koston.org> * Update tests/components/netatmo/test_config_flow.py Co-authored-by: J. Nick Koston <nick@koston.org> * Clean up dead code * Fix formating * Extend coverage * Extend coverage Co-authored-by: J. Nick Koston <nick@koston.org>
2020-08-04 18:46:46 +00:00
"""Support for the Netatmo camera lights."""
import logging
import pyatmo
from homeassistant.components.light import LightEntity
from homeassistant.core import callback
from homeassistant.exceptions import PlatformNotReady
from .const import DATA_HANDLER, DOMAIN, MANUFACTURER, SIGNAL_NAME
from .data_handler import CAMERA_DATA_CLASS_NAME, NetatmoDataHandler
from .netatmo_entity_base import NetatmoBase
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, entry, async_add_entities):
"""Set up the Netatmo camera light platform."""
if "access_camera" not in entry.data["token"]["scope"]:
_LOGGER.info(
"Cameras are currently not supported with this authentication method"
)
return
data_handler = hass.data[DOMAIN][entry.entry_id][DATA_HANDLER]
async def get_entities():
"""Retrieve Netatmo entities."""
await data_handler.register_data_class(
CAMERA_DATA_CLASS_NAME, CAMERA_DATA_CLASS_NAME, None
)
entities = []
try:
all_cameras = []
for home in data_handler.data[CAMERA_DATA_CLASS_NAME].cameras.values():
for camera in home.values():
all_cameras.append(camera)
for camera in all_cameras:
if camera["type"] == "NOC":
if not data_handler.webhook:
raise PlatformNotReady
_LOGGER.debug(
"Adding camera light %s %s", camera["id"], camera["name"]
)
entities.append(
NetatmoLight(
data_handler,
camera["id"],
camera["type"],
camera["home_id"],
)
)
except pyatmo.NoDevice:
_LOGGER.debug("No cameras found")
return entities
async_add_entities(await get_entities(), True)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the Netatmo camera platform."""
return
class NetatmoLight(NetatmoBase, LightEntity):
"""Representation of a Netatmo Presence camera light."""
def __init__(
self,
data_handler: NetatmoDataHandler,
camera_id: str,
camera_type: str,
home_id: str,
):
"""Initialize a Netatmo Presence camera light."""
LightEntity.__init__(self)
super().__init__(data_handler)
self._data_classes.append(
{"name": CAMERA_DATA_CLASS_NAME, SIGNAL_NAME: CAMERA_DATA_CLASS_NAME}
)
self._id = camera_id
self._home_id = home_id
self._model = camera_type
self._device_name = self._data.get_camera(camera_id).get("name")
self._name = f"{MANUFACTURER} {self._device_name}"
self._is_on = False
self._unique_id = f"{self._id}-light"
async def async_added_to_hass(self) -> None:
"""Entity created."""
await super().async_added_to_hass()
self._listeners.append(
self.hass.bus.async_listen("netatmo_event", self.handle_event)
)
async def handle_event(self, event):
"""Handle webhook events."""
data = event.data["data"]
if not data.get("event_type"):
return
if not data.get("camera_id"):
return
if (
data["home_id"] == self._home_id
and data["camera_id"] == self._id
and data["push_type"] == "NOC-light_mode"
):
self._is_on = bool(data["sub_type"] == "on")
self.async_write_ha_state()
return
@property
def is_on(self):
"""Return true if light is on."""
return self._is_on
def turn_on(self, **kwargs):
"""Turn camera floodlight on."""
_LOGGER.debug("Turn camera '%s' on", self._name)
self._data.set_state(
home_id=self._home_id, camera_id=self._id, floodlight="on",
)
def turn_off(self, **kwargs):
"""Turn camera floodlight into auto mode."""
_LOGGER.debug("Turn camera '%s' off", self._name)
self._data.set_state(
home_id=self._home_id, camera_id=self._id, floodlight="auto",
)
@callback
def async_update_callback(self):
"""Update the entity's state."""
self._is_on = bool(self._data.get_light_state(self._id) == "on")