Add basic matter config panel (#14489)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
Bram Kragten 2022-11-30 22:12:46 +01:00 committed by GitHub
parent 9b6e33cfec
commit 29452841c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 226 additions and 13 deletions

39
src/data/matter.ts Normal file
View File

@ -0,0 +1,39 @@
import { HomeAssistant } from "../types";
export const commissionMatterDevice = (
hass: HomeAssistant,
code: string
): Promise<void> =>
hass.callWS({
type: "matter/commission",
code,
});
export const acceptSharedMatterDevice = (
hass: HomeAssistant,
pin: number
): Promise<void> =>
hass.callWS({
type: "matter/commission_on_network",
pin,
});
export const matterSetWifi = (
hass: HomeAssistant,
network_name: string,
password: string
): Promise<void> =>
hass.callWS({
type: "matter/set_wifi_credentials",
network_name,
password,
});
export const matterSetThread = (
hass: HomeAssistant,
thread_operation_dataset: string
): Promise<void> =>
hass.callWS({
type: "matter/set_thread",
thread_operation_dataset,
});

View File

@ -42,12 +42,6 @@ type EMOutgoingMessageWithAnswer = {
request: EMOutgoingMessageConfigGet;
response: ExternalConfig;
};
"matter/commission": {
request: EMOutgoingMessageMatterCommission;
response: {
code: string;
};
};
};
interface EMOutgoingMessageExoplayerPlayHLS extends EMMessage {
@ -112,7 +106,8 @@ type EMOutgoingMessageWithoutAnswer =
| EMOutgoingMessageExoplayerStop
| EMOutgoingMessageThemeUpdate
| EMMessageResultSuccess
| EMMessageResultError;
| EMMessageResultError
| EMOutgoingMessageMatterCommission;
interface EMIncomingMessageRestart {
id: number;

View File

@ -478,6 +478,13 @@ class HaPanelConfig extends HassRouterPage {
"./integrations/integration-panels/zwave_js/zwave_js-config-router"
),
},
matter: {
tag: "matter-config-panel",
load: () =>
import(
"./integrations/integration-panels/matter/matter-config-panel"
),
},
application_credentials: {
tag: "ha-config-application-credentials",
load: () =>

View File

@ -70,6 +70,7 @@ const integrationsWithPanel = {
mqtt: "/config/mqtt",
zha: "/config/zha/dashboard",
zwave_js: "/config/zwave_js/dashboard",
matter: "/config/matter",
};
@customElement("ha-integration-card")

View File

@ -0,0 +1,172 @@
import "@material/mwc-button";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../../components/ha-card";
import {
acceptSharedMatterDevice,
commissionMatterDevice,
matterSetThread,
matterSetWifi,
} from "../../../../../data/matter";
import "../../../../../layouts/hass-subpage";
import { haStyle } from "../../../../../resources/styles";
import { HomeAssistant } from "../../../../../types";
import "../../../../../components/ha-alert";
import { showPromptDialog } from "../../../../../dialogs/generic/show-dialog-box";
@customElement("matter-config-panel")
export class MatterConfigPanel extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public narrow!: boolean;
@state() private _error?: string;
private get _canCommissionMatter() {
return this.hass.auth.external?.config.canCommissionMatter;
}
protected render(): TemplateResult {
return html`
<hass-subpage .narrow=${this.narrow} .hass=${this.hass} header="Matter">
<div class="content">
<ha-card header="Matter">
<div class="card-content">
${this._error
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
: ""}
<ha-alert alert-type="warning"
>Matter is still in the early phase of development, it is not
meant to be used in production. This panel is for development
only.</ha-alert
>
You can add Matter devices by commissing them if they are not
setup yet, or share them from another controller and enter the
share code.
</div>
<div class="card-actions">
${this._canCommissionMatter
? html`<mwc-button @click=${this._startMobileCommissioning}
>Commission device with mobile app</mwc-button
>`
: ""}
<mwc-button @click=${this._setWifi}
>Set WiFi Credentials</mwc-button
>
<mwc-button @click=${this._setThread}>Set Thread</mwc-button>
<mwc-button @click=${this._commission}
>Commission device</mwc-button
>
<mwc-button @click=${this._acceptSharedDevice}
>Add shared device</mwc-button
>
</div>
</ha-card>
</div>
</hass-subpage>
`;
}
private _startMobileCommissioning() {
this.hass.auth.external!.fireMessage({
type: "matter/commission",
});
}
private async _setWifi(): Promise<void> {
this._error = undefined;
const networkName = await showPromptDialog(this, {
title: "Network name",
inputLabel: "Network name",
inputType: "string",
confirmText: "Continue",
});
if (!networkName) {
return;
}
const psk = await showPromptDialog(this, {
title: "Passcode",
inputLabel: "Code",
inputType: "password",
confirmText: "Set Wifi",
});
if (!psk) {
return;
}
try {
await matterSetWifi(this.hass, networkName, psk);
} catch (err: any) {
this._error = err.message;
}
}
private async _commission(): Promise<void> {
const code = await showPromptDialog(this, {
title: "Commission device",
inputLabel: "Code",
inputType: "string",
confirmText: "Commission",
});
if (!code) {
return;
}
this._error = undefined;
try {
await commissionMatterDevice(this.hass, code);
} catch (err: any) {
this._error = err.message;
}
}
private async _acceptSharedDevice(): Promise<void> {
const code = await showPromptDialog(this, {
title: "Add shared device",
inputLabel: "Pin",
inputType: "number",
confirmText: "Accept device",
});
if (!code) {
return;
}
this._error = undefined;
try {
await acceptSharedMatterDevice(this.hass, Number(code));
} catch (err: any) {
this._error = err.message;
}
}
private async _setThread(): Promise<void> {
const code = await showPromptDialog(this, {
title: "Set Thread operation",
inputLabel: "Dataset",
inputType: "string",
confirmText: "Set Thread",
});
if (!code) {
return;
}
this._error = undefined;
try {
await matterSetThread(this.hass, code);
} catch (err: any) {
this._error = err.message;
}
}
static styles = [
haStyle,
css`
.content {
padding: 24px 0 32px;
max-width: 600px;
margin: 0 auto;
direction: ltr;
}
ha-card:first-child {
margin-bottom: 16px;
}
`,
];
}

View File

@ -1,5 +1,4 @@
import "@material/mwc-button";
import "@polymer/paper-input/paper-input";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../../components/ha-card";
@ -45,16 +44,16 @@ class HaPanelDevMqtt extends LitElement {
</div>
</ha-card>
<ha-card
header=${this.hass.localize(
.header=${this.hass.localize(
"ui.panel.config.mqtt.description_publish"
)}
>
<div class="card-content">
<paper-input
label=${this.hass.localize("ui.panel.config.mqtt.topic")}
<ha-textfield
.label=${this.hass.localize("ui.panel.config.mqtt.topic")}
.value=${this.topic}
@value-changed=${this._handleTopic}
></paper-input>
@change=${this._handleTopic}
></ha-textfield>
<p>${this.hass.localize("ui.panel.config.mqtt.payload")}</p>
<ha-code-editor