mirror of
https://github.com/home-assistant/frontend.git
synced 2026-04-07 03:14:00 +00:00
* Allow to transfer all Thread datasets with TLV This commit allows to transfer all Thread datasets with TLV. Since PR #22022 the preferred dataset is transmitted when using Matter external commissioning. This commit makes the Thread configuration dialog to have feature parity. * Drop preferred border agent id as additional metric for default router We always have the extended address, so use this as primary and only metric which router is the default. The preferred border agent id gets updated best effort. Also use isDefaultRouter consistently in the code.
386 lines
8.9 KiB
TypeScript
386 lines
8.9 KiB
TypeScript
import { AutomationConfig } from "../data/automation";
|
|
|
|
const CALLBACK_EXTERNAL_BUS = "externalBus";
|
|
|
|
interface CommandInFlight {
|
|
resolve: (data: any) => void;
|
|
reject: (err: EMError) => void;
|
|
}
|
|
|
|
export interface EMMessage {
|
|
id?: number;
|
|
type: string;
|
|
}
|
|
|
|
interface EMError {
|
|
code: string;
|
|
message: string;
|
|
}
|
|
|
|
interface EMMessageResultSuccess {
|
|
id: number;
|
|
type: "result";
|
|
success: true;
|
|
result: unknown;
|
|
}
|
|
|
|
interface EMMessageResultError {
|
|
id: number;
|
|
type: "result";
|
|
success: false;
|
|
error: EMError;
|
|
}
|
|
|
|
interface EMOutgoingMessageConfigGet extends EMMessage {
|
|
type: "config/get";
|
|
}
|
|
|
|
interface EMOutgoingMessageBarCodeScan extends EMMessage {
|
|
type: "bar_code/scan";
|
|
payload: {
|
|
title: string;
|
|
description: string;
|
|
alternative_option_label?: string;
|
|
};
|
|
}
|
|
|
|
interface EMOutgoingMessageBarCodeClose extends EMMessage {
|
|
type: "bar_code/close";
|
|
}
|
|
|
|
interface EMOutgoingMessageBarCodeNotify extends EMMessage {
|
|
type: "bar_code/notify";
|
|
payload: {
|
|
message: string;
|
|
};
|
|
}
|
|
|
|
interface EMOutgoingMessageMatterCommission extends EMMessage {
|
|
type: "matter/commission";
|
|
payload?: {
|
|
mac_extended_address: string | null;
|
|
extended_pan_id: string | null;
|
|
border_agent_id: string | null;
|
|
active_operational_dataset: string | null;
|
|
};
|
|
}
|
|
|
|
interface EMOutgoingMessageImportThreadCredentials extends EMMessage {
|
|
type: "thread/import_credentials";
|
|
}
|
|
|
|
type EMOutgoingMessageWithAnswer = {
|
|
"config/get": {
|
|
request: EMOutgoingMessageConfigGet;
|
|
response: ExternalConfig;
|
|
};
|
|
};
|
|
|
|
interface EMOutgoingMessageExoplayerPlayHLS extends EMMessage {
|
|
type: "exoplayer/play_hls";
|
|
payload: {
|
|
url: string;
|
|
muted: boolean;
|
|
};
|
|
}
|
|
interface EMOutgoingMessageExoplayerResize extends EMMessage {
|
|
type: "exoplayer/resize";
|
|
payload: {
|
|
left: number;
|
|
top: number;
|
|
right: number;
|
|
bottom: number;
|
|
};
|
|
}
|
|
|
|
interface EMOutgoingMessageExoplayerStop extends EMMessage {
|
|
type: "exoplayer/stop";
|
|
}
|
|
|
|
interface EMOutgoingMessageThemeUpdate extends EMMessage {
|
|
type: "theme-update";
|
|
}
|
|
|
|
interface EMOutgoingMessageHaptic extends EMMessage {
|
|
type: "haptic";
|
|
payload: { hapticType: string };
|
|
}
|
|
|
|
interface EMOutgoingMessageConnectionStatus extends EMMessage {
|
|
type: "connection-status";
|
|
payload: { event: string };
|
|
}
|
|
|
|
interface EMOutgoingMessageAppConfiguration extends EMMessage {
|
|
type: "config_screen/show";
|
|
}
|
|
|
|
interface EMOutgoingMessageTagWrite extends EMMessage {
|
|
type: "tag/write";
|
|
payload: {
|
|
name: string | null;
|
|
tag: string;
|
|
};
|
|
}
|
|
|
|
interface EMOutgoingMessageSidebarShow extends EMMessage {
|
|
type: "sidebar/show";
|
|
}
|
|
|
|
interface EMOutgoingMessageAssistShow extends EMMessage {
|
|
type: "assist/show";
|
|
payload?: {
|
|
pipeline_id: "preferred" | "last_used" | string;
|
|
start_listening: boolean;
|
|
};
|
|
}
|
|
interface EMOutgoingMessageImprovScan extends EMMessage {
|
|
type: "improv/scan";
|
|
}
|
|
|
|
interface EMOutgoingMessageThreadStoreInPlatformKeychain extends EMMessage {
|
|
type: "thread/store_in_platform_keychain";
|
|
payload: {
|
|
mac_extended_address: string | null;
|
|
border_agent_id: string | null;
|
|
active_operational_dataset: string;
|
|
extended_pan_id: string;
|
|
};
|
|
}
|
|
|
|
type EMOutgoingMessageWithoutAnswer =
|
|
| EMMessageResultError
|
|
| EMMessageResultSuccess
|
|
| EMOutgoingMessageAppConfiguration
|
|
| EMOutgoingMessageAssistShow
|
|
| EMOutgoingMessageBarCodeClose
|
|
| EMOutgoingMessageBarCodeNotify
|
|
| EMOutgoingMessageBarCodeScan
|
|
| EMOutgoingMessageConnectionStatus
|
|
| EMOutgoingMessageExoplayerPlayHLS
|
|
| EMOutgoingMessageExoplayerResize
|
|
| EMOutgoingMessageExoplayerStop
|
|
| EMOutgoingMessageHaptic
|
|
| EMOutgoingMessageImportThreadCredentials
|
|
| EMOutgoingMessageMatterCommission
|
|
| EMOutgoingMessageSidebarShow
|
|
| EMOutgoingMessageTagWrite
|
|
| EMOutgoingMessageThemeUpdate
|
|
| EMOutgoingMessageThreadStoreInPlatformKeychain
|
|
| EMOutgoingMessageImprovScan;
|
|
|
|
interface EMIncomingMessageRestart {
|
|
id: number;
|
|
type: "command";
|
|
command: "restart";
|
|
}
|
|
|
|
interface EMIncomingMessageShowNotifications {
|
|
id: number;
|
|
type: "command";
|
|
command: "notifications/show";
|
|
}
|
|
|
|
interface EMIncomingMessageToggleSidebar {
|
|
id: number;
|
|
type: "command";
|
|
command: "sidebar/toggle";
|
|
}
|
|
|
|
interface EMIncomingMessageShowSidebar {
|
|
id: number;
|
|
type: "command";
|
|
command: "sidebar/show";
|
|
}
|
|
|
|
interface EMIncomingMessageShowAutomationEditor {
|
|
id: number;
|
|
type: "command";
|
|
command: "automation/editor/show";
|
|
payload?: {
|
|
config?: Partial<AutomationConfig>;
|
|
};
|
|
}
|
|
|
|
export interface EMIncomingMessageBarCodeScanResult {
|
|
id: number;
|
|
type: "command";
|
|
command: "bar_code/scan_result";
|
|
payload: {
|
|
// A string decoded from the barcode data.
|
|
rawValue: string;
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/Barcode_Detection_API#supported_barcode_formats
|
|
format:
|
|
| "aztec"
|
|
| "code_128"
|
|
| "code_39"
|
|
| "code_93"
|
|
| "codabar"
|
|
| "data_matrix"
|
|
| "ean_13"
|
|
| "ean_8"
|
|
| "itf"
|
|
| "pdf417"
|
|
| "qr_code"
|
|
| "upc_a"
|
|
| "upc_e"
|
|
| "unknown";
|
|
};
|
|
}
|
|
|
|
export interface EMIncomingMessageBarCodeScanAborted {
|
|
id: number;
|
|
type: "command";
|
|
command: "bar_code/aborted";
|
|
payload: {
|
|
reason: "canceled" | "alternative_options";
|
|
};
|
|
}
|
|
|
|
export type EMIncomingMessageCommands =
|
|
| EMIncomingMessageRestart
|
|
| EMIncomingMessageShowNotifications
|
|
| EMIncomingMessageToggleSidebar
|
|
| EMIncomingMessageShowSidebar
|
|
| EMIncomingMessageShowAutomationEditor
|
|
| EMIncomingMessageBarCodeScanResult
|
|
| EMIncomingMessageBarCodeScanAborted;
|
|
|
|
type EMIncomingMessage =
|
|
| EMMessageResultSuccess
|
|
| EMMessageResultError
|
|
| EMIncomingMessageCommands;
|
|
|
|
type EMIncomingMessageHandler = (msg: EMIncomingMessageCommands) => boolean;
|
|
|
|
export interface ExternalConfig {
|
|
hasSettingsScreen: boolean;
|
|
hasSidebar: boolean;
|
|
canWriteTag: boolean;
|
|
hasExoPlayer: boolean;
|
|
canCommissionMatter: boolean;
|
|
canImportThreadCredentials: boolean;
|
|
canTransferThreadCredentialsToKeychain: boolean;
|
|
hasAssist: boolean;
|
|
hasBarCodeScanner: number;
|
|
canSetupImprov: boolean;
|
|
}
|
|
|
|
export class ExternalMessaging {
|
|
public config!: ExternalConfig;
|
|
|
|
public commands: { [msgId: number]: CommandInFlight } = {};
|
|
|
|
public msgId = 0;
|
|
|
|
private _commandHandler?: EMIncomingMessageHandler;
|
|
|
|
public async attach() {
|
|
window[CALLBACK_EXTERNAL_BUS] = (msg) => this.receiveMessage(msg);
|
|
window.addEventListener("connection-status", (ev) =>
|
|
this.fireMessage({
|
|
type: "connection-status",
|
|
payload: { event: ev.detail },
|
|
})
|
|
);
|
|
this.config = await this.sendMessage<"config/get">({
|
|
type: "config/get",
|
|
});
|
|
}
|
|
|
|
public addCommandHandler(handler: EMIncomingMessageHandler) {
|
|
this._commandHandler = handler;
|
|
}
|
|
|
|
/**
|
|
* Send message to external app that expects a response.
|
|
* @param msg message to send
|
|
*/
|
|
public sendMessage<T extends keyof EMOutgoingMessageWithAnswer>(
|
|
msg: EMOutgoingMessageWithAnswer[T]["request"]
|
|
): Promise<EMOutgoingMessageWithAnswer[T]["response"]> {
|
|
const msgId = ++this.msgId;
|
|
msg.id = msgId;
|
|
|
|
this._sendExternal(msg);
|
|
|
|
return new Promise<EMOutgoingMessageWithAnswer[T]["response"]>(
|
|
(resolve, reject) => {
|
|
this.commands[msgId] = { resolve, reject };
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Send message to external app without expecting a response.
|
|
* @param msg message to send
|
|
*/
|
|
public fireMessage(msg: EMOutgoingMessageWithoutAnswer) {
|
|
if (!msg.id) {
|
|
msg.id = ++this.msgId;
|
|
}
|
|
this._sendExternal(msg);
|
|
}
|
|
|
|
public receiveMessage(msg: EMIncomingMessage) {
|
|
if (__DEV__) {
|
|
// eslint-disable-next-line no-console
|
|
console.log("Receiving message from external app", msg);
|
|
}
|
|
|
|
if (msg.type === "command") {
|
|
if (!this._commandHandler || !this._commandHandler(msg)) {
|
|
let code: string;
|
|
let message: string;
|
|
if (this._commandHandler) {
|
|
code = "not_ready";
|
|
message = "Command handler not ready";
|
|
} else {
|
|
code = "unknown_command";
|
|
message = `Unknown command ${msg.command}`;
|
|
}
|
|
// eslint-disable-next-line no-console
|
|
console.warn(message, msg);
|
|
this.fireMessage({
|
|
id: msg.id,
|
|
type: "result",
|
|
success: false,
|
|
error: {
|
|
code,
|
|
message,
|
|
},
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
const pendingCmd = this.commands[msg.id];
|
|
|
|
if (!pendingCmd) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn(`Received unknown msg ID`, msg.id);
|
|
return;
|
|
}
|
|
|
|
if (msg.type === "result") {
|
|
if (msg.success) {
|
|
pendingCmd.resolve(msg.result);
|
|
} else {
|
|
pendingCmd.reject(msg.error);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected _sendExternal(msg: EMMessage) {
|
|
if (__DEV__) {
|
|
// eslint-disable-next-line no-console
|
|
console.log("Sending message to external app", msg);
|
|
}
|
|
if (window.externalApp) {
|
|
window.externalApp.externalBus(JSON.stringify(msg));
|
|
} else {
|
|
window.webkit!.messageHandlers.externalBus.postMessage(msg);
|
|
}
|
|
}
|
|
}
|