diff --git a/.coveragerc b/.coveragerc index 447e683246b..ca5546cf242 100644 --- a/.coveragerc +++ b/.coveragerc @@ -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 diff --git a/homeassistant/components/camera/__init__.py b/homeassistant/components/camera/__init__.py index 0be1d4118f7..649d540a44d 100644 --- a/homeassistant/components/camera/__init__.py +++ b/homeassistant/components/camera/__init__.py @@ -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' diff --git a/homeassistant/components/camera/netatmo.py b/homeassistant/components/camera/netatmo.py new file mode 100644 index 00000000000..8e03dc932e9 --- /dev/null +++ b/homeassistant/components/camera/netatmo.py @@ -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) diff --git a/homeassistant/components/netatmo.py b/homeassistant/components/netatmo.py new file mode 100644 index 00000000000..737819fffbb --- /dev/null +++ b/homeassistant/components/netatmo.py @@ -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 diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 3c625ae4a85..4cd5c50f22e 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -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', } diff --git a/homeassistant/components/sensor/netatmo.py b/homeassistant/components/sensor/netatmo.py index 184f9fe18a2..22caab1d1fb 100644 --- a/homeassistant/components/sensor/netatmo.py +++ b/homeassistant/components/sensor/netatmo.py @@ -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: diff --git a/requirements_all.txt b/requirements_all.txt index 6c55f638b28..07db2ad3a48 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -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