mirror of
				https://github.com/home-assistant/frontend.git
				synced 2025-11-04 00:19:47 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			20231030.1
			...
			allow-to-s
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					531363ae5d | ||
| 
						 | 
					b19fe68686 | ||
| 
						 | 
					05e08cdcc0 | 
@@ -103,3 +103,14 @@ export const setPreferredThreadDataSet = (
 | 
			
		||||
    type: "thread/set_preferred_dataset",
 | 
			
		||||
    dataset_id,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
export const setPreferredBorderAgent = (
 | 
			
		||||
  hass: HomeAssistant,
 | 
			
		||||
  dataset_id: string,
 | 
			
		||||
  border_agent_id: string
 | 
			
		||||
): Promise<void> =>
 | 
			
		||||
  hass.callWS({
 | 
			
		||||
    type: "thread/set_preferred_border_agent_id",
 | 
			
		||||
    dataset_id,
 | 
			
		||||
    border_agent_id,
 | 
			
		||||
  });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,31 +5,36 @@ import {
 | 
			
		||||
  mdiDevices,
 | 
			
		||||
  mdiDotsVertical,
 | 
			
		||||
  mdiInformationOutline,
 | 
			
		||||
  mdiStar,
 | 
			
		||||
} from "@mdi/js";
 | 
			
		||||
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
 | 
			
		||||
import { LitElement, PropertyValues, TemplateResult, css, html } from "lit";
 | 
			
		||||
import { customElement, property, state } from "lit/decorators";
 | 
			
		||||
import memoizeOne from "memoize-one";
 | 
			
		||||
import { isComponentLoaded } from "../../../../../common/config/is_component_loaded";
 | 
			
		||||
import { stringCompare } from "../../../../../common/string/compare";
 | 
			
		||||
import { extractSearchParam } from "../../../../../common/url/search-params";
 | 
			
		||||
import "../../../../../components/ha-button-menu";
 | 
			
		||||
import "../../../../../components/ha-list-item";
 | 
			
		||||
import "../../../../../components/ha-card";
 | 
			
		||||
import "../../../../../components/ha-alert";
 | 
			
		||||
import { getSignedPath } from "../../../../../data/auth";
 | 
			
		||||
import { getConfigEntryDiagnosticsDownloadUrl } from "../../../../../data/diagnostics";
 | 
			
		||||
import {
 | 
			
		||||
  getOTBRInfo,
 | 
			
		||||
  OTBRCreateNetwork,
 | 
			
		||||
  OTBRInfo,
 | 
			
		||||
  OTBRSetChannel,
 | 
			
		||||
  OTBRSetNetwork,
 | 
			
		||||
  getOTBRInfo,
 | 
			
		||||
} from "../../../../../data/otbr";
 | 
			
		||||
import {
 | 
			
		||||
  ThreadDataSet,
 | 
			
		||||
  ThreadRouter,
 | 
			
		||||
  addThreadDataSet,
 | 
			
		||||
  listThreadDataSets,
 | 
			
		||||
  removeThreadDataSet,
 | 
			
		||||
  setPreferredBorderAgent,
 | 
			
		||||
  setPreferredThreadDataSet,
 | 
			
		||||
  subscribeDiscoverThreadRouters,
 | 
			
		||||
  ThreadDataSet,
 | 
			
		||||
  ThreadRouter,
 | 
			
		||||
} from "../../../../../data/thread";
 | 
			
		||||
import { showConfigFlowDialog } from "../../../../../dialogs/config-flow/show-dialog-config-flow";
 | 
			
		||||
import {
 | 
			
		||||
@@ -48,6 +53,7 @@ interface ThreadNetwork {
 | 
			
		||||
  name: string;
 | 
			
		||||
  dataset?: ThreadDataSet;
 | 
			
		||||
  routers?: ThreadRouter[];
 | 
			
		||||
  preferred_border_agent_found?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@customElement("thread-config-panel")
 | 
			
		||||
@@ -152,6 +158,13 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
            </div>`
 | 
			
		||||
          : ""}
 | 
			
		||||
      </div>
 | 
			
		||||
      ${network.preferred_border_agent_found === false
 | 
			
		||||
        ? html`<ha-alert alert-type="warning">
 | 
			
		||||
            ${this.hass.localize(
 | 
			
		||||
              "ui.panel.config.thread.default_router_not_found"
 | 
			
		||||
            )}
 | 
			
		||||
          </ha-alert>`
 | 
			
		||||
        : ""}
 | 
			
		||||
      ${network.routers?.length
 | 
			
		||||
        ? html`<div class="card-content routers">
 | 
			
		||||
              <h4>
 | 
			
		||||
@@ -160,35 +173,50 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
                })}
 | 
			
		||||
              </h4>
 | 
			
		||||
            </div>
 | 
			
		||||
            ${network.routers.map(
 | 
			
		||||
              (router) =>
 | 
			
		||||
                html`<ha-list-item
 | 
			
		||||
                  class="router"
 | 
			
		||||
                  twoline
 | 
			
		||||
                  graphic="avatar"
 | 
			
		||||
                  .hasMeta=${router.extended_address ===
 | 
			
		||||
                  this._otbrInfo?.extended_address}
 | 
			
		||||
                >
 | 
			
		||||
                  <img
 | 
			
		||||
                    slot="graphic"
 | 
			
		||||
                    .src=${brandsUrl({
 | 
			
		||||
                      domain: router.brand,
 | 
			
		||||
                      brand: true,
 | 
			
		||||
                      type: "icon",
 | 
			
		||||
                      darkOptimized: this.hass.themes?.darkMode,
 | 
			
		||||
                    })}
 | 
			
		||||
                    alt=${router.brand}
 | 
			
		||||
                    referrerpolicy="no-referrer"
 | 
			
		||||
                    @error=${this._onImageError}
 | 
			
		||||
                    @load=${this._onImageLoad}
 | 
			
		||||
                  />
 | 
			
		||||
                  ${router.model_name ||
 | 
			
		||||
                  router.server?.replace(".local.", "") ||
 | 
			
		||||
                  ""}
 | 
			
		||||
                  <span slot="secondary">${router.server}</span>
 | 
			
		||||
                  ${router.extended_address === this._otbrInfo?.extended_address
 | 
			
		||||
                    ? html`<ha-button-menu
 | 
			
		||||
            ${network.routers.map((router) => {
 | 
			
		||||
              const showOverflow =
 | 
			
		||||
                ("dataset" in network && router.border_agent_id) ||
 | 
			
		||||
                router.extended_address === this._otbrInfo?.extended_address;
 | 
			
		||||
              return html`<ha-list-item
 | 
			
		||||
                class="router"
 | 
			
		||||
                twoline
 | 
			
		||||
                graphic="avatar"
 | 
			
		||||
                .hasMeta=${showOverflow}
 | 
			
		||||
              >
 | 
			
		||||
                <img
 | 
			
		||||
                  slot="graphic"
 | 
			
		||||
                  .src=${brandsUrl({
 | 
			
		||||
                    domain: router.brand,
 | 
			
		||||
                    brand: true,
 | 
			
		||||
                    type: "icon",
 | 
			
		||||
                    darkOptimized: this.hass.themes?.darkMode,
 | 
			
		||||
                  })}
 | 
			
		||||
                  alt=${router.brand}
 | 
			
		||||
                  referrerpolicy="no-referrer"
 | 
			
		||||
                  @error=${this._onImageError}
 | 
			
		||||
                  @load=${this._onImageLoad}
 | 
			
		||||
                />
 | 
			
		||||
                ${router.model_name ||
 | 
			
		||||
                router.server?.replace(".local.", "") ||
 | 
			
		||||
                ""}
 | 
			
		||||
                <span slot="secondary">${router.server}</span>
 | 
			
		||||
                ${showOverflow
 | 
			
		||||
                  ? html`${network.dataset &&
 | 
			
		||||
                      router.border_agent_id ===
 | 
			
		||||
                        network.dataset.preferred_border_agent_id
 | 
			
		||||
                        ? html`<ha-svg-icon
 | 
			
		||||
                            .path=${mdiStar}
 | 
			
		||||
                            .title=${this.hass.localize(
 | 
			
		||||
                              "ui.panel.config.thread.default_router"
 | 
			
		||||
                            )}
 | 
			
		||||
                            slot="meta"
 | 
			
		||||
                          >
 | 
			
		||||
                          </ha-svg-icon>`
 | 
			
		||||
                        : ""}
 | 
			
		||||
                      <ha-button-menu
 | 
			
		||||
                        slot="meta"
 | 
			
		||||
                        .network=${network}
 | 
			
		||||
                        .router=${router}
 | 
			
		||||
                        @action=${this._handleRouterAction}
 | 
			
		||||
                      >
 | 
			
		||||
                        <ha-icon-button
 | 
			
		||||
@@ -197,27 +225,46 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
                          )}
 | 
			
		||||
                          .path=${mdiDotsVertical}
 | 
			
		||||
                          slot="trigger"
 | 
			
		||||
                        ></ha-icon-button
 | 
			
		||||
                        ><ha-list-item
 | 
			
		||||
                          >${this.hass.localize(
 | 
			
		||||
                            "ui.panel.config.thread.reset_border_router"
 | 
			
		||||
                          )}</ha-list-item
 | 
			
		||||
                        ><ha-list-item
 | 
			
		||||
                          >${this.hass.localize(
 | 
			
		||||
                            "ui.panel.config.thread.change_channel"
 | 
			
		||||
                          )}</ha-list-item
 | 
			
		||||
                        >${network.dataset?.preferred
 | 
			
		||||
                          ? ""
 | 
			
		||||
                          : html`<ha-list-item
 | 
			
		||||
                          >${this.hass.localize(
 | 
			
		||||
                            "ui.panel.config.thread.add_to_my_network"
 | 
			
		||||
                          )}</ha-list-item
 | 
			
		||||
                        ></ha-button-menu
 | 
			
		||||
                      >`}</ha-button-menu
 | 
			
		||||
                      >`
 | 
			
		||||
                    : ""}
 | 
			
		||||
                </ha-list-item>`
 | 
			
		||||
            )}`
 | 
			
		||||
                        ></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
 | 
			
		||||
                                ? this.hass.localize(
 | 
			
		||||
                                    "ui.panel.config.thread.default_router"
 | 
			
		||||
                                  )
 | 
			
		||||
                                : this.hass.localize(
 | 
			
		||||
                                    "ui.panel.config.thread.set_default_router"
 | 
			
		||||
                                  )}
 | 
			
		||||
                            </ha-list-item>`
 | 
			
		||||
                          : ""}
 | 
			
		||||
                        ${router.extended_address ===
 | 
			
		||||
                        this._otbrInfo?.extended_address
 | 
			
		||||
                          ? html`<ha-list-item>
 | 
			
		||||
                                ${this.hass.localize(
 | 
			
		||||
                                  "ui.panel.config.thread.reset_border_router"
 | 
			
		||||
                                )}</ha-list-item
 | 
			
		||||
                              >
 | 
			
		||||
                              <ha-list-item>
 | 
			
		||||
                                ${this.hass.localize(
 | 
			
		||||
                                  "ui.panel.config.thread.change_channel"
 | 
			
		||||
                                )}</ha-list-item
 | 
			
		||||
                              >
 | 
			
		||||
                              ${network.dataset?.preferred
 | 
			
		||||
                                ? ""
 | 
			
		||||
                                : html`<ha-list-item>
 | 
			
		||||
                                    ${this.hass.localize(
 | 
			
		||||
                                      "ui.panel.config.thread.add_to_my_network"
 | 
			
		||||
                                    )}
 | 
			
		||||
                                  </ha-list-item>`}`
 | 
			
		||||
                          : ""}
 | 
			
		||||
                      </ha-button-menu>`
 | 
			
		||||
                  : ""}
 | 
			
		||||
              </ha-list-item>`;
 | 
			
		||||
            })}`
 | 
			
		||||
        : html`<div class="card-content no-routers">
 | 
			
		||||
            <ha-svg-icon .path=${mdiDevices}></ha-svg-icon>
 | 
			
		||||
            ${network.dataset?.extended_pan_id &&
 | 
			
		||||
@@ -323,11 +370,20 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
        if (!network) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (dataset.preferred_border_agent_id) {
 | 
			
		||||
          networks[network].preferred_border_agent_found =
 | 
			
		||||
            networks[network]?.routers?.find(
 | 
			
		||||
              (router) =>
 | 
			
		||||
                router.border_agent_id === dataset.preferred_border_agent_id
 | 
			
		||||
            ) !== undefined;
 | 
			
		||||
        }
 | 
			
		||||
        if (dataset.preferred) {
 | 
			
		||||
          preferred = {
 | 
			
		||||
            name: dataset.network_name,
 | 
			
		||||
            dataset: dataset,
 | 
			
		||||
            routers: networks[network]?.routers,
 | 
			
		||||
            preferred_border_agent_found:
 | 
			
		||||
              networks[network]?.preferred_border_agent_found || false,
 | 
			
		||||
          };
 | 
			
		||||
          delete networks[network];
 | 
			
		||||
          continue;
 | 
			
		||||
@@ -335,7 +391,11 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
        if (network in networks) {
 | 
			
		||||
          networks[network].dataset = dataset;
 | 
			
		||||
        } else {
 | 
			
		||||
          networks[network] = { name: dataset.network_name, dataset: dataset };
 | 
			
		||||
          networks[network] = {
 | 
			
		||||
            name: dataset.network_name,
 | 
			
		||||
            dataset: dataset,
 | 
			
		||||
            preferred_border_agent_found: false,
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return {
 | 
			
		||||
@@ -382,14 +442,23 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private _handleRouterAction(ev: CustomEvent<ActionDetail>) {
 | 
			
		||||
    switch (ev.detail.index) {
 | 
			
		||||
    const network = (ev.currentTarget as any).network as ThreadNetwork;
 | 
			
		||||
    const router = (ev.currentTarget as any).router as ThreadRouter;
 | 
			
		||||
    const index =
 | 
			
		||||
      network.dataset && router.border_agent_id
 | 
			
		||||
        ? Number(ev.detail.index)
 | 
			
		||||
        : Number(ev.detail.index) + 1;
 | 
			
		||||
    switch (index) {
 | 
			
		||||
      case 0:
 | 
			
		||||
        this._resetBorderRouter();
 | 
			
		||||
        this._setPreferredBorderAgent(network.dataset!, router);
 | 
			
		||||
        break;
 | 
			
		||||
      case 1:
 | 
			
		||||
        this._changeChannel();
 | 
			
		||||
        this._resetBorderRouter();
 | 
			
		||||
        break;
 | 
			
		||||
      case 2:
 | 
			
		||||
        this._changeChannel();
 | 
			
		||||
        break;
 | 
			
		||||
      case 3:
 | 
			
		||||
        this._setDataset();
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -452,6 +521,19 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
    this._refresh();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async _setPreferredBorderAgent(
 | 
			
		||||
    dataset: ThreadDataSet,
 | 
			
		||||
    router: ThreadRouter
 | 
			
		||||
  ) {
 | 
			
		||||
    const datasetId = dataset.dataset_id;
 | 
			
		||||
    const borderAgentId = router.border_agent_id;
 | 
			
		||||
    if (!borderAgentId) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    await setPreferredBorderAgent(this.hass, datasetId, borderAgentId);
 | 
			
		||||
    this._refresh();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async _addTLV() {
 | 
			
		||||
    const tlv = await showPromptDialog(this, {
 | 
			
		||||
      title: this.hass.localize("ui.panel.config.thread.add_dataset"),
 | 
			
		||||
@@ -571,11 +653,22 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
 | 
			
		||||
        direction: ltr;
 | 
			
		||||
      }
 | 
			
		||||
      ha-list-item.router {
 | 
			
		||||
        --mdc-list-item-meta-size: auto;
 | 
			
		||||
        --mdc-list-item-meta-display: flex;
 | 
			
		||||
        --mdc-list-side-padding: 16px;
 | 
			
		||||
        --mdc-list-item-meta-size: 48px;
 | 
			
		||||
        cursor: default;
 | 
			
		||||
        overflow: visible;
 | 
			
		||||
      }
 | 
			
		||||
      ha-alert {
 | 
			
		||||
        margin-bottom: 16px;
 | 
			
		||||
        display: block;
 | 
			
		||||
      }
 | 
			
		||||
      ha-svg-icon[slot="meta"] {
 | 
			
		||||
        width: 24px;
 | 
			
		||||
      }
 | 
			
		||||
      ha-button-menu {
 | 
			
		||||
        width: 48px;
 | 
			
		||||
      }
 | 
			
		||||
      ha-button-menu a {
 | 
			
		||||
        text-decoration: none;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -3707,6 +3707,9 @@
 | 
			
		||||
          "add_open_thread_border_router": "Add an OpenThread border router",
 | 
			
		||||
          "reset_border_router": "Reset border router",
 | 
			
		||||
          "add_to_my_network": "Add to preferred network",
 | 
			
		||||
          "default_router_not_found": "The default border router for this network could not be found.",
 | 
			
		||||
          "default_router": "Default router for network",
 | 
			
		||||
          "set_default_router": "Set as default router for network",
 | 
			
		||||
          "no_routers_otbr_network": "No border routers where found, maybe the border router is not configured correctly. You can try to reset it to the factory settings.",
 | 
			
		||||
          "add_dataset_from_tlv": "Add dataset from TLV",
 | 
			
		||||
          "add_dataset": "Add Thread dataset",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user