Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use voluptuous for aREST #3487

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions homeassistant/components/binary_sensor/arest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Support for exposed aREST RESTful API of a device.
Support for an 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/
Expand All @@ -8,31 +8,32 @@
from datetime import timedelta

import requests
import voluptuous as vol

from homeassistant.components.binary_sensor import (
BinarySensorDevice, SENSOR_CLASSES)
from homeassistant.const import CONF_RESOURCE, CONF_PIN
BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA)
from homeassistant.const import (
CONF_RESOURCE, CONF_PIN, CONF_NAME, CONF_SENSOR_CLASS)
from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_RESOURCE): cv.url,
vol.Optional(CONF_NAME): cv.string,
vol.Required(CONF_PIN): cv.string,
vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA,
})


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
sensor_class = config.get(CONF_SENSOR_CLASS)

try:
response = requests.get(resource, timeout=10).json()
Expand All @@ -49,11 +50,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
arest = ArestData(resource, pin)

add_devices([ArestBinarySensor(
arest,
resource,
config.get('name', response['name']),
sensor_class,
pin)])
arest, resource, config.get(CONF_NAME, response[CONF_NAME]),
sensor_class, pin)])


# pylint: disable=too-many-instance-attributes, too-many-arguments
Expand Down
80 changes: 45 additions & 35 deletions homeassistant/components/sensor/arest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
The arest sensor will consume an exposed aREST API of a device.
Support for an exposed aREST RESTful API of a device.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.arest/
Expand All @@ -8,30 +8,48 @@
from datetime import timedelta

import requests
import voluptuous as vol

from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE, DEVICE_DEFAULT_NAME,
CONF_RESOURCE, CONF_MONITORED_VARIABLES)
CONF_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE, CONF_RESOURCE,
CONF_MONITORED_VARIABLES, CONF_NAME, STATE_UNKNOWN)
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.entity import Entity
from homeassistant.helpers import template
from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)

CONF_FUNCTIONS = 'functions'
CONF_PINS = 'pins'

DEFAULT_NAME = 'aREST sensor'

PIN_VARIABLE_SCHEMA = vol.Schema({
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
})

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_RESOURCE): cv.url,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PINS, default={}):
vol.Schema({cv.string: PIN_VARIABLE_SCHEMA}),
vol.Optional(CONF_MONITORED_VARIABLES, default={}):
vol.Schema({cv.string: PIN_VARIABLE_SCHEMA}),
})


def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the aREST sensor."""
resource = config.get(CONF_RESOURCE)
var_conf = config.get(CONF_MONITORED_VARIABLES)
pins = config.get('pins', None)

if resource is None:
_LOGGER.error('Not all required config keys present: %s',
CONF_RESOURCE)
return False
pins = config.get(CONF_PINS)

try:
response = requests.get(resource, timeout=10).json()
Expand Down Expand Up @@ -65,32 +83,26 @@ def _render(value):

if var_conf is not None:
for variable in var_conf:
if variable['name'] not in response['variables']:
if variable[CONF_NAME] not in response['variables']:
_LOGGER.error('Variable: "%s" does not exist',
variable['name'])
variable[CONF_NAME])
continue

renderer = make_renderer(variable.get(CONF_VALUE_TEMPLATE))
dev.append(ArestSensor(arest,
resource,
config.get('name', response['name']),
variable['name'],
variable=variable['name'],
unit_of_measurement=variable.get(
ATTR_UNIT_OF_MEASUREMENT),
renderer=renderer))
dev.append(ArestSensor(
arest, resource, config.get(CONF_NAME, response[CONF_NAME]),
variable[CONF_NAME], variable=variable[CONF_NAME],
unit_of_measurement=variable.get(CONF_UNIT_OF_MEASUREMENT),
renderer=renderer))

if pins is not None:
for pinnum, pin in pins.items():
renderer = make_renderer(pin.get(CONF_VALUE_TEMPLATE))
dev.append(ArestSensor(ArestData(resource, pinnum),
resource,
config.get('name', response['name']),
pin.get('name'),
pin=pinnum,
unit_of_measurement=pin.get(
ATTR_UNIT_OF_MEASUREMENT),
renderer=renderer))
dev.append(ArestSensor(
ArestData(resource, pinnum), resource,
config.get(CONF_NAME, response[CONF_NAME]), pin.get(CONF_NAME),
pin=pinnum, unit_of_measurement=pin.get(
CONF_UNIT_OF_MEASUREMENT), renderer=renderer))

add_devices(dev)

Expand All @@ -104,18 +116,17 @@ def __init__(self, arest, resource, location, name, variable=None,
"""Initialize the sensor."""
self.arest = arest
self._resource = resource
self._name = '{} {}'.format(location.title(), name.title()) \
or DEVICE_DEFAULT_NAME
self._name = '{} {}'.format(location.title(), name.title())
self._variable = variable
self._pin = pin
self._state = 'n/a'
self._state = STATE_UNKNOWN
self._unit_of_measurement = unit_of_measurement
self._renderer = renderer
self.update()

if self._pin is not None:
request = requests.get('{}/mode/{}/i'.format
(self._resource, self._pin), timeout=10)
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?")

Expand All @@ -137,9 +148,8 @@ def state(self):
if 'error' in values:
return values['error']

value = self._renderer(values.get('value',
values.get(self._variable,
'N/A')))
value = self._renderer(
values.get('value', values.get(self._variable, STATE_UNKNOWN)))
return value

def update(self):
Expand Down
88 changes: 53 additions & 35 deletions homeassistant/components/switch/arest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Support for device running with the aREST RESTful framework.
Support for an exposed aREST RESTful API of a device.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.arest/
Expand All @@ -8,17 +8,36 @@
import logging

import requests
import voluptuous as vol

from homeassistant.components.switch import SwitchDevice
from homeassistant.const import (
DEVICE_DEFAULT_NAME, CONF_NAME, CONF_RESOURCE)
from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_NAME, CONF_RESOURCE)
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

CONF_FUNCTIONS = 'functions'
CONF_PINS = 'pins'

DEFAULT_NAME = 'aREST switch'

PIN_FUNCTION_SCHEMA = vol.Schema({
vol.Optional(CONF_NAME): cv.string,
})

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_RESOURCE): cv.url,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PINS, default={}):
vol.Schema({cv.string: PIN_FUNCTION_SCHEMA}),
vol.Optional(CONF_FUNCTIONS, default={}):
vol.Schema({cv.string: PIN_FUNCTION_SCHEMA}),
})


def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the aREST switches."""
resource = config.get(CONF_RESOURCE, None)
resource = config.get(CONF_RESOURCE)

