Compare commits

...
Sign in to create a new pull request.

11 commits

Author SHA1 Message Date
Pascal Vizeli
8a364ab4f9
Update discovery.py 2018-09-27 12:40:25 +02:00
Pascal Vizeli
ec18d14eb6
Update discovery.py 2018-09-27 12:39:16 +02:00
Pascal Vizeli
f05ec652e6
Update discovery.py 2018-09-27 12:37:52 +02:00
Pascal Vizeli
1fa8eef966
Update __init__.py 2018-09-27 12:37:13 +02:00
Pascal Vizeli
c9710ccc3d
Update discovery.py 2018-09-27 12:35:58 +02:00
Pascal Vizeli
ac9ebeab9e
Update handler.py 2018-09-27 12:18:43 +02:00
Pascal Vizeli
2fe4c42cc1
Create discovery.py 2018-09-27 12:16:25 +02:00
Pascal Vizeli
ba9c88ddda
Update __init__.py 2018-09-27 11:59:57 +02:00
Pascal Vizeli
977f436b39
Update handler.py 2018-09-27 11:52:07 +02:00
Pascal Vizeli
1f27426c01
Update __init__.py 2018-09-27 11:50:46 +02:00
Pascal Vizeli
3a58aee32b
Update handler.py 2018-09-27 11:47:41 +02:00
3 changed files with 116 additions and 29 deletions

View file

@ -20,7 +20,8 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.loader import bind_hass
from homeassistant.util.dt import utcnow
from .handler import HassIO
from .handler import HassIO, HassioAPIError
from .discovery import async_setup_discovery
from .http import HassIOView
_LOGGER = logging.getLogger(__name__)
@ -138,10 +139,12 @@ def is_hassio(hass):
def async_check_config(hass):
"""Check configuration over Hass.io API."""
hassio = hass.data[DOMAIN]
result = yield from hassio.check_homeassistant_config()
if not result:
return "Hass.io config check API error"
try:
result = yield from hassio.check_homeassistant_config()
except HassioAPIError as err:
_LOGGER.error("Error on Hass.io API: %s", err)
if result['result'] == "error":
return result['message']
return None
@ -150,16 +153,11 @@ def async_check_config(hass):
@asyncio.coroutine
def async_setup(hass, config):
"""Set up the Hass.io component."""
try:
host = os.environ['HASSIO']
except KeyError:
_LOGGER.error("Missing HASSIO environment variable.")
return False
try:
os.environ['HASSIO_TOKEN']
except KeyError:
_LOGGER.error("Missing HASSIO_TOKEN environment variable.")
# Check local setup
for env in ('HASSIO', 'HASSIO_TOKEN'):
if os.environ.get(env):
continue
_LOGGER.error("Missing %s environment variable.", env)
return False
websession = hass.helpers.aiohttp_client.async_get_clientsession()
@ -233,13 +231,13 @@ def async_setup(hass, config):
payload = data
# Call API
ret = yield from hassio.send_command(
api_command.format(addon=addon, snapshot=snapshot),
payload=payload, timeout=MAP_SERVICE_API[service.service][2]
)
if not ret or ret['result'] != "ok":
_LOGGER.error("Error on Hass.io API: %s", ret['message'])
try:
ret = yield from hassio.send_command(
api_command.format(addon=addon, snapshot=snapshot),
payload=payload, timeout=MAP_SERVICE_API[service.service][2]
)
except HassioAPIError as err:
_LOGGER.error("Error on Hass.io API: %s", err)
for service, settings in MAP_SERVICE_API.items():
hass.services.async_register(
@ -248,9 +246,11 @@ def async_setup(hass, config):
@asyncio.coroutine
def update_homeassistant_version(now):
"""Update last available Home Assistant version."""
data = yield from hassio.get_homeassistant_info()
if data:
try:
data = yield from hassio.get_homeassistant_info()
hass.data[DATA_HOMEASSISTANT_VERSION] = data['last_version']
except HassioAPIError as err:
_LOGGER.warning("Can't read last version: %s", err)
hass.helpers.event.async_track_point_in_utc_time(
update_homeassistant_version, utcnow() + HASSIO_UPDATE_INTERVAL)
@ -282,4 +282,7 @@ def async_setup(hass, config):
hass.services.async_register(
HASS_DOMAIN, service, async_handle_core_service)
# Init discovery Hass.io feature
async_setup_discovery(hass, hassio)
return True

View file

@ -0,0 +1,59 @@
"""Implement the serivces discovery feature from Hass.io for Add-ons."""
import asyncio
import logging
import os
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.const import EVENT_HOMEASSISTANT_START
from .handler import HassioAPIError
_LOGGER = logging.getLogger(__name__)
EVENT_DISCOVERY_ADD = 'hassio_discovery_add'
EVENT_DISCOVERY_DEL = 'hassio_discovery_del'
ATTR_UUID = 'uuid'
ATTR_DISCOVERY = 'discovery'
@callback
def async_setup_discovery(hass, hassio):
"""Discovery setup."""
async def async_discovery_event_handler(event):
"""Handle events from Hass.io discovery."""
uuid = event.data[ATTR_UUID]
try:
data = await hassio.get_services_discovery(uuid)
except HassioAPIError as err:
_LOGGER.error(
"Can't read discover %s info: %s", uuid, err)
return
hass.async_add_job(async_process_discovery, hass, data)
hass.bus.async_listen(
EVENT_DISCOVERY_ADD, async_discovery_event_handler)
async def async_discovery_start_handler(event):
"""Process all exists discovery on startup."""
try:
data = await hassio.retrieve_services_discovery()
except HassioAPIError as err:
_LOGGER.error(
"Can't read discover %s info: %s", uuid, err)
return
for discovery in data[ATTR_DISCOVERY]:
hass.async_add_job(async_process_discovery, hass, discovery)
hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, async_discovery_start_handler)
@callback
def async_process_discovery(hass, data):
"""Process a discovery request."""

