diff --git a/hassio/src/addon-store/hassio-addon-store.ts b/hassio/src/addon-store/hassio-addon-store.ts
index 6add263da7..0f67342110 100644
--- a/hassio/src/addon-store/hassio-addon-store.ts
+++ b/hassio/src/addon-store/hassio-addon-store.ts
@@ -192,8 +192,10 @@ class HassioAddonStore extends LitElement {
}
private async _loadData() {
- fireEvent(this, "supervisor-store-refresh", { store: "addon" });
- fireEvent(this, "supervisor-store-refresh", { store: "supervisor" });
+ fireEvent(this, "supervisor-colllection-refresh", { colllection: "addon" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "supervisor",
+ });
}
private async _filterChanged(e) {
diff --git a/hassio/src/addon-view/hassio-addon-dashboard.ts b/hassio/src/addon-view/hassio-addon-dashboard.ts
index 4c01e88c87..ebbaf9254b 100644
--- a/hassio/src/addon-view/hassio-addon-dashboard.ts
+++ b/hassio/src/addon-view/hassio-addon-dashboard.ts
@@ -190,7 +190,9 @@ class HassioAddonDashboard extends LitElement {
const path: string = pathSplit[pathSplit.length - 1];
if (["uninstall", "install", "update", "start", "stop"].includes(path)) {
- fireEvent(this, "supervisor-store-refresh", { store: "supervisor" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "supervisor",
+ });
}
if (path === "uninstall") {
diff --git a/hassio/src/addon-view/info/hassio-addon-info.ts b/hassio/src/addon-view/info/hassio-addon-info.ts
index dfb1386662..51f02f651c 100644
--- a/hassio/src/addon-view/info/hassio-addon-info.ts
+++ b/hassio/src/addon-view/info/hassio-addon-info.ts
@@ -25,6 +25,7 @@ import {
TemplateResult,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
+import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { navigate } from "../../../../src/common/navigate";
@@ -57,6 +58,7 @@ import {
fetchHassioStats,
HassioStats,
} from "../../../../src/data/hassio/common";
+import { StoreAddon } from "../../../../src/data/supervisor/store";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import {
showAlertDialog,
@@ -148,7 +150,16 @@ class HassioAddonInfo extends LitElement {
@internalProperty() private _error?: string;
+ private _addonStoreInfo = memoizeOne(
+ (slug: string, storeAddons: StoreAddon[]) =>
+ storeAddons.find((addon) => addon.slug === slug)
+ );
+
protected render(): TemplateResult {
+ const addonStoreInfo =
+ !this.addon.detached && !this.addon.available
+ ? this._addonStoreInfo(this.addon.slug, this.supervisor.store.addons)
+ : undefined;
const metrics = [
{
description: "Add-on CPU Usage",
@@ -176,30 +187,33 @@ class HassioAddonInfo extends LitElement {
icon=${mdiArrowUpBoldCircle}
iconClass="update"
>
- ${!this.addon.available
+ ${!this.addon.available && addonStoreInfo
? !addonArchIsSupported(
this.supervisor.info.supported_arch,
this.addon.arch
)
? html`
-
+
This add-on is not compatible with the processor of
your device or the operating system you have installed
on your device.
`
: html`
-
+
You are running Home Assistant
${this.supervisor.core.version}, to update to this
version of the add-on you need at least version
- ${this.addon.homeassistant} of Home Assistant
+ ${addonStoreInfo.homeassistant} of Home Assistant
`
: ""}
-
+
Update
${this.addon.changelog
@@ -551,7 +565,7 @@ class HassioAddonInfo extends LitElement {
${this._error ? html` ${this._error}
` : ""}
- ${!this.addon.available
+ ${!this.addon.version && addonStoreInfo && !this.addon.available
? !addonArchIsSupported(
this.supervisor.info.supported_arch,
this.addon.arch
@@ -567,8 +581,8 @@ class HassioAddonInfo extends LitElement {
You are running Home Assistant
${this.supervisor.core.version}, to install this add-on you
- need at least version ${this.addon.homeassistant} of Home
- Assistant
+ need at least version ${addonStoreInfo!.homeassistant} of
+ Home Assistant
`
: ""}
diff --git a/hassio/src/dashboard/hassio-update.ts b/hassio/src/dashboard/hassio-update.ts
index 488e541f2f..730d2a245a 100644
--- a/hassio/src/dashboard/hassio-update.ts
+++ b/hassio/src/dashboard/hassio-update.ts
@@ -148,7 +148,9 @@ export class HassioUpdate extends LitElement {
}
try {
await this.hass.callApi>("POST", item.apiPath);
- fireEvent(this, "supervisor-store-refresh", { store: item.key });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: item.key,
+ });
} catch (err) {
// Only show an error if the status code was not expected (user behind proxy)
// or no status at all(connection terminated)
diff --git a/hassio/src/hassio-main.ts b/hassio/src/hassio-main.ts
index 31de2006d7..5283a8cb08 100644
--- a/hassio/src/hassio-main.ts
+++ b/hassio/src/hassio-main.ts
@@ -3,7 +3,7 @@ import { atLeastVersion } from "../../src/common/config/version";
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../src/common/dom/fire_event";
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
-import { supervisorStore } from "../../src/data/supervisor/supervisor";
+import { supervisorCollection } from "../../src/data/supervisor/supervisor";
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
import "../../src/layouts/hass-loading-screen";
import { HomeAssistant, Route } from "../../src/types";
@@ -77,7 +77,9 @@ export class HassioMain extends SupervisorBaseElement {
}
if (
- Object.keys(supervisorStore).some((store) => !this.supervisor![store])
+ Object.keys(supervisorCollection).some(
+ (colllection) => !this.supervisor![colllection]
+ )
) {
return html``;
}
diff --git a/hassio/src/supervisor-base-element.ts b/hassio/src/supervisor-base-element.ts
index 9abdf473a5..8522614ff7 100644
--- a/hassio/src/supervisor-base-element.ts
+++ b/hassio/src/supervisor-base-element.ts
@@ -19,12 +19,13 @@ import {
fetchHassioInfo,
fetchHassioSupervisorInfo,
} from "../../src/data/hassio/supervisor";
+import { fetchSupervisorStore } from "../../src/data/supervisor/store";
import {
getSupervisorEventCollection,
subscribeSupervisorEvents,
Supervisor,
SupervisorObject,
- supervisorStore,
+ supervisorCollection,
} from "../../src/data/supervisor/supervisor";
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
@@ -32,7 +33,7 @@ import { urlSyncMixin } from "../../src/state/url-sync-mixin";
declare global {
interface HASSDomEvents {
"supervisor-update": Partial;
- "supervisor-store-refresh": { store: SupervisorObject };
+ "supervisor-colllection-refresh": { colllection: SupervisorObject };
}
}
@@ -65,40 +66,40 @@ export class SupervisorBaseElement extends urlSyncMixin(
}
private async _handleSupervisorStoreRefreshEvent(ev) {
- const store = ev.detail.store;
+ const colllection = ev.detail.colllection;
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
- this._collections[store].refresh();
+ this._collections[colllection].refresh();
return;
}
const response = await this.hass.callApi>(
"GET",
- `hassio${supervisorStore[store]}`
+ `hassio${supervisorCollection[colllection]}`
);
- this._updateSupervisor({ [store]: response.data });
+ this._updateSupervisor({ [colllection]: response.data });
}
private async _initSupervisor(): Promise {
this.addEventListener(
- "supervisor-store-refresh",
+ "supervisor-colllection-refresh",
this._handleSupervisorStoreRefreshEvent
);
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
- Object.keys(supervisorStore).forEach((store) => {
- this._unsubs[store] = subscribeSupervisorEvents(
+ Object.keys(supervisorCollection).forEach((colllection) => {
+ this._unsubs[colllection] = subscribeSupervisorEvents(
this.hass,
- (data) => this._updateSupervisor({ [store]: data }),
- store,
- supervisorStore[store]
+ (data) => this._updateSupervisor({ [colllection]: data }),
+ colllection,
+ supervisorCollection[colllection]
);
- if (this._collections[store]) {
- this._collections[store].refresh();
+ if (this._collections[colllection]) {
+ this._collections[colllection].refresh();
} else {
- this._collections[store] = getSupervisorEventCollection(
+ this._collections[colllection] = getSupervisorEventCollection(
this.hass.connection,
- store,
- supervisorStore[store]
+ colllection,
+ supervisorCollection[colllection]
);
}
});
@@ -122,6 +123,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
os,
network,
resolution,
+ store,
] = await Promise.all([
fetchHassioAddonsInfo(this.hass),
fetchHassioSupervisorInfo(this.hass),
@@ -131,6 +133,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
fetchHassioHassOsInfo(this.hass),
fetchNetworkInfo(this.hass),
fetchHassioResolution(this.hass),
+ fetchSupervisorStore(this.hass),
]);
this.supervisor = {
@@ -142,6 +145,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
os,
network,
resolution,
+ store,
};
this.addEventListener("supervisor-update", (ev) =>
diff --git a/hassio/src/system/hassio-core-info.ts b/hassio/src/system/hassio-core-info.ts
index 985a242773..c07ea824f5 100644
--- a/hassio/src/system/hassio-core-info.ts
+++ b/hassio/src/system/hassio-core-info.ts
@@ -167,7 +167,9 @@ class HassioCoreInfo extends LitElement {
try {
await updateCore(this.hass);
- fireEvent(this, "supervisor-store-refresh", { store: "core" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "core",
+ });
} catch (err) {
showAlertDialog(this, {
title: "Failed to update Home Assistant Core",
diff --git a/hassio/src/system/hassio-host-info.ts b/hassio/src/system/hassio-host-info.ts
index 69245d8663..2abe3a74cb 100644
--- a/hassio/src/system/hassio-host-info.ts
+++ b/hassio/src/system/hassio-host-info.ts
@@ -340,7 +340,7 @@ class HassioHostInfo extends LitElement {
try {
await updateOS(this.hass);
- fireEvent(this, "supervisor-store-refresh", { store: "os" });
+ fireEvent(this, "supervisor-colllection-refresh", { colllection: "os" });
} catch (err) {
showAlertDialog(this, {
title: "Failed to update",
@@ -369,7 +369,9 @@ class HassioHostInfo extends LitElement {
if (hostname && hostname !== curHostname) {
try {
await changeHostOptions(this.hass, { hostname });
- fireEvent(this, "supervisor-store-refresh", { store: "host" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "host",
+ });
} catch (err) {
showAlertDialog(this, {
title: "Setting hostname failed",
@@ -382,7 +384,9 @@ class HassioHostInfo extends LitElement {
private async _importFromUSB(): Promise {
try {
await configSyncOS(this.hass);
- fireEvent(this, "supervisor-store-refresh", { store: "host" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "host",
+ });
} catch (err) {
showAlertDialog(this, {
title: "Failed to import from USB",
@@ -393,7 +397,9 @@ class HassioHostInfo extends LitElement {
private async _loadData(): Promise {
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
- fireEvent(this, "supervisor-store-refresh", { store: "network" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "network",
+ });
} else {
const network = await fetchNetworkInfo(this.hass);
fireEvent(this, "supervisor-update", { network });
diff --git a/hassio/src/system/hassio-supervisor-info.ts b/hassio/src/system/hassio-supervisor-info.ts
index ebc96ab32a..3afc373e0b 100644
--- a/hassio/src/system/hassio-supervisor-info.ts
+++ b/hassio/src/system/hassio-supervisor-info.ts
@@ -317,7 +317,9 @@ class HassioSupervisorInfo extends LitElement {
private async _reloadSupervisor(): Promise {
await reloadSupervisor(this.hass);
- fireEvent(this, "supervisor-store-refresh", { store: "supervisor" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "supervisor",
+ });
}
private async _supervisorRestart(ev: CustomEvent): Promise {
@@ -366,7 +368,9 @@ class HassioSupervisorInfo extends LitElement {
try {
await updateSupervisor(this.hass);
- fireEvent(this, "supervisor-store-refresh", { store: "supervisor" });
+ fireEvent(this, "supervisor-colllection-refresh", {
+ colllection: "supervisor",
+ });
} catch (err) {
showAlertDialog(this, {
title: "Failed to update the supervisor",
diff --git a/src/data/hassio/addon.ts b/src/data/hassio/addon.ts
index b17f327097..06a4760d42 100644
--- a/src/data/hassio/addon.ts
+++ b/src/data/hassio/addon.ts
@@ -4,20 +4,33 @@ import { HomeAssistant } from "../../types";
import { SupervisorArch } from "../supervisor/supervisor";
import { hassioApiResultExtractor, HassioResponse } from "./common";
+export type AddonStage = "stable" | "experimental" | "deprecated";
+export type AddonAppArmour = "disable" | "default" | "profile";
+export type AddonRole = "default" | "homeassistant" | "manager" | "admin";
+export type AddonStartup =
+ | "initialize"
+ | "system"
+ | "services"
+ | "application"
+ | "once";
+export type AddonState = "started" | "stopped" | null;
+export type AddonRepository = "core" | "local" | string;
+
export interface HassioAddonInfo {
advanced: boolean;
available: boolean;
build: boolean;
description: string;
detached: boolean;
+ homeassistant: string;
icon: boolean;
installed: boolean;
logo: boolean;
name: string;
- repository: "core" | "local" | string;
+ repository: AddonRepository;
slug: string;
- stage: "stable" | "experimental" | "deprecated";
- state: "started" | "stopped" | null;
+ stage: AddonStage;
+ state: AddonState;
update_available: boolean;
url: string | null;
version_latest: string;
@@ -25,7 +38,7 @@ export interface HassioAddonInfo {
}
export interface HassioAddonDetails extends HassioAddonInfo {
- apparmor: "disable" | "default" | "profile";
+ apparmor: AddonAppArmour;
arch: SupervisorArch[];
audio_input: null | string;
audio_output: null | string;
@@ -43,10 +56,9 @@ export interface HassioAddonDetails extends HassioAddonInfo {
full_access: boolean;
gpio: boolean;
hassio_api: boolean;
- hassio_role: "default" | "homeassistant" | "manager" | "admin";
+ hassio_role: AddonRole;
hostname: string;
homeassistant_api: boolean;
- homeassistant: string;
host_dbus: boolean;
host_ipc: boolean;
host_network: boolean;
@@ -68,7 +80,7 @@ export interface HassioAddonDetails extends HassioAddonInfo {
schema: HaFormSchema[] | null;
services_role: string[];
slug: string;
- startup: "initialize" | "system" | "services" | "application" | "once";
+ startup: AddonStartup;
stdin: boolean;
watchdog: null | boolean;
webui: null | string;
diff --git a/src/data/supervisor/store.ts b/src/data/supervisor/store.ts
new file mode 100644
index 0000000000..c917388faf
--- /dev/null
+++ b/src/data/supervisor/store.ts
@@ -0,0 +1,51 @@
+import { atLeastVersion } from "../../common/config/version";
+import { HomeAssistant } from "../../types";
+import { AddonRepository, AddonStage } from "../hassio/addon";
+import { hassioApiResultExtractor, HassioResponse } from "../hassio/common";
+
+export interface StoreAddon {
+ advanced: boolean;
+ available: boolean;
+ build: boolean;
+ description: string;
+ homeassistant: string | null;
+ icon: boolean;
+ installed: boolean;
+ logo: boolean;
+ name: string;
+ repository: AddonRepository;
+ slug: string;
+ stage: AddonStage;
+ update_available: boolean;
+ url: string;
+ version: string | null;
+ version_latest: string;
+}
+interface StoreRepository {
+ maintainer: string;
+ name: string;
+ slug: string;
+ source: string;
+ url: string;
+}
+
+export interface SupervisorStore {
+ addons: StoreAddon[];
+ repositories: StoreRepository[];
+}
+
+export const fetchSupervisorStore = async (
+ hass: HomeAssistant
+): Promise => {
+ if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
+ return await hass.callWS({
+ type: "supervisor/api",
+ endpoint: "/store",
+ method: "get",
+ });
+ }
+
+ return hassioApiResultExtractor(
+ await hass.callApi>("GET", `hassio/store`)
+ );
+};
diff --git a/src/data/supervisor/supervisor.ts b/src/data/supervisor/supervisor.ts
index c884c79e0a..4f1eff928a 100644
--- a/src/data/supervisor/supervisor.ts
+++ b/src/data/supervisor/supervisor.ts
@@ -10,13 +10,14 @@ import {
HassioInfo,
HassioSupervisorInfo,
} from "../hassio/supervisor";
+import { SupervisorStore } from "./store";
export const supervisorWSbaseCommand = {
type: "supervisor/api",
method: "GET",
};
-export const supervisorStore = {
+export const supervisorCollection = {
host: "/host/info",
supervisor: "/supervisor/info",
info: "/info",
@@ -25,6 +26,7 @@ export const supervisorStore = {
resolution: "/resolution/info",
os: "/os/info",
addon: "/addons",
+ store: "/store",
};
export type SupervisorArch = "armhf" | "armv7" | "aarch64" | "i386" | "amd64";
@@ -36,7 +38,8 @@ export type SupervisorObject =
| "network"
| "resolution"
| "os"
- | "addon";
+ | "addon"
+ | "store";
interface supervisorApiRequest {
endpoint: string;
@@ -61,6 +64,7 @@ export interface Supervisor {
resolution: HassioResolution;
os: HassioHassOSInfo;
addon: HassioAddonsInfo;
+ store: SupervisorStore;
}
export const supervisorApiWsRequest = (
@@ -81,7 +85,7 @@ async function processEvent(
if (Object.keys(event.data).length === 0) {
const data = await supervisorApiWsRequest(conn, {
- endpoint: supervisorStore[key],
+ endpoint: supervisorCollection[key],
});
store.setState(data);
return;