mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-24 09:36:31 +00:00
commit
ff903d7b5a
3
API.md
3
API.md
@ -52,7 +52,7 @@ The addons from `addons` are only installed one.
|
||||
"slug": "xy",
|
||||
"description": "description",
|
||||
"repository": "12345678|null",
|
||||
"version": "LAST_VERSION",
|
||||
"version": "LATEST_VERSION",
|
||||
"installed": "INSTALL_VERSION",
|
||||
"icon": "bool",
|
||||
"logo": "bool",
|
||||
@ -537,6 +537,7 @@ Get all available addons.
|
||||
"kernel_modules": "bool",
|
||||
"devicetree": "bool",
|
||||
"docker_api": "bool",
|
||||
"video": "bool",
|
||||
"audio": "bool",
|
||||
"audio_input": "null|0,0",
|
||||
"audio_output": "null|0,0",
|
||||
|
@ -3,8 +3,8 @@
|
||||
trigger:
|
||||
batch: true
|
||||
branches:
|
||||
exclude:
|
||||
- "*"
|
||||
include:
|
||||
- dev
|
||||
tags:
|
||||
include:
|
||||
- "*"
|
||||
|
@ -57,6 +57,7 @@ from ..const import (
|
||||
ATTR_UDEV,
|
||||
ATTR_URL,
|
||||
ATTR_VERSION,
|
||||
ATTR_VIDEO,
|
||||
ATTR_WEBUI,
|
||||
SECURITY_DEFAULT,
|
||||
SECURITY_DISABLE,
|
||||
@ -393,6 +394,11 @@ class AddonModel(CoreSysAttributes):
|
||||
"""Return True if the add-on access to audio."""
|
||||
return self.data[ATTR_AUDIO]
|
||||
|
||||
@property
|
||||
def with_video(self) -> bool:
|
||||
"""Return True if the add-on access to video."""
|
||||
return self.data[ATTR_VIDEO]
|
||||
|
||||
@property
|
||||
def homeassistant_version(self) -> Optional[str]:
|
||||
"""Return min Home Assistant version they needed by Add-on."""
|
||||
|
@ -77,6 +77,7 @@ from ..const import (
|
||||
ATTR_USER,
|
||||
ATTR_UUID,
|
||||
ATTR_VERSION,
|
||||
ATTR_VIDEO,
|
||||
ATTR_WEBUI,
|
||||
BOOT_AUTO,
|
||||
BOOT_MANUAL,
|
||||
@ -219,6 +220,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema(
|
||||
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
|
||||
vol.Optional(ATTR_FULL_ACCESS, default=False): vol.Boolean(),
|
||||
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
|
||||
vol.Optional(ATTR_VIDEO, default=False): vol.Boolean(),
|
||||
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
|
||||
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
|
||||
vol.Optional(ATTR_KERNEL_MODULES, default=False): vol.Boolean(),
|
||||
|
@ -82,6 +82,7 @@ from ..const import (
|
||||
ATTR_UDEV,
|
||||
ATTR_URL,
|
||||
ATTR_VERSION,
|
||||
ATTR_VIDEO,
|
||||
ATTR_WEBUI,
|
||||
BOOT_AUTO,
|
||||
BOOT_MANUAL,
|
||||
@ -238,6 +239,7 @@ class APIAddons(CoreSysAttributes):
|
||||
ATTR_DEVICETREE: addon.with_devicetree,
|
||||
ATTR_UDEV: addon.with_udev,
|
||||
ATTR_DOCKER_API: addon.access_docker_api,
|
||||
ATTR_VIDEO: addon.with_video,
|
||||
ATTR_AUDIO: addon.with_audio,
|
||||
ATTR_AUDIO_INPUT: None,
|
||||
ATTR_AUDIO_OUTPUT: None,
|
||||
|
@ -25,18 +25,21 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
def excract_supervisor_token(request: web.Request) -> Optional[str]:
|
||||
"""Extract Supervisor token from request."""
|
||||
supervisor_token = request.headers.get(HEADER_TOKEN)
|
||||
if supervisor_token:
|
||||
return supervisor_token
|
||||
|
||||
# Remove with old Hass.io fallback
|
||||
supervisor_token = request.headers.get(HEADER_TOKEN_OLD)
|
||||
if supervisor_token:
|
||||
return supervisor_token
|
||||
|
||||
# API access only
|
||||
supervisor_token = request.headers.get(AUTHORIZATION)
|
||||
if supervisor_token:
|
||||
return supervisor_token.split(" ")[-1]
|
||||
|
||||
# Header token handling
|
||||
supervisor_token = request.headers.get(HEADER_TOKEN)
|
||||
|
||||
# Remove with old Hass.io fallback
|
||||
if not supervisor_token:
|
||||
supervisor_token = request.headers.get(HEADER_TOKEN_OLD)
|
||||
|
||||
return supervisor_token
|
||||
return None
|
||||
|
||||
|
||||
def json_loads(data: Any) -> Dict[str, Any]:
|
||||
|
@ -3,7 +3,7 @@ from enum import Enum
|
||||
from ipaddress import ip_network
|
||||
from pathlib import Path
|
||||
|
||||
HASSIO_VERSION = "198"
|
||||
HASSIO_VERSION = "199"
|
||||
|
||||
|
||||
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
|
||||
@ -149,6 +149,7 @@ ATTR_TYPE = "type"
|
||||
ATTR_TIMEOUT = "timeout"
|
||||
ATTR_AUTO_UPDATE = "auto_update"
|
||||
ATTR_CUSTOM = "custom"
|
||||
ATTR_VIDEO = "video"
|
||||
ATTR_AUDIO = "audio"
|
||||
ATTR_AUDIO_INPUT = "audio_input"
|
||||
ATTR_AUDIO_OUTPUT = "audio_output"
|
||||
|
@ -147,6 +147,11 @@ class DockerAddon(DockerInterface):
|
||||
for device in serial_devs:
|
||||
devices.append(f"{device}:{device}:rwm")
|
||||
|
||||
# Use video devices
|
||||
if self.addon.with_video:
|
||||
for device in self.sys_hardware.video_devices:
|
||||
devices.append(f"{device.path!s}:{device.path!s}:rwm")
|
||||
|
||||
# Return None if no devices is present
|
||||
return devices or None
|
||||
|
||||
|
@ -243,10 +243,14 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
|
||||
_LOGGER.warning("Fails install landingpage, retry after 30sec")
|
||||
await asyncio.sleep(30)
|
||||
else:
|
||||
self.version = self.instance.version
|
||||
self.save_data()
|
||||
break
|
||||
|
||||
self.version = self.instance.version
|
||||
self.save_data()
|
||||
# Start landingpage
|
||||
_LOGGER.info("Start HomeAssistant landingpage")
|
||||
with suppress(HomeAssistantError):
|
||||
await self._start()
|
||||
|
||||
@process_lock
|
||||
async def install(self) -> None:
|
||||
|
@ -4,13 +4,15 @@ from datetime import datetime
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import re
|
||||
from typing import Any, Dict, Optional, Set
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
|
||||
import attr
|
||||
import pyudev
|
||||
|
||||
from ..const import ATTR_DEVICES, ATTR_NAME, ATTR_TYPE, CHAN_ID, CHAN_TYPE
|
||||
from ..exceptions import HardwareNotSupportedError
|
||||
|
||||
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
ASOUND_CARDS: Path = Path("/proc/asound/cards")
|
||||
@ -26,6 +28,17 @@ GPIO_DEVICES: Path = Path("/sys/class/gpio")
|
||||
SOC_DEVICES: Path = Path("/sys/devices/platform/soc")
|
||||
RE_TTY: re.Pattern = re.compile(r"tty[A-Z]+")
|
||||
|
||||
RE_VIDEO_DEVICES = re.compile(r"^(?:vchiq|cec)")
|
||||
|
||||
|
||||
@attr.s(frozen=True)
|
||||
class Device:
|
||||
"""Represent a device."""
|
||||
|
||||
name: str = attr.ib()
|
||||
path: Path = attr.ib()
|
||||
links: List[Path] = attr.ib()
|
||||
|
||||
|
||||
class Hardware:
|
||||
"""Representation of an interface to procfs, sysfs and udev."""
|
||||
@ -34,6 +47,33 @@ class Hardware:
|
||||
"""Init hardware object."""
|
||||
self.context = pyudev.Context()
|
||||
|
||||
@property
|
||||
def devices(self) -> List[Device]:
|
||||
"""Return a list of all available devices."""
|
||||
dev_list: List[Device] = []
|
||||
|
||||
# Exctract all devices
|
||||
for device in self.context.list_devices():
|
||||
dev_list.append(
|
||||
Device(device.sys_name),
|
||||
Path(device.device_node),
|
||||
[Path(node) for node in device.device_links],
|
||||
)
|
||||
|
||||
return dev_list
|
||||
|
||||
@property
|
||||
def video_devices(self) -> List[Device]:
|
||||
"""Return all available video devices."""
|
||||
dev_list: List[Device] = []
|
||||
|
||||
for device in self.devices:
|
||||
if not RE_VIDEO_DEVICES.match(device.name):
|
||||
continue
|
||||
dev_list.append(device)
|
||||
|
||||
return dev_list
|
||||
|
||||
@property
|
||||
def serial_devices(self) -> Set[str]:
|
||||
"""Return all serial and connected devices."""
|
||||
|
@ -75,6 +75,7 @@ function install_cli() {
|
||||
function setup_test_env() {
|
||||
mkdir -p /workspaces/test_hassio
|
||||
|
||||
echo "Start Supervisor"
|
||||
docker run --rm --privileged \
|
||||
--name hassio_supervisor \
|
||||
--security-opt seccomp=unconfined \
|
||||
@ -88,6 +89,10 @@ function setup_test_env() {
|
||||
-e SUPERVISOR_DEV=1 \
|
||||
-e HOMEASSISTANT_REPOSITORY="homeassistant/qemux86-64-homeassistant" \
|
||||
homeassistant/amd64-hassio-supervisor:latest
|
||||
|
||||
if docker rm homeassistant 2> /dev/null; then
|
||||
echo "Cleanup HomeAssistant instance"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Start Test-Env"
|
||||
|
Loading…
x
Reference in New Issue
Block a user