Added Wyze
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
"""
|
||||
This module describes the connection between Home Assistant and Wyze for the Sensors
|
||||
"""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from typing import Callable, List, Any
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntity,
|
||||
BinarySensorDeviceClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_ATTRIBUTION
|
||||
from homeassistant.core import HomeAssistant
|
||||
from wyzeapy import Wyzeapy, CameraService, SensorService
|
||||
from wyzeapy.services.camera_service import Camera
|
||||
from wyzeapy.services.sensor_service import Sensor
|
||||
from wyzeapy.types import DeviceTypes
|
||||
from .token_manager import token_exception_handler
|
||||
|
||||
from .const import DOMAIN, CONF_CLIENT
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
ATTRIBUTION = "Data provided by Wyze"
|
||||
|
||||
|
||||
@token_exception_handler
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: Callable[[List[Any], bool], None],
|
||||
):
|
||||
"""
|
||||
This function sets up the config entry for use in Home Assistant
|
||||
|
||||
:param hass: Home Assistant instance
|
||||
:param config_entry: The current config_entry
|
||||
:param async_add_entities: This function adds entities to the config_entry
|
||||
:return:
|
||||
"""
|
||||
|
||||
_LOGGER.debug("""Creating new WyzeApi binary sensor component""")
|
||||
client: Wyzeapy = hass.data[DOMAIN][config_entry.entry_id][CONF_CLIENT]
|
||||
|
||||
sensor_service = await client.sensor_service
|
||||
camera_service = await client.camera_service
|
||||
|
||||
cameras = [
|
||||
WyzeCameraMotion(camera_service, camera)
|
||||
for camera in await camera_service.get_cameras()
|
||||
]
|
||||
sensors = [
|
||||
WyzeSensor(sensor_service, sensor)
|
||||
for sensor in await sensor_service.get_sensors()
|
||||
]
|
||||
|
||||
async_add_entities(cameras, True)
|
||||
async_add_entities(sensors, True)
|
||||
|
||||
|
||||
class WyzeSensor(BinarySensorEntity):
|
||||
"""
|
||||
A representation of the WyzeSensor for use in Home Assistant
|
||||
"""
|
||||
|
||||
def __init__(self, sensor_service: SensorService, sensor: Sensor):
|
||||
"""Initializes the class"""
|
||||
self._sensor_service = sensor_service
|
||||
self._sensor = sensor
|
||||
self._last_event = int(str(int(time.time())) + "000")
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Registers for updates when the entity is added to Home Assistant"""
|
||||
await self._sensor_service.register_for_updates(
|
||||
self._sensor, self.process_update
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
await self._sensor_service.deregister_for_updates(self._sensor)
|
||||
|
||||
def process_update(self, sensor: Sensor):
|
||||
"""
|
||||
This function processes an update for the Wyze Sensor
|
||||
|
||||
:param sensor: The sensor with the updated values
|
||||
"""
|
||||
self._sensor = sensor
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self._sensor.mac)},
|
||||
"name": self.name,
|
||||
"manufacturer": "WyzeLabs",
|
||||
"model": self._sensor.product_model,
|
||||
}
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
return True
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the display name of this switch."""
|
||||
return self._sensor.nickname
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if sensor detects motion"""
|
||||
return self._sensor.detected
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return "{}-motion".format(self._sensor.mac)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return device attributes of the entity."""
|
||||
return {
|
||||
ATTR_ATTRIBUTION: ATTRIBUTION,
|
||||
"device model": self._sensor.product_model,
|
||||
"mac": self.unique_id,
|
||||
}
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
# pylint: disable=R1705
|
||||
if self._sensor.type is DeviceTypes.MOTION_SENSOR:
|
||||
return BinarySensorDeviceClass.MOTION
|
||||
elif self._sensor.type is DeviceTypes.CONTACT_SENSOR:
|
||||
return BinarySensorDeviceClass.DOOR
|
||||
else:
|
||||
raise RuntimeError(
|
||||
f"The device type {self._sensor.type} is not supported by this class"
|
||||
)
|
||||
|
||||
|
||||
class WyzeCameraMotion(BinarySensorEntity):
|
||||
"""
|
||||
A representation of the Wyze Camera for use as a binary sensor in Home Assistant
|
||||
"""
|
||||
|
||||
_is_on = False
|
||||
_last_event = time.time() * 1000
|
||||
|
||||
def __init__(self, camera_service: CameraService, camera: Camera):
|
||||
self._camera_service = camera_service
|
||||
self._camera = camera
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self._camera.mac)},
|
||||
"name": self.name,
|
||||
"manufacturer": "WyzeLabs",
|
||||
"model": self._camera.product_model,
|
||||
}
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
return self._camera.available
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the display name of this switch."""
|
||||
return self._camera.nickname
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if the binary sensor is on"""
|
||||
return self._is_on
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
return "{}-motion".format(self._camera.mac)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return device attributes of the entity."""
|
||||
return {
|
||||
ATTR_ATTRIBUTION: ATTRIBUTION,
|
||||
"device model": self._camera.product_model,
|
||||
"mac": self.unique_id,
|
||||
}
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
return BinarySensorDeviceClass.MOTION
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
await self._camera_service.register_for_updates(
|
||||
self._camera, self.process_update
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
await self._camera_service.deregister_for_updates(self._camera)
|
||||
|
||||
@token_exception_handler
|
||||
def process_update(self, camera: Camera) -> None:
|
||||
"""
|
||||
Is called by the update worker for events to update the values in this sensor
|
||||
|
||||
:param camera: An updated version of the current camera
|
||||
"""
|
||||
self._camera = camera
|
||||
|
||||
if camera.last_event_ts > self._last_event:
|
||||
self._is_on = True
|
||||
self._last_event = camera.last_event_ts
|
||||
else:
|
||||
self._is_on = False
|
||||
self._last_event = camera.last_event_ts
|
||||
|
||||
self.schedule_update_ha_state()
|
||||
Reference in New Issue
Block a user