Add out-of-the-box Frigate PTZ support.
This commit is contained in:
@@ -216,6 +216,22 @@ export class ActionsManager {
|
||||
.getViewManager()
|
||||
.setViewWithNewDisplayMode(frigateCardAction.display_mode);
|
||||
break;
|
||||
case 'ptz':
|
||||
const cameraID = this._api.getViewManager().getView()?.camera;
|
||||
if (cameraID) {
|
||||
this._api
|
||||
.getCameraManager()
|
||||
.executePTZAction(cameraID, frigateCardAction.ptz_action, {
|
||||
phase: frigateCardAction.ptz_phase,
|
||||
preset: frigateCardAction.ptz_preset,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'show_ptz':
|
||||
this._api
|
||||
.getViewManager()
|
||||
.setViewWithNewContext({ live: { ptzVisible: frigateCardAction.show_ptz } });
|
||||
break;
|
||||
default:
|
||||
console.warn(`Frigate card received unknown card action: ${action}`);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export enum InitializationAspect {
|
||||
|
||||
export class InitializationManager {
|
||||
protected _api: CardInitializerAPI;
|
||||
protected _initializer;
|
||||
protected _initializer: Initializer;
|
||||
|
||||
constructor(api: CardInitializerAPI, initializer?: Initializer) {
|
||||
this._api = api;
|
||||
@@ -21,11 +21,15 @@ export class InitializationManager {
|
||||
}
|
||||
|
||||
public isInitializedMandatory(): boolean {
|
||||
return this._initializer.isInitializedMultiple([
|
||||
InitializationAspect.LANGUAGES,
|
||||
InitializationAspect.SIDE_LOAD_ELEMENTS,
|
||||
InitializationAspect.CAMERAS,
|
||||
]);
|
||||
return (
|
||||
this._initializer.isInitializedMultiple([
|
||||
InitializationAspect.LANGUAGES,
|
||||
InitializationAspect.SIDE_LOAD_ELEMENTS,
|
||||
InitializationAspect.CAMERAS,
|
||||
]) &&
|
||||
// If there's no view, re-initialize (e.g. config changes).
|
||||
this._api.getViewManager().hasView()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +84,6 @@ export class InitializationManager {
|
||||
}
|
||||
}
|
||||
|
||||
this._api.getCardElementManager().update();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ export class MediaPlayerManager {
|
||||
return this._mediaPlayers.length > 0;
|
||||
}
|
||||
|
||||
public async initialize(): Promise<void> {
|
||||
public async initialize(): Promise<boolean> {
|
||||
const hass = this._api.getHASSManager().getHASS();
|
||||
if (!hass) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const isValidMediaPlayer = (entityID: string): boolean => {
|
||||
@@ -66,6 +66,8 @@ export class MediaPlayerManager {
|
||||
const entity = mediaPlayerEntities?.get(entityID);
|
||||
return !entity || !entity.hidden_by;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async stop(mediaPlayer: string): Promise<void> {
|
||||
|
||||
@@ -16,7 +16,7 @@ export class MicrophoneManager {
|
||||
this._api = api;
|
||||
}
|
||||
|
||||
public async connect(): Promise<void> {
|
||||
public async connect(): Promise<boolean> {
|
||||
try {
|
||||
this._stream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: true,
|
||||
@@ -24,15 +24,19 @@ export class MicrophoneManager {
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
errorToConsole(e as Error);
|
||||
|
||||
this._stream = null;
|
||||
this._api.getCardElementManager().update();
|
||||
return false;
|
||||
}
|
||||
this._setMute();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async disconnect(): Promise<void> {
|
||||
this._stream?.getTracks().forEach((track) => track.stop());
|
||||
this._stream = undefined;
|
||||
|
||||
this._stream = undefined;
|
||||
this._api.getCardElementManager().update();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FrigateCardCustomAction, FrigateCardViewAction } from '../config/types';
|
||||
import { createFrigateCardCustomAction } from '../utils/action.js';
|
||||
import { createFrigateCardCameraAction, createFrigateCardSimpleAction } from '../utils/action.js';
|
||||
import { CardQueryStringAPI } from './types';
|
||||
import { ViewManagerSetViewParameters } from './view-manager';
|
||||
|
||||
@@ -139,8 +139,7 @@ export class QueryStringManager {
|
||||
case 'camera_select':
|
||||
case 'live_substream_select':
|
||||
if (value) {
|
||||
customAction = createFrigateCardCustomAction(action, {
|
||||
camera: value,
|
||||
customAction = createFrigateCardCameraAction(action, value, {
|
||||
cardID: cardID,
|
||||
});
|
||||
}
|
||||
@@ -160,7 +159,7 @@ export class QueryStringManager {
|
||||
case 'snapshot':
|
||||
case 'snapshots':
|
||||
case 'timeline':
|
||||
customAction = createFrigateCardCustomAction(action, {
|
||||
customAction = createFrigateCardSimpleAction(action, {
|
||||
cardID: cardID,
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -28,8 +28,14 @@ export class TriggersManager {
|
||||
const now = new Date();
|
||||
let triggerChanges = false;
|
||||
|
||||
const cameras = this._api.getCameraManager().getStore().getVisibleCameras();
|
||||
for (const [cameraID, config] of cameras?.entries()) {
|
||||
const visibleCameraIDs = this._api
|
||||
.getCameraManager()
|
||||
.getStore()
|
||||
.getVisibleCameraIDs();
|
||||
for (const [cameraID, config] of this._api
|
||||
.getCameraManager()
|
||||
.getStore()
|
||||
.getCameraConfigEntries(visibleCameraIDs)) {
|
||||
const triggerEntities = config.triggers.entities;
|
||||
const diffs = getHassDifferences(hass, oldHass, triggerEntities, {
|
||||
stateOnly: true,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ViewContext } from 'view';
|
||||
import { FrigateCardConfig, FrigateCardView, ViewDisplayMode } from '../config/types';
|
||||
import { View } from '../view/view';
|
||||
import { getAllDependentCameras } from '../utils/camera';
|
||||
import { log } from '../utils/debug';
|
||||
import { executeMediaQueryForView } from '../utils/media-to-view';
|
||||
import { CardViewAPI } from './types';
|
||||
@@ -28,6 +27,10 @@ export class ViewManager {
|
||||
return this._view;
|
||||
}
|
||||
|
||||
public hasView(): boolean {
|
||||
return !!this.getView();
|
||||
}
|
||||
|
||||
public setView(view: View): void {
|
||||
this._setView(view);
|
||||
}
|
||||
@@ -255,7 +258,7 @@ export class ViewManager {
|
||||
|
||||
protected _createViewWithNextStream(baseView: View): View {
|
||||
const dependencies = [
|
||||
...getAllDependentCameras(this._api.getCameraManager(), baseView.camera),
|
||||
...this._api.getCameraManager().getStore().getAllDependentCameras(baseView.camera),
|
||||
];
|
||||
if (dependencies.length <= 1) {
|
||||
return baseView.clone();
|
||||
|
||||
Reference in New Issue
Block a user