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.
This commit is contained in:
Stefan Agner 2024-10-02 15:06:06 +02:00 committed by GitHub
parent cdd29295e5
commit fe0fb2382a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 43 additions and 29 deletions

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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`<ha-card>
<div class="card-header">
@ -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`<ha-list-item
class="router"
twoline
@ -235,9 +239,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
""}
<span slot="secondary">${router.server}</span>
${showOverflow
? html`${network.dataset &&
router.extended_address ===
network.dataset.preferred_extended_address
? html`${isDefaultRouter
? html`<ha-svg-icon
.path=${mdiCellphoneKey}
.title=${this.hass.localize(
@ -259,13 +261,9 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
.path=${mdiDotsVertical}
slot="trigger"
></ha-icon-button>
${network.dataset && router.border_agent_id
? html`<ha-list-item
.disabled=${router.border_agent_id ===
network.dataset.preferred_border_agent_id}
>
${router.border_agent_id ===
network.dataset.preferred_border_agent_id
${showDefaultRouter
? html`<ha-list-item .disabled=${isDefaultRouter}>
${isDefaultRouter
? this.hass.localize(
"ui.panel.config.thread.default_router"
)
@ -321,9 +319,13 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
>
</div>`
: ""}
${canImportKeychain
${canImportKeychain &&
network.dataset?.preferred &&
network.routers?.length
? html`<div class="card-actions">
<mwc-button .otbr=${otbrForNetwork} @click=${this._sendCredentials}
<mwc-button
.networkDataset=${network.dataset}
@click=${this._sendCredentials}
>Send credentials to phone</mwc-button
>
</div>`
@ -331,17 +333,30 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
</ha-card>`;
}
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);

View File

@ -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",