diff --git a/README.md b/README.md index 55d245da..0ce5fa77 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ cameras: | `title` | Autodetected from `camera_entity` if that is specified. | :heavy_multiplication_x: | A friendly name for this camera to use in the card. | | `icon` | Autodetected from `camera_entity` if that is specified. | :heavy_multiplication_x: | The icon to use for this camera in the camera menu and in the next & previous controls when using the `icon` style. | | `webrtc` | | :heavy_multiplication_x: | The WebRTC entity/URL to use for this camera. See below. | -| `id` | `camera_entity`, or `camera_name` if set (in that preference order). | :heavy_multiplication_x: | An optional identifier to use throughout the card configuration to refer unambiguously to this camera. See [camera IDs](#camera-ids). | +| `id` | `camera_entity`, `webrtc.entity` or `camera_name` if set (in that preference order). | :heavy_multiplication_x: | An optional identifier to use throughout the card configuration to refer unambiguously to this camera. See [camera IDs](#camera-ids). | #### Camera WebRTC configuration @@ -118,7 +118,7 @@ See [Using WebRTC](#webrtc) below for more details on how to use WebRTC with thi #### Camera IDs: Refering to cameras in card configuration -Each camera configured in the card has a single identifier (`id`). For a given camera, this will be one of the camera {`id`, `camera_entity` or `camera_name`} parameters for that camera -- in that order of precedence. These ids may be used in conditions or custom actions to refer to a given camera unambiguously. | +Each camera configured in the card has a single identifier (`id`). For a given camera, this will be one of the camera {`id`, `camera_entity`, `webrtc.entity` or `camera_name`} parameters for that camera -- in that order of precedence. These ids may be used in conditions or custom actions to refer to a given camera unambiguously. | #### Example diff --git a/src/browse-media-util.ts b/src/browse-media-util.ts index ff438705..336dcc1c 100644 --- a/src/browse-media-util.ts +++ b/src/browse-media-util.ts @@ -147,13 +147,25 @@ export class BrowseMediaUtil { * Get the parameters to search for media related to the current view. * @returns A BrowseMediaQueryParameters object. */ - static getBrowseMediaQueryParametersFromView( + static getBrowseMediaQueryParametersOrDispatchError( + node: HTMLElement, view: View, cameraConfig: CameraConfig, ): BrowseMediaQueryParameters | undefined { if (!view.isClipRelatedView() && !view.isSnapshotRelatedView()) { return undefined; } + + // Verify there is a camera name, otherwise getBrowseMediaQueryParameters() + // will return undefined. + if (!cameraConfig.camera_name) { + dispatchErrorMessageEvent( + node, + localize('error.no_camera_name') + `: ${JSON.stringify(cameraConfig)}`, + ); + return undefined; + } + return BrowseMediaUtil.getBrowseMediaQueryParameters( view.isClipRelatedView() ? 'clips' : 'snapshots', cameraConfig, diff --git a/src/card.ts b/src/card.ts index 4b2fc2a1..a0c3a7ba 100644 --- a/src/card.ts +++ b/src/card.ts @@ -432,17 +432,23 @@ export class FrigateCard extends LitElement { } } - if (config.camera_name) { - const id = config.id || config.camera_entity || config.camera_name; - if (cameras.has(id)) { - this._setMessageAndUpdate({ - message: localize('error.duplicate_camera_id'), - type: 'error', - }); - errorFree = false; - } else { - cameras.set(id, config); - } + const id = + config.id || config.camera_entity || config.webrtc?.entity || config.camera_name; + + if (!id) { + this._setMessageAndUpdate({ + message: localize('error.no_camera_id') + `: ${JSON.stringify(config)}`, + type: 'error', + }); + errorFree = false; + } else if (cameras.has(id)) { + this._setMessageAndUpdate({ + message: localize('error.duplicate_camera_id') + `: ${JSON.stringify(config)}`, + type: 'error', + }); + errorFree = false; + } else { + cameras.set(id, config); } }; @@ -506,11 +512,6 @@ export class FrigateCard extends LitElement { // Pass. } - // Fallback: Guess from the entity_id. - if (entity.includes('.')) { - return entity.split('.', 2)[1]; - } - return null; } @@ -842,6 +843,9 @@ export class FrigateCard extends LitElement { if (!cameraConfig || !cameraConfig.frigate_url || !this._view) { return null; } + if (!cameraConfig.camera_name) { + return cameraConfig.frigate_url; + } if (this._view.isViewerView() || this._view.isGalleryView()) { return `${cameraConfig.frigate_url}/events?camera=${cameraConfig.camera_name}`; } @@ -1015,12 +1019,14 @@ export class FrigateCard extends LitElement { // Do not artifically constrain aspect ratio if: // - It's fullscreen. // - Aspect ratio enforcement is disabled. - // - Or aspect ratio enforcement is dynamic and it's a media view (i.e. not the gallery). + // - Aspect ratio enforcement is dynamic and it's a media view (i.e. not the gallery). + // - There is a message to display to the user. return !( (screenfull.isEnabled && screenfull.isFullscreen) || aspectRatioMode == 'unconstrained' || - (aspectRatioMode == 'dynamic' && this._view?.isMediaView()) + (aspectRatioMode == 'dynamic' && this._view?.isMediaView() || + this._message != null) ); } @@ -1187,10 +1193,7 @@ export class FrigateCard extends LitElement { ? html` ` @@ -1199,10 +1202,7 @@ export class FrigateCard extends LitElement { ? html` ; @property({ attribute: false }) - protected browseMediaQueryParameters?: BrowseMediaQueryParameters; + protected cameraConfig?: CameraConfig; /** * Master render method. * @returns A rendered template. */ protected render(): TemplateResult | void { - if (!this.hass || !this.view || !this.browseMediaQueryParameters) { + if (!this.hass || !this.view || !this.cameraConfig) { return; } if (!this.view.target) { + const browseMediaQueryParameters = + BrowseMediaUtil.getBrowseMediaQueryParametersOrDispatchError( + this, + this.view, + this.cameraConfig, + ); + if (!browseMediaQueryParameters) { + return; + } + BrowseMediaUtil.fetchLatestMediaAndDispatchViewChange( this, this.hass, this.view, - this.browseMediaQueryParameters, + browseMediaQueryParameters, ); return renderProgressIndicator(); } diff --git a/src/components/live.ts b/src/components/live.ts index 4bba9d8f..644819bc 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -1,4 +1,5 @@ -// TODO readme +// TODO autodetect live provider from cameras configuration, or allow explicit setting. +// TODO verify README links worked correctly (e.g. basic cameras configuration) import { CSSResultGroup, @@ -371,7 +372,8 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel { const config = getOverriddenConfig( this.liveConfig, this.liveOverrides, - conditionState) as LiveConfig; + conditionState, + ) as LiveConfig; return html`
`; } diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json index ecb372c7..8251db6f 100644 --- a/src/localize/languages/en.json +++ b/src/localize/languages/en.json @@ -171,12 +171,14 @@ "upgrade_available": "An automated card configuration upgrade is available, please visit the visual card editor", "webrtc_missing": "WebRTC component not found", "webrtc_reported_error": "WebRTC component reported an error", - "no_cameras": "No valid cameras found, you must configure at least one camera with either a camera_entity or camera_name", - "duplicate_camera_id": "Duplicate Frigate camera, use the 'id' parameter to uniquely identify cameras with the same 'camera_entity' or 'camera_name'", + "no_cameras": "No valid cameras found, you must configure at least one camera entry", + "no_camera_id": "Could not determine camera id for the following camera, may need to set 'id' parameter manually", + "duplicate_camera_id": "Duplicate Frigate camera id for the following camera, use the 'id' parameter to uniquely identify cameras", "could_not_render_elements": "Could not render picture elements", "invalid_elements_config": "Invalid picture elements configuration", "jsmpeg_no_sign": "Could not retrieve or sign JSMPEG websocket path", "jsmpeg_no_player": "Could not start JSMPEG player", + "no_camera_name": "Could not determine Frigate camera name for camera, please specify either 'camera_entity' or 'camera_name' for the following camera", "download_no_media": "No media to download", "download_no_event_id": "Could not extract Frigate event id from media", "download_sign_failed": "Could not sign media URL for download" diff --git a/src/scss/message.scss b/src/scss/message.scss index 21181063..11a039c7 100644 --- a/src/scss/message.scss +++ b/src/scss/message.scss @@ -19,4 +19,5 @@ span { padding: 10px; + word-break: break-word; } \ No newline at end of file