Send event when add-on changes state (#2608)

* Send event when add-on changes state

* fix test
This commit is contained in:
Joakim Sørensen 2021-02-23 15:12:30 +01:00 committed by GitHub
parent 3802b97bb6
commit 90d8832cd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 38 deletions

View File

@ -22,6 +22,8 @@ from ..const import (
ATTR_AUDIO_OUTPUT,
ATTR_AUTO_UPDATE,
ATTR_BOOT,
ATTR_DATA,
ATTR_EVENT,
ATTR_IMAGE,
ATTR_INGRESS_ENTRY,
ATTR_INGRESS_PANEL,
@ -32,8 +34,10 @@ from ..const import (
ATTR_PORTS,
ATTR_PROTECTED,
ATTR_SCHEMA,
ATTR_SLUG,
ATTR_STATE,
ATTR_SYSTEM,
ATTR_TYPE,
ATTR_USER,
ATTR_UUID,
ATTR_VERSION,
@ -56,6 +60,7 @@ from ..exceptions import (
JsonFileError,
)
from ..hardware.data import Device
from ..homeassistant.const import WSEvent, WSType
from ..utils import check_port
from ..utils.apparmor import adjust_profile
from ..utils.json import read_json_file, write_json_file
@ -89,12 +94,34 @@ class Addon(AddonModel):
"""Initialize data holder."""
super().__init__(coresys, slug)
self.instance: DockerAddon = DockerAddon(coresys, self)
self.state: AddonState = AddonState.UNKNOWN
self._state: AddonState = AddonState.UNKNOWN
def __repr__(self) -> str:
"""Return internal representation."""
return f"<Addon: {self.slug}>"
@property
def state(self) -> AddonState:
"""Return state of the add-on."""
return self._state
@state.setter
def state(self, new_state: AddonState) -> None:
"""Set the add-on into new state."""
if self._state == new_state:
return
self._state = new_state
self.sys_homeassistant.websocket.send_command(
{
ATTR_TYPE: WSType.SUPERVISOR_EVENT,
ATTR_DATA: {
ATTR_EVENT: WSEvent.ADDON,
ATTR_SLUG: self.slug,
ATTR_STATE: new_state,
},
}
)
@property
def in_progress(self) -> bool:
"""Return True if a task is in progress."""

View File

@ -73,6 +73,7 @@ ENV_SUPERVISOR_CPU_RT = "SUPERVISOR_CPU_RT"
REQUEST_FROM = "HASSIO_FROM"
ATTR_ACCESS_TOKEN = "access_token"
ATTR_ACCESSPOINTS = "accesspoints"
ATTR_ACTIVE = "active"
ATTR_ADDON = "addon"
ATTR_ADDONS = "addons"
@ -89,8 +90,8 @@ ATTR_ARGS = "args"
ATTR_AUDIO = "audio"
ATTR_AUDIO_INPUT = "audio_input"
ATTR_AUDIO_OUTPUT = "audio_output"
ATTR_AUTH = "auth"
ATTR_AUTH_API = "auth_api"
ATTR_UART = "uart"
ATTR_AUTO_UPDATE = "auto_update"
ATTR_AVAILABLE = "available"
ATTR_BLK_READ = "blk_read"
@ -106,11 +107,13 @@ ATTR_CHANNEL = "channel"
ATTR_CHASSIS = "chassis"
ATTR_CLI = "cli"
ATTR_CONFIG = "config"
ATTR_CONNECTED = "connected"
ATTR_CONNECTIONS = "connections"
ATTR_CONTAINERS = "containers"
ATTR_CPE = "cpe"
ATTR_CPU_PERCENT = "cpu_percent"
ATTR_CRYPTO = "crypto"
ATTR_DATA = "data"
ATTR_DATE = "date"
ATTR_DEBUG = "debug"
ATTR_DEBUG_BLOCK = "debug_block"
@ -124,6 +127,7 @@ ATTR_DIAGNOSTICS = "diagnostics"
ATTR_DISCOVERY = "discovery"
ATTR_DISK = "disk"
ATTR_DISK_FREE = "disk_free"
ATTR_DISK_LIFE_TIME = "disk_life_time"
ATTR_DISK_TOTAL = "disk_total"
ATTR_DISK_USED = "disk_used"
ATTR_DNS = "dns"
@ -132,11 +136,14 @@ ATTR_DOCKER_API = "docker_api"
ATTR_DOCUMENTATION = "documentation"
ATTR_DOMAINS = "domains"
ATTR_ENABLE = "enable"
ATTR_ENABLED = "enabled"
ATTR_ENVIRONMENT = "environment"
ATTR_EVENT = "event"
ATTR_FEATURES = "features"
ATTR_FILENAME = "filename"
ATTR_FLAGS = "flags"
ATTR_FOLDERS = "folders"
ATTR_FREQUENCY = "frequency"
ATTR_FULL_ACCESS = "full_access"
ATTR_GATEWAY = "gateway"
ATTR_GPIO = "gpio"
@ -155,7 +162,6 @@ ATTR_HOST_PID = "host_pid"
ATTR_HOSTNAME = "hostname"
ATTR_ICON = "icon"
ATTR_ID = "id"
ATTR_ISSUES = "issues"
ATTR_IMAGE = "image"
ATTR_IMAGES = "images"
ATTR_INDEX = "index"
@ -174,6 +180,7 @@ ATTR_INTERFACES = "interfaces"
ATTR_IP_ADDRESS = "ip_address"
ATTR_IPV4 = "ipv4"
ATTR_IPV6 = "ipv6"
ATTR_ISSUES = "issues"
ATTR_KERNEL = "kernel"
ATTR_KERNEL_MODULES = "kernel_modules"
ATTR_LAST_BOOT = "last_boot"
@ -183,6 +190,7 @@ ATTR_LOCATON = "location"
ATTR_LOGGING = "logging"
ATTR_LOGO = "logo"
ATTR_LONG_DESCRIPTION = "long_description"
ATTR_MAC = "mac"
ATTR_MACHINE = "machine"
ATTR_MAINTAINER = "maintainer"
ATTR_MAP = "map"
@ -199,15 +207,17 @@ ATTR_NETWORK = "network"
ATTR_NETWORK_DESCRIPTION = "network_description"
ATTR_NETWORK_RX = "network_rx"
ATTR_NETWORK_TX = "network_tx"
ATTR_OBSERVER = "observer"
ATTR_OPERATING_SYSTEM = "operating_system"
ATTR_OPTIONS = "options"
ATTR_OTA = "ota"
ATTR_OUTPUT = "output"
ATTR_PANEL_ADMIN = "panel_admin"
ATTR_PANEL_ICON = "panel_icon"
ATTR_PANEL_TITLE = "panel_title"
ATTR_PANELS = "panels"
ATTR_PASSWORD = "password"
ATTR_PARENT = "parent"
ATTR_PASSWORD = "password"
ATTR_PORT = "port"
ATTR_PORTS = "ports"
ATTR_PORTS_DESCRIPTION = "ports_description"
@ -217,7 +227,9 @@ ATTR_PRIORITY = "priority"
ATTR_PRIVILEGED = "privileged"
ATTR_PROTECTED = "protected"
ATTR_PROVIDERS = "providers"
ATTR_PSK = "psk"
ATTR_RATING = "rating"
ATTR_REALTIME = "realtime"
ATTR_REFRESH_TOKEN = "refresh_token"
ATTR_REGISTRIES = "registries"
ATTR_REGISTRY = "registry"
@ -230,14 +242,15 @@ ATTR_SERVERS = "servers"
ATTR_SERVICE = "service"
ATTR_SERVICES = "services"
ATTR_SESSION = "session"
ATTR_SIGNAL = "signal"
ATTR_SIZE = "size"
ATTR_SLUG = "slug"
ATTR_SNAPSHOT_EXCLUDE = "snapshot_exclude"
ATTR_SNAPSHOTS = "snapshots"
ATTR_SOURCE = "source"
ATTR_SQUASH = "squash"
ATTR_SSD = "ssid"
ATTR_SSID = "ssid"
ATTR_DISK_LIFE_TIME = "disk_life_time"
ATTR_SSL = "ssl"
ATTR_STAGE = "stage"
ATTR_STARTUP = "startup"
@ -257,9 +270,13 @@ ATTR_TITLE = "title"
ATTR_TMPFS = "tmpfs"
ATTR_TOTP = "totp"
ATTR_TYPE = "type"
ATTR_UART = "uart"
ATTR_UDEV = "udev"
ATTR_UNHEALTHY = "unhealthy"
ATTR_UNSAVED = "unsaved"
ATTR_UNSUPPORTED = "unsupported"
ATTR_UPDATE_AVAILABLE = "update_available"
ATTR_UPDATE_KEY = "update_key"
ATTR_URL = "url"
ATTR_USB = "usb"
ATTR_USER = "user"
@ -270,27 +287,13 @@ ATTR_VALUE = "value"
ATTR_VERSION = "version"
ATTR_VERSION_LATEST = "version_latest"
ATTR_VIDEO = "video"
ATTR_VLAN = "vlan"
ATTR_VOLUME = "volume"
ATTR_VPN = "vpn"
ATTR_WAIT_BOOT = "wait_boot"
ATTR_WATCHDOG = "watchdog"
ATTR_WEBUI = "webui"
ATTR_OBSERVER = "observer"
ATTR_UPDATE_AVAILABLE = "update_available"
ATTR_WIFI = "wifi"
ATTR_VLAN = "vlan"
ATTR_SSD = "ssid"
ATTR_AUTH = "auth"
ATTR_PSK = "psk"
ATTR_CONNECTED = "connected"
ATTR_ENABLED = "enabled"
ATTR_SIGNAL = "signal"
ATTR_MAC = "mac"
ATTR_FREQUENCY = "frequency"
ATTR_ACCESSPOINTS = "accesspoints"
ATTR_UNHEALTHY = "unhealthy"
ATTR_OTA = "ota"
ATTR_REALTIME = "realtime"
PROVIDE_SERVICE = "provide"
NEED_SERVICE = "need"

View File

@ -47,6 +47,8 @@ class Core(CoreSysAttributes):
@state.setter
def state(self, new_state: CoreState) -> None:
"""Set core into new state."""
if self._state == new_state:
return
try:
RUN_SUPERVISOR_STATE.write_text(new_state.value)
except OSError as err:

View File

@ -0,0 +1,26 @@
"""Constants for homeassistant."""
from enum import Enum
from ..const import CoreState
MIN_VERSION = {"supervisor/event": "2021.2.4"}
CLOSING_STATES = [
CoreState.SHUTDOWN,
CoreState.STOPPING,
CoreState.CLOSE,
]
class WSType(str, Enum):
"""Websocket types."""
AUTH = "auth"
SUPERVISOR_EVENT = "supervisor/event"
class WSEvent(str, Enum):
"""Websocket events."""
ADDON = "addon"
SUPERVISOR_UPDATE = "supervisor_update"

View File

@ -5,24 +5,17 @@ from typing import Any, Dict, Optional
import aiohttp
from awesomeversion import AwesomeVersion
from ..const import CoreState
from ..const import ATTR_ACCESS_TOKEN, ATTR_DATA, ATTR_EVENT, ATTR_TYPE, ATTR_UPDATE_KEY
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
HomeAssistantAPIError,
HomeAssistantWSError,
HomeAssistantWSNotSupported,
)
from .const import CLOSING_STATES, MIN_VERSION, WSEvent, WSType
_LOGGER: logging.Logger = logging.getLogger(__name__)
CLOSING_STATES = [
CoreState.SHUTDOWN,
CoreState.STOPPING,
CoreState.CLOSE,
]
MIN_VERSION = {"supervisor/event": "2021.2.4"}
class WSClient:
"""Home Assistant Websocket client."""
@ -68,13 +61,13 @@ class WSClient:
hello_message = await client.receive_json()
try:
await client.send_json({"type": "auth", "access_token": token})
await client.send_json({ATTR_TYPE: WSType.AUTH, ATTR_ACCESS_TOKEN: token})
except HomeAssistantWSNotSupported:
return
auth_ok_message = await client.receive_json()
if auth_ok_message["type"] != "auth_ok":
if auth_ok_message[ATTR_TYPE] != "auth_ok":
raise HomeAssistantAPIError("AUTH NOT OK")
return cls(AwesomeVersion(hello_message["ha_version"]), client)
@ -138,11 +131,11 @@ class HomeAssistantWebSocket(CoreSysAttributes):
try:
await self.async_send_command(
{
"type": "supervisor/event",
"data": {
"event": "supervisor-update",
"update_key": key,
"data": data or {},
ATTR_TYPE: WSType.SUPERVISOR_EVENT,
ATTR_DATA: {
ATTR_EVENT: WSEvent.SUPERVISOR_UPDATE,
ATTR_UPDATE_KEY: key,
ATTR_DATA: data or {},
},
}
)

View File

@ -5,6 +5,7 @@ import logging
from awesomeversion import AwesomeVersion
from supervisor.coresys import CoreSys
from supervisor.homeassistant.const import WSEvent, WSType
async def test_send_command(coresys: CoreSys):
@ -18,9 +19,9 @@ async def test_send_command(coresys: CoreSys):
)
client.async_send_command.assert_called_with(
{
"type": "supervisor/event",
"type": WSType.SUPERVISOR_EVENT,
"data": {
"event": "supervisor-update",
"event": WSEvent.SUPERVISOR_UPDATE,
"update_key": "test",
"data": {"lorem": "ipsum"},
},