mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-19 15:16:33 +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
|
- commands
|
||||||
```
|
```
|
||||||
# info
|
# info
|
||||||
-> {'host', 'version'}
|
-> {'os', 'version', 'level', 'hostname'}
|
||||||
# reboot
|
# reboot
|
||||||
# shutdown
|
# shutdown
|
||||||
# host-update [v]
|
# host-update [v]
|
||||||
@ -22,6 +22,12 @@ Communicate over unix socket with a host daemon.
|
|||||||
# network int route xy
|
# network int route xy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
level:
|
||||||
|
- 1: power functions
|
||||||
|
- 2: supervisor update
|
||||||
|
- 4: host update
|
||||||
|
- 8: network functions
|
||||||
|
|
||||||
- Answer
|
- Answer
|
||||||
```
|
```
|
||||||
{}|OK|ERROR
|
{}|OK|ERROR
|
||||||
@ -33,15 +39,13 @@ Interface for HomeAssistant to controll things from supervisor.
|
|||||||
|
|
||||||
### HassIO
|
### HassIO
|
||||||
|
|
||||||
- `/update`
|
- `/supervisor/info`
|
||||||
|
|
||||||
|
- `/supervisor/update`
|
||||||
Payload: {'version': '0.XX'}
|
Payload: {'version': '0.XX'}
|
||||||
If version is None it read last version from server.
|
If version is None it read last version from server.
|
||||||
|
|
||||||
### Host
|
### Host
|
||||||
- `/host/network`
|
|
||||||
Payload: {'hostname': '', 'mode': 'dhcp|fixed', 'ssid': '', 'ip': '', 'netmask': '', 'gateway': ''}
|
|
||||||
|
|
||||||
- `/host/reboot`
|
|
||||||
|
|
||||||
- `/host/shutdown`
|
- `/host/shutdown`
|
||||||
|
|
||||||
@ -50,6 +54,13 @@ Payload: {'hostname': '', 'mode': 'dhcp|fixed', 'ssid': '', 'ip': '', 'netmask':
|
|||||||
- `/host/update`
|
- `/host/update`
|
||||||
On some device we support host upates. Like ResinOS.
|
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
|
||||||
|
|
||||||
- `/homeassistant/info`
|
- `/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()
|
host_info = await self.host_controll.info()
|
||||||
if host_info:
|
if host_info:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Connected to host controll daemon. OS: %s Version: %s",
|
"Connected to HostControll. OS: %s Version: %s Hostname: %s "
|
||||||
host_info.get('host'), host_info.get('version'))
|
"Feature-lvl: %d", host_info.get('os'),
|
||||||
|
host_info.get('version'), host_info.get('hostname'),
|
||||||
|
host_info.get('level'))
|
||||||
|
|
||||||
# api views
|
# api views
|
||||||
self.api.registerHost(self.host_controll)
|
self.api.registerHost(self.host_controll)
|
||||||
@ -61,7 +63,7 @@ class HassIO(object):
|
|||||||
await self._setup_homeassistant()
|
await self._setup_homeassistant()
|
||||||
|
|
||||||
# start api
|
# start api
|
||||||
self.api.start()
|
await self.api.start()
|
||||||
|
|
||||||
# run HomeAssistant
|
# run HomeAssistant
|
||||||
_LOGGER.info("Run HomeAssistant now.")
|
_LOGGER.info("Run HomeAssistant now.")
|
||||||
|
@ -4,7 +4,7 @@ import logging
|
|||||||
import docker
|
import docker
|
||||||
|
|
||||||
from . import DockerBase
|
from . import DockerBase
|
||||||
from ..tools import get_version_from_env
|
from ..tools import get_version_from_env, get_local_ip
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -31,6 +31,8 @@ class DockerHomeAssistant(DockerBase):
|
|||||||
if self._is_running():
|
if self._is_running():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
api_endpoint = get_local_ip(self.loop)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.container = self.dock.containers.run(
|
self.container = self.dock.containers.run(
|
||||||
self.image,
|
self.image,
|
||||||
@ -42,6 +44,9 @@ class DockerHomeAssistant(DockerBase):
|
|||||||
"Name": "always",
|
"Name": "always",
|
||||||
"MaximumRetryCount": 10,
|
"MaximumRetryCount": 10,
|
||||||
},
|
},
|
||||||
|
environment={
|
||||||
|
'HASSIO': api_endpoint,
|
||||||
|
}
|
||||||
volumes={
|
volumes={
|
||||||
self.config.path_config_docker:
|
self.config.path_config_docker:
|
||||||
{'bind': '/config', 'mode': 'rw'},
|
{'bind': '/config', 'mode': 'rw'},
|
||||||
|
@ -13,6 +13,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
TIMEOUT = 15
|
TIMEOUT = 15
|
||||||
|
|
||||||
|
LEVEL_POWER = 1
|
||||||
|
LEVEL_UPDATE_SUPERVISOR = 2
|
||||||
|
LEVEL_UPDATE_HOST = 4
|
||||||
|
LEVEL_NETWORK = 8
|
||||||
|
|
||||||
|
|
||||||
class HostControll(object):
|
class HostControll(object):
|
||||||
"""Client for host controll."""
|
"""Client for host controll."""
|
||||||
|
@ -3,6 +3,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import socket
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import async_timeout
|
import async_timeout
|
||||||
@ -15,7 +16,10 @@ _RE_VERSION = re.compile(r"VERSION=(.*)")
|
|||||||
|
|
||||||
|
|
||||||
async def fetch_current_versions(websession):
|
async def fetch_current_versions(websession):
|
||||||
"""Fetch current versions from github."""
|
"""Fetch current versions from github.
|
||||||
|
|
||||||
|
Is a coroutine.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(10, loop=websession.loop):
|
with async_timeout.timeout(10, loop=websession.loop):
|
||||||
async with websession.get(URL_HASSIO_VERSION) as request:
|
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")
|
_LOGGER.error("Can't find VERSION in env")
|
||||||
return None
|
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
|
IFS=" " read -r -a parse <<< $cmd
|
||||||
|
|
||||||
if [ ${parse[0]} == "info" ]; then
|
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
|
continue
|
||||||
fi
|
fi
|
||||||
if [ ${parse[0]} == "reboot" ]; then
|
if [ ${parse[0]} == "reboot" ]; then
|
||||||
|
Loading…
x
Reference in New Issue
Block a user