mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Hook Smart Home support (#4392)
* Support for Hook (hooksmarthome.com) * Linting * Add asyncio * Move to aiohttp * Yield more
This commit is contained in:
parent
05181bf232
commit
5013a82655
@ -317,6 +317,7 @@ omit =
|
||||
homeassistant/components/switch/dlink.py
|
||||
homeassistant/components/switch/edimax.py
|
||||
homeassistant/components/switch/hikvisioncam.py
|
||||
homeassistant/components/switch/hook.py
|
||||
homeassistant/components/switch/mystrom.py
|
||||
homeassistant/components/switch/netio.py
|
||||
homeassistant/components/switch/orvibo.py
|
||||
|
137
homeassistant/components/switch/hook.py
Normal file
137
homeassistant/components/switch/hook.py
Normal file
@ -0,0 +1,137 @@
|
||||
"""
|
||||
Support Hook, available at hooksmarthome.com.
|
||||
|
||||
Controls RF switches like these:
|
||||
https://www.amazon.com/Etekcity-Wireless-Electrical-Household-Appliances/dp/B00DQELHBS
|
||||
|
||||
There is no way to query for state or success of commands.
|
||||
|
||||
"""
|
||||
import logging
|
||||
import asyncio
|
||||
import voluptuous as vol
|
||||
import async_timeout
|
||||
import aiohttp
|
||||
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
HOOK_ENDPOINT = "https://api.gethook.io/v1/"
|
||||
TIMEOUT = 10
|
||||
|
||||
SWITCH_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string
|
||||
})
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||
"""Setup Hook by getting the access token and list of actions."""
|
||||
username = config.get(CONF_USERNAME)
|
||||
password = config.get(CONF_PASSWORD)
|
||||
|
||||
try:
|
||||
with async_timeout.timeout(TIMEOUT, loop=hass.loop):
|
||||
response = yield from hass.websession.post(
|
||||
HOOK_ENDPOINT + 'user/login',
|
||||
data={
|
||||
'username': username,
|
||||
'password': password})
|
||||
data = yield from response.json()
|
||||
except (asyncio.TimeoutError,
|
||||
aiohttp.errors.ClientError,
|
||||
aiohttp.errors.ClientDisconnectedError) as error:
|
||||
_LOGGER.error("Failed authentication API call: %s", error)
|
||||
return False
|
||||
|
||||
try:
|
||||
token = data['data']['token']
|
||||
except KeyError:
|
||||
_LOGGER.error("No token. Check username and password")
|
||||
return False
|
||||
|
||||
try:
|
||||
with async_timeout.timeout(TIMEOUT, loop=hass.loop):
|
||||
response = yield from hass.websession.get(
|
||||
HOOK_ENDPOINT + 'device',
|
||||
params={"token": data['data']['token']})
|
||||
data = yield from response.json()
|
||||
except (asyncio.TimeoutError,
|
||||
aiohttp.errors.ClientError,
|
||||
aiohttp.errors.ClientDisconnectedError) as error:
|
||||
_LOGGER.error("Failed getting devices: %s", error)
|
||||
return False
|
||||
|
||||
yield from async_add_devices(
|
||||
HookSmartHome(
|
||||
hass,
|
||||
token,
|
||||
d['device_id'],
|
||||
d['device_name'])
|
||||
for lst in data['data']
|
||||
for d in lst)
|
||||
|
||||
|
||||
class HookSmartHome(SwitchDevice):
|
||||
"""Representation of a Hook device, allowing on and off commands."""
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def __init__(self, hass, token, device_id, device_name):
|
||||
"""Initialize the switch."""
|
||||
self._hass = hass
|
||||
self._token = token
|
||||
self._state = False
|
||||
self._id = device_id
|
||||
self._name = device_name
|
||||
_LOGGER.debug(
|
||||
"Creating Hook object: ID: " + self._id +
|
||||
" Name: " + self._name)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the switch."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on."""
|
||||
return self._state
|
||||
|
||||
@asyncio.coroutine
|
||||
def _send(self, url):
|
||||
"""Send the url to the Hook API."""
|
||||
try:
|
||||
_LOGGER.debug("Sending: %s", url)
|
||||
with async_timeout.timeout(TIMEOUT, loop=self._hass.loop):
|
||||
response = yield from self._hass.websession.get(
|
||||
url,
|
||||
params={"token": self._token})
|
||||
data = yield from response.json()
|
||||
except (asyncio.TimeoutError,
|
||||
aiohttp.errors.ClientError,
|
||||
aiohttp.errors.ClientDisconnectedError) as error:
|
||||
_LOGGER.error("Failed setting state: %s", error)
|
||||
return False
|
||||
_LOGGER.debug("Got: %s", data)
|
||||
return data['return_value'] == '1'
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_turn_on(self):
|
||||
"""Turn the device on asynchronously."""
|
||||
_LOGGER.debug("Turning on: %s", self._name)
|
||||
success = yield from self._send(
|
||||
HOOK_ENDPOINT + 'device/trigger/' + self._id + '/On')
|
||||
self._state = success
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_turn_off(self):
|
||||
"""Turn the device off asynchronously."""
|
||||
_LOGGER.debug("Turning off: %s", self._name)
|
||||
success = yield from self._send(
|
||||
HOOK_ENDPOINT + 'device/trigger/' + self._id + '/Off')
|
||||
# If it wasn't successful, keep state as true
|
||||
self._state = not success
|
Loading…
x
Reference in New Issue
Block a user