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