2019-02-14 04:35:12 +00:00
|
|
|
"""Support for the Netatmo cameras."""
|
2016-06-10 06:31:36 +00:00
|
|
|
import logging
|
2016-08-26 20:50:32 +00:00
|
|
|
|
2016-06-10 06:31:36 +00:00
|
|
|
import requests
|
2016-08-26 20:50:32 +00:00
|
|
|
import voluptuous as vol
|
2016-06-10 06:31:36 +00:00
|
|
|
|
2019-04-10 23:10:14 +00:00
|
|
|
from homeassistant.components.camera import (
|
|
|
|
PLATFORM_SCHEMA, Camera, SUPPORT_STREAM)
|
2017-02-01 16:33:32 +00:00
|
|
|
from homeassistant.const import CONF_VERIFY_SSL
|
2016-08-26 20:50:32 +00:00
|
|
|
from homeassistant.helpers import config_validation as cv
|
2016-06-10 06:31:36 +00:00
|
|
|
|
2019-04-26 15:15:37 +00:00
|
|
|
from .const import DATA_NETATMO_AUTH
|
|
|
|
from . import CameraData
|
2019-03-21 05:56:46 +00:00
|
|
|
|
2016-06-10 06:31:36 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
CONF_HOME = 'home'
|
2016-08-26 20:50:32 +00:00
|
|
|
CONF_CAMERAS = 'cameras'
|
2019-04-10 23:10:14 +00:00
|
|
|
CONF_QUALITY = 'quality'
|
|
|
|
|
|
|
|
DEFAULT_QUALITY = 'high'
|
|
|
|
|
|
|
|
VALID_QUALITIES = ['high', 'medium', 'low', 'poor']
|
2016-06-10 06:31:36 +00:00
|
|
|
|
2016-08-26 20:50:32 +00:00
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
2017-02-01 16:33:32 +00:00
|
|
|
vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
|
2016-08-26 20:50:32 +00:00
|
|
|
vol.Optional(CONF_HOME): cv.string,
|
|
|
|
vol.Optional(CONF_CAMERAS, default=[]):
|
|
|
|
vol.All(cv.ensure_list, [cv.string]),
|
2019-04-10 23:10:14 +00:00
|
|
|
vol.Optional(CONF_QUALITY, default=DEFAULT_QUALITY):
|
|
|
|
vol.All(cv.string, vol.In(VALID_QUALITIES)),
|
2016-08-26 20:50:32 +00:00
|
|
|
})
|
|
|
|
|
2016-06-10 06:31:36 +00:00
|
|
|
|
2018-08-24 14:37:30 +00:00
|
|
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
2017-04-30 05:04:49 +00:00
|
|
|
"""Set up access to Netatmo cameras."""
|
2016-08-26 20:50:32 +00:00
|
|
|
home = config.get(CONF_HOME)
|
2017-02-01 16:33:32 +00:00
|
|
|
verify_ssl = config.get(CONF_VERIFY_SSL, True)
|
2019-04-10 23:10:14 +00:00
|
|
|
quality = config.get(CONF_QUALITY, DEFAULT_QUALITY)
|
2018-06-05 15:55:53 +00:00
|
|
|
import pyatmo
|
2019-04-26 15:15:37 +00:00
|
|
|
|
|
|
|
auth = hass.data[DATA_NETATMO_AUTH]
|
|
|
|
|
2016-09-29 14:45:54 +00:00
|
|
|
try:
|
2019-04-26 15:15:37 +00:00
|
|
|
data = CameraData(hass, auth, home)
|
2016-10-13 16:21:22 +00:00
|
|
|
for camera_name in data.get_camera_names():
|
2017-01-17 07:10:18 +00:00
|
|
|
camera_type = data.get_camera_type(camera=camera_name, home=home)
|
2016-10-13 16:21:22 +00:00
|
|
|
if CONF_CAMERAS in config:
|
|
|
|
if config[CONF_CAMERAS] != [] and \
|
|
|
|
camera_name not in config[CONF_CAMERAS]:
|
|
|
|
continue
|
2018-08-24 14:37:30 +00:00
|
|
|
add_entities([NetatmoCamera(data, camera_name, home,
|
2019-04-10 23:10:14 +00:00
|
|
|
camera_type, verify_ssl, quality)])
|
2019-02-17 11:31:47 +00:00
|
|
|
data.get_persons()
|
2018-06-05 15:55:53 +00:00
|
|
|
except pyatmo.NoDevice:
|
2016-09-29 14:45:54 +00:00
|
|
|
return None
|
2016-06-10 06:31:36 +00:00
|
|
|
|
|
|
|
|
2017-01-17 07:10:18 +00:00
|
|
|
class NetatmoCamera(Camera):
|
|
|
|
"""Representation of the images published from a Netatmo camera."""
|
2016-06-10 06:31:36 +00:00
|
|
|
|
2019-04-10 23:10:14 +00:00
|
|
|
def __init__(self, data, camera_name, home, camera_type, verify_ssl,
|
|
|
|
quality):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Set up for access to the Netatmo camera images."""
|
2017-01-17 07:10:18 +00:00
|
|
|
super(NetatmoCamera, self).__init__()
|
2016-06-10 06:31:36 +00:00
|
|
|
self._data = data
|
|
|
|
self._camera_name = camera_name
|
2017-02-01 16:33:32 +00:00
|
|
|
self._verify_ssl = verify_ssl
|
2019-04-10 23:10:14 +00:00
|
|
|
self._quality = quality
|
2016-06-10 06:31:36 +00:00
|
|
|
if home:
|
|
|
|
self._name = home + ' / ' + camera_name
|
|
|
|
else:
|
|
|
|
self._name = camera_name
|
2017-01-17 07:10:18 +00:00
|
|
|
self._vpnurl, self._localurl = self._data.camera_data.cameraUrls(
|
2016-06-10 06:31:36 +00:00
|
|
|
camera=camera_name
|
|
|
|
)
|
2017-01-17 07:10:18 +00:00
|
|
|
self._cameratype = camera_type
|
2016-06-10 06:31:36 +00:00
|
|
|
|
|
|
|
def camera_image(self):
|
|
|
|
"""Return a still image response from the camera."""
|
|
|
|
try:
|
|
|
|
if self._localurl:
|
|
|
|
response = requests.get('{0}/live/snapshot_720.jpg'.format(
|
2016-06-18 20:06:14 +00:00
|
|
|
self._localurl), timeout=10)
|
2017-02-01 16:33:32 +00:00
|
|
|
elif self._vpnurl:
|
2016-06-10 06:31:36 +00:00
|
|
|
response = requests.get('{0}/live/snapshot_720.jpg'.format(
|
2017-02-01 16:33:32 +00:00
|
|
|
self._vpnurl), timeout=10, verify=self._verify_ssl)
|
|
|
|
else:
|
2017-04-30 05:04:49 +00:00
|
|
|
_LOGGER.error("Welcome VPN URL is None")
|
2017-02-01 16:33:32 +00:00
|
|
|
self._data.update()
|
|
|
|
(self._vpnurl, self._localurl) = \
|
|
|
|
self._data.camera_data.cameraUrls(camera=self._camera_name)
|
|
|
|
return None
|
2016-06-10 06:31:36 +00:00
|
|
|
except requests.exceptions.RequestException as error:
|
2017-04-30 05:04:49 +00:00
|
|
|
_LOGGER.error("Welcome URL changed: %s", error)
|
2016-06-10 06:31:36 +00:00
|
|
|
self._data.update()
|
|
|
|
(self._vpnurl, self._localurl) = \
|
2017-01-17 07:10:18 +00:00
|
|
|
self._data.camera_data.cameraUrls(camera=self._camera_name)
|
2016-06-10 06:31:36 +00:00
|
|
|
return None
|
|
|
|
return response.content
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
2017-01-17 07:10:18 +00:00
|
|
|
"""Return the name of this Netatmo camera device."""
|
2016-06-10 06:31:36 +00:00
|
|
|
return self._name
|
|
|
|
|
2017-01-17 07:10:18 +00:00
|
|
|
@property
|
|
|
|
def brand(self):
|
2017-04-30 05:04:49 +00:00
|
|
|
"""Return the camera brand."""
|
2017-01-17 07:10:18 +00:00
|
|
|
return "Netatmo"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def model(self):
|
2017-04-30 05:04:49 +00:00
|
|
|
"""Return the camera model."""
|
2017-01-17 07:10:18 +00:00
|
|
|
if self._cameratype == "NOC":
|
|
|
|
return "Presence"
|
2018-07-23 08:16:05 +00:00
|
|
|
if self._cameratype == "NACamera":
|
2017-01-17 07:10:18 +00:00
|
|
|
return "Welcome"
|
2017-07-06 06:30:01 +00:00
|
|
|
return None
|
2019-04-10 23:10:14 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def supported_features(self):
|
|
|
|
"""Return supported features."""
|
|
|
|
return SUPPORT_STREAM
|
|
|
|
|
2019-05-23 16:45:30 +00:00
|
|
|
async def stream_source(self):
|
2019-04-10 23:10:14 +00:00
|
|
|
"""Return the stream source."""
|
|
|
|
url = '{0}/live/files/{1}/index.m3u8'
|
|
|
|
if self._localurl:
|
|
|
|
return url.format(self._localurl, self._quality)
|
|
|
|
return url.format(self._vpnurl, self._quality)
|