Rename live providers to avoid WebRTC confusion

This commit is contained in:
Dermot Duffy
2022-02-13 08:55:15 -08:00
parent 0cd270cf69
commit 305d054395
7 changed files with 213 additions and 115 deletions
+28 -23
View File
@@ -13,7 +13,7 @@ import {
JSMPEGConfig,
LiveConfig,
MediaShowInfo,
WebRTCConfig,
WebRTCCardConfig,
FrigateCardError,
FrigateCardMediaPlayer,
LiveOverrides,
@@ -635,10 +635,13 @@ export class FrigateCardLiveProvider extends LitElement {
protected _getResolvedProvider(): LiveProvider {
if (this.cameraConfig?.live_provider === 'auto') {
if (this.cameraConfig?.webrtc?.entity || this.cameraConfig?.webrtc?.url) {
return 'webrtc';
if (
this.cameraConfig?.webrtc_card?.entity ||
this.cameraConfig?.webrtc_card?.url
) {
return 'webrtc-card';
} else if (this.cameraConfig?.camera_entity) {
return 'frigate';
return 'ha';
} else if (this.cameraConfig?.camera_name) {
return 'frigate-jsmpeg';
}
@@ -665,21 +668,21 @@ export class FrigateCardLiveProvider extends LitElement {
const provider = this._getResolvedProvider();
return html`
${provider == 'frigate'
? html` <frigate-card-live-frigate
${provider == 'ha'
? html` <frigate-card-live-ha
${ref(this._providerRef)}
.hass=${this.hass}
.cameraEntity=${this.cameraConfig.camera_entity}
>
</frigate-card-live-frigate>`
: provider == 'webrtc'
? html`<frigate-card-live-webrtc
</frigate-card-live-ha>`
: provider == 'webrtc-card'
? html`<frigate-card-live-webrtc-card
${ref(this._providerRef)}
.hass=${this.hass}
.cameraConfig=${this.cameraConfig}
.webRTCConfig=${this.liveConfig.webrtc}
.webRTCConfig=${this.liveConfig.webrtc_card}
>
</frigate-card-live-webrtc>`
</frigate-card-live-webrtc-card>`
: html` <frigate-card-live-jsmpeg
${ref(this._providerRef)}
.hass=${this.hass}
@@ -691,7 +694,7 @@ export class FrigateCardLiveProvider extends LitElement {
}
}
@customElement('frigate-card-live-frigate')
@customElement('frigate-card-live-ha')
export class FrigateCardLiveFrigate extends LitElement {
@property({ attribute: false })
protected hass?: HomeAssistant & ExtendedHomeAssistant;
@@ -763,12 +766,12 @@ export class FrigateCardLiveFrigate extends LitElement {
}
}
// Create a wrapper for the WebRTC element
// Create a wrapper for AlexxIT's WebRTC card
// - https://github.com/AlexxIT/WebRTC
@customElement('frigate-card-live-webrtc')
export class FrigateCardLiveWebRTC extends LitElement {
@customElement('frigate-card-live-webrtc-card')
export class FrigateCardLiveWebRTCCard extends LitElement {
@property({ attribute: false, hasChanged: contentsChanged })
protected webRTCConfig?: WebRTCConfig;
protected webRTCConfig?: WebRTCCardConfig;
@property({ attribute: false })
protected cameraConfig?: CameraConfig;
@@ -776,7 +779,7 @@ export class FrigateCardLiveWebRTC extends LitElement {
protected hass?: HomeAssistant & ExtendedHomeAssistant;
// A task to await the load of the WebRTC component.
protected _webrtcTask = new Task(this, this._getWebRTCElement, () => [1]);
protected _webrtcTask = new Task(this, this._getWebRTCCardElement, () => [1]);
/**
* Play the video.
@@ -826,7 +829,9 @@ export class FrigateCardLiveWebRTC extends LitElement {
return this.renderRoot?.querySelector('#video') as HTMLVideoElement | null;
}
protected async _getWebRTCElement(): Promise<CustomElementConstructor | undefined> {
protected async _getWebRTCCardElement(): Promise<
CustomElementConstructor | undefined
> {
await customElements.whenDefined('webrtc-camera');
return customElements.get('webrtc-camera');
}
@@ -848,10 +853,10 @@ export class FrigateCardLiveWebRTC extends LitElement {
// then take values from the camera configuration instead (if there are
// any).
if (!config.url) {
config.url = this.cameraConfig?.webrtc?.url;
config.url = this.cameraConfig?.webrtc_card?.url;
}
if (!config.entity) {
config.entity = this.cameraConfig?.webrtc?.entity;
config.entity = this.cameraConfig?.webrtc_card?.entity;
}
webrtc.setConfig(config);
webrtc.hass = this.hass;
@@ -874,7 +879,7 @@ export class FrigateCardLiveWebRTC extends LitElement {
this,
e instanceof FrigateCardError
? (e as FrigateCardError).message
: localize('error.webrtc_reported_error') + ': ' + (e as Error).message,
: localize('error.webrtc_card_reported_error') + ': ' + (e as Error).message,
);
}
return html`${webrtcElement}`;
@@ -884,8 +889,8 @@ export class FrigateCardLiveWebRTC extends LitElement {
// load, but yet still have the card load be followed by the updated()
// lifecycle callback (unlike just using `until`).
return html`${this._webrtcTask.render({
initial: () => renderProgressIndicator(localize('error.webrtc_waiting')),
pending: () => renderProgressIndicator(localize('error.webrtc_waiting')),
initial: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
pending: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
error: (e: unknown) => dispatchErrorMessageEvent(this, (e as Error).message),
complete: () => render(),
})}`;
+94 -7
View File
@@ -7,14 +7,13 @@ import {
CONF_CAMERAS_ARRAY_LABEL,
CONF_CAMERAS_ARRAY_LIVE_PROVIDER,
CONF_CAMERAS_ARRAY_URL,
CONF_CAMERAS_ARRAY_WEBRTC_ENTITY,
CONF_CAMERAS_ARRAY_WEBRTC_URL,
CONF_CAMERAS_ARRAY_ZONE,
CONF_EVENT_VIEWER_AUTO_PLAY,
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE,
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE,
CONF_IMAGE_SRC,
CONF_LIVE_PRELOAD,
CONF_LIVE_WEBRTC_CARD,
CONF_MENU,
CONF_MENU_BUTTON_SIZE,
CONF_MENU_MODE,
@@ -142,7 +141,7 @@ const isNotObject = function (value: unknown) {
* @returns A number or undefined.
*/
const toNumberOrIgnore = function (value: unknown) {
return isNaN(value as number) ? undefined : Number(value)
return isNaN(value as number) ? undefined : Number(value);
};
/**
@@ -198,6 +197,86 @@ const upgradeMoveTo = function (
};
};
/**
* Upgrade a property by changing it if it is present.
* @param path The property path.
* @param transform A callback that transforms the old value to the new value,
* if undefined is returned the property is removed.
* @returns `true` if the configuration was modified.
*/
const upgradeChangeIfPresent = function (
path: string,
transform: (valueIn: unknown) => unknown,
): (obj: RawFrigateCardConfig) => boolean {
return function (obj: RawFrigateCardConfig): boolean {
const oldValue = getConfigValue(obj, path);
if (oldValue !== undefined) {
const newValue = transform(oldValue);
if (newValue === undefined) {
deleteConfigValue(obj, path);
return true;
} else if (newValue !== oldValue) {
setConfigValue(obj, path, newValue);
return true;
}
}
return false;
};
};
/**
* Upgrade by moving a property from one location to another, and moving a
* property specified in a top-level overrides object.
* @param oldPath The old property path.
* @param newPath The new property path.
* @param transform An optional transform for the value.
* @returns A function that returns `true` if the configuration was modified.
*/
const upgradeMoveToWithOverrides = function (
oldPath: string,
newPath: string,
transform?: (valueIn: unknown) => unknown,
): (obj: RawFrigateCardConfig) => boolean {
return function (obj: RawFrigateCardConfig): boolean {
let modified = upgradeMoveTo(oldPath, newPath, transform)(obj);
modified =
upgradeArrayValue(
CONF_OVERRIDES,
upgradeMoveTo(oldPath, newPath, transform),
(obj) => obj.overrides as RawFrigateCardConfig | undefined,
)(obj) || modified;
return modified;
};
};
/**
* Given a path to an array, apply an upgrade to each object in the array.
* @param arrayPath The path to the array to upgrade.
* @param upgrade A function that applies an upgrade to an object.
* @param getObject A optional function that takes an item in the array and
* returns the object to modify within it.
* @returns A function that returns `true` if the configuration was modified.
*/
const upgradeArrayValue = function (
arrayPath: string,
upgrade: (obj: RawFrigateCardConfig) => boolean,
getObject?: (obj: RawFrigateCardConfig) => RawFrigateCardConfig | undefined,
): (obj: RawFrigateCardConfig) => boolean {
return function (obj: RawFrigateCardConfig): boolean {
let modified = false;
const array = getConfigValue(obj, arrayPath);
if (Array.isArray(array)) {
array.forEach((item) => {
const object = getObject ? getObject(item) : item;
if (object && typeof object === 'object') {
modified = upgrade(object) || modified;
}
});
}
return modified;
};
};
/**
* Upgrade from a singular camera model to multiple.
* @param key A string key.
@@ -220,8 +299,8 @@ const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) =>
'frigate.label': CONF_CAMERAS_ARRAY_LABEL,
'frigate.url': CONF_CAMERAS_ARRAY_URL,
'frigate.zone': CONF_CAMERAS_ARRAY_ZONE,
'live.webrtc.entity': CONF_CAMERAS_ARRAY_WEBRTC_ENTITY,
'live.webrtc.url': CONF_CAMERAS_ARRAY_WEBRTC_URL,
'live.webrtc.entity': `cameras.#.webrtc.entity`,
'live.webrtc.url': `cameras.#.webrtc.url`,
'live.provider': CONF_CAMERAS_ARRAY_LIVE_PROVIDER,
};
Object.keys(imports).forEach((key) => {
@@ -278,7 +357,7 @@ const UPGRADES = [
upgradeMoveTo('live_provider', 'live.provider'),
upgradeMoveTo('live_preload', CONF_LIVE_PRELOAD),
upgradeMoveTo('webrtc', 'live.webrtc'),
upgradeMoveTo('autoplay_clip', "event_viewer.autoplay_clip"),
upgradeMoveTo('autoplay_clip', 'event_viewer.autoplay_clip'),
upgradeMoveTo('controls.nextprev', CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE),
upgradeMoveTo('controls.nextprev_size', CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE),
upgradeMoveTo('menu_mode', CONF_MENU_MODE),
@@ -289,9 +368,17 @@ const UPGRADES = [
// v2.0.0 -> v2.1.0
upgradeMoveTo('update_entities', CONF_VIEW_UPDATE_ENTITIES),
// v2.1.0 -> v3.0.0
// v2.1.0 -> v3.0.0-rc.1
upgradeToMultipleCameras(),
updateMenuConditionToMenuOverride(),
upgradeMoveTo('view.timeout', CONF_VIEW_TIMEOUT_SECONDS, toNumberOrIgnore),
upgradeMoveTo('event_viewer.autoplay_clip', CONF_EVENT_VIEWER_AUTO_PLAY),
// v3.0.0-rc.1 -> v3.0.0-rc.2
upgradeArrayValue(
CONF_CAMERAS,
upgradeChangeIfPresent('live_provider', (val) => (val === 'frigate' ? 'ha' : val)),
),
upgradeArrayValue(CONF_CAMERAS, upgradeMoveTo('webrtc', 'webrtc_card')),
upgradeMoveToWithOverrides('live.webrtc', CONF_LIVE_WEBRTC_CARD),
];
+4 -6
View File
@@ -13,9 +13,9 @@ export const CONF_CAMERAS_ARRAY_ZONE = `${CONF_CAMERAS}.#.zone` as const;
export const CONF_CAMERAS_ARRAY_ID = `${CONF_CAMERAS}.#.id` as const;
export const CONF_CAMERAS_ARRAY_TITLE = `${CONF_CAMERAS}.#.title` as const;
export const CONF_CAMERAS_ARRAY_ICON = `${CONF_CAMERAS}.#.icon` as const;
export const CONF_CAMERAS_ARRAY_WEBRTC_ENTITY =
`${CONF_CAMERAS}.#.webrtc.entity` as const;
export const CONF_CAMERAS_ARRAY_WEBRTC_URL = `${CONF_CAMERAS}.#.webrtc.url` as const;
export const CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY =
`${CONF_CAMERAS}.#.webrtc_card.entity` as const;
export const CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL = `${CONF_CAMERAS}.#.webrtc_card.url` as const;
export const CONF_CAMERAS_ARRAY_LIVE_PROVIDER =
`${CONF_CAMERAS}.#.live_provider` as const;
@@ -73,9 +73,7 @@ export const CONF_LIVE_LAZY_LOAD = `${CONF_LIVE}.lazy_load` as const;
export const CONF_LIVE_LAZY_UNLOAD = `${CONF_LIVE}.lazy_unload` as const;
export const CONF_LIVE_PRELOAD = `${CONF_LIVE}.preload` as const;
export const CONF_LIVE_TRANSITION_EFFECT = `${CONF_LIVE}.transition_effect` as const;
export const CONF_LIVE_WEBRTC = `${CONF_LIVE}.webrtc` as const;
export const CONF_LIVE_WEBRTC_ENTITY = `${CONF_LIVE_WEBRTC}.entity` as const;
export const CONF_LIVE_WEBRTC_URL = `${CONF_LIVE_WEBRTC}.url` as const;
export const CONF_LIVE_WEBRTC_CARD = `${CONF_LIVE}.webrtc_card` as const;
export const CONF_IMAGE = 'image' as const;
export const CONF_IMAGE_REFRESH_SECONDS = `${CONF_IMAGE}.refresh_seconds` as const;
+6 -6
View File
@@ -22,8 +22,8 @@ import {
CONF_CAMERAS_ARRAY_LIVE_PROVIDER,
CONF_CAMERAS_ARRAY_TITLE,
CONF_CAMERAS_ARRAY_URL,
CONF_CAMERAS_ARRAY_WEBRTC_ENTITY,
CONF_CAMERAS_ARRAY_WEBRTC_URL,
CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY,
CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL,
CONF_CAMERAS_ARRAY_ZONE,
CONF_DIMENSIONS_ASPECT_RATIO,
CONF_DIMENSIONS_ASPECT_RATIO_MODE,
@@ -491,9 +491,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
const liveProviders = new Map([
['', ''],
['auto', localize('config.cameras.live_providers.auto')],
['frigate', localize('config.cameras.live_providers.frigate')],
['ha', localize('config.cameras.live_providers.ha')],
['frigate-jsmpeg', localize('config.cameras.live_providers.frigate-jsmpeg')],
['webrtc', localize('config.cameras.live_providers.webrtc')],
['webrtc-card', localize('config.cameras.live_providers.webrtc-card')],
]);
// Make a new config and update the editor with changes on it,
@@ -605,11 +605,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
getArrayConfigPath(CONF_CAMERAS_ARRAY_ID, cameraIndex),
)}
${this._renderDropdown(
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_ENTITY, cameraIndex),
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY, cameraIndex),
cameraEntities,
)}
${this._renderStringInput(
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_URL, cameraIndex),
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL, cameraIndex),
)}
</div>`
: ``}
+7 -7
View File
@@ -22,13 +22,13 @@
"live_provider": "Live view provider for this camera",
"live_providers": {
"auto": "Automatic",
"frigate": "Frigate",
"ha": "Home Assistant (i.e. HLS, LL-HLS, WebRTC native)",
"frigate-jsmpeg": "Frigate JSMpeg",
"webrtc": "WebRTC"
"webrtc-card": "WebRTC Card (i.e. AlexxIT's WebRTC Card)"
},
"webrtc": {
"entity": "WebRTC Camera Entity (Not a Frigate camera)",
"url": "WebRTC Camera URL"
"webrtc_card": {
"entity": "WebRTC Card Camera Entity (Not a Frigate camera)",
"url": "WebRTC Card Camera URL"
},
"zone": "Frigate zone"
},
@@ -210,8 +210,8 @@
"invalid_configuration": "Invalid configuration",
"invalid_configuration_no_hint": "No location hint available (bad or missing type?)",
"upgrade_available": "An automated card configuration upgrade is available, please visit the visual card editor",
"webrtc_reported_error": "WebRTC component reported an error",
"webrtc_waiting": "Waiting for WebRTC Card to load ...",
"webrtc_card_reported_error": "WebRTC card reported an error",
"webrtc_card_waiting": "Waiting for WebRTC card to load ...",
"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",
+6 -6
View File
@@ -53,7 +53,7 @@ const FRIGATE_MENU_MODES = [
'above',
'below',
] as const;
const LIVE_PROVIDERS = ['auto', 'frigate', 'frigate-jsmpeg', 'webrtc'] as const;
const LIVE_PROVIDERS = ['auto', 'ha', 'frigate-jsmpeg', 'webrtc-card'] as const;
export type LiveProvider = typeof LIVE_PROVIDERS[number];
export class FrigateCardError extends Error {}
@@ -281,7 +281,7 @@ export const cameraConfigDefault = {
client_id: 'frigate' as const,
live_provider: 'auto' as const,
};
const webrtcCameraConfigSchema = z.object({
const webrtcCardCameraConfigSchema = z.object({
entity: z.string().optional(),
url: z.string().optional(),
});
@@ -306,7 +306,7 @@ const cameraConfigSchema = z
id: z.string().optional(),
// Camera identifiers for WebRTC.
webrtc: webrtcCameraConfigSchema.optional(),
webrtc_card: webrtcCardCameraConfigSchema.optional(),
})
.default(cameraConfigDefault);
export type CameraConfig = z.infer<typeof cameraConfigSchema>;
@@ -484,8 +484,8 @@ const liveConfigDefault = {
},
};
const webrtcConfigSchema = webrtcCameraConfigSchema.passthrough().optional();
export type WebRTCConfig = z.infer<typeof webrtcConfigSchema>;
const webrtcCardConfigSchema = webrtcCardCameraConfigSchema.passthrough().optional();
export type WebRTCCardConfig = z.infer<typeof webrtcCardConfigSchema>;
const jsmpegConfigSchema = z
.object({
@@ -512,7 +512,7 @@ export type JSMPEGConfig = z.infer<typeof jsmpegConfigSchema>;
const liveOverridableConfigSchema = z
.object({
webrtc: webrtcConfigSchema,
webrtc_card: webrtcCardConfigSchema,
jsmpeg: jsmpegConfigSchema,
controls: z
.object({