Remove the MediaQuery wrapper from the camera manager.
This commit is contained in:
@@ -31,8 +31,6 @@ import {
|
||||
import orderBy from 'lodash-es/orderBy';
|
||||
import { CameraManagerEngineFactory } from './engine-factory.js';
|
||||
import { ViewMedia } from '../view/media.js';
|
||||
import { MediaQueriesResults } from '../view/media-queries-results';
|
||||
import { MediaQueries } from '../view/media-queries.js';
|
||||
import uniqBy from 'lodash-es/uniqBy';
|
||||
import { CameraManagerEngine } from './engine.js';
|
||||
import sum from 'lodash-es/sum';
|
||||
@@ -123,9 +121,7 @@ export class CameraManager {
|
||||
});
|
||||
}
|
||||
|
||||
public async getMediaMetadata(
|
||||
hass: HomeAssistant,
|
||||
): Promise<MediaMetadata | null> {
|
||||
public async getMediaMetadata(hass: HomeAssistant): Promise<MediaMetadata | null> {
|
||||
const what: Set<string> = new Set();
|
||||
const where: Set<string> = new Set();
|
||||
const days: Set<string> = new Set();
|
||||
@@ -148,7 +144,7 @@ export class CameraManager {
|
||||
engineMetadata.days.forEach(days.add, days);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await allPromises(engines, (engine) => processMetadata(engine));
|
||||
|
||||
@@ -159,7 +155,7 @@ export class CameraManager {
|
||||
...(what.size && { what: what }),
|
||||
...(where.size && { where: where }),
|
||||
...(days.size && { days: days }),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected _generateDefaultQueries<PQT extends PartialDataQuery>(
|
||||
@@ -228,25 +224,14 @@ export class CameraManager {
|
||||
return await this._handleQuery(hass, query);
|
||||
}
|
||||
|
||||
public async executeMediaQueries(
|
||||
public async executeMediaQueries<T extends MediaQuery>(
|
||||
hass: HomeAssistant,
|
||||
mediaQueries: MediaQueries,
|
||||
): Promise<MediaQueriesResults | null> {
|
||||
const queries: (RecordingQuery | EventQuery)[] | null = mediaQueries.getQueries();
|
||||
if (!queries) {
|
||||
return null;
|
||||
}
|
||||
const mediaArray = this._convertQueryResultsToMedia(
|
||||
queries: T[],
|
||||
): Promise<ViewMedia[] | null> {
|
||||
return this._convertQueryResultsToMedia(
|
||||
hass,
|
||||
await this._handleQuery(hass, queries),
|
||||
);
|
||||
|
||||
return new MediaQueriesResults(
|
||||
mediaArray,
|
||||
|
||||
// Select the first (most-recent) item.
|
||||
mediaArray.length ? 0 : null,
|
||||
);
|
||||
}
|
||||
|
||||
public async extendMediaQueries<T extends MediaQuery>(
|
||||
@@ -328,9 +313,13 @@ export class CameraManager {
|
||||
}
|
||||
|
||||
return {
|
||||
canFavoriteEvents: engines.some((engine) => engine.getCapabilities()?.canFavoriteEvents),
|
||||
canFavoriteRecordings: engines.some((engine) => engine.getCapabilities()?.canFavoriteRecordings),
|
||||
}
|
||||
canFavoriteEvents: engines.some(
|
||||
(engine) => engine.getCapabilities()?.canFavoriteEvents,
|
||||
),
|
||||
canFavoriteRecordings: engines.some(
|
||||
(engine) => engine.getCapabilities()?.canFavoriteRecordings,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
public getMediaCapabilities(media: ViewMedia): CameraManagerMediaCapabilities | null {
|
||||
@@ -368,18 +357,13 @@ export class CameraManager {
|
||||
}
|
||||
}
|
||||
|
||||
public areMediaQueriesResultsFresh(
|
||||
queries: MediaQueries,
|
||||
results: MediaQueriesResults,
|
||||
public areMediaQueriesResultsFresh<T extends MediaQuery>(
|
||||
queries: T[],
|
||||
resultsTimestamp: Date,
|
||||
): boolean {
|
||||
const now = new Date();
|
||||
const resultsTimestamp = results.getResultsTimestamp();
|
||||
|
||||
if (!resultsTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const query of queries.getQueries() ?? []) {
|
||||
for (const query of queries) {
|
||||
const engines = this._engineFactory.getEnginesForCameraIDs(
|
||||
this._cameras,
|
||||
query.cameraIDs,
|
||||
|
||||
@@ -239,7 +239,6 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
@property({ attribute: false })
|
||||
public hass?: ExtendedHomeAssistant;
|
||||
|
||||
// CameraManager used for marking media as favorite.
|
||||
@property({ attribute: false })
|
||||
public cameraManager?: CameraManager;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import { ViewMedia } from '../view/media';
|
||||
import { ViewMediaClassifier } from '../view/media-classifier';
|
||||
import { rangesOverlap } from '../camera-manager/range';
|
||||
import { View } from '../view/view';
|
||||
import { MediaQuery } from '../camera-manager/types';
|
||||
|
||||
interface FrigateCardGroupData {
|
||||
id: string;
|
||||
@@ -501,11 +502,9 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
targetTime: properties.time,
|
||||
},
|
||||
);
|
||||
} else if (
|
||||
properties.item &&
|
||||
properties.what === 'item'
|
||||
) {
|
||||
const newResults = this.view.queryResults?.clone()
|
||||
} else if (properties.item && properties.what === 'item') {
|
||||
const newResults = this.view.queryResults
|
||||
?.clone()
|
||||
.resetSelectedResult()
|
||||
.selectResultIfFound(
|
||||
(media) => !!this.cameras && media.getID() === properties.item,
|
||||
@@ -972,14 +971,17 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
}
|
||||
|
||||
protected _alreadyHasAcceptableMediaQuery(freshMediaQuery: MediaQueries): boolean {
|
||||
const currentQueries = this.view?.query?.getQueries();
|
||||
const currentResultTimestamp = this.view?.queryResults?.getResultsTimestamp();
|
||||
|
||||
return (
|
||||
!!this.cameraManager &&
|
||||
!!this.view?.query &&
|
||||
!!this.view.queryResults &&
|
||||
freshMediaQuery.isEqual(this.view.query) &&
|
||||
this.cameraManager.areMediaQueriesResultsFresh(
|
||||
this.view.query,
|
||||
this.view.queryResults,
|
||||
!!currentQueries &&
|
||||
!!currentResultTimestamp &&
|
||||
isEqual(currentQueries, freshMediaQuery.getQueries()) &&
|
||||
this.cameraManager.areMediaQueriesResultsFresh<MediaQuery>(
|
||||
currentQueries,
|
||||
currentResultTimestamp,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ export class FrigateCardTimeline extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.view=${this.view}
|
||||
.thumbnailConfig=${this.timelineConfig.controls.thumbnails}
|
||||
.cameraManager=${this.cameraManager}
|
||||
.cameras=${this.cameras}
|
||||
>
|
||||
<frigate-card-timeline-core
|
||||
|
||||
@@ -380,18 +380,23 @@ export class FrigateCardViewerCarousel extends LitElement {
|
||||
const clipQuery = this.view.query.clone();
|
||||
clipQuery.convertToClipsQueries();
|
||||
|
||||
let results: MediaQueriesResults | null;
|
||||
const queries = clipQuery.getQueries();
|
||||
if (!queries) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mediaArray: ViewMedia[] | null;
|
||||
try {
|
||||
results = await this.cameraManager.executeMediaQueries(this.hass, clipQuery);
|
||||
mediaArray = await this.cameraManager.executeMediaQueries(this.hass, queries);
|
||||
} catch (e) {
|
||||
errorToConsole(e as Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!results) {
|
||||
if (!mediaArray) {
|
||||
return;
|
||||
}
|
||||
|
||||
const results = new MediaQueriesResults(mediaArray);
|
||||
results.selectResultIfFound((clipMedia) => clipMedia.getID() === media.getID());
|
||||
if (!results.hasSelectedResult()) {
|
||||
return;
|
||||
|
||||
@@ -15,6 +15,7 @@ import { HomeAssistant } from 'custom-card-helpers';
|
||||
import { dispatchFrigateCardErrorEvent } from '../components/message';
|
||||
import { MediaQueriesResults } from '../view/media-queries-results';
|
||||
import { errorToConsole } from './basic';
|
||||
import { MediaQuery } from '../camera-manager/types';
|
||||
|
||||
export const changeViewToRecentEventsForCameraAndDependents = async (
|
||||
element: HTMLElement,
|
||||
@@ -179,19 +180,29 @@ const executeMediaQueryForView = async (
|
||||
targetTime?: Date;
|
||||
},
|
||||
): Promise<View | null> => {
|
||||
let queryResults: MediaQueriesResults | null;
|
||||
let mediaArray: ViewMedia[] | null;
|
||||
|
||||
const queries = query.getQueries();
|
||||
if (!queries) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
queryResults = await cameraManager.executeMediaQueries(hass, query);
|
||||
mediaArray = await cameraManager.executeMediaQueries<MediaQuery>(hass, queries);
|
||||
} catch (e) {
|
||||
errorToConsole(e as Error);
|
||||
dispatchFrigateCardErrorEvent(element, e as Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!mediaArray) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const queryResults = new MediaQueriesResults(mediaArray);
|
||||
let viewerContext: ViewContext | undefined = {};
|
||||
const mediaArray = queryResults?.getResults();
|
||||
if (queryResults && mediaArray && options?.targetTime && options.cameraIDs) {
|
||||
|
||||
if (options?.targetTime && options.cameraIDs) {
|
||||
queryResults.selectBestResult((media) =>
|
||||
findClosestMediaIndex(media, options.targetTime as Date, options.cameraIDs),
|
||||
);
|
||||
|
||||
@@ -7,9 +7,12 @@ import { ClipsOrSnapshotsOrAll, RecordingSegment } from '../types';
|
||||
import { CameraManager } from '../camera-manager/manager';
|
||||
import { EventQuery } from '../camera-manager/types';
|
||||
import { capEndDate, convertRangeToCacheFriendlyTimes } from '../camera-manager/util';
|
||||
import { EventMediaQueries } from '../view/media-queries';
|
||||
import { ViewMedia } from '../view/media';
|
||||
import { compressRanges, ExpiringMemoryRangeSet, MemoryRangeSet } from '../camera-manager/range';
|
||||
import {
|
||||
compressRanges,
|
||||
ExpiringMemoryRangeSet,
|
||||
MemoryRangeSet,
|
||||
} from '../camera-manager/range';
|
||||
import { errorToConsole, ModifyInterface } from './basic.js';
|
||||
|
||||
// Allow timeline freshness to be at least this number of seconds out of date
|
||||
@@ -132,14 +135,13 @@ export class TimelineDataSource {
|
||||
}
|
||||
|
||||
const cacheFriendlyWindow = this.getCacheFriendlyEventWindow(window);
|
||||
const eventQueries = this.getTimelineEventQueries(cacheFriendlyWindow)
|
||||
const eventQueries = this.getTimelineEventQueries(cacheFriendlyWindow);
|
||||
if (!eventQueries) {
|
||||
return;
|
||||
}
|
||||
const query = new EventMediaQueries(eventQueries);
|
||||
|
||||
const results = await this._cameraManager.executeMediaQueries(hass, query);
|
||||
for (const media of results?.getResults() ?? []) {
|
||||
const mediaArray = await this._cameraManager.executeMediaQueries(hass, eventQueries);
|
||||
for (const media of mediaArray ?? []) {
|
||||
const endTime = media.getEndTime();
|
||||
const startTime = media.getStartTime();
|
||||
const id = media.getID();
|
||||
@@ -234,7 +236,10 @@ export class TimelineDataSource {
|
||||
if (!recordingQueries) {
|
||||
return;
|
||||
}
|
||||
const results = await this._cameraManager.getRecordingSegments(hass, recordingQueries);
|
||||
const results = await this._cameraManager.getRecordingSegments(
|
||||
hass,
|
||||
recordingQueries,
|
||||
);
|
||||
|
||||
const newSegments: Map<string, RecordingSegment[]> = new Map();
|
||||
for (const [query, result] of results) {
|
||||
|
||||
@@ -10,9 +10,7 @@ export class MediaQueriesResults {
|
||||
if (results) {
|
||||
this.setResults(results);
|
||||
}
|
||||
if (selectedIndex !== undefined) {
|
||||
this.selectResult(selectedIndex);
|
||||
}
|
||||
this.selectResult(selectedIndex ?? 0);
|
||||
}
|
||||
|
||||
public clone(): MediaQueriesResults {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import cloneDeep from 'lodash-es/cloneDeep.js';
|
||||
import { EventQuery, MediaQuery, RecordingQuery } from '../camera-manager/types.js';
|
||||
|
||||
@@ -17,10 +16,6 @@ export class MediaQueriesBase<T extends MediaQuery> {
|
||||
return cloneDeep(this);
|
||||
}
|
||||
|
||||
public isEqual(that: MediaQueries): boolean {
|
||||
return isEqual(this.getQueries(), that.getQueries());
|
||||
}
|
||||
|
||||
public getQueries(): T[] | null {
|
||||
return this._queries;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user