2017-05-31 07:25:25 +00:00
|
|
|
"""
|
|
|
|
This component provides HA sensor for Netgear Arlo IP cameras.
|
|
|
|
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/sensor.arlo/
|
|
|
|
"""
|
|
|
|
import asyncio
|
|
|
|
import logging
|
|
|
|
from datetime import timedelta
|
2017-10-07 08:59:46 +00:00
|
|
|
|
2017-05-31 07:25:25 +00:00
|
|
|
import voluptuous as vol
|
|
|
|
|
2017-10-07 08:59:46 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2017-05-31 07:25:25 +00:00
|
|
|
from homeassistant.components.arlo import (
|
2017-07-04 08:06:46 +00:00
|
|
|
CONF_ATTRIBUTION, DEFAULT_BRAND, DATA_ARLO)
|
2017-05-31 07:25:25 +00:00
|
|
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
2017-10-07 08:59:46 +00:00
|
|
|
from homeassistant.const import (ATTR_ATTRIBUTION, CONF_MONITORED_CONDITIONS)
|
2017-05-31 07:25:25 +00:00
|
|
|
from homeassistant.helpers.entity import Entity
|
2017-10-08 08:05:41 +00:00
|
|
|
from homeassistant.helpers.icon import icon_for_battery_level
|
2017-05-31 07:25:25 +00:00
|
|
|
|
2017-10-07 08:59:46 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2017-05-31 07:25:25 +00:00
|
|
|
DEPENDENCIES = ['arlo']
|
|
|
|
|
2017-10-07 08:59:46 +00:00
|
|
|
SCAN_INTERVAL = timedelta(seconds=90)
|
2017-05-31 07:25:25 +00:00
|
|
|
|
|
|
|
# sensor_type [ description, unit, icon ]
|
|
|
|
SENSOR_TYPES = {
|
|
|
|
'last_capture': ['Last', None, 'run-fast'],
|
|
|
|
'total_cameras': ['Arlo Cameras', None, 'video'],
|
|
|
|
'captured_today': ['Captured Today', None, 'file-video'],
|
2017-11-15 22:33:50 +00:00
|
|
|
'battery_level': ['Battery Level', '%', 'battery-50'],
|
|
|
|
'signal_strength': ['Signal Strength', None, 'signal']
|
2017-05-31 07:25:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|
|
|
vol.Required(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)):
|
|
|
|
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
@asyncio.coroutine
|
|
|
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|
|
|
"""Set up an Arlo IP sensor."""
|
2017-07-04 08:06:46 +00:00
|
|
|
arlo = hass.data.get(DATA_ARLO)
|
2017-05-31 07:25:25 +00:00
|
|
|
if not arlo:
|
|
|
|
return False
|
|
|
|
|
|
|
|
sensors = []
|
|
|
|
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
|
|
|
|
if sensor_type == 'total_cameras':
|
2017-10-07 08:59:46 +00:00
|
|
|
sensors.append(ArloSensor(
|
|
|
|
hass, SENSOR_TYPES[sensor_type][0], arlo, sensor_type))
|
2017-05-31 07:25:25 +00:00
|
|
|
else:
|
|
|
|
for camera in arlo.cameras:
|
2017-10-07 08:59:46 +00:00
|
|
|
name = '{0} {1}'.format(
|
|
|
|
SENSOR_TYPES[sensor_type][0], camera.name)
|
2017-05-31 07:25:25 +00:00
|
|
|
sensors.append(ArloSensor(hass, name, camera, sensor_type))
|
|
|
|
|
|
|
|
async_add_devices(sensors, True)
|
|
|
|
|
|
|
|
|
|
|
|
class ArloSensor(Entity):
|
|
|
|
"""An implementation of a Netgear Arlo IP sensor."""
|
|
|
|
|
|
|
|
def __init__(self, hass, name, device, sensor_type):
|
|
|
|
"""Initialize an Arlo sensor."""
|
|
|
|
super().__init__()
|
|
|
|
self._name = name
|
|
|
|
self._hass = hass
|
|
|
|
self._data = device
|
|
|
|
self._sensor_type = sensor_type
|
|
|
|
self._state = None
|
|
|
|
self._icon = 'mdi:{}'.format(SENSOR_TYPES.get(self._sensor_type)[2])
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of this camera."""
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the state of the sensor."""
|
|
|
|
return self._state
|
|
|
|
|
|
|
|
@property
|
|
|
|
def icon(self):
|
|
|
|
"""Icon to use in the frontend, if any."""
|
2017-10-08 08:05:41 +00:00
|
|
|
if self._sensor_type == 'battery_level' and self._state is not None:
|
|
|
|
return icon_for_battery_level(battery_level=int(self._state),
|
|
|
|
charging=False)
|
2017-05-31 07:25:25 +00:00
|
|
|
return self._icon
|
|
|
|
|
|
|
|
@property
|
|
|
|
def unit_of_measurement(self):
|
|
|
|
"""Return the units of measurement."""
|
|
|
|
return SENSOR_TYPES.get(self._sensor_type)[1]
|
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Get the latest data and updates the state."""
|
2017-11-15 22:33:50 +00:00
|
|
|
try:
|
|
|
|
base_station = self._data.base_station
|
|
|
|
except (AttributeError, IndexError):
|
|
|
|
return
|
|
|
|
|
|
|
|
if not base_station:
|
|
|
|
return
|
|
|
|
|
|
|
|
base_station.refresh_rate = SCAN_INTERVAL.total_seconds()
|
|
|
|
|
2017-05-31 07:25:25 +00:00
|
|
|
self._data.update()
|
|
|
|
|
|
|
|
if self._sensor_type == 'total_cameras':
|
|
|
|
self._state = len(self._data.cameras)
|
|
|
|
|
|
|
|
elif self._sensor_type == 'captured_today':
|
|
|
|
self._state = len(self._data.captured_today)
|
|
|
|
|
|
|
|
elif self._sensor_type == 'last_capture':
|
|
|
|
try:
|
|
|
|
video = self._data.videos()[0]
|
|
|
|
self._state = video.created_at_pretty("%m-%d-%Y %H:%M:%S")
|
|
|
|
except (AttributeError, IndexError):
|
2017-10-02 10:38:55 +00:00
|
|
|
self._state = None
|
|
|
|
|
|
|
|
elif self._sensor_type == 'battery_level':
|
|
|
|
try:
|
2017-11-15 22:33:50 +00:00
|
|
|
self._state = self._data.battery_level
|
|
|
|
except TypeError:
|
|
|
|
self._state = None
|
|
|
|
|
|
|
|
elif self._sensor_type == 'signal_strength':
|
|
|
|
try:
|
|
|
|
self._state = self._data.signal_strength
|
2017-10-02 10:38:55 +00:00
|
|
|
except TypeError:
|
|
|
|
self._state = None
|
2017-05-31 07:25:25 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def device_state_attributes(self):
|
2017-10-07 08:59:46 +00:00
|
|
|
"""Return the device state attributes."""
|
2017-05-31 07:25:25 +00:00
|
|
|
attrs = {}
|
|
|
|
|
|
|
|
attrs[ATTR_ATTRIBUTION] = CONF_ATTRIBUTION
|
|
|
|
attrs['brand'] = DEFAULT_BRAND
|
|
|
|
|
|
|
|
if self._sensor_type == 'last_capture' or \
|
2017-10-02 10:38:55 +00:00
|
|
|
self._sensor_type == 'captured_today' or \
|
2017-11-15 22:33:50 +00:00
|
|
|
self._sensor_type == 'battery_level' or \
|
|
|
|
self._sensor_type == 'signal_strength':
|
2017-05-31 07:25:25 +00:00
|
|
|
attrs['model'] = self._data.model_id
|
|
|
|
|
|
|
|
return attrs
|