Add Netatmo component and add support for Netatmo Welcome Camera (#2233)

* Introducing the Netatmo component

As Netatmo is providing several type of device (sensor, camera), a new Netatmo
component needs to be created in order to centralize the Netatmo login data.
Currently this change only impacts the Netatmo Weather station

* Add new Netatmo library

This new API will provide access to the Welcome Camera

* Basic support for Netatmo Welcome camera

This change introduces support for Netatmo Welcome camera. Currently, it will
add all detected camera to Home Assistant, camera filtering (similar to the one
used for weather station modules) will be added later

* Remove useless REQUIREMENTS

* Fixes for Netatmo Welcome support

* Allow to filter Welcome cameras by name and/or home

* Update requirements for Netatmo components

* Fix multi-camera support for Welcome

* Fix pep8 error/warning

* This commit also adds improved logging for bad credentials

* Add Throttle decorator for Welcome update function

As the update function updates the data for all cameras, we should prevent this
function to be called several time during an interval
This commit is contained in:
Hugo Dupras 2016-06-10 08:31:36 +02:00 committed by Paulus Schoutsen
parent e4fe8336cc
commit 213a738240
7 changed files with 182 additions and 39 deletions

View File

@ -78,6 +78,9 @@ omit =
homeassistant/components/enocean.py
homeassistant/components/*/enocean.py
homeassistant/components/netatmo.py
homeassistant/components/*/netatmo.py
homeassistant/components/alarm_control_panel/alarmdotcom.py
homeassistant/components/alarm_control_panel/nx584.py
homeassistant/components/binary_sensor/arest.py
@ -171,7 +174,6 @@ omit =
homeassistant/components/sensor/gtfs.py
homeassistant/components/sensor/lastfm.py
homeassistant/components/sensor/loopenergy.py
homeassistant/components/sensor/netatmo.py
homeassistant/components/sensor/neurio_energy.py
homeassistant/components/sensor/nzbget.py
homeassistant/components/sensor/onewire.py

View File

@ -9,7 +9,7 @@ import logging
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.components import bloomsky
from homeassistant.components import bloomsky, netatmo
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
from homeassistant.components.http import HomeAssistantView
@ -21,6 +21,7 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}'
# Maps discovered services to their platforms
DISCOVERY_PLATFORMS = {
bloomsky.DISCOVER_CAMERAS: 'bloomsky',
netatmo.DISCOVER_CAMERAS: 'netatmo',
}
STATE_RECORDING = 'recording'

View File

