mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 17:26:42 +00:00
Supervisor network changes (#7676)
This commit is contained in:
parent
0b896ddfb1
commit
c409ba149d
@ -1,5 +1,7 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import "@material/mwc-icon-button";
|
import "@material/mwc-icon-button";
|
||||||
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import "@material/mwc-tab";
|
import "@material/mwc-tab";
|
||||||
import "@material/mwc-tab-bar";
|
import "@material/mwc-tab-bar";
|
||||||
import { mdiClose } from "@mdi/js";
|
import { mdiClose } from "@mdi/js";
|
||||||
@ -16,18 +18,22 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { cache } from "lit-html/directives/cache";
|
import { cache } from "lit-html/directives/cache";
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
|
import "../../../../src/components/ha-chips";
|
||||||
import "../../../../src/components/ha-circular-progress";
|
import "../../../../src/components/ha-circular-progress";
|
||||||
import "../../../../src/components/ha-dialog";
|
import "../../../../src/components/ha-dialog";
|
||||||
|
import "../../../../src/components/ha-expansion-panel";
|
||||||
import "../../../../src/components/ha-formfield";
|
import "../../../../src/components/ha-formfield";
|
||||||
import "../../../../src/components/ha-header-bar";
|
import "../../../../src/components/ha-header-bar";
|
||||||
import "../../../../src/components/ha-radio";
|
import "../../../../src/components/ha-radio";
|
||||||
import type { HaRadio } from "../../../../src/components/ha-radio";
|
|
||||||
import "../../../../src/components/ha-related-items";
|
import "../../../../src/components/ha-related-items";
|
||||||
import "../../../../src/components/ha-svg-icon";
|
import "../../../../src/components/ha-svg-icon";
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
import {
|
import {
|
||||||
|
AccessPoints,
|
||||||
|
accesspointScan,
|
||||||
NetworkInterface,
|
NetworkInterface,
|
||||||
updateNetworkInterface,
|
updateNetworkInterface,
|
||||||
|
WifiConfiguration,
|
||||||
} from "../../../../src/data/hassio/network";
|
} from "../../../../src/data/hassio/network";
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
@ -38,54 +44,51 @@ import { haStyleDialog } from "../../../../src/resources/styles";
|
|||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { HassioNetworkDialogParams } from "./show-dialog-network";
|
import { HassioNetworkDialogParams } from "./show-dialog-network";
|
||||||
|
|
||||||
|
const IP_VERSIONS = ["ipv4", "ipv6"];
|
||||||
|
|
||||||
@customElement("dialog-hassio-network")
|
@customElement("dialog-hassio-network")
|
||||||
export class DialogHassioNetwork extends LitElement
|
export class DialogHassioNetwork extends LitElement
|
||||||
implements HassDialog<HassioNetworkDialogParams> {
|
implements HassDialog<HassioNetworkDialogParams> {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@internalProperty() private _prosessing = false;
|
@internalProperty() private _accessPoints?: AccessPoints;
|
||||||
|
|
||||||
@internalProperty() private _params?: HassioNetworkDialogParams;
|
|
||||||
|
|
||||||
@internalProperty() private _network!: {
|
|
||||||
interface: string;
|
|
||||||
data: NetworkInterface;
|
|
||||||
}[];
|
|
||||||
|
|
||||||
@internalProperty() private _curTabIndex = 0;
|
@internalProperty() private _curTabIndex = 0;
|
||||||
|
|
||||||
@internalProperty() private _device?: {
|
|
||||||
interface: string;
|
|
||||||
data: NetworkInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
@internalProperty() private _dirty = false;
|
@internalProperty() private _dirty = false;
|
||||||
|
|
||||||
|
@internalProperty() private _interface?: NetworkInterface;
|
||||||
|
|
||||||
|
@internalProperty() private _interfaces!: NetworkInterface[];
|
||||||
|
|
||||||
|
@internalProperty() private _params?: HassioNetworkDialogParams;
|
||||||
|
|
||||||
|
@internalProperty() private _processing = false;
|
||||||
|
|
||||||
|
@internalProperty() private _scanning = false;
|
||||||
|
|
||||||
|
@internalProperty() private _wifiConfiguration?: WifiConfiguration;
|
||||||
|
|
||||||
public async showDialog(params: HassioNetworkDialogParams): Promise<void> {
|
public async showDialog(params: HassioNetworkDialogParams): Promise<void> {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._dirty = false;
|
this._dirty = false;
|
||||||
this._curTabIndex = 0;
|
this._curTabIndex = 0;
|
||||||
this._network = Object.keys(params.network?.interfaces)
|
this._interfaces = params.network.interfaces.sort((a, b) => {
|
||||||
.map((device) => ({
|
return a.primary > b.primary ? -1 : 1;
|
||||||
interface: device,
|
|
||||||
data: params.network.interfaces[device],
|
|
||||||
}))
|
|
||||||
.sort((a, b) => {
|
|
||||||
return a.data.primary > b.data.primary ? -1 : 1;
|
|
||||||
});
|
});
|
||||||
this._device = this._network[this._curTabIndex];
|
this._interface = { ...this._interfaces[this._curTabIndex] };
|
||||||
this._device.data.nameservers = String(this._device.data.nameservers);
|
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
this._prosessing = false;
|
this._processing = false;
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this._params || !this._network) {
|
if (!this._params || !this._interface) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +110,11 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
</ha-header-bar>
|
</ha-header-bar>
|
||||||
${this._network.length > 1
|
${this._interfaces.length > 1
|
||||||
? html` <mwc-tab-bar
|
? html` <mwc-tab-bar
|
||||||
.activeIndex=${this._curTabIndex}
|
.activeIndex=${this._curTabIndex}
|
||||||
@MDCTabBar:activated=${this._handleTabActivated}
|
@MDCTabBar:activated=${this._handleTabActivated}
|
||||||
>${this._network.map(
|
>${this._interfaces.map(
|
||||||
(device) =>
|
(device) =>
|
||||||
html`<mwc-tab
|
html`<mwc-tab
|
||||||
.id=${device.interface}
|
.id=${device.interface}
|
||||||
@ -129,81 +132,296 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
|
|
||||||
private _renderTab() {
|
private _renderTab() {
|
||||||
return html` <div class="form container">
|
return html` <div class="form container">
|
||||||
|
${IP_VERSIONS.map((version) =>
|
||||||
|
this._interface![version] ? this._renderIPConfiguration(version) : ""
|
||||||
|
)}
|
||||||
|
${this._interface?.type === "wireless"
|
||||||
|
? html`
|
||||||
|
<ha-expansion-panel outlined>
|
||||||
|
<span slot="title">Wi-Fi</span>
|
||||||
|
${this._interface?.wifi?.ssid
|
||||||
|
? html`<p>Connected to: ${this._interface?.wifi?.ssid}</p>`
|
||||||
|
: ""}
|
||||||
|
<mwc-button
|
||||||
|
class="scan"
|
||||||
|
@click=${this._scanForAP}
|
||||||
|
.disabled=${this._scanning}
|
||||||
|
>
|
||||||
|
${this._scanning
|
||||||
|
? html`<ha-circular-progress active size="small">
|
||||||
|
</ha-circular-progress>`
|
||||||
|
: "Scan for accesspoints"}
|
||||||
|
</mwc-button>
|
||||||
|
${this._accessPoints &&
|
||||||
|
this._accessPoints.accesspoints &&
|
||||||
|
this._accessPoints.accesspoints.length !== 0
|
||||||
|
? html`
|
||||||
|
<mwc-list>
|
||||||
|
${this._accessPoints.accesspoints
|
||||||
|
.filter((ap) => ap.ssid)
|
||||||
|
.map(
|
||||||
|
(ap) =>
|
||||||
|
html`
|
||||||
|
<mwc-list-item
|
||||||
|
twoline
|
||||||
|
@click=${this._selectAP}
|
||||||
|
.activated=${ap.ssid ===
|
||||||
|
this._wifiConfiguration?.ssid}
|
||||||
|
.ap=${ap}
|
||||||
|
>
|
||||||
|
<span>${ap.ssid}</span>
|
||||||
|
<span slot="secondary">
|
||||||
|
${ap.mac} - Strength: ${ap.signal}
|
||||||
|
</span>
|
||||||
|
</mwc-list-item>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
${this._wifiConfiguration
|
||||||
|
? html`
|
||||||
|
<div class="radio-row">
|
||||||
|
<ha-formfield label="open">
|
||||||
|
<ha-radio
|
||||||
|
@change=${this._handleRadioValueChangedAp}
|
||||||
|
.ap=${this._wifiConfiguration}
|
||||||
|
value="open"
|
||||||
|
name="auth"
|
||||||
|
.checked=${this._wifiConfiguration.auth ===
|
||||||
|
undefined ||
|
||||||
|
this._wifiConfiguration.auth === "open"}
|
||||||
|
>
|
||||||
|
</ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield label="wep">
|
||||||
|
<ha-radio
|
||||||
|
@change=${this._handleRadioValueChangedAp}
|
||||||
|
.ap=${this._wifiConfiguration}
|
||||||
|
value="wep"
|
||||||
|
name="auth"
|
||||||
|
.checked=${this._wifiConfiguration.auth === "wep"}
|
||||||
|
>
|
||||||
|
</ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield label="wpa-psk">
|
||||||
|
<ha-radio
|
||||||
|
@change=${this._handleRadioValueChangedAp}
|
||||||
|
.ap=${this._wifiConfiguration}
|
||||||
|
value="wpa-psk"
|
||||||
|
name="auth"
|
||||||
|
.checked=${this._wifiConfiguration.auth ===
|
||||||
|
"wpa-psk"}
|
||||||
|
>
|
||||||
|
</ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
</div>
|
||||||
|
${this._wifiConfiguration.auth === "wpa-psk" ||
|
||||||
|
this._wifiConfiguration.auth === "wep"
|
||||||
|
? html`
|
||||||
|
<paper-input
|
||||||
|
class="flex-auto"
|
||||||
|
type="password"
|
||||||
|
id="psk"
|
||||||
|
label="Password"
|
||||||
|
version="wifi"
|
||||||
|
@value-changed=${this
|
||||||
|
._handleInputValueChangedWifi}
|
||||||
|
>
|
||||||
|
</paper-input>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</ha-expansion-panel>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
${this._dirty
|
||||||
|
? html`<div class="warning">
|
||||||
|
If you are changing the Wi-Fi, IP or gateway addresses, you might
|
||||||
|
lose the connection!
|
||||||
|
</div>`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
|
<mwc-button label="close" @click=${this.closeDialog}> </mwc-button>
|
||||||
|
<mwc-button @click=${this._updateNetwork} .disabled=${!this._dirty}>
|
||||||
|
${this._processing
|
||||||
|
? html`<ha-circular-progress active size="small">
|
||||||
|
</ha-circular-progress>`
|
||||||
|
: "Save"}
|
||||||
|
</mwc-button>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectAP(event) {
|
||||||
|
this._wifiConfiguration = event.currentTarget.ap;
|
||||||
|
this._dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _scanForAP() {
|
||||||
|
if (!this._interface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._scanning = true;
|
||||||
|
try {
|
||||||
|
this._accessPoints = await accesspointScan(
|
||||||
|
this.hass,
|
||||||
|
this._interface.interface
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
title: "Failed to scan for accesspoints",
|
||||||
|
text: extractApiErrorMessage(err),
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this._scanning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderIPConfiguration(version: string) {
|
||||||
|
return html`
|
||||||
|
<ha-expansion-panel outlined>
|
||||||
|
<span slot="title">IPv${version.charAt(version.length - 1)}</span>
|
||||||
|
<div class="radio-row">
|
||||||
<ha-formfield label="DHCP">
|
<ha-formfield label="DHCP">
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChanged}
|
@change=${this._handleRadioValueChanged}
|
||||||
value="dhcp"
|
.version=${version}
|
||||||
name="method"
|
value="auto"
|
||||||
?checked=${this._device!.data.method === "dhcp"}
|
name="${version}method"
|
||||||
|
.checked=${this._interface![version]?.method === "auto"}
|
||||||
>
|
>
|
||||||
</ha-radio>
|
</ha-radio>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
<ha-formfield label="Static">
|
<ha-formfield label="Static">
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@change=${this._handleRadioValueChanged}
|
@change=${this._handleRadioValueChanged}
|
||||||
|
.version=${version}
|
||||||
value="static"
|
value="static"
|
||||||
name="method"
|
name="${version}method"
|
||||||
?checked=${this._device!.data.method === "static"}
|
.checked=${this._interface![version]?.method === "static"}
|
||||||
>
|
>
|
||||||
</ha-radio>
|
</ha-radio>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
${this._device!.data.method !== "dhcp"
|
<ha-formfield label="Disabled" class="warning">
|
||||||
? html` <paper-input
|
<ha-radio
|
||||||
|
@change=${this._handleRadioValueChanged}
|
||||||
|
.version=${version}
|
||||||
|
value="disabled"
|
||||||
|
name="${version}method"
|
||||||
|
.checked=${this._interface![version]?.method === "disabled"}
|
||||||
|
>
|
||||||
|
</ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
</div>
|
||||||
|
${this._interface![version].method === "static"
|
||||||
|
? html`
|
||||||
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="ip_address"
|
id="address"
|
||||||
label="IP address/Netmask"
|
label="IP address/Netmask"
|
||||||
.value="${this._device!.data.ip_address}"
|
.version=${version}
|
||||||
|
.value=${this._toString(this._interface![version].address)}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@value-changed=${this._handleInputValueChanged}
|
||||||
></paper-input>
|
>
|
||||||
|
</paper-input>
|
||||||
<paper-input
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="gateway"
|
id="gateway"
|
||||||
label="Gateway address"
|
label="Gateway address"
|
||||||
.value="${this._device!.data.gateway}"
|
.version=${version}
|
||||||
|
.value=${this._interface![version].gateway}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@value-changed=${this._handleInputValueChanged}
|
||||||
></paper-input>
|
>
|
||||||
|
</paper-input>
|
||||||
<paper-input
|
<paper-input
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="nameservers"
|
id="nameservers"
|
||||||
label="DNS servers"
|
label="DNS servers"
|
||||||
.value="${this._device!.data.nameservers as string}"
|
.version=${version}
|
||||||
|
.value=${this._toString(this._interface![version].nameservers)}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@value-changed=${this._handleInputValueChanged}
|
||||||
></paper-input>
|
>
|
||||||
NB!: If you are changing IP or gateway addresses, you might lose
|
</paper-input>
|
||||||
the connection.`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
</ha-expansion-panel>
|
||||||
<div class="buttons">
|
`;
|
||||||
<mwc-button label="close" @click=${this.closeDialog}> </mwc-button>
|
}
|
||||||
<mwc-button @click=${this._updateNetwork} ?disabled=${!this._dirty}>
|
|
||||||
${this._prosessing
|
_toArray(data: string | string[]): string[] {
|
||||||
? html`<ha-circular-progress active></ha-circular-progress>`
|
if (Array.isArray(data)) {
|
||||||
: "Update"}
|
if (data && typeof data[0] === "string") {
|
||||||
</mwc-button>
|
data = data[0];
|
||||||
</div>`;
|
}
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (typeof data === "string") {
|
||||||
|
return data.replace(/ /g, "").split(",");
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
_toString(data: string | string[]): string {
|
||||||
|
if (!data) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
return data.join(", ");
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _updateNetwork() {
|
private async _updateNetwork() {
|
||||||
this._prosessing = true;
|
this._processing = true;
|
||||||
let options: Partial<NetworkInterface> = {
|
let interfaceOptions: Partial<NetworkInterface> = {};
|
||||||
method: this._device!.data.method,
|
|
||||||
|
IP_VERSIONS.forEach((version) => {
|
||||||
|
interfaceOptions[version] = {
|
||||||
|
method: this._interface![version]?.method || "auto",
|
||||||
};
|
};
|
||||||
if (options.method !== "dhcp") {
|
if (this._interface![version]?.method === "static") {
|
||||||
options = {
|
interfaceOptions[version] = {
|
||||||
...options,
|
...interfaceOptions[version],
|
||||||
address: this._device!.data.ip_address,
|
address: this._toArray(this._interface![version]?.address),
|
||||||
gateway: this._device!.data.gateway,
|
gateway: this._interface![version]?.gateway,
|
||||||
dns: String(this._device!.data.nameservers).split(","),
|
nameservers: this._toArray(this._interface![version]?.nameservers),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (this._wifiConfiguration) {
|
||||||
|
interfaceOptions = {
|
||||||
|
...interfaceOptions,
|
||||||
|
enabled: true,
|
||||||
|
wifi: {
|
||||||
|
ssid: this._wifiConfiguration.ssid,
|
||||||
|
mode: this._wifiConfiguration.mode,
|
||||||
|
auth: this._wifiConfiguration.auth || "open",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (interfaceOptions.wifi!.auth !== "open") {
|
||||||
|
interfaceOptions.wifi = {
|
||||||
|
...interfaceOptions.wifi,
|
||||||
|
psk: this._wifiConfiguration.psk,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateNetworkInterface(this.hass, this._device!.interface, options);
|
await updateNetworkInterface(
|
||||||
|
this.hass,
|
||||||
|
this._interface!.interface,
|
||||||
|
interfaceOptions
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: "Failed to change network settings",
|
title: "Failed to change network settings",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
this._prosessing = false;
|
this._processing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._params?.loadData();
|
this._params?.loadData();
|
||||||
@ -219,40 +437,73 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
dismissText: "no",
|
dismissText: "no",
|
||||||
});
|
});
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
this.requestUpdate("_device");
|
this.requestUpdate("_interface");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._curTabIndex = ev.detail.index;
|
this._curTabIndex = ev.detail.index;
|
||||||
this._device = this._network[ev.detail.index];
|
this._interface = { ...this._interfaces[ev.detail.index] };
|
||||||
this._device.data.nameservers = String(this._device.data.nameservers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleRadioValueChanged(ev: CustomEvent): void {
|
private _handleRadioValueChanged(ev: CustomEvent): void {
|
||||||
const value = (ev.target as HaRadio).value as "dhcp" | "static";
|
const value = (ev.target as any).value as "disabled" | "auto" | "static";
|
||||||
|
const version = (ev.target as any).version as "ipv4" | "ipv6";
|
||||||
|
|
||||||
if (!value || !this._device || this._device!.data.method === value) {
|
if (
|
||||||
|
!value ||
|
||||||
|
!this._interface ||
|
||||||
|
this._interface[version]!.method === value
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._dirty = true;
|
this._dirty = true;
|
||||||
|
|
||||||
this._device!.data.method = value;
|
this._interface[version]!.method = value;
|
||||||
this.requestUpdate("_device");
|
this.requestUpdate("_interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleRadioValueChangedAp(ev: CustomEvent): void {
|
||||||
|
const value = ((ev.target as any).value as string) as
|
||||||
|
| "open"
|
||||||
|
| "wep"
|
||||||
|
| "wpa-psk";
|
||||||
|
this._wifiConfiguration!.auth = value;
|
||||||
|
this._dirty = true;
|
||||||
|
this.requestUpdate("_wifiConfiguration");
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleInputValueChanged(ev: CustomEvent): void {
|
private _handleInputValueChanged(ev: CustomEvent): void {
|
||||||
const value: string | null | undefined = (ev.target as PaperInputElement)
|
const value: string | null | undefined = (ev.target as PaperInputElement)
|
||||||
.value;
|
.value;
|
||||||
|
const version = (ev.target as any).version as "ipv4" | "ipv6";
|
||||||
const id = (ev.target as PaperInputElement).id;
|
const id = (ev.target as PaperInputElement).id;
|
||||||
|
|
||||||
if (!value || !this._device || this._device.data[id] === value) {
|
if (
|
||||||
|
!value ||
|
||||||
|
!this._interface ||
|
||||||
|
this._toString(this._interface[version]![id]) === this._toString(value)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._dirty = true;
|
this._dirty = true;
|
||||||
|
this._interface[version]![id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
this._device.data[id] = value;
|
private _handleInputValueChangedWifi(ev: CustomEvent): void {
|
||||||
|
const value: string | null | undefined = (ev.target as PaperInputElement)
|
||||||
|
.value;
|
||||||
|
const id = (ev.target as PaperInputElement).id;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!value ||
|
||||||
|
!this._wifiConfiguration ||
|
||||||
|
this._wifiConfiguration![id] === value
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._dirty = true;
|
||||||
|
this._wifiConfiguration![id] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
@ -299,12 +550,16 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
--mdc-theme-primary: var(--error-color);
|
--mdc-theme-primary: var(--error-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mwc-button.scan {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
:host([rtl]) app-toolbar {
|
:host([rtl]) app-toolbar {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
padding: 20px 24px;
|
padding: 0 8px 4px;
|
||||||
}
|
}
|
||||||
.form {
|
.form {
|
||||||
margin-bottom: 53px;
|
margin-bottom: 53px;
|
||||||
@ -322,6 +577,23 @@ export class DialogHassioNetwork extends LitElement
|
|||||||
padding-bottom: max(env(safe-area-inset-bottom), 8px);
|
padding-bottom: max(env(safe-area-inset-bottom), 8px);
|
||||||
background-color: var(--mdc-theme-surface, #fff);
|
background-color: var(--mdc-theme-surface, #fff);
|
||||||
}
|
}
|
||||||
|
.warning {
|
||||||
|
color: var(--error-color);
|
||||||
|
--primary-color: var(--error-color);
|
||||||
|
}
|
||||||
|
div.warning {
|
||||||
|
margin: 12px 4px -12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-expansion-panel {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
paper-input {
|
||||||
|
padding: 0 14px;
|
||||||
|
}
|
||||||
|
mwc-list-item {
|
||||||
|
--mdc-list-side-padding: 10px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ import { hassioStyle } from "../resources/hassio-style";
|
|||||||
class HassioHostInfo extends LitElement {
|
class HassioHostInfo extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public hostInfo!: HassioHostInfoType;
|
@property({ attribute: false }) public hostInfo!: HassioHostInfoType;
|
||||||
|
|
||||||
@property({ attribute: false }) public hassioInfo!: HassioInfo;
|
@property({ attribute: false }) public hassioInfo!: HassioInfo;
|
||||||
|
|
||||||
@ -193,12 +193,10 @@ class HassioHostInfo extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
|
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
|
||||||
if (!network_info) {
|
if (!network_info || !network_info.interfaces) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return Object.keys(network_info?.interfaces)
|
return network_info.interfaces.find((a) => a.primary)?.ipv4?.address![0];
|
||||||
.map((device) => network_info.interfaces[device])
|
|
||||||
.find((device) => device.primary)?.ip_address;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
|
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
|
||||||
|
@ -1,24 +1,54 @@
|
|||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { hassioApiResultExtractor, HassioResponse } from "./common";
|
import { hassioApiResultExtractor, HassioResponse } from "./common";
|
||||||
|
|
||||||
export interface NetworkInterface {
|
interface IpConfiguration {
|
||||||
|
address: string[];
|
||||||
gateway: string;
|
gateway: string;
|
||||||
id: string;
|
method: "disabled" | "static" | "auto";
|
||||||
ip_address: string;
|
nameservers: string[];
|
||||||
address?: string;
|
|
||||||
method: "static" | "dhcp";
|
|
||||||
nameservers: string[] | string;
|
|
||||||
dns?: string[];
|
|
||||||
primary: boolean;
|
|
||||||
type: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NetworkInterfaces {
|
export interface NetworkInterface {
|
||||||
[key: string]: NetworkInterface;
|
primary: boolean;
|
||||||
|
privacy: boolean;
|
||||||
|
interface: string;
|
||||||
|
enabled: boolean;
|
||||||
|
ipv4?: Partial<IpConfiguration>;
|
||||||
|
ipv6?: Partial<IpConfiguration>;
|
||||||
|
type: "ethernet" | "wireless" | "vlan";
|
||||||
|
wifi?: Partial<WifiConfiguration>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DockerNetwork {
|
||||||
|
address: string;
|
||||||
|
dns: string;
|
||||||
|
gateway: string;
|
||||||
|
interface: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AccessPoint {
|
||||||
|
mode: "infrastructure" | "mesh" | "adhoc" | "ap";
|
||||||
|
ssid: string;
|
||||||
|
mac: string;
|
||||||
|
frequency: number;
|
||||||
|
signal: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccessPoints {
|
||||||
|
accesspoints: AccessPoint[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WifiConfiguration {
|
||||||
|
mode: "infrastructure" | "mesh" | "adhoc" | "ap";
|
||||||
|
auth: "open" | "wep" | "wpa-psk";
|
||||||
|
ssid: string;
|
||||||
|
signal: number;
|
||||||
|
psk?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NetworkInfo {
|
export interface NetworkInfo {
|
||||||
interfaces: NetworkInterfaces;
|
interfaces: NetworkInterface[];
|
||||||
|
docker: DockerNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchNetworkInfo = async (hass: HomeAssistant) => {
|
export const fetchNetworkInfo = async (hass: HomeAssistant) => {
|
||||||
@ -41,3 +71,15 @@ export const updateNetworkInterface = async (
|
|||||||
options
|
options
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const accesspointScan = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
network_interface: string
|
||||||
|
) => {
|
||||||
|
return hassioApiResultExtractor(
|
||||||
|
await hass.callApi<HassioResponse<AccessPoints>>(
|
||||||
|
"GET",
|
||||||
|
`hassio/network/interface/${network_interface}/accesspoints`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user