mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-25 18:16:32 +00:00
commit
e52af3bfb4
8
API.md
8
API.md
@ -379,7 +379,9 @@ Trigger an udev reload
|
|||||||
"port": 8123,
|
"port": 8123,
|
||||||
"ssl": "bool",
|
"ssl": "bool",
|
||||||
"watchdog": "bool",
|
"watchdog": "bool",
|
||||||
"wait_boot": 600
|
"wait_boot": 600,
|
||||||
|
"audio_input": "null|profile",
|
||||||
|
"audio_output": "null|profile"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -413,7 +415,9 @@ Output is the raw Docker log.
|
|||||||
"ssl": "bool",
|
"ssl": "bool",
|
||||||
"refresh_token": "",
|
"refresh_token": "",
|
||||||
"watchdog": "bool",
|
"watchdog": "bool",
|
||||||
"wait_boot": 600
|
"wait_boot": 600,
|
||||||
|
"audio_input": "null|profile",
|
||||||
|
"audio_output": "null|profile"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -294,11 +294,8 @@ class Addon(AddonModel):
|
|||||||
|
|
||||||
@audio_output.setter
|
@audio_output.setter
|
||||||
def audio_output(self, value: Optional[str]):
|
def audio_output(self, value: Optional[str]):
|
||||||
"""Set/reset audio output profile settings."""
|
"""Set audio output profile settings."""
|
||||||
if value is None:
|
self.persist[ATTR_AUDIO_OUTPUT] = value
|
||||||
self.persist.pop(ATTR_AUDIO_OUTPUT, None)
|
|
||||||
else:
|
|
||||||
self.persist[ATTR_AUDIO_OUTPUT] = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def audio_input(self) -> Optional[str]:
|
def audio_input(self) -> Optional[str]:
|
||||||
@ -315,11 +312,8 @@ class Addon(AddonModel):
|
|||||||
|
|
||||||
@audio_input.setter
|
@audio_input.setter
|
||||||
def audio_input(self, value: Optional[str]):
|
def audio_input(self, value: Optional[str]):
|
||||||
"""Set/reset audio input settings."""
|
"""Set audio input settings."""
|
||||||
if value is None:
|
self.persist[ATTR_AUDIO_INPUT] = value
|
||||||
self.persist.pop(ATTR_AUDIO_INPUT, None)
|
|
||||||
else:
|
|
||||||
self.persist[ATTR_AUDIO_INPUT] = value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def image(self):
|
def image(self):
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
"""Init file for Supervisor Home Assistant RESTful API."""
|
"""Init file for Supervisor Home Assistant RESTful API."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from typing import Coroutine, Dict, Any
|
from typing import Any, Coroutine, Dict
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ARCH,
|
ATTR_ARCH,
|
||||||
|
ATTR_AUDIO_INPUT,
|
||||||
|
ATTR_AUDIO_OUTPUT,
|
||||||
ATTR_BLK_READ,
|
ATTR_BLK_READ,
|
||||||
ATTR_BLK_WRITE,
|
ATTR_BLK_WRITE,
|
||||||
ATTR_BOOT,
|
ATTR_BOOT,
|
||||||
ATTR_CPU_PERCENT,
|
ATTR_CPU_PERCENT,
|
||||||
ATTR_CUSTOM,
|
ATTR_CUSTOM,
|
||||||
ATTR_IMAGE,
|
ATTR_IMAGE,
|
||||||
|
ATTR_IP_ADDRESS,
|
||||||
ATTR_LAST_VERSION,
|
ATTR_LAST_VERSION,
|
||||||
ATTR_MACHINE,
|
ATTR_MACHINE,
|
||||||
ATTR_MEMORY_LIMIT,
|
ATTR_MEMORY_LIMIT,
|
||||||
ATTR_MEMORY_USAGE,
|
|
||||||
ATTR_MEMORY_PERCENT,
|
ATTR_MEMORY_PERCENT,
|
||||||
|
ATTR_MEMORY_USAGE,
|
||||||
ATTR_NETWORK_RX,
|
ATTR_NETWORK_RX,
|
||||||
ATTR_NETWORK_TX,
|
ATTR_NETWORK_TX,
|
||||||
ATTR_PORT,
|
ATTR_PORT,
|
||||||
@ -27,7 +30,6 @@ from ..const import (
|
|||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_WAIT_BOOT,
|
ATTR_WAIT_BOOT,
|
||||||
ATTR_WATCHDOG,
|
ATTR_WATCHDOG,
|
||||||
ATTR_IP_ADDRESS,
|
|
||||||
CONTENT_TYPE_BINARY,
|
CONTENT_TYPE_BINARY,
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
@ -48,6 +50,8 @@ SCHEMA_OPTIONS = vol.Schema(
|
|||||||
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
|
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
|
||||||
vol.Optional(ATTR_WAIT_BOOT): vol.All(vol.Coerce(int), vol.Range(min=60)),
|
vol.Optional(ATTR_WAIT_BOOT): vol.All(vol.Coerce(int), vol.Range(min=60)),
|
||||||
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(vol.Coerce(str)),
|
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(vol.Coerce(str)),
|
||||||
|
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)),
|
||||||
|
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,6 +77,8 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||||||
ATTR_SSL: self.sys_homeassistant.api_ssl,
|
ATTR_SSL: self.sys_homeassistant.api_ssl,
|
||||||
ATTR_WATCHDOG: self.sys_homeassistant.watchdog,
|
ATTR_WATCHDOG: self.sys_homeassistant.watchdog,
|
||||||
ATTR_WAIT_BOOT: self.sys_homeassistant.wait_boot,
|
ATTR_WAIT_BOOT: self.sys_homeassistant.wait_boot,
|
||||||
|
ATTR_AUDIO_INPUT: self.sys_homeassistant.audio_input,
|
||||||
|
ATTR_AUDIO_OUTPUT: self.sys_homeassistant.audio_output,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
@ -102,6 +108,12 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||||||
if ATTR_REFRESH_TOKEN in body:
|
if ATTR_REFRESH_TOKEN in body:
|
||||||
self.sys_homeassistant.refresh_token = body[ATTR_REFRESH_TOKEN]
|
self.sys_homeassistant.refresh_token = body[ATTR_REFRESH_TOKEN]
|
||||||
|
|
||||||
|
if ATTR_AUDIO_INPUT in body:
|
||||||
|
self.sys_homeassistant.audio_input = body[ATTR_AUDIO_INPUT]
|
||||||
|
|
||||||
|
if ATTR_AUDIO_OUTPUT in body:
|
||||||
|
self.sys_homeassistant.audio_output = body[ATTR_AUDIO_OUTPUT]
|
||||||
|
|
||||||
self.sys_homeassistant.save_data()
|
self.sys_homeassistant.save_data()
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
|
@ -4,11 +4,11 @@ from contextlib import suppress
|
|||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
from typing import Awaitable, List, Optional
|
from typing import Awaitable, Optional
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
|
|
||||||
from .const import ATTR_VERSION, FILE_HASSIO_AUDIO, STATE_STARTED
|
from .const import ATTR_VERSION, FILE_HASSIO_AUDIO
|
||||||
from .coresys import CoreSys, CoreSysAttributes
|
from .coresys import CoreSys, CoreSysAttributes
|
||||||
from .docker.audio import DockerAudio
|
from .docker.audio import DockerAudio
|
||||||
from .docker.stats import DockerStats
|
from .docker.stats import DockerStats
|
||||||
@ -35,7 +35,7 @@ class Audio(JsonConfig, CoreSysAttributes):
|
|||||||
@property
|
@property
|
||||||
def path_extern_pulse(self) -> Path:
|
def path_extern_pulse(self) -> Path:
|
||||||
"""Return path of pulse socket file."""
|
"""Return path of pulse socket file."""
|
||||||
return self.sys_config.path_extern_audio.joinpath("external/pulse.sock")
|
return self.sys_config.path_extern_audio.joinpath("external")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path_extern_asound(self) -> Path:
|
def path_extern_asound(self) -> Path:
|
||||||
@ -157,8 +157,6 @@ class Audio(JsonConfig, CoreSysAttributes):
|
|||||||
_LOGGER.error("Can't start Audio plugin")
|
_LOGGER.error("Can't start Audio plugin")
|
||||||
raise AudioError() from None
|
raise AudioError() from None
|
||||||
|
|
||||||
await self._restart_audio_addons()
|
|
||||||
|
|
||||||
async def start(self) -> None:
|
async def start(self) -> None:
|
||||||
"""Run CoreDNS."""
|
"""Run CoreDNS."""
|
||||||
# Start Instance
|
# Start Instance
|
||||||
@ -169,8 +167,6 @@ class Audio(JsonConfig, CoreSysAttributes):
|
|||||||
_LOGGER.error("Can't start Audio plugin")
|
_LOGGER.error("Can't start Audio plugin")
|
||||||
raise AudioError() from None
|
raise AudioError() from None
|
||||||
|
|
||||||
await self._restart_audio_addons()
|
|
||||||
|
|
||||||
def logs(self) -> Awaitable[bytes]:
|
def logs(self) -> Awaitable[bytes]:
|
||||||
"""Get CoreDNS docker logs.
|
"""Get CoreDNS docker logs.
|
||||||
|
|
||||||
@ -221,22 +217,3 @@ class Audio(JsonConfig, CoreSysAttributes):
|
|||||||
default_source=input_profile,
|
default_source=input_profile,
|
||||||
default_sink=output_profile,
|
default_sink=output_profile,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _restart_audio_addons(self):
|
|
||||||
"""Restart all Add-ons they can be connect to unix socket."""
|
|
||||||
tasks: List[Awaitable[None]] = []
|
|
||||||
|
|
||||||
# Find all Add-ons running with audio
|
|
||||||
for addon in self.sys_addons.installed:
|
|
||||||
if not addon.with_audio:
|
|
||||||
continue
|
|
||||||
if await addon.state() != STATE_STARTED:
|
|
||||||
continue
|
|
||||||
tasks.append(addon.restart())
|
|
||||||
|
|
||||||
if not tasks:
|
|
||||||
return
|
|
||||||
|
|
||||||
# restart
|
|
||||||
_LOGGER.info("Restart all Add-ons attach to pulse server: %d", len(tasks))
|
|
||||||
await asyncio.wait(tasks)
|
|
||||||
|
@ -3,7 +3,7 @@ from enum import Enum
|
|||||||
from ipaddress import ip_network
|
from ipaddress import ip_network
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
SUPERVISOR_VERSION = "204"
|
SUPERVISOR_VERSION = "205"
|
||||||
|
|
||||||
|
|
||||||
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
|
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
{% if default_sink %}default-sink = {{ default_sink }}{% endif %}
|
{% if default_sink %}default-sink = {{ default_sink }}{% endif %}
|
||||||
{% if default_source %}default-source = {{ default_source }}{% endif %}
|
{% if default_source %}default-source = {{ default_source }}{% endif %}
|
||||||
|
|
||||||
default-server = unix://run/pulse.sock
|
default-server = unix://run/audio/pulse.sock
|
||||||
; default-dbus-server =
|
; default-dbus-server =
|
||||||
|
|
||||||
autospawn = no
|
autospawn = no
|
||||||
|
@ -213,10 +213,10 @@ class DockerAddon(DockerInterface):
|
|||||||
@property
|
@property
|
||||||
def volumes(self) -> Dict[str, Dict[str, str]]:
|
def volumes(self) -> Dict[str, Dict[str, str]]:
|
||||||
"""Generate volumes for mappings."""
|
"""Generate volumes for mappings."""
|
||||||
volumes = {str(self.addon.path_extern_data): {"bind": "/data", "mode": "rw"}}
|
|
||||||
|
|
||||||
addon_mapping = self.addon.map_volumes
|
addon_mapping = self.addon.map_volumes
|
||||||
|
|
||||||
|
volumes = {str(self.addon.path_extern_data): {"bind": "/data", "mode": "rw"}}
|
||||||
|
|
||||||
# setup config mappings
|
# setup config mappings
|
||||||
if MAP_CONFIG in addon_mapping:
|
if MAP_CONFIG in addon_mapping:
|
||||||
volumes.update(
|
volumes.update(
|
||||||
@ -298,7 +298,7 @@ class DockerAddon(DockerInterface):
|
|||||||
|
|
||||||
# Host D-Bus system
|
# Host D-Bus system
|
||||||
if self.addon.host_dbus:
|
if self.addon.host_dbus:
|
||||||
volumes.update({"/run/dbus": {"bind": "/run/dbus", "mode": "rw"}})
|
volumes.update({"/run/dbus": {"bind": "/run/dbus", "mode": "ro"}})
|
||||||
|
|
||||||
# Configuration Audio
|
# Configuration Audio
|
||||||
if self.addon.with_audio:
|
if self.addon.with_audio:
|
||||||
@ -309,8 +309,8 @@ class DockerAddon(DockerInterface):
|
|||||||
"mode": "ro",
|
"mode": "ro",
|
||||||
},
|
},
|
||||||
str(self.sys_audio.path_extern_pulse): {
|
str(self.sys_audio.path_extern_pulse): {
|
||||||
"bind": "/run/pulse.sock",
|
"bind": "/run/audio",
|
||||||
"mode": "rw",
|
"mode": "ro",
|
||||||
},
|
},
|
||||||
str(self.sys_audio.path_extern_asound): {
|
str(self.sys_audio.path_extern_asound): {
|
||||||
"bind": "/etc/asound.conf",
|
"bind": "/etc/asound.conf",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
import logging
|
import logging
|
||||||
from typing import Awaitable, Optional
|
from typing import Awaitable, Dict, Optional
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
|
|
||||||
@ -45,6 +45,46 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
"""Return IP address of this container."""
|
"""Return IP address of this container."""
|
||||||
return self.sys_docker.network.gateway
|
return self.sys_docker.network.gateway
|
||||||
|
|
||||||
|
@property
|
||||||
|
def volumes(self) -> Dict[str, Dict[str, str]]:
|
||||||
|
"""Return Volumes for the mount."""
|
||||||
|
volumes = {}
|
||||||
|
|
||||||
|
# Add folders
|
||||||
|
volumes.update(
|
||||||
|
{
|
||||||
|
str(self.sys_config.path_extern_homeassistant): {
|
||||||
|
"bind": "/config",
|
||||||
|
"mode": "rw",
|
||||||
|
},
|
||||||
|
str(self.sys_config.path_extern_ssl): {"bind": "/ssl", "mode": "ro"},
|
||||||
|
str(self.sys_config.path_extern_share): {
|
||||||
|
"bind": "/share",
|
||||||
|
"mode": "rw",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configuration Audio
|
||||||
|
volumes.update(
|
||||||
|
{
|
||||||
|
str(self.sys_homeassistant.path_extern_pulse): {
|
||||||
|
"bind": "/etc/pulse/client.conf",
|
||||||
|
"mode": "ro",
|
||||||
|
},
|
||||||
|
str(self.sys_audio.path_extern_pulse): {
|
||||||
|
"bind": "/run/audio",
|
||||||
|
"mode": "ro",
|
||||||
|
},
|
||||||
|
str(self.sys_audio.path_extern_asound): {
|
||||||
|
"bind": "/etc/asound.conf",
|
||||||
|
"mode": "ro",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return volumes
|
||||||
|
|
||||||
def _run(self) -> None:
|
def _run(self) -> None:
|
||||||
"""Run Docker image.
|
"""Run Docker image.
|
||||||
|
|
||||||
@ -67,6 +107,7 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
privileged=True,
|
privileged=True,
|
||||||
init=False,
|
init=False,
|
||||||
network_mode="host",
|
network_mode="host",
|
||||||
|
volumes=self.volumes,
|
||||||
environment={
|
environment={
|
||||||
"HASSIO": self.sys_docker.network.supervisor,
|
"HASSIO": self.sys_docker.network.supervisor,
|
||||||
"SUPERVISOR": self.sys_docker.network.supervisor,
|
"SUPERVISOR": self.sys_docker.network.supervisor,
|
||||||
@ -74,17 +115,6 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
ENV_TOKEN: self.sys_homeassistant.hassio_token,
|
ENV_TOKEN: self.sys_homeassistant.hassio_token,
|
||||||
ENV_TOKEN_OLD: self.sys_homeassistant.hassio_token,
|
ENV_TOKEN_OLD: self.sys_homeassistant.hassio_token,
|
||||||
},
|
},
|
||||||
volumes={
|
|
||||||
str(self.sys_config.path_extern_homeassistant): {
|
|
||||||
"bind": "/config",
|
|
||||||
"mode": "rw",
|
|
||||||
},
|
|
||||||
str(self.sys_config.path_extern_ssl): {"bind": "/ssl", "mode": "ro"},
|
|
||||||
str(self.sys_config.path_extern_share): {
|
|
||||||
"bind": "/share",
|
|
||||||
"mode": "rw",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self._meta = docker_container.attrs
|
self._meta = docker_container.attrs
|
||||||
@ -105,18 +135,8 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
detach=True,
|
detach=True,
|
||||||
stdout=True,
|
stdout=True,
|
||||||
stderr=True,
|
stderr=True,
|
||||||
|
volumes=self.volumes,
|
||||||
environment={ENV_TIME: self.sys_timezone},
|
environment={ENV_TIME: self.sys_timezone},
|
||||||
volumes={
|
|
||||||
str(self.sys_config.path_extern_homeassistant): {
|
|
||||||
"bind": "/config",
|
|
||||||
"mode": "rw",
|
|
||||||
},
|
|
||||||
str(self.sys_config.path_extern_ssl): {"bind": "/ssl", "mode": "ro"},
|
|
||||||
str(self.sys_config.path_extern_share): {
|
|
||||||
"bind": "/share",
|
|
||||||
"mode": "ro",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_initialize(self) -> Awaitable[bool]:
|
def is_initialize(self) -> Awaitable[bool]:
|
||||||
|
@ -19,6 +19,8 @@ from packaging import version as pkg_version
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_ACCESS_TOKEN,
|
ATTR_ACCESS_TOKEN,
|
||||||
|
ATTR_AUDIO_INPUT,
|
||||||
|
ATTR_AUDIO_OUTPUT,
|
||||||
ATTR_BOOT,
|
ATTR_BOOT,
|
||||||
ATTR_IMAGE,
|
ATTR_IMAGE,
|
||||||
ATTR_LAST_VERSION,
|
ATTR_LAST_VERSION,
|
||||||
@ -232,6 +234,36 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
|||||||
"""Set Home Assistant refresh_token."""
|
"""Set Home Assistant refresh_token."""
|
||||||
self._data[ATTR_REFRESH_TOKEN] = value
|
self._data[ATTR_REFRESH_TOKEN] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path_pulse(self):
|
||||||
|
"""Return path to asound config."""
|
||||||
|
return Path(self.sys_config.path_tmp, f"homeassistant_pulse")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path_extern_pulse(self):
|
||||||
|
"""Return path to asound config for Docker."""
|
||||||
|
return Path(self.sys_config.path_extern_tmp, f"homeassistant_pulse")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def audio_output(self) -> Optional[str]:
|
||||||
|
"""Return a pulse profile for output or None."""
|
||||||
|
return self._data[ATTR_AUDIO_OUTPUT]
|
||||||
|
|
||||||
|
@audio_output.setter
|
||||||
|
def audio_output(self, value: Optional[str]):
|
||||||
|
"""Set audio output profile settings."""
|
||||||
|
self._data[ATTR_AUDIO_OUTPUT] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def audio_input(self) -> Optional[str]:
|
||||||
|
"""Return pulse profile for input or None."""
|
||||||
|
return self._data[ATTR_AUDIO_INPUT]
|
||||||
|
|
||||||
|
@audio_input.setter
|
||||||
|
def audio_input(self, value: Optional[str]):
|
||||||
|
"""Set audio input settings."""
|
||||||
|
self._data[ATTR_AUDIO_INPUT] = value
|
||||||
|
|
||||||
@process_lock
|
@process_lock
|
||||||
async def install_landingpage(self) -> None:
|
async def install_landingpage(self) -> None:
|
||||||
"""Install a landing page."""
|
"""Install a landing page."""
|
||||||
@ -334,6 +366,9 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
|||||||
self._data[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
|
self._data[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
|
||||||
self.save_data()
|
self.save_data()
|
||||||
|
|
||||||
|
# Write audio settings
|
||||||
|
self.write_pulse()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.instance.run()
|
await self.instance.run()
|
||||||
except DockerAPIError:
|
except DockerAPIError:
|
||||||
@ -602,3 +637,18 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
|||||||
await self.instance.install(self.version)
|
await self.instance.install(self.version)
|
||||||
except DockerAPIError:
|
except DockerAPIError:
|
||||||
_LOGGER.error("Repairing of Home Assistant fails")
|
_LOGGER.error("Repairing of Home Assistant fails")
|
||||||
|
|
||||||
|
def write_pulse(self):
|
||||||
|
"""Write asound config to file and return True on success."""
|
||||||
|
pulse_config = self.sys_audio.pulse_client(
|
||||||
|
input_profile=self.audio_input, output_profile=self.audio_output
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with self.path_pulse.open("w") as config_file:
|
||||||
|
config_file.write(pulse_config)
|
||||||
|
except OSError as err:
|
||||||
|
_LOGGER.error("Home Assistant can't write pulse/client.config: %s", err)
|
||||||
|
raise HomeAssistantError()
|
||||||
|
|
||||||
|
_LOGGER.debug("Home Assistant write pulse/client.config: %s", self.path_pulse)
|
||||||
|
@ -16,6 +16,8 @@ from voluptuous.humanize import humanize_error
|
|||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ADDONS,
|
ATTR_ADDONS,
|
||||||
|
ATTR_AUDIO_INPUT,
|
||||||
|
ATTR_AUDIO_OUTPUT,
|
||||||
ATTR_BOOT,
|
ATTR_BOOT,
|
||||||
ATTR_CRYPTO,
|
ATTR_CRYPTO,
|
||||||
ATTR_DATE,
|
ATTR_DATE,
|
||||||
@ -443,6 +445,10 @@ class Snapshot(CoreSysAttributes):
|
|||||||
self.sys_homeassistant.refresh_token
|
self.sys_homeassistant.refresh_token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Audio
|
||||||
|
self.homeassistant[ATTR_AUDIO_INPUT] = self.sys_homeassistant.audio_input
|
||||||
|
self.homeassistant[ATTR_AUDIO_OUTPUT] = self.sys_homeassistant.audio_output
|
||||||
|
|
||||||
def restore_homeassistant(self):
|
def restore_homeassistant(self):
|
||||||
"""Write all data to the Home Assistant object."""
|
"""Write all data to the Home Assistant object."""
|
||||||
self.sys_homeassistant.watchdog = self.homeassistant[ATTR_WATCHDOG]
|
self.sys_homeassistant.watchdog = self.homeassistant[ATTR_WATCHDOG]
|
||||||
@ -463,6 +469,10 @@ class Snapshot(CoreSysAttributes):
|
|||||||
self.homeassistant[ATTR_REFRESH_TOKEN]
|
self.homeassistant[ATTR_REFRESH_TOKEN]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Audio
|
||||||
|
self.sys_homeassistant.audio_input = self.homeassistant[ATTR_AUDIO_INPUT]
|
||||||
|
self.sys_homeassistant.audio_output = self.homeassistant[ATTR_AUDIO_OUTPUT]
|
||||||
|
|
||||||
# save
|
# save
|
||||||
self.sys_homeassistant.save_data()
|
self.sys_homeassistant.save_data()
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ADDONS,
|
ATTR_ADDONS,
|
||||||
|
ATTR_AUDIO_INPUT,
|
||||||
|
ATTR_AUDIO_OUTPUT,
|
||||||
ATTR_BOOT,
|
ATTR_BOOT,
|
||||||
ATTR_CRYPTO,
|
ATTR_CRYPTO,
|
||||||
ATTR_DATE,
|
ATTR_DATE,
|
||||||
@ -68,6 +70,12 @@ SCHEMA_SNAPSHOT = vol.Schema(
|
|||||||
vol.Optional(ATTR_WAIT_BOOT, default=600): vol.All(
|
vol.Optional(ATTR_WAIT_BOOT, default=600): vol.All(
|
||||||
vol.Coerce(int), vol.Range(min=60)
|
vol.Coerce(int), vol.Range(min=60)
|
||||||
),
|
),
|
||||||
|
vol.Optional(ATTR_AUDIO_OUTPUT, default=None): vol.Maybe(
|
||||||
|
vol.Coerce(str)
|
||||||
|
),
|
||||||
|
vol.Optional(ATTR_AUDIO_INPUT, default=None): vol.Maybe(
|
||||||
|
vol.Coerce(str)
|
||||||
|
),
|
||||||
},
|
},
|
||||||
extra=vol.REMOVE_EXTRA,
|
extra=vol.REMOVE_EXTRA,
|
||||||
),
|
),
|
||||||
|
@ -9,6 +9,8 @@ from .const import (
|
|||||||
ATTR_ACCESS_TOKEN,
|
ATTR_ACCESS_TOKEN,
|
||||||
ATTR_ADDONS_CUSTOM_LIST,
|
ATTR_ADDONS_CUSTOM_LIST,
|
||||||
ATTR_AUDIO,
|
ATTR_AUDIO,
|
||||||
|
ATTR_AUDIO_INPUT,
|
||||||
|
ATTR_AUDIO_OUTPUT,
|
||||||
ATTR_BOOT,
|
ATTR_BOOT,
|
||||||
ATTR_CHANNEL,
|
ATTR_CHANNEL,
|
||||||
ATTR_CLI,
|
ATTR_CLI,
|
||||||
@ -111,6 +113,8 @@ SCHEMA_HASS_CONFIG = vol.Schema(
|
|||||||
vol.Optional(ATTR_WAIT_BOOT, default=600): vol.All(
|
vol.Optional(ATTR_WAIT_BOOT, default=600): vol.All(
|
||||||
vol.Coerce(int), vol.Range(min=60)
|
vol.Coerce(int), vol.Range(min=60)
|
||||||
),
|
),
|
||||||
|
vol.Optional(ATTR_AUDIO_OUTPUT, default=None): vol.Maybe(vol.Coerce(str)),
|
||||||
|
vol.Optional(ATTR_AUDIO_INPUT, default=None): vol.Maybe(vol.Coerce(str)),
|
||||||
},
|
},
|
||||||
extra=vol.REMOVE_EXTRA,
|
extra=vol.REMOVE_EXTRA,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user