mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-25 10:06:34 +00:00
Fix
This commit is contained in:
commit
cb2dd3b81c
7
API.md
7
API.md
@ -34,6 +34,7 @@ The addons from `addons` are only installed one.
|
|||||||
"last_version": "LAST_VERSION",
|
"last_version": "LAST_VERSION",
|
||||||
"arch": "armhf|aarch64|i386|amd64",
|
"arch": "armhf|aarch64|i386|amd64",
|
||||||
"beta_channel": "true|false",
|
"beta_channel": "true|false",
|
||||||
|
"timezone": "TIMEZONE",
|
||||||
"addons": [
|
"addons": [
|
||||||
{
|
{
|
||||||
"name": "xy bla",
|
"name": "xy bla",
|
||||||
@ -98,6 +99,7 @@ Optional:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"beta_channel": "true|false",
|
"beta_channel": "true|false",
|
||||||
|
"timezone": "TIMEZONE",
|
||||||
"addons_repositories": [
|
"addons_repositories": [
|
||||||
"REPO_URL"
|
"REPO_URL"
|
||||||
]
|
]
|
||||||
@ -176,6 +178,11 @@ Optional:
|
|||||||
### Network
|
### Network
|
||||||
|
|
||||||
- GET `/network/info`
|
- GET `/network/info`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hostname": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- POST `/network/options`
|
- POST `/network/options`
|
||||||
```json
|
```json
|
||||||
|
@ -9,9 +9,9 @@ Hass.io is a Docker based system for managing your Home Assistant installation a
|
|||||||
|
|
||||||
**HassIO is under active development and is not ready yet for production use.**
|
**HassIO is under active development and is not ready yet for production use.**
|
||||||
|
|
||||||
## Installing Hass.io
|
## Installation
|
||||||
|
|
||||||
Looks to our [website](https://home-assistant.io/hassio).
|
Installation instructions can be found at [https://home-assistant.io/hassio](https://home-assistant.io/hassio).
|
||||||
|
|
||||||
# HomeAssistant
|
# HomeAssistant
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ from ..const import (
|
|||||||
FILE_HASSIO_ADDONS, ATTR_NAME, ATTR_VERSION, ATTR_SLUG, ATTR_DESCRIPTON,
|
FILE_HASSIO_ADDONS, ATTR_NAME, ATTR_VERSION, ATTR_SLUG, ATTR_DESCRIPTON,
|
||||||
ATTR_STARTUP, ATTR_BOOT, ATTR_MAP, ATTR_OPTIONS, ATTR_PORTS, BOOT_AUTO,
|
ATTR_STARTUP, ATTR_BOOT, ATTR_MAP, ATTR_OPTIONS, ATTR_PORTS, BOOT_AUTO,
|
||||||
ATTR_SCHEMA, ATTR_IMAGE, ATTR_REPOSITORY, ATTR_URL, ATTR_ARCH,
|
ATTR_SCHEMA, ATTR_IMAGE, ATTR_REPOSITORY, ATTR_URL, ATTR_ARCH,
|
||||||
ATTR_LOCATON, ATTR_DEVICES, ATTR_ENVIRONMENT)
|
ATTR_LOCATON, ATTR_DEVICES, ATTR_ENVIRONMENT, ATTR_HOST_NETWORK)
|
||||||
from ..config import Config
|
from ..config import Config
|
||||||
from ..tools import read_json_file, write_json_file
|
from ..tools import read_json_file, write_json_file
|
||||||
|
|
||||||
@ -294,6 +294,12 @@ class AddonsData(Config):
|
|||||||
"""Return ports of addon."""
|
"""Return ports of addon."""
|
||||||
return self._system_data[addon].get(ATTR_PORTS)
|
return self._system_data[addon].get(ATTR_PORTS)
|
||||||
|
|
||||||
|
def get_network_mode(self, addon):
|
||||||
|
"""Return network mode of addon."""
|
||||||
|
if self._system_data[addon][ATTR_HOST_NETWORK]:
|
||||||
|
return 'host'
|
||||||
|
return 'bridge'
|
||||||
|
|
||||||
def get_devices(self, addon):
|
def get_devices(self, addon):
|
||||||
"""Return devices of addon."""
|
"""Return devices of addon."""
|
||||||
return self._system_data[addon].get(ATTR_DEVICES)
|
return self._system_data[addon].get(ATTR_DEVICES)
|
||||||
|
@ -6,7 +6,8 @@ from ..const import (
|
|||||||
ATTR_BOOT, ATTR_MAP, ATTR_OPTIONS, ATTR_PORTS, STARTUP_ONCE, STARTUP_AFTER,
|
ATTR_BOOT, ATTR_MAP, ATTR_OPTIONS, ATTR_PORTS, STARTUP_ONCE, STARTUP_AFTER,
|
||||||
STARTUP_BEFORE, STARTUP_INITIALIZE, BOOT_AUTO, BOOT_MANUAL, ATTR_SCHEMA,
|
STARTUP_BEFORE, STARTUP_INITIALIZE, BOOT_AUTO, BOOT_MANUAL, ATTR_SCHEMA,
|
||||||
ATTR_IMAGE, ATTR_URL, ATTR_MAINTAINER, ATTR_ARCH, ATTR_DEVICES,
|
ATTR_IMAGE, ATTR_URL, ATTR_MAINTAINER, ATTR_ARCH, ATTR_DEVICES,
|
||||||
ATTR_ENVIRONMENT, ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64, ARCH_I386)
|
ATTR_ENVIRONMENT, ATTR_HOST_NETWORK, ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64,
|
||||||
|
ARCH_I386)
|
||||||
|
|
||||||
|
|
||||||
MAP_VOLUME = r"^(config|ssl|addons|backup|share)(?::(rw|:ro))?$"
|
MAP_VOLUME = r"^(config|ssl|addons|backup|share)(?::(rw|:ro))?$"
|
||||||
@ -24,8 +25,19 @@ ARCH_ALL = [
|
|||||||
ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64, ARCH_I386
|
ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64, ARCH_I386
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def check_network(data):
|
||||||
|
"""Validate network settings."""
|
||||||
|
host_network = data[ATTR_HOST_NETWORK]
|
||||||
|
|
||||||
|
if ATTR_PORTS in data and host_network:
|
||||||
|
raise vol.Invalid("Hostnetwork & ports are not allow!")
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
SCHEMA_ADDON_CONFIG = vol.Schema({
|
SCHEMA_ADDON_CONFIG = vol.Schema(vol.All({
|
||||||
vol.Required(ATTR_NAME): vol.Coerce(str),
|
vol.Required(ATTR_NAME): vol.Coerce(str),
|
||||||
vol.Required(ATTR_VERSION): vol.Coerce(str),
|
vol.Required(ATTR_VERSION): vol.Coerce(str),
|
||||||
vol.Required(ATTR_SLUG): vol.Coerce(str),
|
vol.Required(ATTR_SLUG): vol.Coerce(str),
|
||||||
@ -38,6 +50,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
|
|||||||
vol.Required(ATTR_BOOT):
|
vol.Required(ATTR_BOOT):
|
||||||
vol.In([BOOT_AUTO, BOOT_MANUAL]),
|
vol.In([BOOT_AUTO, BOOT_MANUAL]),
|
||||||
vol.Optional(ATTR_PORTS): dict,
|
vol.Optional(ATTR_PORTS): dict,
|
||||||
|
vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")],
|
vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")],
|
||||||
vol.Optional(ATTR_MAP, default=[]): [vol.Match(MAP_VOLUME)],
|
vol.Optional(ATTR_MAP, default=[]): [vol.Match(MAP_VOLUME)],
|
||||||
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
|
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
|
||||||
@ -48,7 +61,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
|
|||||||
])
|
])
|
||||||
},
|
},
|
||||||
vol.Optional(ATTR_IMAGE): vol.Match(r"\w*/\w*"),
|
vol.Optional(ATTR_IMAGE): vol.Match(r"\w*/\w*"),
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, check_network), extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
"""Init file for HassIO network rest api."""
|
"""Init file for HassIO network rest api."""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from .util import api_process_hostcontrol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from .util import api_process, api_process_hostcontrol, api_validate
|
||||||
|
from ..const import ATTR_HOSTNAME
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
SCHEMA_OPTIONS = vol.Schema({
|
||||||
|
vol.Optional(ATTR_HOSTNAME): vol.Coerce(str),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class APINetwork(object):
|
class APINetwork(object):
|
||||||
"""Handle rest api for network functions."""
|
"""Handle rest api for network functions."""
|
||||||
|
|
||||||
@ -15,12 +23,21 @@ class APINetwork(object):
|
|||||||
self.loop = loop
|
self.loop = loop
|
||||||
self.host_control = host_control
|
self.host_control = host_control
|
||||||
|
|
||||||
@api_process_hostcontrol
|
@api_process
|
||||||
def info(self, request):
|
async def info(self, request):
|
||||||
"""Show network settings."""
|
"""Show network settings."""
|
||||||
pass
|
return {
|
||||||
|
ATTR_HOSTNAME: self.host_control.hostname,
|
||||||
|
}
|
||||||
|
|
||||||
@api_process_hostcontrol
|
@api_process_hostcontrol
|
||||||
def options(self, request):
|
async def options(self, request):
|
||||||
"""Edit network settings."""
|
"""Edit network settings."""
|
||||||
pass
|
body = await api_validate(SCHEMA_OPTIONS, request)
|
||||||
|
|
||||||
|
# hostname
|
||||||
|
if ATTR_HOSTNAME in body:
|
||||||
|
if self.host_control.hostname != body[ATTR_HOSTNAME]:
|
||||||
|
await self.host_control.set_hostname(body[ATTR_HOSTNAME])
|
||||||
|
|
||||||
|
return True
|
||||||
|
@ -11,7 +11,8 @@ from ..const import (
|
|||||||
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_REPOSITORIES,
|
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_REPOSITORIES,
|
||||||
ATTR_REPOSITORY, ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED,
|
ATTR_REPOSITORY, ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED,
|
||||||
ATTR_DETACHED, ATTR_SOURCE, ATTR_MAINTAINER, ATTR_URL, ATTR_ARCH,
|
ATTR_DETACHED, ATTR_SOURCE, ATTR_MAINTAINER, ATTR_URL, ATTR_ARCH,
|
||||||
ATTR_BUILD)
|
ATTR_BUILD, ATTR_TIMEZONE)
|
||||||
|
from ..tools import validate_timezone
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ SCHEMA_OPTIONS = vol.Schema({
|
|||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
vol.Optional(ATTR_BETA_CHANNEL): vol.Boolean(),
|
vol.Optional(ATTR_BETA_CHANNEL): vol.Boolean(),
|
||||||
vol.Optional(ATTR_ADDONS_REPOSITORIES): [vol.Url()],
|
vol.Optional(ATTR_ADDONS_REPOSITORIES): [vol.Url()],
|
||||||
|
vol.Optional(ATTR_TIMEZONE): validate_timezone,
|
||||||
})
|
})
|
||||||
|
|
||||||
SCHEMA_VERSION = vol.Schema({
|
SCHEMA_VERSION = vol.Schema({
|
||||||
@ -92,6 +94,7 @@ class APISupervisor(object):
|
|||||||
ATTR_LAST_VERSION: self.config.last_hassio,
|
ATTR_LAST_VERSION: self.config.last_hassio,
|
||||||
ATTR_BETA_CHANNEL: self.config.upstream_beta,
|
ATTR_BETA_CHANNEL: self.config.upstream_beta,
|
||||||
ATTR_ARCH: self.addons.arch,
|
ATTR_ARCH: self.addons.arch,
|
||||||
|
ATTR_TIMEZONE: self.config.timezone,
|
||||||
ATTR_ADDONS: self._addons_list(only_installed=True),
|
ATTR_ADDONS: self._addons_list(only_installed=True),
|
||||||
ATTR_ADDONS_REPOSITORIES: self.config.addons_repositories,
|
ATTR_ADDONS_REPOSITORIES: self.config.addons_repositories,
|
||||||
}
|
}
|
||||||
@ -112,6 +115,9 @@ class APISupervisor(object):
|
|||||||
if ATTR_BETA_CHANNEL in body:
|
if ATTR_BETA_CHANNEL in body:
|
||||||
self.config.upstream_beta = body[ATTR_BETA_CHANNEL]
|
self.config.upstream_beta = body[ATTR_BETA_CHANNEL]
|
||||||
|
|
||||||
|
if ATTR_TIMEZONE in body:
|
||||||
|
self.config.timezone = body[ATTR_TIMEZONE]
|
||||||
|
|
||||||
if ATTR_ADDONS_REPOSITORIES in body:
|
if ATTR_ADDONS_REPOSITORIES in body:
|
||||||
new = set(body[ATTR_ADDONS_REPOSITORIES])
|
new = set(body[ATTR_ADDONS_REPOSITORIES])
|
||||||
old = set(self.config.addons_repositories)
|
old = set(self.config.addons_repositories)
|
||||||
|
@ -10,7 +10,7 @@ from voluptuous.humanize import humanize_error
|
|||||||
|
|
||||||
from .const import FILE_HASSIO_CONFIG, HASSIO_SHARE
|
from .const import FILE_HASSIO_CONFIG, HASSIO_SHARE
|
||||||
from .tools import (
|
from .tools import (
|
||||||
fetch_last_versions, write_json_file, read_json_file)
|
fetch_last_versions, write_json_file, read_json_file, validate_timezone)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -35,8 +35,8 @@ BACKUP_DATA = PurePath("backup")
|
|||||||
SHARE_DATA = PurePath("share")
|
SHARE_DATA = PurePath("share")
|
||||||
|
|
||||||
UPSTREAM_BETA = 'upstream_beta'
|
UPSTREAM_BETA = 'upstream_beta'
|
||||||
|
|
||||||
API_ENDPOINT = 'api_endpoint'
|
API_ENDPOINT = 'api_endpoint'
|
||||||
|
TIMEZONE = 'timezone'
|
||||||
|
|
||||||
SECURITY_INITIALIZE = 'security_initialize'
|
SECURITY_INITIALIZE = 'security_initialize'
|
||||||
SECURITY_TOTP = 'security_totp'
|
SECURITY_TOTP = 'security_totp'
|
||||||
@ -48,6 +48,7 @@ SECURITY_SESSIONS = 'security_sessions'
|
|||||||
SCHEMA_CONFIG = vol.Schema({
|
SCHEMA_CONFIG = vol.Schema({
|
||||||
vol.Optional(UPSTREAM_BETA, default=False): vol.Boolean(),
|
vol.Optional(UPSTREAM_BETA, default=False): vol.Boolean(),
|
||||||
vol.Optional(API_ENDPOINT): vol.Coerce(str),
|
vol.Optional(API_ENDPOINT): vol.Coerce(str),
|
||||||
|
vol.Optional(TIMEZONE, default='UTC'): validate_timezone,
|
||||||
vol.Optional(HOMEASSISTANT_LAST): vol.Coerce(str),
|
vol.Optional(HOMEASSISTANT_LAST): vol.Coerce(str),
|
||||||
vol.Optional(HASSIO_LAST): vol.Coerce(str),
|
vol.Optional(HASSIO_LAST): vol.Coerce(str),
|
||||||
vol.Optional(HASSIO_CLEANUP): vol.Coerce(str),
|
vol.Optional(HASSIO_CLEANUP): vol.Coerce(str),
|
||||||
@ -136,6 +137,17 @@ class CoreConfig(Config):
|
|||||||
"""Set beta upstream mode."""
|
"""Set beta upstream mode."""
|
||||||
self._data[UPSTREAM_BETA] = bool(value)
|
self._data[UPSTREAM_BETA] = bool(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timezone(self):
|
||||||
|
"""Return system timezone."""
|
||||||
|
return self._data[TIMEZONE]
|
||||||
|
|
||||||
|
@timezone.setter
|
||||||
|
def timezone(self, value):
|
||||||
|
"""Set system timezone."""
|
||||||
|
self._data[TIMEZONE] = value
|
||||||
|
self.save()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hassio_cleanup(self):
|
def hassio_cleanup(self):
|
||||||
"""Return Version they need to cleanup."""
|
"""Return Version they need to cleanup."""
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Const file for HassIO."""
|
"""Const file for HassIO."""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
HASSIO_VERSION = '0.31'
|
HASSIO_VERSION = '0.32'
|
||||||
|
|
||||||
URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/'
|
URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/'
|
||||||
'hassio/master/version.json')
|
'hassio/master/version.json')
|
||||||
@ -43,6 +43,7 @@ RESULT_OK = 'ok'
|
|||||||
|
|
||||||
ATTR_ARCH = 'arch'
|
ATTR_ARCH = 'arch'
|
||||||
ATTR_HOSTNAME = 'hostname'
|
ATTR_HOSTNAME = 'hostname'
|
||||||
|
ATTR_TIMEZONE = 'timezone'
|
||||||
ATTR_OS = 'os'
|
ATTR_OS = 'os'
|
||||||
ATTR_TYPE = 'type'
|
ATTR_TYPE = 'type'
|
||||||
ATTR_SOURCE = 'source'
|
ATTR_SOURCE = 'source'
|
||||||
@ -77,6 +78,7 @@ ATTR_LOCATON = 'location'
|
|||||||
ATTR_BUILD = 'build'
|
ATTR_BUILD = 'build'
|
||||||
ATTR_DEVICES = 'devices'
|
ATTR_DEVICES = 'devices'
|
||||||
ATTR_ENVIRONMENT = 'environment'
|
ATTR_ENVIRONMENT = 'environment'
|
||||||
|
ATTR_HOST_NETWORK = 'host_network'
|
||||||
|
|
||||||
STARTUP_INITIALIZE = 'initialize'
|
STARTUP_INITIALIZE = 'initialize'
|
||||||
STARTUP_BEFORE = 'before'
|
STARTUP_BEFORE = 'before'
|
||||||
|
@ -28,6 +28,16 @@ class DockerAddon(DockerBase):
|
|||||||
"""Return name of docker container."""
|
"""Return name of docker container."""
|
||||||
return "addon_{}".format(self.addon)
|
return "addon_{}".format(self.addon)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def environment(self):
|
||||||
|
"""Return environment for docker add-on."""
|
||||||
|
addon_env = self.addons_data.get_environment(self.addon) or {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
**addon_env,
|
||||||
|
'TZ': self.config.timezone,
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def volumes(self):
|
def volumes(self):
|
||||||
"""Generate volumes for mappings."""
|
"""Generate volumes for mappings."""
|
||||||
@ -86,11 +96,11 @@ class DockerAddon(DockerBase):
|
|||||||
self.image,
|
self.image,
|
||||||
name=self.docker_name,
|
name=self.docker_name,
|
||||||
detach=True,
|
detach=True,
|
||||||
network_mode='bridge',
|
network_mode=self.addons_data.get_network_mode(self.addon),
|
||||||
ports=self.addons_data.get_ports(self.addon),
|
ports=self.addons_data.get_ports(self.addon),
|
||||||
devices=self.addons_data.get_devices(self.addon),
|
devices=self.addons_data.get_devices(self.addon),
|
||||||
environment=self.addons_data.get_environment(self.addon),
|
environment=self.environment,
|
||||||
volumes=self.volumes,
|
volumes=self.volumes
|
||||||
)
|
)
|
||||||
|
|
||||||
self.process_metadata()
|
self.process_metadata()
|
||||||
|
@ -42,6 +42,7 @@ class DockerHomeAssistant(DockerBase):
|
|||||||
network_mode='host',
|
network_mode='host',
|
||||||
environment={
|
environment={
|
||||||
'HASSIO': self.config.api_endpoint,
|
'HASSIO': self.config.api_endpoint,
|
||||||
|
'TZ': self.config.timezone,
|
||||||
},
|
},
|
||||||
volumes={
|
volumes={
|
||||||
str(self.config.path_extern_config):
|
str(self.config.path_extern_config):
|
||||||
|
@ -17,6 +17,7 @@ UNKNOWN = 'unknown'
|
|||||||
FEATURES_SHUTDOWN = 'shutdown'
|
FEATURES_SHUTDOWN = 'shutdown'
|
||||||
FEATURES_REBOOT = 'reboot'
|
FEATURES_REBOOT = 'reboot'
|
||||||
FEATURES_UPDATE = 'update'
|
FEATURES_UPDATE = 'update'
|
||||||
|
FEATURES_HOSTNAME = 'hostname'
|
||||||
FEATURES_NETWORK_INFO = 'network_info'
|
FEATURES_NETWORK_INFO = 'network_info'
|
||||||
FEATURES_NETWORK_CONTROL = 'network_control'
|
FEATURES_NETWORK_CONTROL = 'network_control'
|
||||||
|
|
||||||
@ -117,3 +118,7 @@ class HostControl(object):
|
|||||||
if version:
|
if version:
|
||||||
return self._send_command("update {}".format(version))
|
return self._send_command("update {}".format(version))
|
||||||
return self._send_command("update")
|
return self._send_command("update")
|
||||||
|
|
||||||
|
def set_hostname(self, hostname):
|
||||||
|
"""Update hostname on host."""
|
||||||
|
return self._send_command("hostname {}".format(hostname))
|
||||||
|
@ -7,6 +7,8 @@ import socket
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import async_timeout
|
import async_timeout
|
||||||
|
import pytz
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from .const import URL_HASSIO_VERSION, URL_HASSIO_VERSION_BETA
|
from .const import URL_HASSIO_VERSION, URL_HASSIO_VERSION_BETA
|
||||||
|
|
||||||
@ -90,3 +92,16 @@ def read_json_file(jsonfile):
|
|||||||
"""Read a json file and return a dict."""
|
"""Read a json file and return a dict."""
|
||||||
with jsonfile.open('r') as cfile:
|
with jsonfile.open('r') as cfile:
|
||||||
return json.loads(cfile.read())
|
return json.loads(cfile.read())
|
||||||
|
|
||||||
|
|
||||||
|
def validate_timezone(timezone):
|
||||||
|
"""Validate voluptuous timezone."""
|
||||||
|
try:
|
||||||
|
pytz.timezone(timezone)
|
||||||
|
except pytz.exceptions.UnknownTimeZoneError:
|
||||||
|
raise vol.Invalid(
|
||||||
|
"Invalid time zone passed in. Valid options can be found here: "
|
||||||
|
"http://en.wikipedia.org/wiki/List_of_tz_database_time_zones") \
|
||||||
|
from None
|
||||||
|
|
||||||
|
return timezone
|
||||||
|
3
setup.py
3
setup.py
@ -39,6 +39,7 @@ setup(
|
|||||||
'voluptuous',
|
'voluptuous',
|
||||||
'gitpython',
|
'gitpython',
|
||||||
'pyotp',
|
'pyotp',
|
||||||
'pyqrcode'
|
'pyqrcode',
|
||||||
|
'pytz'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"hassio": "0.31",
|
"hassio": "0.32",
|
||||||
"homeassistant": "0.45",
|
"homeassistant": "0.45",
|
||||||
"resinos": "0.8",
|
"resinos": "0.8",
|
||||||
"resinhup": "0.1",
|
"resinhup": "0.1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user