@ -0,0 +1,104 @@
"""
Support for the Netatmo Welcome camera.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.netatmo/
"""
import logging
from datetime import timedelta
import requests
from homeassistant.util import Throttle
from homeassistant.components.camera import Camera
from homeassistant.loader import get_component
DEPENDENCIES = ["netatmo"]
_LOGGER = logging.getLogger(__name__)
CONF_HOME = 'home'
ATTR_CAMERAS = 'cameras'
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
"""Setup access to Netatmo Welcome cameras."""
netatmo = get_component('netatmo')
home = config.get(CONF_HOME, None)
data = WelcomeData(netatmo.NETATMO_AUTH, home)
for camera_name in data.get_camera_names():
if ATTR_CAMERAS in config:
if camera_name not in config[ATTR_CAMERAS]:
continue
add_devices_callback([WelcomeCamera(data, camera_name, home)])
class WelcomeCamera(Camera):
"""Representation of the images published from Welcome camera."""
def __init__(self, data, camera_name, home):
"""Setup for access to the BloomSky camera images."""
super(WelcomeCamera, self).__init__()
self._data = data
self._camera_name = camera_name
if home:
self._name = home + ' / ' + camera_name
else:
self._name = camera_name
self._vpnurl, self._localurl = self._data.welcomedata.cameraUrls(
camera=camera_name
)
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(
self._localurl))
else:
response = requests.get('{0}/live/snapshot_720.jpg'.format(
self._vpnurl))
except requests.exceptions.RequestException as error:
_LOGGER.error('Welcome VPN url changed: %s', error)
self._data.update()
(self._vpnurl, self._localurl) = \
self._data.welcomedata.cameraUrls(camera=self._camera_name)
return None
return response.content
@property
def name(self):
"""Return the name of this Netatmo Welcome device."""
return self._name
class WelcomeData(object):
"""Get the latest data from NetAtmo."""
def __init__(self, auth, home=None):
"""Initialize the data object."""
self.auth = auth
self.welcomedata = None
self.camera_names = []
self.home = home
def get_camera_names(self):
"""Return all module available on the API as a list."""
self.update()
if not self.home:
for home in self.welcomedata.cameras.keys():
for camera in self.welcomedata.cameras[home].values():
self.camera_names.append(camera['name'])
else:
for camera in self.welcomedata.cameras[self.home].values():
self.camera_names.append(camera['name'])
return self.camera_names
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Call the NetAtmo API to update the data."""
import lnetatmo
self.welcomedata = lnetatmo.WelcomeData(self.auth)

View File

@ -0,0 +1,62 @@
"""
Support for the Netatmo devices (Weather Station and Welcome camera).
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/netatmo/
"""
import logging
from urllib.error import HTTPError
from homeassistant.components import discovery
from homeassistant.const import (
CONF_API_KEY, CONF_PASSWORD, CONF_USERNAME)
from homeassistant.helpers import validate_config
REQUIREMENTS = [
'https://github.com/jabesq/netatmo-api-python/archive/'
'v0.5.0.zip#lnetatmo==0.5.0']
_LOGGER = logging.getLogger(__name__)
CONF_SECRET_KEY = 'secret_key'
DOMAIN = "netatmo"
NETATMO_AUTH = None
_LOGGER = logging.getLogger(__name__)
DISCOVER_SENSORS = 'netatmo.sensors'
DISCOVER_CAMERAS = 'netatmo.cameras'
def setup(hass, config):
"""Setup the Netatmo devices."""
if not validate_config(config,
{DOMAIN: [CONF_API_KEY,
CONF_USERNAME,
CONF_PASSWORD,
CONF_SECRET_KEY]},
_LOGGER):
return None
import lnetatmo
global NETATMO_AUTH
try:
NETATMO_AUTH = lnetatmo.ClientAuth(config[DOMAIN][CONF_API_KEY],
config[DOMAIN][CONF_SECRET_KEY],
config[DOMAIN][CONF_USERNAME],
config[DOMAIN][CONF_PASSWORD],
"read_station read_camera "
"access_camera")
except HTTPError:
_LOGGER.error(
"Connection error "
"Please check your settings for NatAtmo API.")
return False
for component, discovery_service in (
('camera', DISCOVER_CAMERAS), ('sensor', DISCOVER_SENSORS)):
discovery.discover(hass, discovery_service, component=component,
hass_config=config)
return True

View File

@ -10,7 +10,7 @@ from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
from homeassistant.components import (
wink, zwave, isy994, verisure, ecobee, tellduslive, mysensors,
bloomsky, vera)
bloomsky, vera, netatmo)
DOMAIN = 'sensor'
SCAN_INTERVAL = 30
@ -28,6 +28,7 @@ DISCOVERY_PLATFORMS = {
tellduslive.DISCOVER_SENSORS: 'tellduslive',
mysensors.DISCOVER_SENSORS: 'mysensors',
vera.DISCOVER_SENSORS: 'vera',
netatmo.DISCOVER_SENSORS: 'netatmo',
}

View File

@ -6,18 +6,12 @@ https://home-assistant.io/components/sensor.netatmo/
"""
import logging
from datetime import timedelta
from homeassistant.components.sensor import DOMAIN
from homeassistant.const import (
CONF_API_KEY, CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS)
from homeassistant.helpers import validate_config
from homeassistant.const import TEMP_CELSIUS
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle
from homeassistant.loader import get_component
REQUIREMENTS = [
'https://github.com/HydrelioxGitHub/netatmo-api-python/archive/'
'43ff238a0122b0939a0dc4e8836b6782913fb6e2.zip'
'#lnetatmo==0.4.0']
DEPENDENCIES = ["netatmo"]
_LOGGER = logging.getLogger(__name__)
@ -32,7 +26,6 @@ SENSOR_TYPES = {
'sum_rain_24': ['sum_rain_24', 'mm', 'mdi:weather-rainy'],
}
CONF_SECRET_KEY = 'secret_key'
CONF_STATION = 'station'
ATTR_MODULE = 'modules'
@ -43,29 +36,9 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=600)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the NetAtmo sensor."""
if not validate_config({DOMAIN: config},
{DOMAIN: [CONF_API_KEY,
CONF_USERNAME,
CONF_PASSWORD,
CONF_SECRET_KEY]},
_LOGGER):
return None
import lnetatmo
authorization = lnetatmo.ClientAuth(config.get(CONF_API_KEY, None),
config.get(CONF_SECRET_KEY, None),
config.get(CONF_USERNAME, None),
config.get(CONF_PASSWORD, None))
if not authorization:
_LOGGER.error(
"Connection error "
"Please check your settings for NatAtmo API.")
return False
data = NetAtmoData(authorization, config.get(CONF_STATION, None))
"""Setup the available Netatmo weather sensors."""
netatmo = get_component('netatmo')
data = NetAtmoData(netatmo.NETATMO_AUTH, config.get(CONF_STATION, None))
dev = []
try:

View File

@ -94,9 +94,6 @@ hikvision==0.4
# homeassistant.components.sensor.dht
# http://github.com/mala-zaba/Adafruit_Python_DHT/archive/4101340de8d2457dd194bca1e8d11cbfc237e919.zip#Adafruit_DHT==1.1.0
# homeassistant.components.sensor.netatmo
https://github.com/HydrelioxGitHub/netatmo-api-python/archive/43ff238a0122b0939a0dc4e8836b6782913fb6e2.zip#lnetatmo==0.4.0
# homeassistant.components.switch.dlink
https://github.com/LinuxChristian/pyW215/archive/v0.1.1.zip#pyW215==0.1.1
@ -123,6 +120,9 @@ https://github.com/danieljkemp/onkyo-eiscp/archive/python3.zip#onkyo-eiscp==0.9.
# homeassistant.components.device_tracker.fritz
# https://github.com/deisi/fritzconnection/archive/b5c14515e1c8e2652b06b6316a7f3913df942841.zip#fritzconnection==0.4.6
# homeassistant.components.netatmo
https://github.com/jabesq/netatmo-api-python/archive/v0.5.0.zip#lnetatmo==0.5.0
# homeassistant.components.sensor.sabnzbd
https://github.com/jamespcole/home-assistant-nzb-clients/archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip#python-sabnzbd==0.1