mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-18 22:56:31 +00:00
Part 2 of rest api
This commit is contained in:
parent
3f3d013db0
commit
1d627961f5
@ -7,7 +7,7 @@ Communicate over unix socket with a host daemon.
|
||||
- commands
|
||||
```
|
||||
# info
|
||||
-> {'host', 'version'}
|
||||
-> {'os', 'version', 'level', 'hostname'}
|
||||
# reboot
|
||||
# shutdown
|
||||
# host-update [v]
|
||||
@ -22,6 +22,12 @@ Communicate over unix socket with a host daemon.
|
||||
# network int route xy
|
||||
```
|
||||
|
||||
level:
|
||||
- 1: power functions
|
||||
- 2: supervisor update
|
||||
- 4: host update
|
||||
- 8: network functions
|
||||
|
||||
- Answer
|
||||
```
|
||||
{}|OK|ERROR
|
||||
@ -33,15 +39,13 @@ Interface for HomeAssistant to controll things from supervisor.
|
||||
|
||||
### HassIO
|
||||
|
||||
- `/update`
|
||||
- `/supervisor/info`
|
||||
|
||||
- `/supervisor/update`
|
||||
Payload: {'version': '0.XX'}
|
||||
If version is None it read last version from server.
|
||||
|
||||
### Host
|
||||
- `/host/network`
|
||||
Payload: {'hostname': '', 'mode': 'dhcp|fixed', 'ssid': '', 'ip': '', 'netmask': '', 'gateway': ''}
|
||||
|
||||
- `/host/reboot`
|
||||
|
||||
- `/host/shutdown`
|
||||
|
||||
@ -50,6 +54,13 @@ Payload: {'hostname': '', 'mode': 'dhcp|fixed', 'ssid': '', 'ip': '', 'netmask':
|
||||
- `/host/update`
|
||||
On some device we support host upates. Like ResinOS.
|
||||
|
||||
- `/host/network/info`
|
||||
|
||||
- `/host/network/update`
|
||||
Payload: {'hostname': '', 'mode': 'dhcp|fixed', 'ssid': '', 'ip': '', 'netmask': '', 'gateway': ''}
|
||||
|
||||
- `/host/reboot`
|
||||
|
||||
### HomeAssistant
|
||||
|
||||
- `/homeassistant/info`
|
||||
|
63
hassio_api/hassio/api/__init__.py
Normal file
63
hassio_api/hassio/api/__init__.py
Normal file
@ -0,0 +1,63 @@
|
||||
"""Init file for HassIO rest api."""
|
||||
import logging
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from .homeassistant import APIHomeAssistant
|
||||
from .host import APIHost
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RestAPI(object):
|
||||
"""Handle rest api for hassio."""
|
||||
|
||||
def __init__(self, config, loop):
|
||||
"""Initialize docker base wrapper."""
|
||||
self.config = config
|
||||
self.loop = loop
|
||||
self.webapp = web.Application(loop=self.loop)
|
||||
|
||||
self._handler = None
|
||||
self.server = None
|
||||
|
||||
def registerHost(self, host_controll):
|
||||
"""Register hostcontroll function."""
|
||||
api_host = APIHost(self.config, self.loop, host_controll)
|
||||
|
||||
self.webapp.router.add_get('/host/info', api_host.info)
|
||||
self.webapp.router.add_get('/host/reboot', api_host.reboot)
|
||||
self.webapp.router.add_get('/host/shutdown', api_host.shutdown)
|
||||
self.webapp.router.add_get('/host/update', api_host.update_host)
|
||||
self.webapp.router.add_get(
|
||||
'/host/network/info', api_host.network_info)
|
||||
self.webapp.router.add_get(
|
||||
'/host/network/update', api_host.network_update)
|
||||
|
||||
def registerHomeAssistant(self, dock_homeassistant):
|
||||
"""Register homeassistant function."""
|
||||
api_hass = APIHomeAssistant(self.config, self.loop, dock_homeassistant)
|
||||
|
||||
self.webapp.router.add_get('/homeassistant/info', api_hass.info)
|
||||
self.webapp.router.add_get('/homeassistant/update', api_hass.update)
|
||||
|
||||
async def start(self):
|
||||
"""Run rest api webserver."""
|
||||
self._handler = self.webapp.make_handler(loop=self.loop)
|
||||
|
||||
try:
|
||||
self.server = await self.loop.create_server(
|
||||
self._handler, "0.0.0.0", "80")
|
||||
except OSError as err:
|
||||
_LOGGER.fatal("Failed to create HTTP server at 0.0.0.0:80")
|
||||
|
||||
async def stop(self):
|
||||
"""Stop rest api webserver."""
|
||||
if self.server:
|
||||
self.server.close()
|
||||
await self.server.wait_closed()
|
||||
await self.webapp.shutdown()
|
||||
|
||||
if self._handler:
|
||||
await self._handler.finish_connections(60)
|
||||
await self.webapp.cleanup()
|
50
hassio_api/hassio/api/host.py
Normal file
50
hassio_api/hassio/api/host.py
Normal file
@ -0,0 +1,50 @@
|
||||
"""Init file for HassIO rest api."""
|
||||
import logging
|
||||
|
||||
from aiohttp import web
|
||||
from aiohttp.web_exceptions import HTTPOk, HTTPMethodNotAllowed
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class APIHost(object):
|
||||
"""Handle rest api for host functions."""
|
||||
|
||||
def __init__(self, config, loop, host_controll):
|
||||
"""Initialize docker base wrapper."""
|
||||
self.config = config
|
||||
self.loop = loop
|
||||
self.host_controll
|
||||
|
||||
async def info(self, request):
|
||||
"""Return host information."""
|
||||
host_info = await self.host_controll.info()
|
||||
if host_info:
|
||||
return web.json_response(host_info)
|
||||
raise HTTPMethodNotAllowed()
|
||||
|
||||
async def reboot(self, request):
|
||||
"""Reboot host."""
|
||||
if await self.host_controll.reboot():
|
||||
raise HTTPOk()
|
||||
raise HTTPMethodNotAllowed()
|
||||
|
||||
async def shutdown(self, request):
|
||||
"""Poweroff host."""
|
||||
if await self.host_controll.shutdown():
|
||||
raise HTTPOk()
|
||||
raise HTTPMethodNotAllowed()
|
||||
|
||||
async def network_info(self, request):
|
||||
"""Edit network settings."""
|
||||
raise HTTPMethodNotAllowed()
|
||||
|
||||
async def network_update(self, request):
|
||||
"""Edit network settings."""
|
||||
raise HTTPMethodNotAllowed()
|
||||
|
||||
async def update_host(self, request):
|
||||
"""Update host OS."""
|
||||
if await self.host_controll.host_update():
|
||||
raise HTTPOk()
|
||||
raise HTTPMethodNotAllowed()
|
@ -48,8 +48,10 @@ class HassIO(object):
|
||||
host_info = await self.host_controll.info()
|
||||
if host_info:
|
||||
_LOGGER.info(
|
||||
"Connected to host controll daemon. OS: %s Version: %s",
|
||||
host_info.get('host'), host_info.get('version'))
|
||||
"Connected to HostControll. OS: %s Version: %s Hostname: %s "
|
||||
"Feature-lvl: %d", host_info.get('os'),
|
||||
host_info.get('version'), host_info.get('hostname'),
|
||||
host_info.get('level'))
|
||||
|
||||
# api views
|
||||
self.api.registerHost(self.host_controll)
|
||||
@ -61,7 +63,7 @@ class HassIO(object):
|
||||
await self._setup_homeassistant()
|
||||
|
||||
# start api
|
||||
self.api.start()
|
||||
await self.api.start()
|
||||
|
||||
# run HomeAssistant
|
||||
_LOGGER.info("Run HomeAssistant now.")
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
import docker
|
||||
|
||||
from . import DockerBase
|
||||
from ..tools import get_version_from_env
|
||||
from ..tools import get_version_from_env, get_local_ip
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -31,6 +31,8 @@ class DockerHomeAssistant(DockerBase):
|
||||
if self._is_running():
|
||||
return
|
||||
|
||||
api_endpoint = get_local_ip(self.loop)
|
||||
|
||||
try:
|
||||
self.container = self.dock.containers.run(
|
||||
self.image,
|
||||
@ -42,6 +44,9 @@ class DockerHomeAssistant(DockerBase):
|
||||
"Name": "always",
|
||||
"MaximumRetryCount": 10,
|
||||
},
|
||||
environment={
|
||||
'HASSIO': api_endpoint,
|
||||
}
|
||||
volumes={
|
||||
self.config.path_config_docker:
|
||||
{'bind': '/config', 'mode': 'rw'},
|
||||
|
@ -13,6 +13,11 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
TIMEOUT = 15
|
||||
|
||||
LEVEL_POWER = 1
|
||||
LEVEL_UPDATE_SUPERVISOR = 2
|
||||
LEVEL_UPDATE_HOST = 4
|
||||
LEVEL_NETWORK = 8
|
||||
|
||||
|
||||
class HostControll(object):
|
||||
"""Client for host controll."""
|
||||
|
@ -3,6 +3,7 @@ import asyncio
|
||||
import logging
|
||||
import json
|
||||
import re
|
||||
import socket
|
||||
|
||||
import aiohttp
|
||||
import async_timeout
|
||||
@ -15,7 +16,10 @@ _RE_VERSION = re.compile(r"VERSION=(.*)")
|
||||
|
||||
|
||||
async def fetch_current_versions(websession):
|
||||
"""Fetch current versions from github."""
|
||||
"""Fetch current versions from github.
|
||||
|
||||
Is a coroutine.
|
||||
"""
|
||||
try:
|
||||
with async_timeout.timeout(10, loop=websession.loop):
|
||||
async with websession.get(URL_HASSIO_VERSION) as request:
|
||||
@ -35,3 +39,20 @@ def get_version_from_env(env_list):
|
||||
|
||||
_LOGGER.error("Can't find VERSION in env")
|
||||
return None
|
||||
|
||||
def get_local_ip(loop):
|
||||
"""Retrieve local IP address.
|
||||
|
||||
Need run inside executor.
|
||||
"""
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
# Use Google Public DNS server to determine own IP
|
||||
sock.connect(('8.8.8.8', 80))
|
||||
|
||||
return sock.getsockname()[0]
|
||||
except socket.error:
|
||||
return socket.gethostbyname(socket.gethostname())
|
||||
finally:
|
||||
sock.close()
|
||||
|
@ -17,7 +17,7 @@ do
|
||||
IFS=" " read -r -a parse <<< $cmd
|
||||
|
||||
if [ ${parse[0]} == "info" ]; then
|
||||
echo "{ \"host\": \"resinos\", \"version\": \"$RESINOS_HASSIO_VERSION\" }"
|
||||
echo "{ \"level\": 15, \"os\": \"resinos\", \"version\": \"$RESINOS_HASSIO_VERSION\", \"hostname\": \"$CONFIG_HOSTNAME\" }"
|
||||
continue
|
||||
fi
|
||||
if [ ${parse[0]} == "reboot" ]; then
|
||||
|
Loading…
x
Reference in New Issue
Block a user