From fe0fb2382afa6c32763103c278ccf48949b7745f Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 2 Oct 2024 15:06:06 +0200 Subject: [PATCH] Allow to transfer all Thread datasets with TLV (#22183) * 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. --- src/data/thread.ts | 2 +- src/external_app/external_messaging.ts | 5 +- .../thread/thread-config-panel.ts | 64 +++++++++++-------- src/translations/en.json | 1 + 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/data/thread.ts b/src/data/thread.ts index 82c19fbe03..d999690a68 100644 --- a/src/data/thread.ts +++ b/src/data/thread.ts @@ -18,7 +18,7 @@ export interface ThreadDataSet { channel: number | null; created: string; dataset_id: string; - extended_pan_id: string | null; + extended_pan_id: string; network_name: string; pan_id: string | null; preferred_border_agent_id: string | null; diff --git a/src/external_app/external_messaging.ts b/src/external_app/external_messaging.ts index e8a436e203..5e0461585b 100644 --- a/src/external_app/external_messaging.ts +++ b/src/external_app/external_messaging.ts @@ -141,9 +141,10 @@ interface EMOutgoingMessageImprovScan extends EMMessage { interface EMOutgoingMessageThreadStoreInPlatformKeychain extends EMMessage { type: "thread/store_in_platform_keychain"; payload: { - mac_extended_address: string; - border_agent_id: string; + mac_extended_address: string | null; + border_agent_id: string | null; active_operational_dataset: string; + extended_pan_id: string; }; } diff --git a/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts b/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts index 23dfce2198..206ab96194 100644 --- a/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts @@ -37,6 +37,7 @@ import { ThreadDataSet, ThreadRouter, addThreadDataSet, + getThreadDataSetTLV, listThreadDataSets, removeThreadDataSet, setPreferredBorderAgent, @@ -168,8 +169,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) { (otbr) => otbr.extended_pan_id === network.dataset!.extended_pan_id )); const canImportKeychain = - this.hass.auth.external?.config.canTransferThreadCredentialsToKeychain && - otbrForNetwork; + this.hass.auth.external?.config.canTransferThreadCredentialsToKeychain; return html`
@@ -208,8 +208,12 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) { ${network.routers.map((router) => { const otbr = this._otbrInfo && this._otbrInfo[router.extended_address]; - const showOverflow = - ("dataset" in network && router.border_agent_id) || otbr; + const showDefaultRouter = !!network.dataset; + const isDefaultRouter = + showDefaultRouter && + router.extended_address === + network.dataset!.preferred_extended_address; + const showOverflow = showDefaultRouter || otbr; return html`${router.server} ${showOverflow - ? html`${network.dataset && - router.extended_address === - network.dataset.preferred_extended_address + ? html`${isDefaultRouter ? html` - ${network.dataset && router.border_agent_id - ? html` - ${router.border_agent_id === - network.dataset.preferred_border_agent_id + ${showDefaultRouter + ? html` + ${isDefaultRouter ? this.hass.localize( "ui.panel.config.thread.default_router" ) @@ -321,9 +319,13 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) { >
` : ""} - ${canImportKeychain + ${canImportKeychain && + network.dataset?.preferred && + network.routers?.length ? html`
- Send credentials to phone
` @@ -331,17 +333,30 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
`; } - private _sendCredentials(ev) { - const otbr = (ev.currentTarget as any).otbr as OTBRInfo; - if (!otbr) { + private async _sendCredentials(ev) { + const dataset = (ev.currentTarget as any).networkDataset as ThreadDataSet; + if (!dataset) { + return; + } + if ( + !dataset.preferred_extended_address && + !dataset.preferred_border_agent_id + ) { + showAlertDialog(this, { + title: "Error", + text: this.hass.localize("ui.panel.config.thread.no_preferred_router"), + }); return; } this.hass.auth.external!.fireMessage({ type: "thread/store_in_platform_keychain", payload: { - mac_extended_address: otbr.extended_address, - border_agent_id: otbr.border_agent_id, - active_operational_dataset: otbr.active_dataset_tlvs, + mac_extended_address: dataset.preferred_extended_address, + border_agent_id: dataset.preferred_border_agent_id, + active_operational_dataset: ( + await getThreadDataSetTLV(this.hass, dataset.dataset_id) + ).tlv, + extended_pan_id: dataset.extended_pan_id, }, }); } @@ -467,10 +482,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) { const network = (ev.currentTarget as any).network as ThreadNetwork; const router = (ev.currentTarget as any).router as ThreadRouter; const otbr = (ev.currentTarget as any).otbr as OTBRInfo; - const index = - network.dataset && router.border_agent_id - ? Number(ev.detail.index) - : Number(ev.detail.index) + 1; + const index = Number(ev.detail.index); switch (index) { case 0: this._setPreferredBorderAgent(network.dataset!, router); diff --git a/src/translations/en.json b/src/translations/en.json index 32c55ddef7..92d5b38048 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4590,6 +4590,7 @@ "confirm_delete_dataset": "Delete {name} dataset?", "confirm_delete_dataset_text": "This network will be removed from Home Assistant.", "no_border_routers": "No border routers found", + "no_preferred_router": "No preferred border router defined", "border_routers": "{count} border {count, plural,\n one {router}\n other {routers}\n}", "managed_by_home_assistant": "Managed by Home Assistant", "operational_dataset": "Operational dataset",