View file

@ -21,12 +21,20 @@ _LOGGER = logging.getLogger(__name__)
X_HASSIO = 'X-HASSIO-KEY'
class HassioAPIError(RuntimeError):
"""Return if a API trow a error."""
pass
def _api_bool(funct):
"""Return a boolean."""
async def _wrapper(*argv, **kwargs):
"""Wrap function."""
data = await funct(*argv, **kwargs)
return data and data['result'] == "ok"
try:
data = await funct(*argv, **kwargs)
return data['result'] == "ok"
except HassioAPIError:
return False
return _wrapper
@ -36,9 +44,9 @@ def _api_data(funct):
async def _wrapper(*argv, **kwargs):
"""Wrap function."""
data = await funct(*argv, **kwargs)
if data and data['result'] == "ok":
if data['result'] == "ok":
return data['data']
return None
raise HassioAPIError(data['message'])
return _wrapper
@ -91,6 +99,23 @@ class HassIO:
"""
return self.send_command("/homeassistant/check", timeout=300)
@_api_data
def retrieve_services_discovery(self):
"""Return all discovery data from Hass.io API.
This method return a coroutine.
"""
return self.send_command("/services/discovery", method="get")
@_api_data
def get_services_discovery_entry(self, uuid):
"""Return a single discovery data entry.
This method return a coroutine.
"""
return self.send_command(
"/services/discovery/{}".format(uuid), method="get")
@_api_bool
async def update_hass_api(self, http_config, refresh_token):
"""Update Home Assistant API data on Hass.io."""
@ -137,7 +162,7 @@ class HassIO:
if request.status not in (200, 400):
_LOGGER.error(
"%s return code %d.", command, request.status)
return None
raise HassioAPIError()
answer = yield from request.json()
return answer
@ -148,4 +173,4 @@ class HassIO:
except aiohttp.ClientError as err:
_LOGGER.error("Client error on %s request %s", command, err)
return None
raise HassioAPIError()