From c77e5dee84e4c09bbb41e8dcb8fd63b96b7178c7 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Mon, 3 Oct 2022 18:10:57 -0700 Subject: [PATCH 1/8] Allow remote WebRTC playback using STUN server from RTSPtoWeb integration (#13942) Co-authored-by: Bram Kragten --- src/components/ha-web-rtc-player.ts | 37 +++++++++++++++++++++++++++-- src/data/rtsp_to_webrtc.ts | 10 ++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/data/rtsp_to_webrtc.ts diff --git a/src/components/ha-web-rtc-player.ts b/src/components/ha-web-rtc-player.ts index 3987ff918c..0e7d31bc3a 100644 --- a/src/components/ha-web-rtc-player.ts +++ b/src/components/ha-web-rtc-player.ts @@ -7,7 +7,9 @@ import { TemplateResult, } from "lit"; import { customElement, property, state, query } from "lit/decorators"; +import { isComponentLoaded } from "../common/config/is_component_loaded"; import { handleWebRtcOffer, WebRtcAnswer } from "../data/camera"; +import { fetchWebRtcSettings } from "../data/rtsp_to_webrtc"; import type { HomeAssistant } from "../types"; import "./ha-alert"; @@ -86,7 +88,8 @@ class HaWebRtcPlayer extends LitElement { private async _startWebRtc(): Promise { this._error = undefined; - const peerConnection = new RTCPeerConnection(); + const configuration = await this._fetchPeerConfiguration(); + const peerConnection = new RTCPeerConnection(configuration); // Some cameras (such as nest) require a data channel to establish a stream // however, not used by any integrations. peerConnection.createDataChannel("dataSendChannel"); @@ -102,12 +105,25 @@ class HaWebRtcPlayer extends LitElement { ); await peerConnection.setLocalDescription(offer); + let candidates = ""; // Build an Offer SDP string with ice candidates + const iceResolver = new Promise((resolve) => { + peerConnection.addEventListener("icecandidate", async (event) => { + if (!event.candidate) { + resolve(); // Gathering complete + return; + } + candidates += `a=${event.candidate.candidate}\r\n`; + }); + }); + await iceResolver; + const offer_sdp = offer.sdp! + candidates; + let webRtcAnswer: WebRtcAnswer; try { webRtcAnswer = await handleWebRtcOffer( this.hass, this.entityid, - offer.sdp! + offer_sdp ); } catch (err: any) { this._error = "Failed to start WebRTC stream: " + err.message; @@ -138,6 +154,23 @@ class HaWebRtcPlayer extends LitElement { this._peerConnection = peerConnection; } + private async _fetchPeerConfiguration(): Promise { + if (!isComponentLoaded(this.hass!, "rtsp_to_webrtc")) { + return {}; + } + const settings = await fetchWebRtcSettings(this.hass!); + if (!settings || !settings.stun_server) { + return {}; + } + return { + iceServers: [ + { + urls: [`stun:${settings.stun_server!}`], + }, + ], + }; + } + private _cleanUp() { if (this._remoteStream) { this._remoteStream.getTracks().forEach((track) => { diff --git a/src/data/rtsp_to_webrtc.ts b/src/data/rtsp_to_webrtc.ts new file mode 100644 index 0000000000..777d7147e4 --- /dev/null +++ b/src/data/rtsp_to_webrtc.ts @@ -0,0 +1,10 @@ +import { HomeAssistant } from "../types"; + +export interface WebRtcSettings { + stun_server?: string; +} + +export const fetchWebRtcSettings = async (hass: HomeAssistant) => + hass.callWS({ + type: "rtsp_to_webrtc/get_settings", + }); From c38892a1629b3f837fefaf811df8ae625a733bf6 Mon Sep 17 00:00:00 2001 From: "Arun S. Sekher" Date: Tue, 4 Oct 2022 10:33:08 +0400 Subject: [PATCH 2/8] Add Malayalam language. (#13854) * Add Malayalam language. Update translationMetadata.json to add the language Malayalam. * Apply suggestions from code review Remove two extra spaces on line 121. Co-authored-by: Bram Kragten Co-authored-by: Bram Kragten --- src/translations/translationMetadata.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/translations/translationMetadata.json b/src/translations/translationMetadata.json index 285d9265d8..2368f41fa3 100644 --- a/src/translations/translationMetadata.json +++ b/src/translations/translationMetadata.json @@ -116,6 +116,9 @@ "lv": { "nativeName": "Latviešu" }, + "ml": { + "nativeName": "മലയാളം" + }, "nl": { "nativeName": "Nederlands" }, From 0ac2393ecbe8382835c0dd0860974d0d9c68323a Mon Sep 17 00:00:00 2001 From: krazos Date: Tue, 4 Oct 2022 04:45:15 -0400 Subject: [PATCH 3/8] Update automation picker to use differenceInDays from date-fns (#13980) --- .../config/automation/ha-automation-picker.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index 66cb64e64a..2c8d9d3afa 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -14,6 +14,7 @@ import "@polymer/paper-tooltip/paper-tooltip"; import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; +import { differenceInDays } from "date-fns/esm"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { relativeTime } from "../../../common/datetime/relative_time"; @@ -50,8 +51,6 @@ import { documentationUrl } from "../../../util/documentation-url"; import { configSections } from "../ha-panel-config"; import { showNewAutomationDialog } from "./show-dialog-new-automation"; -const DAY_IN_MILLISECONDS = 86400000; - @customElement("ha-automation-picker") class HaAutomationPicker extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -109,16 +108,13 @@ class HaAutomationPicker extends LitElement { ? (name, automation: any) => { const date = new Date(automation.attributes.last_triggered); const now = new Date(); - - const diff = now.getTime() - date.getTime(); - const dayDiff = diff / DAY_IN_MILLISECONDS; - + const dayDifference = differenceInDays(now, date); return html` ${name}
${this.hass.localize("ui.card.automation.last_triggered")}: ${automation.attributes.last_triggered - ? dayDiff > 3 + ? dayDifference > 3 ? formatShortDateTime(date, this.hass.locale) : relativeTime(date, this.hass.locale) : this.hass.localize("ui.components.relative_time.never")} @@ -136,13 +132,10 @@ class HaAutomationPicker extends LitElement { template: (last_triggered) => { const date = new Date(last_triggered); const now = new Date(); - - const diff = now.getTime() - date.getTime(); - const dayDiff = diff / DAY_IN_MILLISECONDS; - + const dayDifference = differenceInDays(now, date); return html` ${last_triggered - ? dayDiff > 3 + ? dayDifference > 3 ? formatShortDateTime(date, this.hass.locale) : relativeTime(date, this.hass.locale) : this.hass.localize("ui.components.relative_time.never")} From d5cdd53fabccc8ba06a6832803806babe8c8f910 Mon Sep 17 00:00:00 2001 From: krazos Date: Tue, 4 Oct 2022 05:39:55 -0400 Subject: [PATCH 4/8] Update scene dashboard to use relative time for last_activated (#13974) --- src/panels/config/scene/ha-scene-dashboard.ts | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/panels/config/scene/ha-scene-dashboard.ts b/src/panels/config/scene/ha-scene-dashboard.ts index 76e857a7f3..652420dca0 100644 --- a/src/panels/config/scene/ha-scene-dashboard.ts +++ b/src/panels/config/scene/ha-scene-dashboard.ts @@ -11,6 +11,7 @@ import "@polymer/paper-tooltip/paper-tooltip"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; +import { differenceInDays } from "date-fns/esm"; import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { navigate } from "../../../common/navigate"; @@ -42,7 +43,8 @@ import { HomeAssistant, Route } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; import { showToast } from "../../../util/toast"; import { configSections } from "../ha-panel-config"; -import { formatDateTime } from "../../../common/datetime/format_date_time"; +import { formatShortDateTime } from "../../../common/datetime/format_date_time"; +import { relativeTime } from "../../../common/datetime/relative_time"; import { UNAVAILABLE_STATES } from "../../../data/entity"; @customElement("ha-scene-dashboard") @@ -109,11 +111,18 @@ class HaSceneDashboard extends LitElement { ), sortable: true, width: "30%", - template: (last_activated) => html` - ${last_activated && !UNAVAILABLE_STATES.includes(last_activated) - ? formatDateTime(new Date(last_activated), this.hass.locale) - : this.hass.localize("ui.components.relative_time.never")} - `, + template: (last_activated) => { + const date = new Date(last_activated); + const now = new Date(); + const dayDifference = differenceInDays(now, date); + return html` + ${last_activated && !UNAVAILABLE_STATES.includes(last_activated) + ? dayDifference > 3 + ? formatShortDateTime(date, this.hass.locale) + : relativeTime(date, this.hass.locale) + : this.hass.localize("ui.components.relative_time.never")} + `; + }, }; } columns.only_editable = { From 37394f7bc536e8fe4173e6f675e9d6e99b7cb3e4 Mon Sep 17 00:00:00 2001 From: krazos Date: Tue, 4 Oct 2022 05:40:12 -0400 Subject: [PATCH 5/8] Update script picker to use relative time for last_triggered (#13973) --- src/panels/config/script/ha-script-picker.ts | 49 +++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts index 97ef655d18..73a7eaa762 100644 --- a/src/panels/config/script/ha-script-picker.ts +++ b/src/panels/config/script/ha-script-picker.ts @@ -11,7 +11,9 @@ import { HassEntity } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; -import { formatDateTime } from "../../../common/datetime/format_date_time"; +import { differenceInDays } from "date-fns/esm"; +import { formatShortDateTime } from "../../../common/datetime/format_date_time"; +import { relativeTime } from "../../../common/datetime/relative_time"; import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { navigate } from "../../../common/navigate"; @@ -99,18 +101,22 @@ class HaScriptPicker extends LitElement { direction: "asc", grows: true, template: narrow - ? (name, script: any) => html` - ${name} -
- ${this.hass.localize("ui.card.automation.last_triggered")}: - ${script.attributes.last_triggered - ? formatDateTime( - new Date(script.attributes.last_triggered), - this.hass.locale - ) - : this.hass.localize("ui.components.relative_time.never")} -
- ` + ? (name, script: any) => { + const date = new Date(script.attributes.last_triggered); + const now = new Date(); + const dayDifference = differenceInDays(now, date); + return html` + ${name} +
+ ${this.hass.localize("ui.card.automation.last_triggered")}: + ${script.attributes.last_triggered + ? dayDifference > 3 + ? formatShortDateTime(date, this.hass.locale) + : relativeTime(date, this.hass.locale) + : this.hass.localize("ui.components.relative_time.never")} +
+ `; + } : undefined, }, }; @@ -119,11 +125,18 @@ class HaScriptPicker extends LitElement { sortable: true, width: "40%", title: this.hass.localize("ui.card.automation.last_triggered"), - template: (last_triggered) => html` - ${last_triggered - ? formatDateTime(new Date(last_triggered), this.hass.locale) - : this.hass.localize("ui.components.relative_time.never")} - `, + template: (last_triggered) => { + const date = new Date(last_triggered); + const now = new Date(); + const dayDifference = differenceInDays(now, date); + return html` + ${last_triggered + ? dayDifference > 3 + ? formatShortDateTime(date, this.hass.locale) + : relativeTime(date, this.hass.locale) + : this.hass.localize("ui.components.relative_time.never")} + `; + }, }; } From 8eddaa1914697bf67369c49f54c9f47f90fa2641 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 4 Oct 2022 16:25:30 +0200 Subject: [PATCH 6/8] Filter out homekit and matter iot standards (#13985) * Filter out homekit and matter iot standards * add divider between discovered * Update dialog-add-integration.ts * Update ha-domain-integrations.ts * Update en.json * Change headers * update styling * translation --- .../config/areas/ha-config-area-page.ts | 15 ---- .../integrations/dialog-add-integration.ts | 7 +- .../integrations/ha-domain-integrations.ts | 89 ++++++++++++------- .../integrations/ha-integration-list-item.ts | 4 +- src/translations/en.json | 8 +- 5 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/panels/config/areas/ha-config-area-page.ts b/src/panels/config/areas/ha-config-area-page.ts index 00c0f99a4d..bf3cbacac8 100644 --- a/src/panels/config/areas/ha-config-area-page.ts +++ b/src/panels/config/areas/ha-config-area-page.ts @@ -639,21 +639,6 @@ class HaConfigAreaPage extends SubscribeMixin(LitElement) { return [ haStyle, css` - h1 { - margin: 0; - font-family: var(--paper-font-headline_-_font-family); - -webkit-font-smoothing: var( - --paper-font-headline_-_-webkit-font-smoothing - ); - font-size: var(--paper-font-headline_-_font-size); - font-weight: var(--paper-font-headline_-_font-weight); - letter-spacing: var(--paper-font-headline_-_letter-spacing); - line-height: var(--paper-font-headline_-_line-height); - opacity: var(--dark-primary-opacity); - display: flex; - align-items: center; - } - h3 { margin: 0; padding: 0 16px; diff --git a/src/panels/config/integrations/dialog-add-integration.ts b/src/panels/config/integrations/dialog-add-integration.ts index c2b6837169..a775b05506 100644 --- a/src/panels/config/integrations/dialog-add-integration.ts +++ b/src/panels/config/integrations/dialog-add-integration.ts @@ -187,12 +187,7 @@ class AddIntegrationDialog extends LitElement { for (const [domain, domainBrands] of Object.entries(sb)) { const integration = this._findIntegration(domain); - if ( - !integration || - (!integration.config_flow && - !integration.iot_standards && - !integration.integrations) - ) { + if (!integration) { continue; } for (const [slug, name] of Object.entries(domainBrands)) { diff --git a/src/panels/config/integrations/ha-domain-integrations.ts b/src/panels/config/integrations/ha-domain-integrations.ts index 610414d77f..45a2716ac0 100644 --- a/src/panels/config/integrations/ha-domain-integrations.ts +++ b/src/panels/config/integrations/ha-domain-integrations.ts @@ -36,7 +36,9 @@ class HaDomainIntegrations extends LitElement { protected render() { return html` ${this.flowsInProgress?.length - ? html`

We discovered the following:

+ ? html`

+ ${this.hass.localize("ui.panel.config.integrations.discovered")} +

${this.flowsInProgress.map( (flow) => html` ` - )}` + )} +
  • + ${this.integration?.integrations + ? html`

    + ${this.hass.localize( + "ui.panel.config.integrations.available_integrations" + )} +

    ` + : ""}` : ""} ${this.integration?.iot_standards - ? this.integration.iot_standards.map((standard) => { - const domain: string = standardToDomain[standard] || standard; - return html` - - ${this.hass.localize( - `ui.panel.config.integrations.add_${domain}_device` - )} standard in standardToDomain) + .map((standard) => { + const domain: string = standardToDomain[standard]; + return html` - - `; - }) + + ${this.hass.localize( + `ui.panel.config.integrations.add_${domain}_device` + )} + + `; + }) : ""} ${this.integration?.integrations ? Object.entries(this.integration.integrations) @@ -155,9 +167,11 @@ class HaDomainIntegrations extends LitElement { @click=${this._integrationPicked} hasMeta > - Setup another instance of - ${this.integration.name || - domainToName(this.hass.localize, this.domain)} + ${this.hass.localize("ui.panel.config.integrations.new_flow", { + integration: + this.integration.name || + domainToName(this.hass.localize, this.domain), + })} ` : html` Date: Tue, 4 Oct 2022 16:42:19 +0200 Subject: [PATCH 7/8] Bumped version to 20221004.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bd5d34eab8..14b67e7416 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20221003.0" +version = "20221004.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From ed54c70e75e1b709732cc20c1c4beb7af2ba38c4 Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Tue, 4 Oct 2022 10:43:05 -0400 Subject: [PATCH 8/8] Update zwave_js firmware update event interfaces (#13982) --- src/data/zwave_js.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/data/zwave_js.ts b/src/data/zwave_js.ts index 7863c3de84..336c9824b6 100644 --- a/src/data/zwave_js.ts +++ b/src/data/zwave_js.ts @@ -306,14 +306,19 @@ export interface ZWaveJSNodeStatusUpdatedMessage { export interface ZWaveJSNodeFirmwareUpdateProgressMessage { event: "firmware update progress"; + current_file: number; + total_files: number; sent_fragments: number; total_fragments: number; + progress: number; } export interface ZWaveJSNodeFirmwareUpdateFinishedMessage { event: "firmware update finished"; status: FirmwareUpdateStatus; - wait_time: number; + success: boolean; + wait_time?: number; + reinterview: boolean; } export type ZWaveJSNodeFirmwareUpdateCapabilities =