Add birdseye support.
This commit is contained in:
@@ -63,19 +63,19 @@ lovelace:
|
||||
|
||||
## Options
|
||||
|
||||
### Required
|
||||
### Basic
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------- | - | --------------------------------------------- |
|
||||
| `camera_entity` | | The Frigate camera entity to use in the live camera view.|
|
||||
| `camera_entity` | | The optional Frigate camera entity to use in the `frigate` live provider view. Also used to automatically detect the `frigate_camera_name`.|
|
||||
| `frigate_camera_name` | Autodetected from `camera_entity` if that is specified. | The Frigate camera name to use when communicating with the Frigate server, e.g. for viewing clips/snapshots or the JSMPEG live view. To view the birdseye view set this to `birdseye` and use the `frigate-jsmpeg` live provider.|
|
||||
| `view_default` | `live` | The view to show by default. See [views](#views) below.|
|
||||
|
||||
### Optional
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------- | --------------------------------------------- | - |
|
||||
| `frigate_camera_name` | The Frigate camera name Home Assistant associates with that camera entity, if none then the string after the `camera.` in the `camera_entity` field. | This parameter allows the Frigate camera name to be overriden. This name is used for communicating with the Frigate backend, e.g. for fetching events. |
|
||||
| `live_provider` | `frigate` | The means through which the live camera view is displayed. See [Live Provider](#live-provider) below.|
|
||||
| `view_default` | `live` | The view to show by default. See [views](#views) below.|
|
||||
| `frigate_client_id` | `frigate` | The Frigate client id to use. If this Home Assistant server has multiple Frigate server backends configured, this selects which server should be used. It should be set to the MQTT client id configured for this server, see [Frigate Integration Multiple Instance Support](https://blakeblackshear.github.io/frigate/usage/home-assistant/#multiple-instance-support).|
|
||||
| `view_timeout` | | A numbers of seconds of inactivity after which the card will reset to the default configured view. Inactivity is defined as lack of interaction with the Frigate menu.|
|
||||
| `frigate_url` | | The URL of the frigate server. If set, this value will be (exclusively) used for a `Frigate UI` menu button. |
|
||||
@@ -87,7 +87,7 @@ lovelace:
|
||||
|Live Provider|Latency|Frame Rate|Installation|Description|
|
||||
| -- | -- | -- | -- | -- |
|
||||
|`frigate`|High|High|Builtin|Use the built-in Home Assistant camera stream from Frigate (RTMP). The camera doesn't even need to be a Frigate camera! |
|
||||
|`frigate-jsmpeg`|Lower|Low|Builtin|Stream the JSMPEG stream from Frigate (proxied via the Frigate integration). See [note below on the required integration version](#jsmpeg-troubleshooting) for this live provider to function.|
|
||||
|`frigate-jsmpeg`|Lower|Low|Builtin|Stream the JSMPEG stream from Frigate (proxied via the Frigate integration). See [note below on the required integration version](#jsmpeg-troubleshooting) for this live provider to function. This is the only live provider that can view the Frigate `birdseye` view.|
|
||||
|`webrtc`|Lowest|High|Separate installation required|Uses [WebRTC](https://github.com/AlexxIT/WebRTC) to stream live feed, requires manual extra setup, see [below](#webrtc).|
|
||||
|
||||
### Appearance
|
||||
|
||||
+6
-6
@@ -19,17 +19,17 @@
|
||||
"custom-card-helpers": "^1.8.0",
|
||||
"dayjs": "^1.10.7",
|
||||
"home-assistant-js-websocket": "^5.11.1",
|
||||
"lit": "^2.0.0",
|
||||
"lit": "^2.0.2",
|
||||
"screenfull": "^5.1.0",
|
||||
"zod": "^3.9.5"
|
||||
"zod": "^3.9.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.5",
|
||||
"@babel/core": "^7.15.8",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-decorators": "^7.15.4",
|
||||
"@babel/plugin-proposal-decorators": "^7.15.8",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.32.0",
|
||||
"@typescript-eslint/parser": "^4.32.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
|
||||
+12
-5
@@ -33,7 +33,6 @@ import { CARD_VERSION } from './const';
|
||||
import { FrigateCardMenu, MENU_HEIGHT } from './components/menu';
|
||||
import { View } from './view';
|
||||
import {
|
||||
getParseErrorKeys,
|
||||
homeAssistantWSRequest,
|
||||
shouldUpdateBasedOnHass,
|
||||
} from './common';
|
||||
@@ -221,6 +220,7 @@ export class FrigateCard extends LitElement {
|
||||
return this.config.frigate_camera_name;
|
||||
}
|
||||
|
||||
if (this.config.camera_entity) {
|
||||
// Option 2: Find entity unique_id in registry.
|
||||
const request = {
|
||||
type: 'config/entity_registry/get',
|
||||
@@ -246,6 +246,7 @@ export class FrigateCard extends LitElement {
|
||||
if (this.config.camera_entity.includes('.')) {
|
||||
return this.config.camera_entity.split('.', 2)[1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -287,11 +288,13 @@ export class FrigateCard extends LitElement {
|
||||
getLovelace().setEditMode(true);
|
||||
}
|
||||
|
||||
this._frigateCameraName = null;
|
||||
this.config = config;
|
||||
this._entitiesToMonitor = [
|
||||
...(this.config.update_entities || []),
|
||||
this.config.camera_entity,
|
||||
];
|
||||
|
||||
this._entitiesToMonitor = this.config.update_entities || [];
|
||||
if (this.config.camera_entity) {
|
||||
this._entitiesToMonitor.push(this.config.camera_entity);
|
||||
}
|
||||
this._changeView();
|
||||
}
|
||||
|
||||
@@ -636,6 +639,8 @@ export class FrigateCard extends LitElement {
|
||||
</frigate-card-live>
|
||||
`
|
||||
: ``}
|
||||
${this.config.elements
|
||||
? html`
|
||||
<frigate-card-elements
|
||||
.hass=${this._hass}
|
||||
.elements=${this.config.elements}
|
||||
@@ -651,6 +656,8 @@ export class FrigateCard extends LitElement {
|
||||
}}
|
||||
>
|
||||
</frigate-card-elements>
|
||||
`
|
||||
: ``}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -68,10 +68,10 @@ export class FrigateCardViewerFrigate extends LitElement {
|
||||
protected hass!: HomeAssistant & ExtendedHomeAssistant;
|
||||
|
||||
@property({ attribute: false })
|
||||
protected cameraEntity!: string;
|
||||
protected cameraEntity?: string;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!(this.cameraEntity in this.hass.states)) {
|
||||
if (!this.cameraEntity || !(this.cameraEntity in this.hass.states)) {
|
||||
return dispatchMessageEvent(
|
||||
this,
|
||||
localize('error.no_live_camera'),
|
||||
|
||||
+38
-38
@@ -9,10 +9,10 @@ import type { FrigateCardConfig } from './types';
|
||||
import frigate_card_editor_style from './scss/editor.scss';
|
||||
|
||||
const options = {
|
||||
required: {
|
||||
basic: {
|
||||
icon: 'cog',
|
||||
name: localize('editor.required'),
|
||||
secondary: localize('editor.required_secondary'),
|
||||
name: localize('editor.basic'),
|
||||
secondary: localize('editor.basic_secondary'),
|
||||
show: true,
|
||||
},
|
||||
optional: {
|
||||
@@ -146,14 +146,14 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
|
||||
return html`
|
||||
<div class="card-config">
|
||||
<div class="option" @click=${this._toggleOption} .option=${'required'}>
|
||||
<div class="option" @click=${this._toggleOption} .option=${'basic'}>
|
||||
<div class="row">
|
||||
<ha-icon .icon=${`mdi:${options.required.icon}`}></ha-icon>
|
||||
<div class="title">${options.required.name}</div>
|
||||
<ha-icon .icon=${`mdi:${options.basic.icon}`}></ha-icon>
|
||||
<div class="title">${options.basic.name}</div>
|
||||
</div>
|
||||
<div class="secondary">${options.required.secondary}</div>
|
||||
<div class="secondary">${options.basic.secondary}</div>
|
||||
</div>
|
||||
${options.required.show
|
||||
${options.basic.show
|
||||
? html`
|
||||
<div class="values">
|
||||
<paper-dropdown-menu
|
||||
@@ -172,42 +172,12 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
})}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
<div class="option" @click=${this._toggleOption} .option=${'optional'}>
|
||||
<div class="row">
|
||||
<ha-icon .icon=${`mdi:${options.optional.icon}`}></ha-icon>
|
||||
<div class="title">${options.optional.name}</div>
|
||||
</div>
|
||||
<div class="secondary">${options.optional.secondary}</div>
|
||||
</div>
|
||||
${options.optional.show
|
||||
? html` <div class="values">
|
||||
<paper-input
|
||||
label=${localize('editor.frigate_camera_name')}
|
||||
.value=${this._config?.frigate_camera_name || ''}
|
||||
.configValue=${'frigate_camera_name'}
|
||||
@value-changed=${this._valueChanged}
|
||||
></paper-input>
|
||||
<paper-dropdown-menu
|
||||
.label=${localize('editor.live_provider')}
|
||||
@value-changed=${this._valueChanged}
|
||||
.configValue=${'live_provider'}
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
.selected=${Object.keys(liveProvider).indexOf(
|
||||
this._config?.live_provider || '',
|
||||
)}
|
||||
>
|
||||
${Object.keys(liveProvider).map((key) => {
|
||||
return html`
|
||||
<paper-item .label="${key}">${liveProvider[key]} </paper-item>
|
||||
`;
|
||||
})}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-dropdown-menu
|
||||
label=${localize('editor.default_view')}
|
||||
@value-changed=${this._valueChanged}
|
||||
@@ -226,6 +196,36 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
})}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
<div class="option" @click=${this._toggleOption} .option=${'optional'}>
|
||||
<div class="row">
|
||||
<ha-icon .icon=${`mdi:${options.optional.icon}`}></ha-icon>
|
||||
<div class="title">${options.optional.name}</div>
|
||||
</div>
|
||||
<div class="secondary">${options.optional.secondary}</div>
|
||||
</div>
|
||||
${options.optional.show
|
||||
? html` <div class="values">
|
||||
<paper-dropdown-menu
|
||||
.label=${localize('editor.live_provider')}
|
||||
@value-changed=${this._valueChanged}
|
||||
.configValue=${'live_provider'}
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
.selected=${Object.keys(liveProvider).indexOf(
|
||||
this._config?.live_provider || '',
|
||||
)}
|
||||
>
|
||||
${Object.keys(liveProvider).map((key) => {
|
||||
return html`
|
||||
<paper-item .label="${key}">${liveProvider[key]} </paper-item>
|
||||
`;
|
||||
})}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-input
|
||||
label=${localize('editor.frigate_client_id')}
|
||||
.value=${this._config?.frigate_client_id || ''}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"no_clip": "No recent clip"
|
||||
},
|
||||
"editor": {
|
||||
"required": "Required",
|
||||
"required_secondary": "Required options for this card to function",
|
||||
"basic": "Basic",
|
||||
"basic_secondary": "Basic options for most users",
|
||||
"optional": "Optional",
|
||||
"optional_secondary": "Optional configuration to tweak card behavior",
|
||||
"appearance": "Appearance",
|
||||
@@ -21,8 +21,8 @@
|
||||
"webrtc_secondary": "Optional WebRTC parameters",
|
||||
"advanced": "Advanced",
|
||||
"advanced_secondary": "Advanced options",
|
||||
"camera_entity": "Camera Entity (Required)",
|
||||
"frigate_camera_name": "Frigate camera name (Optional)",
|
||||
"camera_entity": "Camera Entity (Optional)",
|
||||
"frigate_camera_name": "Frigate camera name (Optional, autodetected from entity)",
|
||||
"default_view": "Default view (Optional)",
|
||||
"frigate_client_id": "Frigate client id (Optional, for >1 Frigate server)",
|
||||
"view_timeout": "View timeout (seconds)",
|
||||
@@ -92,10 +92,10 @@
|
||||
"unknown": "Unknown error",
|
||||
"troubleshooting": "Check troubleshooting",
|
||||
"could_not_resolve": "Could not resolve media URL",
|
||||
"no_live_camera": "No live camera",
|
||||
"no_live_camera": "The camera_entity parameter must be set and valid for this live provider",
|
||||
"invalid_configuration": "Invalid configuration",
|
||||
"missing_webrtc": "WebRTC component not found",
|
||||
"no_frigate_camera_name": "Cannot derive frigate_camera_name, you may need to set it manually",
|
||||
"no_frigate_camera_name": "Cannot autodetect Frigate camera name, you need to either set camera_entity and / or frigate_camera_name",
|
||||
"could_not_render_elements": "Could not render picture elements",
|
||||
"invalid_elements_config": "Invalid picture elements configuration"
|
||||
}
|
||||
|
||||
+2
-1
@@ -244,7 +244,8 @@ const pictureElementsSchema = pictureElementSchema.array().optional();
|
||||
export type PictureElements = z.infer<typeof pictureElementsSchema>;
|
||||
|
||||
export const frigateCardConfigSchema = z.object({
|
||||
camera_entity: z.string(),
|
||||
camera_entity: z.string().optional(),
|
||||
|
||||
// No URL validation to allow relative URLs within HA (e.g. addons).
|
||||
frigate_url: z.string().optional(),
|
||||
frigate_client_id: z.string().optional().default('frigate'),
|
||||
|
||||
Reference in New Issue
Block a user