Rename DataManager to CameraManager.

This commit is contained in:
Dermot Duffy
2023-01-24 19:36:54 -08:00
parent e0d2dfaa60
commit 39b44863ce
23 changed files with 183 additions and 187 deletions
@@ -1,9 +1,9 @@
import isEqual from 'lodash-es/isEqual';
import orderBy from 'lodash-es/orderBy';
import sortedUniqBy from 'lodash-es/sortedUniqBy';
import { RecordingSegment, RecordingSegments } from '../frigate';
import { DateRange, MemoryRangeSet } from './data-manager-range';
import { DataQuery, QueryResults } from './data-types';
import { RecordingSegment, RecordingSegments } from '../utils/frigate';
import { DateRange, MemoryRangeSet } from './range';
import { DataQuery, QueryResults } from './types';
interface RequestCacheItem<Request, Response> {
request: Request;
@@ -11,14 +11,14 @@ interface RequestCacheItem<Request, Response> {
expires?: Date;
}
interface DataManagerCache<Request, Response> {
interface CameraManagerCache<Request, Response> {
get(request: Request): Response | null;
has(request: Request): boolean;
set(request: Request, response: Response, expiry?: Date): void;
}
export class MemoryRequestCache<Request, Response>
implements DataManagerCache<Request, Response>
implements CameraManagerCache<Request, Response>
{
protected _data: RequestCacheItem<Request, Response>[] = [];
+42
View File
@@ -0,0 +1,42 @@
import { CameraConfig } from '../types';
import { RecordingSegmentsCache } from './cache';
import { CameraManagerEngine } from './engine';
import { FrigateCameraManagerEngine } from './engine-frigate';
import { DataQuery } from './types';
export class CameraManagerEngineFactory {
protected _engines: Map<string, CameraManagerEngine> = new Map();
protected _getOrCreateEngine(engineKey: string): CameraManagerEngine | null {
const cachedEngine = this._engines.get(engineKey);
if (cachedEngine) {
return cachedEngine;
}
let newEngine: CameraManagerEngine | null = null;
switch (engineKey) {
case 'frigate':
newEngine = new FrigateCameraManagerEngine(new RecordingSegmentsCache());
break;
}
if (newEngine) {
this._engines.set(engineKey, newEngine);
}
return newEngine;
}
public getEngineForQuery(
cameras: Map<string, CameraConfig>,
query: DataQuery,
): CameraManagerEngine | null {
const cameraConfig = cameras.get(query.cameraID);
return cameraConfig ? this.getEngineForCamera(cameraConfig) : null;
}
public getEngineForCamera(cameraConfig: CameraConfig): CameraManagerEngine | null {
let engineKey: string | null = null;
if (cameraConfig.frigate.camera_name) {
engineKey = 'frigate';
}
return engineKey ? this._getOrCreateEngine(engineKey) : null;
}
}
@@ -3,11 +3,11 @@ import add from 'date-fns/add';
import endOfHour from 'date-fns/endOfHour';
import getUnixTime from 'date-fns/getUnixTime';
import startOfHour from 'date-fns/startOfHour';
import { CAMERA_BIRDSEYE } from '../../const';
import { CameraConfig, FrigateRecording } from '../../types';
import { MediaQueries, MediaQueriesResults } from '../../view';
import { ViewMedia, ViewMediaClassifier, ViewMediaFactory } from '../../view-media';
import { errorToConsole } from '../basic';
import { CAMERA_BIRDSEYE } from '../const';
import { CameraConfig, FrigateRecording } from '../types';
import { MediaQueries, MediaQueriesResults } from '../view';
import { ViewMedia, ViewMediaClassifier, ViewMediaFactory } from '../view-media';
import { errorToConsole } from '../utils/basic';
import {
getEvents,
getRecordingSegments,
@@ -17,14 +17,14 @@ import {
RecordingSegments,
RecordingSummary,
retainEvent,
} from '../frigate';
import { RecordingSegmentsCache } from './data-manager-cache';
} from '../utils/frigate';
import { RecordingSegmentsCache } from './cache';
import {
DataManagerEngine,
DATA_MANAGER_ENGINE_EVENT_LIMIT_DEFAULT,
} from './data-manager-engine';
import { DataManagerError } from './data-manager-error';
import { DateRange } from './data-manager-range';
CameraManagerEngine,
CAMERA_MANAGER_ENGINE_EVENT_LIMIT_DEFAULT,
} from './engine';
import { CameraManagerError } from './error';
import { DateRange } from './range';
import {
Engine,
EventQuery,
@@ -40,7 +40,7 @@ import {
QueryType,
RecordingQuery,
RecordingSegmentsQuery,
} from './data-types';
} from './types';
const EVENT_REQUEST_CACHE_MAX_AGE_SECONDS = 60;
const RECORDING_SUMMARY_REQUEST_CACHE_MAX_AGE_SECONDS = 60;
@@ -70,7 +70,7 @@ class FrigateQueryResultsClassifier {
}
}
export class FrigateDataManagerEngine implements DataManagerEngine {
export class FrigateCameraManagerEngine implements CameraManagerEngine {
protected _recordingSegmentsCache: RecordingSegmentsCache;
constructor(recordingSegmentsCache: RecordingSegmentsCache) {
@@ -157,7 +157,7 @@ export class FrigateDataManagerEngine implements DataManagerEngine {
await retainEvent(hass, clientID, media.getID(cameraConfig), favorite);
} catch (e) {
errorToConsole(e as Error);
throw new DataManagerError((e as Error).message);
throw new CameraManagerError((e as Error).message);
}
media.setFavorite(favorite);
@@ -183,7 +183,7 @@ export class FrigateDataManagerEngine implements DataManagerEngine {
...(query?.limit && { limit: query.limit }),
...(query?.hasClip && { has_clip: query.hasClip }),
...(query?.hasSnapshot && { has_snapshot: query.hasSnapshot }),
limit: query?.limit ?? DATA_MANAGER_ENGINE_EVENT_LIMIT_DEFAULT,
limit: query?.limit ?? CAMERA_MANAGER_ENGINE_EVENT_LIMIT_DEFAULT,
};
try {
@@ -196,7 +196,7 @@ export class FrigateDataManagerEngine implements DataManagerEngine {
return result;
} catch (e) {
errorToConsole(e as Error);
throw new DataManagerError((e as Error).message, query);
throw new CameraManagerError((e as Error).message, query);
}
}
@@ -222,7 +222,7 @@ export class FrigateDataManagerEngine implements DataManagerEngine {
);
} catch (e) {
errorToConsole(e as Error);
throw new DataManagerError((e as Error).message, query);
throw new CameraManagerError((e as Error).message, query);
}
const recordings: FrigateRecording[] = [];
@@ -295,7 +295,7 @@ export class FrigateDataManagerEngine implements DataManagerEngine {
segments = await getRecordingSegments(hass, request);
} catch (e) {
errorToConsole(e as Error);
throw new DataManagerError((e as Error).message, query);
throw new CameraManagerError((e as Error).message, query);
}
this._recordingSegmentsCache.add(query.cameraID, range, segments);
@@ -1,7 +1,7 @@
import { HomeAssistant } from 'custom-card-helpers';
import { CameraConfig } from '../../types';
import { MediaQueries, MediaQueriesResults } from '../../view';
import { ViewMedia } from '../../view-media';
import { CameraConfig } from '../types';
import { MediaQueries, MediaQueriesResults } from '../view';
import { ViewMedia } from '../view-media';
import {
EventQuery,
PartialEventQuery,
@@ -10,11 +10,11 @@ import {
QueryReturnType,
RecordingQuery,
RecordingSegmentsQuery,
} from './data-types';
} from './types';
export const DATA_MANAGER_ENGINE_EVENT_LIMIT_DEFAULT = 10000;
export const CAMERA_MANAGER_ENGINE_EVENT_LIMIT_DEFAULT = 10000;
export interface DataManagerEngine {
export interface CameraManagerEngine {
generateDefaultEventQuery(
cameraID: string,
cameraConfig: CameraConfig,
+3
View File
@@ -0,0 +1,3 @@
import { FrigateCardError } from '../types';
export class CameraManagerError extends FrigateCardError {}
@@ -1,6 +1,6 @@
import { HomeAssistant } from 'custom-card-helpers';
import { CameraConfig } from '../../types.js';
import { arrayify, setify } from '../basic.js';
import { CameraConfig } from '../types.js';
import { arrayify, setify } from '../utils/basic.js';
import {
DataQuery,
EventQuery,
@@ -18,12 +18,12 @@ import {
RecordingQueryResults,
RecordingSegmentsQuery,
RecordingSegmentsQueryResults,
} from './data-types.js';
} from './types.js';
import orderBy from 'lodash-es/orderBy';
import { DataManagerEngineFactory } from './data-manager-engine-factory.js';
import { ViewMedia } from '../../view-media.js';
import { MediaQueries, MediaQueriesResults } from '../../view.js';
import { MemoryRequestCache } from './data-manager-cache.js';
import { CameraManagerEngineFactory } from './engine-factory.js';
import { ViewMedia } from '../view-media.js';
import { MediaQueries, MediaQueriesResults } from '../view.js';
import { MemoryRequestCache } from './cache.js';
export class QueryClassifier {
public static isEventQuery(query: DataQuery | PartialDataQuery): query is EventQuery {
@@ -61,13 +61,13 @@ export class QueryResultClassifier {
export type RequestCache = MemoryRequestCache<DataQuery, QueryResults>;
export class DataManager {
protected _engineFactory: DataManagerEngineFactory;
export class CameraManager {
protected _engineFactory: CameraManagerEngineFactory;
protected _cameras: Map<string, CameraConfig>;
protected _requestCache: RequestCache;
constructor(
engineFactory: DataManagerEngineFactory,
engineFactory: CameraManagerEngineFactory,
cameras: Map<string, CameraConfig>,
requestCache: RequestCache,
) {
@@ -296,7 +296,7 @@ export class DataManager {
await Promise.all(_queries.map((query) => processQuery(query)));
console.debug(
'Frigate Card DataManager request (Cached:',
'Frigate Card CameraManager request (Cached:',
`${queryCachedCount}/${_queries.length},`,
`Duration: ${(new Date().getTime() - queryStartTime.getTime()) / 1000}s,`,
'Queries:',
@@ -1,5 +1,5 @@
import { FrigateEvents, FrigateRecording } from '../../types';
import { RecordingSegments } from '../frigate';
import { FrigateEvents, FrigateRecording } from '../types';
import { RecordingSegments } from '../utils/frigate';
// ====
// Base
@@ -5,7 +5,7 @@ import endOfDay from 'date-fns/endOfDay';
import endOfMinute from 'date-fns/endOfMinute';
import endOfWeek from 'date-fns/endOfWeek';
import startOfWeek from 'date-fns/startOfWeek';
import { DateRange } from './data-manager-range';
import { DateRange } from './range';
export const convertRangeToCacheFriendlyTimes = (
range: DateRange,
+11 -11
View File
@@ -91,10 +91,10 @@ import { isValidMediaLoadedInfo } from './utils/media-info.js';
import { View } from './view.js';
import pkg from '../package.json';
import { ViewContext } from 'view';
import { DataManager } from './utils/data/data-manager.js';
import { CameraManager } from './camera/manager.js';
import { setLowPerformanceProfile, setPerformanceCSSStyles } from './performance.js';
import { DataManagerEngineFactory } from './utils/data/data-manager-engine-factory.js';
import { RequestCache } from './utils/data/data-manager-cache.js';
import { CameraManagerEngineFactory } from './camera/engine-factory.js';
import { RequestCache } from './camera/cache.js';
/** A note on media callbacks:
*
@@ -205,7 +205,7 @@ export class FrigateCard extends LitElement {
// A cache of resolved media URLs/mimetypes for use in the whole card.
protected _resolvedMediaCache = new ResolvedMediaCache();
protected _dataManager?: DataManager;
protected _cameraManager?: CameraManager;
// The mouse handler may be called continually, throttle it to at most once
// per second for performance reasons.
@@ -1101,8 +1101,8 @@ export class FrigateCard extends LitElement {
*/
protected willUpdate(changedProps: PropertyValues): void {
if (this._cameras && (changedProps.has('_config') || changedProps.has('_cameras'))) {
this._dataManager = new DataManager(
new DataManagerEngineFactory(),
this._cameraManager = new CameraManager(
new CameraManagerEngineFactory(),
this._cameras,
new RequestCache(),
);
@@ -1336,7 +1336,7 @@ export class FrigateCard extends LitElement {
return;
}
const path = this._dataManager?.getMediaDownloadPath(media);
const path = this._cameraManager?.getMediaDownloadPath(media);
if (!path) {
return;
}
@@ -2018,7 +2018,7 @@ export class FrigateCard extends LitElement {
.view=${this._view}
.cameras=${this._cameras}
.galleryConfig=${this._getConfig().event_gallery}
.dataManager=${this._dataManager}
.cameraManager=${this._cameraManager}
.cardWideConfig=${this._cardWideConfig}
>
</frigate-card-gallery>`
@@ -2030,7 +2030,7 @@ export class FrigateCard extends LitElement {
.cameras=${this._cameras}
.viewerConfig=${this._getConfig().media_viewer}
.resolvedMediaCache=${this._resolvedMediaCache}
.dataManager=${this._dataManager}
.cameraManager=${this._cameraManager}
.cardWideConfig=${this._cardWideConfig}
>
</frigate-card-viewer>`
@@ -2041,7 +2041,7 @@ export class FrigateCard extends LitElement {
.view=${this._view}
.cameras=${this._cameras}
.timelineConfig=${this._getConfig().timeline}
.dataManager=${this._dataManager}
.cameraManager=${this._cameraManager}
>
</frigate-card-timeline>`
: ``}
@@ -2062,7 +2062,7 @@ export class FrigateCard extends LitElement {
.conditionState=${this._conditionState}
.liveOverrides=${getOverridesByKey(this._getConfig().overrides, 'live')}
.cameras=${this._cameras}
.dataManager=${this._dataManager}
.cameraManager=${this._cameraManager}
.cardWideConfig=${this._cardWideConfig}
class="${classMap(liveClasses)}"
>
+5 -5
View File
@@ -22,7 +22,7 @@ import {
getFullDependentBrowseMediaQueryParametersOrDispatchError,
} from '../utils/ha/browse-media';
import { changeViewToRecentEventsForCameraAndDependents, changeViewToRecentRecordingForCameraAndDependents } from '../utils/media-to-view.js';
import { DataManager } from '../utils/data/data-manager.js';
import { CameraManager } from '../camera/manager.js';
import { View } from '../view.js';
import { renderProgressIndicator } from './message.js';
import './thumbnail.js';
@@ -54,7 +54,7 @@ export class FrigateCardGallery extends LitElement {
public cameras?: Map<string, CameraConfig>;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
@@ -71,7 +71,7 @@ export class FrigateCardGallery extends LitElement {
// !this.cameras ||
// !this.view.isGalleryView() ||
// !mediaType ||
// !this.dataManager
// !this.cameraManager
// ) {
// return;
// }
@@ -81,7 +81,7 @@ export class FrigateCardGallery extends LitElement {
// changeViewToRecentRecordingForCameraAndDependents(
// this,
// this.hass,
// this.dataManager,
// this.cameraManager,
// this.cameras,
// this.view,
// {
@@ -92,7 +92,7 @@ export class FrigateCardGallery extends LitElement {
// changeViewToRecentEventsForCameraAndDependents(
// this,
// this.hass,
// this.dataManager,
// this.cameraManager,
// this.cameras,
// this.view,
// {
+3 -3
View File
@@ -51,7 +51,7 @@ import '../surround.js';
import { EmblaCarouselPlugins } from '../carousel.js';
import { classMap } from 'lit/directives/class-map.js';
import { updateElementStyleFromMediaLayoutConfig } from '../../utils/media-layout.js';
import { DataManager } from '../../utils/data/data-manager.js';
import { CameraManager } from '../../camera/manager.js';
import { HomeAssistant } from 'custom-card-helpers';
import { dispatchMessageEvent, dispatchErrorMessageEvent } from '../message.js';
import { HassEntity } from 'home-assistant-js-websocket';
@@ -115,7 +115,7 @@ export class FrigateCardLive extends LitElement {
public liveOverrides?: LiveOverrides;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
@@ -231,7 +231,7 @@ export class FrigateCardLive extends LitElement {
.thumbnailConfig=${config.controls.thumbnails}
.timelineConfig=${config.controls.timeline}
.cameras=${this.cameras}
.dataManager=${this.dataManager}
.cameraManager=${this.cameraManager}
.inBackground=${this._inBackground}
@frigate-card:message=${(ev: CustomEvent<Message>) => {
this._renderKey++;
+6 -6
View File
@@ -16,7 +16,7 @@ import {
ThumbnailsControlConfig,
} from '../types.js';
import { contentsChanged, dispatchFrigateCardEvent } from '../utils/basic.js';
import { DataManager } from '../utils/data/data-manager.js';
import { CameraManager } from '../camera/manager.js';
import { View } from '../view.js';
import { ThumbnailCarouselTap } from './thumbnail-carousel.js';
import './surround-basic.js';
@@ -58,7 +58,7 @@ export class FrigateCardSurround extends LitElement {
public cameras?: Map<string, CameraConfig>;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
/**
* Fetch thumbnail media when a target is not specified in the view (e.g. for
@@ -69,7 +69,7 @@ export class FrigateCardSurround extends LitElement {
protected async _fetchMedia(): Promise<void> {
if (
!this.cameras ||
!this.dataManager ||
!this.cameraManager ||
!this.fetchMedia ||
this.inBackground ||
!this.hass ||
@@ -84,7 +84,7 @@ export class FrigateCardSurround extends LitElement {
await changeViewToRecentEventsForCameraAndDependents(
this,
this.hass,
this.dataManager,
this.cameraManager,
this.cameras,
this.view,
{
@@ -156,7 +156,7 @@ export class FrigateCardSurround extends LitElement {
slot=${this.thumbnailConfig.mode}
.hass=${this.hass}
.config=${this.thumbnailConfig}
.dataManager=${this.dataManager}
.cameraManager=${this.cameraManager}
.view=${this.view}
.cameras=${this.cameras}
.selected=${this.view.queryResults?.getSelectedIndex() ?? undefined}
@@ -194,7 +194,7 @@ export class FrigateCardSurround extends LitElement {
.timelineConfig=${this.timelineConfig}
.thumbnailDetails=${this.thumbnailConfig?.show_details}
.thumbnailSize=${this.thumbnailConfig?.size}
.dataManager=${this.dataManager}
.cameraManager=${this.cameraManager}
>
</frigate-card-timeline-core>`
: ''}
+3 -3
View File
@@ -24,7 +24,7 @@ import { FrigateCardCarousel } from './carousel.js';
import './thumbnail.js';
import './carousel.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { DataManager } from '../utils/data/data-manager.js';
import { CameraManager } from '../camera/manager.js';
export interface ThumbnailCarouselTap {
queryResults: MediaQueriesResults;
@@ -42,7 +42,7 @@ export class FrigateCardThumbnailCarousel extends LitElement {
public cameras?: Map<string, CameraConfig>;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
protected _refCarousel: Ref<FrigateCardCarousel> = createRef();
@@ -161,7 +161,7 @@ export class FrigateCardThumbnailCarousel extends LitElement {
return html` <frigate-card-thumbnail
class="${classMap(classes)}"
.dataManager=${this.dataManager}
.cameraManager=${this.cameraManager}
.hass=${this.hass}
.media=${media}
.cameraConfig=${cameraConfig}
+4 -4
View File
@@ -19,7 +19,7 @@ import { TaskStatus } from '@lit-labs/task';
import type { CameraConfig, ExtendedHomeAssistant } from '../types.js';
import { ViewMedia } from '../view-media.js';
import { DataManager } from '../utils/data/data-manager.js';
import { CameraManager } from '../camera/manager.js';
// The minimum width of a thumbnail with details enabled.
export const THUMBNAIL_DETAILS_WIDTH_MIN = 300;
@@ -221,9 +221,9 @@ export class FrigateCardThumbnail extends LitElement {
@property({ attribute: false })
public hass?: ExtendedHomeAssistant;
// DataManager used for marking media as favorite.
// CameraManager used for marking media as favorite.
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
@property({ attribute: true })
public media?: ViewMedia;
@@ -296,7 +296,7 @@ export class FrigateCardThumbnail extends LitElement {
@click=${(ev: Event) => {
stopEventFromActivatingCardWideActions(ev);
if (this.hass && this.cameraConfig && this.media) {
this.dataManager?.favoriteMedia(
this.cameraManager?.favoriteMedia(
this.hass,
this.cameraConfig,
this.media,
+22 -22
View File
@@ -49,13 +49,13 @@ import {
createViewForRecordings,
generateMediaViewerContext,
} from '../utils/media-to-view';
import { DataManager } from '../utils/data/data-manager';
import { CameraManager } from '../camera/manager';
import { EventMediaQueries, MediaQueries, View } from '../view';
import { dispatchMessageEvent } from './message.js';
import './thumbnail.js';
import { FrigateCardTimelineItem, TimelineDataSource } from '../utils/timeline-source';
import { ViewMedia, ViewMediaClassifier } from '../view-media';
import { rangesOverlap } from '../utils/data/data-manager-range';
import { rangesOverlap } from '../camera/range';
interface FrigateCardGroupData {
id: string;
@@ -89,7 +89,7 @@ declare module 'view' {
interface ThumbnailDataRequest {
item: IdType;
hass?: ExtendedHomeAssistant;
dataManager?: DataManager;
cameraManager?: CameraManager;
cameraConfig?: CameraConfig;
media?: ViewMedia;
view?: View;
@@ -142,7 +142,7 @@ export class FrigateCardTimelineThumbnail extends LitElement {
if (
!dataRequest.hass ||
!dataRequest.dataManager ||
!dataRequest.cameraManager ||
!dataRequest.cameraConfig ||
!dataRequest.media ||
!dataRequest.view
@@ -152,7 +152,7 @@ export class FrigateCardTimelineThumbnail extends LitElement {
return html` <frigate-card-thumbnail
.hass=${dataRequest.hass}
.dataManager=${dataRequest.dataManager}
.cameraManager=${dataRequest.cameraManager}
.cameraConfig=${dataRequest.cameraConfig}
.media=${dataRequest.media}
.view=${dataRequest.view}
@@ -188,7 +188,7 @@ export class FrigateCardTimelineCore extends LitElement {
public mini = false;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
@state()
protected _locked = false;
@@ -245,7 +245,7 @@ export class FrigateCardTimelineCore extends LitElement {
request.detail.cameraConfig = media
? this.cameras?.get(media.getCameraID())
: undefined;
request.detail.dataManager = this.dataManager;
request.detail.cameraManager = this.cameraManager;
request.detail.media = media;
request.detail.view = this.view;
}
@@ -392,7 +392,7 @@ export class FrigateCardTimelineCore extends LitElement {
!this._timeline ||
!this.view ||
// !this.view.target?.length ||
!this.dataManager
!this.cameraManager
) {
return;
}
@@ -401,7 +401,7 @@ export class FrigateCardTimelineCore extends LitElement {
// const canSeek = !!this.view?.isViewerView();
// const context = canSeek
// ? generateMediaViewerContextForChildren(
// this.dataManager,
// this.cameraManager,
// this.view.target,
// targetTime,
// )
@@ -453,7 +453,7 @@ export class FrigateCardTimelineCore extends LitElement {
!this._timeline ||
!this.cameras ||
!this.view ||
!this.dataManager ||
!this.cameraManager ||
!properties.what
) {
return;
@@ -467,7 +467,7 @@ export class FrigateCardTimelineCore extends LitElement {
) {
viewPromise = createViewForRecordings(
this.hass,
this.dataManager,
this.cameraManager,
this.cameras,
this.view,
{
@@ -483,7 +483,7 @@ export class FrigateCardTimelineCore extends LitElement {
} else if (this.timelineConfig?.show_recordings && properties.what === 'axis') {
viewPromise = createViewForRecordings(
this.hass,
this.dataManager,
this.cameraManager,
this.cameras,
this.view,
{
@@ -499,7 +499,7 @@ export class FrigateCardTimelineCore extends LitElement {
this.view.query?.areRecordingQueries()
) {
viewPromise = (async (): Promise<View | null> => {
if (!properties.item || !this.dataManager || !this.hass) {
if (!properties.item || !this.cameraManager || !this.hass) {
return null;
}
const view = await this._createViewWithEventMediaQuery(
@@ -518,7 +518,7 @@ export class FrigateCardTimelineCore extends LitElement {
view.mergeInContext(
await generateMediaViewerContext(
this.hass,
this.dataManager,
this.cameraManager,
results,
properties.time,
),
@@ -645,12 +645,12 @@ export class FrigateCardTimelineCore extends LitElement {
noSetWindow?: boolean;
},
): Promise<View | null> {
if (!this.hass || !this.dataManager || !this.cameras || !this.view || !query) {
if (!this.hass || !this.cameraManager || !this.cameras || !this.view || !query) {
return null;
}
const view = await createViewForEvents(
this.hass,
this.dataManager,
this.cameraManager,
this.cameras,
this.view,
{
@@ -983,11 +983,11 @@ export class FrigateCardTimelineCore extends LitElement {
protected _alreadyHasAcceptableMediaQuery(freshMediaQuery: MediaQueries): boolean {
return (
!!this.dataManager &&
!!this.cameraManager &&
!!this.view?.query &&
!!this.view.queryResults &&
freshMediaQuery.isEqual(this.view.query) &&
this.dataManager.areMediaQueriesResultsFresh(
this.cameraManager.areMediaQueriesResultsFresh(
this.view.query,
this.view.queryResults,
)
@@ -1033,13 +1033,13 @@ export class FrigateCardTimelineCore extends LitElement {
}
if (
changedProps.has('dataManager') ||
changedProps.has('cameraManager') ||
changedProps.has('cameras') ||
changedProps.has('timelineConfig')
) {
if (this.dataManager && this.cameras && this.timelineConfig) {
if (this.cameraManager && this.cameras && this.timelineConfig) {
this._timelineSource = new TimelineDataSource(
this.dataManager,
this.cameraManager,
this._getTimelineCameraIDs(),
this.timelineConfig.media,
);
@@ -1069,7 +1069,7 @@ export class FrigateCardTimelineCore extends LitElement {
protected updated(changedProperties: PropertyValues): void {
super.updated(changedProperties);
if (changedProperties.has('cameras') || changedProperties.has('dataManager')) {
if (changedProperties.has('cameras') || changedProperties.has('cameraManager')) {
this._destroy();
}
+3 -3
View File
@@ -2,7 +2,7 @@ import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit
import { customElement, property } from 'lit/decorators.js';
import timelineStyle from '../scss/timeline.scss';
import { CameraConfig, ExtendedHomeAssistant, TimelineConfig } from '../types';
import { DataManager } from '../utils/data/data-manager';
import { CameraManager } from '../camera/manager';
import { View } from '../view';
import './surround.js';
import './timeline-core.js';
@@ -27,7 +27,7 @@ export class FrigateCardTimeline extends LitElement {
public timelineConfig?: TimelineConfig;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
/**
* Master render method.
@@ -51,7 +51,7 @@ export class FrigateCardTimeline extends LitElement {
.timelineConfig=${this.timelineConfig}
.thumbnailDetails=${this.timelineConfig.controls.thumbnails.show_details}
.thumbnailSize=${this.timelineConfig.controls.thumbnails.size}
.dataManager=${this.dataManager}
.cameraManager=${this.cameraManager}
>
</frigate-card-timeline-core>
</frigate-card-surround>`;
+6 -6
View File
@@ -46,7 +46,7 @@ import '../patches/ha-hls-player';
import './surround.js';
import { renderTask } from '../utils/task.js';
import { updateElementStyleFromMediaLayoutConfig } from '../utils/media-layout.js';
import { DataManager } from '../utils/data/data-manager.js';
import { CameraManager } from '../camera/manager.js';
import {
changeViewToRecentEventsForCameraAndDependents,
changeViewToRecentRecordingForCameraAndDependents,
@@ -92,7 +92,7 @@ export class FrigateCardViewer extends LitElement {
public resolvedMediaCache?: ResolvedMediaCache;
@property({ attribute: false })
public dataManager?: DataManager;
public cameraManager?: CameraManager;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
@@ -107,7 +107,7 @@ export class FrigateCardViewer extends LitElement {
!this.view ||
!this.cameras ||
!this.viewerConfig ||
!this.dataManager
!this.cameraManager
) {
return;
}
@@ -134,7 +134,7 @@ export class FrigateCardViewer extends LitElement {
changeViewToRecentRecordingForCameraAndDependents(
this,
this.hass,
this.dataManager,
this.cameraManager,
this.cameras,
this.view,
{
@@ -145,7 +145,7 @@ export class FrigateCardViewer extends LitElement {
changeViewToRecentEventsForCameraAndDependents(
this,
this.hass,
this.dataManager,
this.cameraManager,
this.cameras,
this.view,
{
@@ -161,7 +161,7 @@ export class FrigateCardViewer extends LitElement {
.view=${this.view}
.thumbnailConfig=${this.viewerConfig.controls.thumbnails}
.timelineConfig=${this.viewerConfig.controls.timeline}
.dataManager=${this.dataManager}
.cameraManager=${this.cameraManager}
.cameras=${this.cameras}
>
<frigate-card-viewer-carousel
@@ -1,42 +0,0 @@
import { CameraConfig } from '../../types';
import { RecordingSegmentsCache } from './data-manager-cache';
import { DataManagerEngine } from './data-manager-engine';
import { FrigateDataManagerEngine } from './data-manager-engine-frigate';
import { DataQuery } from './data-types';
export class DataManagerEngineFactory {
protected _engines: Map<string, DataManagerEngine> = new Map();
protected _getOrCreateEngine(engineKey: string): DataManagerEngine | null {
const cachedEngine = this._engines.get(engineKey);
if (cachedEngine) {
return cachedEngine;
}
let newEngine: DataManagerEngine | null = null;
switch (engineKey) {
case 'frigate':
newEngine = new FrigateDataManagerEngine(new RecordingSegmentsCache());
break;
}
if (newEngine) {
this._engines.set(engineKey, newEngine);
}
return newEngine;
}
public getEngineForQuery(
cameras: Map<string, CameraConfig>,
query: DataQuery,
): DataManagerEngine | null {
const cameraConfig = cameras.get(query.cameraID);
return cameraConfig ? this.getEngineForCamera(cameraConfig) : null;
}
public getEngineForCamera(cameraConfig: CameraConfig): DataManagerEngine | null {
let engineKey: string | null = null;
if (cameraConfig.frigate.camera_name) {
engineKey = 'frigate';
}
return engineKey ? this._getOrCreateEngine(engineKey) : null;
}
}
-3
View File
@@ -1,3 +0,0 @@
import { FrigateCardError } from '../../types';
export class DataManagerError extends FrigateCardError {}
+18 -18
View File
@@ -6,7 +6,7 @@ import { ViewContext } from 'view';
import { CameraConfig, ClipsOrSnapshotsOrAll, FrigateCardView } from '../types';
import { EventMediaQueries, RecordingMediaQueries, View } from '../view';
import { RecordingSegments } from './frigate';
import { DataManager } from './data/data-manager';
import { CameraManager } from '../camera/manager';
import { getAllDependentCameras } from './camera.js';
import { ViewMedia, ViewMediaClassifier } from '../view-media';
import { HomeAssistant } from 'custom-card-helpers';
@@ -14,7 +14,7 @@ import { HomeAssistant } from 'custom-card-helpers';
export const changeViewToRecentEventsForCameraAndDependents = async (
element: HTMLElement,
hass: HomeAssistant,
dataManager: DataManager,
cameraManager: CameraManager,
cameras: Map<string, CameraConfig>,
view: View,
options?: {
@@ -23,7 +23,7 @@ export const changeViewToRecentEventsForCameraAndDependents = async (
},
): Promise<void> => {
(
await createViewForEvents(hass, dataManager, cameras, view, {
await createViewForEvents(hass, cameraManager, cameras, view, {
...options,
limit: 50, // Capture the 50 most recent events.
})
@@ -32,7 +32,7 @@ export const changeViewToRecentEventsForCameraAndDependents = async (
export const createViewForEvents = async (
hass: HomeAssistant,
dataManager: DataManager,
cameraManager: CameraManager,
cameras: Map<string, CameraConfig>,
view: View,
options?: {
@@ -51,7 +51,7 @@ export const createViewForEvents = async (
? options.cameraIDs
: new Set(getAllDependentCameras(cameras, view.camera));
const queries = dataManager.generateDefaultEventQueries(cameraIDs, {
const queries = cameraManager.generateDefaultEventQueries(cameraIDs, {
...(options?.limit && { limit: options.limit }),
...((!options?.mediaType || ['clips', 'all'].includes(options.mediaType)) && {
hasClip: true,
@@ -60,7 +60,7 @@ export const createViewForEvents = async (
});
query = new EventMediaQueries(queries);
}
const queryResults = await dataManager.executeMediaQuery(hass, query);
const queryResults = await cameraManager.executeMediaQuery(hass, query);
return view?.evolve({
view: options?.targetView,
@@ -73,7 +73,7 @@ export const createViewForEvents = async (
* Change the view to a recent recording.
* @param element The element to dispatch the view change from.
* @param hass The Home Assistant object.
* @param dataManager The datamanager to use for data access.
* @param cameraManager The datamanager to use for data access.
* @param cameras The camera configurations.
* @param view The current view.
* @param options A set of cameraIDs to fetch recordings for, and a targetView to dispatch to.
@@ -81,7 +81,7 @@ export const createViewForEvents = async (
export const changeViewToRecentRecordingForCameraAndDependents = async (
element: HTMLElement,
hass: HomeAssistant,
dataManager: DataManager,
cameraManager: CameraManager,
cameras: Map<string, CameraConfig>,
view: View,
options?: {
@@ -90,7 +90,7 @@ export const changeViewToRecentRecordingForCameraAndDependents = async (
): Promise<void> => {
const now = new Date();
(
await createViewForRecordings(hass, dataManager, cameras, view, {
await createViewForRecordings(hass, cameraManager, cameras, view, {
...options,
// Fetch 7 days worth of recordings (including recordings that are for the
// current hour).
@@ -103,7 +103,7 @@ export const changeViewToRecentRecordingForCameraAndDependents = async (
/**
* Create a view for recordings.
* @param hass The Home Assistant object.
* @param dataManager The datamanager to use for data access.
* @param cameraManager The datamanager to use for data access.
* @param cameras The camera configurations.
* @param view The current view.
* @param options A specific window (start and end) to fetch recordings for, a
@@ -112,7 +112,7 @@ export const changeViewToRecentRecordingForCameraAndDependents = async (
*/
export const createViewForRecordings = async (
hass: HomeAssistant,
dataManager: DataManager,
cameraManager: CameraManager,
cameras: Map<string, CameraConfig>,
view: View,
options?: {
@@ -127,13 +127,13 @@ export const createViewForRecordings = async (
? options.cameraIDs
: new Set(getAllDependentCameras(cameras, view.camera));
const queries = dataManager.generateDefaultRecordingQueries(cameraIDs, {
const queries = cameraManager.generateDefaultRecordingQueries(cameraIDs, {
...(options?.start && { start: options.start }),
...(options?.end && { end: options.end }),
});
const query = new RecordingMediaQueries(queries);
const queryResults = await dataManager.executeMediaQuery(hass, query);
const queryResults = await cameraManager.executeMediaQuery(hass, query);
let viewerContext: ViewContext | undefined = {};
const mediaArray = queryResults?.getResults();
@@ -143,7 +143,7 @@ export const createViewForRecordings = async (
);
viewerContext = await generateMediaViewerContext(
hass,
dataManager,
cameraManager,
mediaArray,
options.targetTime,
);
@@ -164,14 +164,14 @@ export const createViewForRecordings = async (
* Generate the media view context for a set of media children (used to set
* seek times into each media item).
* @param hass The Home Assistant object.
* @param dataManager The datamanager to use for data access.
* @param cameraManager The datamanager to use for data access.
* @param media The media.
* @param targetTime The target time.
* @returns The ViewContext.
*/
export const generateMediaViewerContext = async (
hass: HomeAssistant,
dataManager: DataManager,
cameraManager: CameraManager,
media: ViewMedia[],
targetTime: Date,
): Promise<ViewContext> => {
@@ -188,14 +188,14 @@ export const generateMediaViewerContext = async (
let seekSeconds: number | null = null;
if (targetTime >= start && targetTime <= end) {
const query = dataManager.generateDefaultRecordingSegmentsQueries(
const query = cameraManager.generateDefaultRecordingSegmentsQueries(
child.getCameraID(),
{
start: start,
end: end,
},
)[0];
const segments = (await dataManager.getRecordingSegments(hass, query)).get(query);
const segments = (await cameraManager.getRecordingSegments(hass, query)).get(query);
if (segments) {
seekSeconds = getSeekTimeInSegments(
+11 -15
View File
@@ -4,17 +4,13 @@ import sub from 'date-fns/sub';
import { DataSet } from 'vis-data';
import { IdType, TimelineItem, TimelineWindow } from 'vis-timeline/esnext';
import { CameraConfig, ClipsOrSnapshotsOrAll } from '../types';
import { DataManager } from './data/data-manager';
import { EventQuery } from './data/data-types';
import { CameraManager } from '../camera/manager';
import { EventQuery } from '../camera/types';
import { RecordingSegment, RecordingSegments } from './frigate';
import { capEndDate, convertRangeToCacheFriendlyTimes } from './data/data-manager-util';
import { capEndDate, convertRangeToCacheFriendlyTimes } from '../camera/util';
import { EventMediaQueries } from '../view';
import { ViewMedia } from '../view-media';
import {
compressRanges,
ExpiringMemoryRangeSet,
MemoryRangeSet,
} from './data/data-manager-range';
import { compressRanges, ExpiringMemoryRangeSet, MemoryRangeSet } from '../camera/range';
import { ModifyInterface } from './basic';
// Allow timeline freshness to be at least this number of seconds out of date
@@ -36,7 +32,7 @@ export interface FrigateCardTimelineItem extends TimelineItem {
}
export class TimelineDataSource {
protected _dataManager: DataManager;
protected _cameraManager: CameraManager;
protected _dataset: DataSet<FrigateCardTimelineItem> = new DataSet();
// The ranges in which recordings have been calculated and added for.
@@ -53,11 +49,11 @@ export class TimelineDataSource {
protected _mediaType: ClipsOrSnapshotsOrAll;
constructor(
dataManager: DataManager,
cameraManager: CameraManager,
cameraIDs: Set<string>,
media: ClipsOrSnapshotsOrAll,
) {
this._dataManager = dataManager;
this._cameraManager = cameraManager;
this._cameraIDs = cameraIDs;
this._mediaType = media;
}
@@ -108,7 +104,7 @@ export class TimelineDataSource {
}
public getTimelineEventQueries(window: TimelineWindow): EventQuery[] {
return this._dataManager.generateDefaultEventQueries(this._cameraIDs, {
return this._cameraManager.generateDefaultEventQueries(this._cameraIDs, {
start: window.start,
end: window.end,
...(this._mediaType === 'clips' && { hasClip: true }),
@@ -137,7 +133,7 @@ export class TimelineDataSource {
this.getTimelineEventQueries(cacheFriendlyWindow),
);
const results = await this._dataManager.executeMediaQuery(hass, query);
const results = await this._cameraManager.executeMediaQuery(hass, query);
for (const media of results?.getResults() ?? []) {
const endTime = media.getEndTime();
const startTime = media.getStartTime();
@@ -222,7 +218,7 @@ export class TimelineDataSource {
endCap: true,
});
const queries = this._dataManager.generateDefaultRecordingSegmentsQueries(
const queries = this._cameraManager.generateDefaultRecordingSegmentsQueries(
this._cameraIDs,
{
start: cacheFriendlyWindow.start,
@@ -230,7 +226,7 @@ export class TimelineDataSource {
},
);
const results = await this._dataManager.getRecordingSegments(hass, queries);
const results = await this._cameraManager.getRecordingSegments(hass, queries);
const newSegments: Map<string, RecordingSegments> = new Map();
for (const [query, result] of results) {
+2 -2
View File
@@ -1,5 +1,5 @@
// Easy:
// - TODO: Search for references to frigate.js and see where it's being called outside of the dataManager. Can I collapse some of those functions in?
// - TODO: Search for references to frigate.js and see where it's being called outside of the cameraManager. Can I collapse some of those functions in?
// - TODO: Refactor thumbnailsControlSchema to all use the shortform for other thumbnail users beyond live.
// - TODO: limit param in recordings should do something
// - TODO: Should be able to set live media to 'all' and have it work.
@@ -36,7 +36,7 @@ import {
FRIGATE_CARD_VIEW_DEFAULT,
} from './types.js';
import { dispatchFrigateCardEvent } from './utils/basic.js';
import { EventQuery, MediaQuery, RecordingQuery } from './utils/data/data-types.js';
import { EventQuery, MediaQuery, RecordingQuery } from './camera/types.js';
import { ViewMedia } from './view-media.js';
export interface ViewEvolveParameters {