import { css, CSSResult, customElement, html, internalProperty, LitElement, property, PropertyValues, TemplateResult, } from "lit-element"; import { fireEvent } from "../common/dom/fire_event"; import { computeStateName } from "../common/entity/compute_state_name"; import { supportsFeature } from "../common/entity/supports-feature"; import { CameraEntity, CAMERA_SUPPORT_STREAM, computeMJPEGStreamUrl, fetchStreamUrl, } from "../data/camera"; import { HomeAssistant } from "../types"; import "./ha-hls-player"; @customElement("ha-camera-stream") class HaCameraStream extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public stateObj?: CameraEntity; @property({ type: Boolean, attribute: "controls" }) public controls = false; @property({ type: Boolean, attribute: "muted" }) public muted = false; @property({ type: Boolean, attribute: "allow-exoplayer" }) public allowExoPlayer = false; // We keep track if we should force MJPEG with a string // that way it automatically resets if we change entity. @internalProperty() private _forceMJPEG?: string; @internalProperty() private _url?: string; protected render(): TemplateResult { if (!this.stateObj) { return html``; } return html` ${__DEMO__ || this._shouldRenderMJPEG ? html` ` : this._url ? html` ` : ""} `; } protected updated(changedProps: PropertyValues): void { if (changedProps.has("stateObj") && !this._shouldRenderMJPEG) { this._forceMJPEG = undefined; this._getStreamUrl(); } } private get _shouldRenderMJPEG() { return ( this._forceMJPEG === this.stateObj!.entity_id || !this.hass!.config.components.includes("stream") || !supportsFeature(this.stateObj!, CAMERA_SUPPORT_STREAM) ); } private async _getStreamUrl(): Promise { try { const { url } = await fetchStreamUrl( this.hass!, this.stateObj!.entity_id ); this._url = url; } catch (err) { // Fails if we were unable to get a stream // eslint-disable-next-line console.error(err); this._forceMJPEG = this.stateObj!.entity_id; } } private _elementResized() { fireEvent(this, "iron-resize"); } static get styles(): CSSResult { return css` :host, img { display: block; } img { width: 100%; } `; } } declare global { interface HTMLElementTagNameMap { "ha-camera-stream": HaCameraStream; } }