""" Support for exposed aREST RESTful API of a device. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.arest/ """ import logging from datetime import timedelta import requests from homeassistant.components.binary_sensor import (BinarySensorDevice, SENSOR_CLASSES) from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) # Return cached results if last scan was less then this time ago MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) CONF_RESOURCE = 'resource' CONF_PIN = 'pin' def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the aREST binary sensor.""" resource = config.get(CONF_RESOURCE) pin = config.get(CONF_PIN) sensor_class = config.get('sensor_class') if sensor_class not in SENSOR_CLASSES: _LOGGER.warning('Unknown sensor class: %s', sensor_class) sensor_class = None if None in (resource, pin): _LOGGER.error('Not all required config keys present: %s', ', '.join((CONF_RESOURCE, CONF_PIN))) return False try: response = requests.get(resource, timeout=10).json() except requests.exceptions.MissingSchema: _LOGGER.error('Missing resource or schema in configuration. ' 'Add http:// to your URL.') return False except requests.exceptions.ConnectionError: _LOGGER.error('No route to device at %s. ' 'Please check the IP address in the configuration file.', resource) return False arest = ArestData(resource, pin) add_devices([ArestBinarySensor( arest, resource, config.get('name', response['name']), sensor_class, pin)]) # pylint: disable=too-many-instance-attributes, too-many-arguments class ArestBinarySensor(BinarySensorDevice): """Implement an aREST binary sensor for a pin.""" def __init__(self, arest, resource, name, sensor_class, pin): """Initialize the aREST device.""" self.arest = arest self._resource = resource self._name = name self._sensor_class = sensor_class self._pin = pin self.update() if self._pin is not None: request = requests.get('{}/mode/{}/i'.format (self._resource, self._pin), timeout=10) if request.status_code is not 200: _LOGGER.error("Can't set mode. Is device offline?") @property def name(self): """Return the name of the binary sensor.""" return self._name @property def is_on(self): """Return true if the binary sensor is on.""" return bool(self.arest.data.get('state')) @property def sensor_class(self): """Return the class of this sensor.""" return self._sensor_class def update(self): """Get the latest data from aREST API.""" self.arest.update() # pylint: disable=too-few-public-methods class ArestData(object): """Class for handling the data retrieval for pins.""" def __init__(self, resource, pin): """Initialize the aREST data object.""" self._resource = resource self._pin = pin self.data = {} @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Get the latest data from aREST device.""" try: response = requests.get('{}/digital/{}'.format( self._resource, self._pin), timeout=10) self.data = {'state': response.json()['return_value']} except requests.exceptions.ConnectionError: _LOGGER.error("No route to device '%s'. Is device offline?", self._resource)