try:
response = requests.get(resource, timeout=10)
Expand All @@ -33,29 +52,28 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
return False

dev = []
pins = config.get('pins', {})
pins = config.get(CONF_PINS)
for pinnum, pin in pins.items():
dev.append(ArestSwitchPin(
resource, config.get(CONF_NAME, response.json()['name']),
pin.get('name'), pinnum))
resource, config.get(CONF_NAME, response.json()[CONF_NAME]),
pin.get(CONF_NAME), pinnum))

functions = config.get('functions', {})
functions = config.get(CONF_FUNCTIONS)
for funcname, func in functions.items():
dev.append(ArestSwitchFunction(
resource, config.get(CONF_NAME, response.json()['name']),
func.get('name'), funcname))
resource, config.get(CONF_NAME, response.json()[CONF_NAME]),
func.get(CONF_NAME), funcname))

add_devices(dev)


class ArestSwitchBase(SwitchDevice):
"""representation of an aREST switch."""
"""Representation of an aREST switch."""

def __init__(self, resource, location, name):
"""Initialize the switch."""
self._resource = resource
self._name = '{} {}'.format(location.title(), name.title()) \
or DEVICE_DEFAULT_NAME
self._name = '{} {}'.format(location.title(), name.title())
self._state = None

@property
Expand All @@ -77,8 +95,8 @@ def __init__(self, resource, location, name, func):
super().__init__(resource, location, name)
self._func = func

request = requests.get('{}/{}'.format(self._resource, self._func),
timeout=10)
request = requests.get(
'{}/{}'.format(self._resource, self._func), timeout=10)

if request.status_code is not 200:
_LOGGER.error("Can't find function. Is device offline?")
Expand All @@ -90,36 +108,36 @@ def __init__(self, resource, location, name, func):
_LOGGER.error("No return_value received. "
"Is the function name correct.")
except ValueError:
_LOGGER.error("Response invalid. Is the function name correct.")
_LOGGER.error("Response invalid. Is the function name correct?")

def turn_on(self, **kwargs):
"""Turn the device on."""
request = requests.get('{}/{}'.format(self._resource, self._func),
timeout=10, params={"params": "1"})
request = requests.get(
'{}/{}'.format(self._resource, self._func), timeout=10,
params={'params': '1'})

if request.status_code == 200:
self._state = True
else:
_LOGGER.error("Can't turn on function %s at %s. "
"Is device offline?",
self._func, self._resource)
"Is device offline?", self._func, self._resource)

def turn_off(self, **kwargs):
"""Turn the device off."""
request = requests.get('{}/{}'.format(self._resource, self._func),
timeout=10, params={"params": "0"})
request = requests.get(
'{}/{}'.format(self._resource, self._func), timeout=10,
params={'params': '0'})

if request.status_code == 200:
self._state = False
else:
_LOGGER.error("Can't turn off function %s at %s. "
"Is device offline?",
self._func, self._resource)
"Is device offline?", self._func, self._resource)

def update(self):
"""Get the latest data from aREST API and update the state."""
request = requests.get('{}/{}'.format(self._resource,
self._func), timeout=10)
request = requests.get(
'{}/{}'.format(self._resource, self._func), timeout=10)
self._state = request.json()['return_value'] != 0


Expand All @@ -131,15 +149,15 @@ def __init__(self, resource, location, name, pin):
super().__init__(resource, location, name)
self._pin = pin

request = requests.get('{}/mode/{}/o'.format(self._resource,
self._pin), timeout=10)
request = requests.get(
'{}/mode/{}/o'.format(self._resource, self._pin), timeout=10)
if request.status_code is not 200:
_LOGGER.error("Can't set mode. Is device offline?")

def turn_on(self, **kwargs):
"""Turn the device on."""
request = requests.get('{}/digital/{}/1'.format(self._resource,
self._pin), timeout=10)
request = requests.get(
'{}/digital/{}/1'.format(self._resource, self._pin), timeout=10)
if request.status_code == 200:
self._state = True
else:
Expand All @@ -148,8 +166,8 @@ def turn_on(self, **kwargs):

def turn_off(self, **kwargs):
"""Turn the device off."""
request = requests.get('{}/digital/{}/0'.format(self._resource,
self._pin), timeout=10)
request = requests.get(
'{}/digital/{}/0'.format(self._resource, self._pin), timeout=10)
if request.status_code == 200:
self._state = False
else:
Expand All @@ -158,6 +176,6 @@ def turn_off(self, **kwargs):

def update(self):
"""Get the latest data from aREST API and update the state."""
request = requests.get('{}/digital/{}'.format(self._resource,
self._pin), timeout=10)
request = requests.get(
'{}/digital/{}'.format(self._resource, self._pin), timeout=10)
self._state = request.json()['return_value'] != 0