Dedup same cameras with different zones.
This commit is contained in:
@@ -107,3 +107,34 @@ export const getAllDependentCameras = (
|
||||
}
|
||||
return cameraIDs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the cameraIDs of truly unique cameras (some configured cameras may be
|
||||
* the same Frigate came but with different zone/labels).
|
||||
* @param cameras The full set of cameras.
|
||||
* @param cameraIDs The specific IDs to dedup.
|
||||
*/
|
||||
export const getTrueCameras = (
|
||||
cameras: Map<string, CameraConfig>,
|
||||
cameraIDs: Set<string>,
|
||||
): Set<string> => {
|
||||
const getTrueCameraID = (cameraConfig: CameraConfig): string => {
|
||||
return `${cameraConfig.frigate?.client_id ?? ''}/${
|
||||
cameraConfig.frigate.camera_name ?? ''
|
||||
}`;
|
||||
};
|
||||
|
||||
const output = new Set<string>();
|
||||
const visitedTrueCameras = new Set<string>();
|
||||
cameraIDs.forEach((cameraID: string) => {
|
||||
const cameraConfig = cameras.get(cameraID) ?? null;
|
||||
if (cameraConfig && cameraConfig.frigate.camera_name) {
|
||||
const trueCameraID = getTrueCameraID(cameraConfig);
|
||||
if (!visitedTrueCameras.has(trueCameraID)) {
|
||||
output.add(cameraID);
|
||||
visitedTrueCameras.add(trueCameraID);
|
||||
}
|
||||
}
|
||||
});
|
||||
return output;
|
||||
};
|
||||
|
||||
@@ -183,27 +183,7 @@ export const mergeFrigateBrowseMediaSources = async (
|
||||
}
|
||||
}
|
||||
|
||||
const eventSort = (
|
||||
a: FrigateBrowseMediaSource,
|
||||
b: FrigateBrowseMediaSource,
|
||||
): number => {
|
||||
if (
|
||||
!a.frigate?.event ||
|
||||
(b.frigate?.event && b.frigate.event.start_time > a.frigate.event.start_time)
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (
|
||||
!b.frigate?.event ||
|
||||
(a.frigate?.event && b.frigate.event.start_time < a.frigate.event.start_time)
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
return createEventParentForChildren('Merged events', children.sort(eventSort));
|
||||
return createEventParentForChildren('Merged events', children.sort(sortYoungestToOldest));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -445,3 +425,32 @@ export const createChild = (
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort the timeline items most recent to least recent.
|
||||
* @param a The first item.
|
||||
* @param b The second item.
|
||||
* @returns -1, 0, 1 (standard array sort function configuration).
|
||||
*/
|
||||
export const sortYoungestToOldest = (
|
||||
a: FrigateBrowseMediaSource,
|
||||
b: FrigateBrowseMediaSource,
|
||||
): number => {
|
||||
const a_source = a.frigate?.event ?? a.frigate?.recording;
|
||||
const b_source = b.frigate?.event ?? b.frigate?.recording;
|
||||
|
||||
if (
|
||||
!a_source ||
|
||||
(b_source && b_source.start_time > a_source.start_time)
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (
|
||||
!b_source ||
|
||||
(a_source && b_source.start_time < a_source.start_time)
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
@@ -6,13 +6,13 @@ import { CameraConfig, ExtendedHomeAssistant, FrigateBrowseMediaSource } from '.
|
||||
import { View } from '../view';
|
||||
import { formatDateAndTime, prettifyTitle } from './basic';
|
||||
import { getRecordingMediaContentID } from './frigate';
|
||||
import { createChild, createEventParentForChildren } from './ha/browse-media';
|
||||
import { createChild, createEventParentForChildren, sortYoungestToOldest } from './ha/browse-media';
|
||||
import {
|
||||
RecordingSegmentsItem,
|
||||
sortSegmentsOldestToYoungest,
|
||||
sortOldestToYoungest,
|
||||
TimelineDataManager,
|
||||
} from './timeline-data-manager';
|
||||
import { getAllDependentCameras } from './camera.js';
|
||||
import { getAllDependentCameras, getTrueCameras } from './camera.js';
|
||||
|
||||
/**
|
||||
* Change the view to a recent recording.
|
||||
@@ -132,8 +132,10 @@ const createRecordingChildren = (
|
||||
): FrigateBrowseMediaSource[] => {
|
||||
const children: FrigateBrowseMediaSource[] = [];
|
||||
|
||||
for (const cameraID of cameraIDs) {
|
||||
const config = cameras.get(cameraID);
|
||||
for (const cameraID of getTrueCameras(
|
||||
cameras, cameraIDs
|
||||
)) {
|
||||
const config = cameras.get(cameraID) ?? null;
|
||||
const recordingSummary = dataManager.getRecordingSummaryForCamera(cameraID);
|
||||
if (!config?.frigate.camera_name || !recordingSummary) {
|
||||
continue;
|
||||
@@ -175,7 +177,9 @@ const createRecordingChildren = (
|
||||
}
|
||||
}
|
||||
}
|
||||
return children;
|
||||
// Sort the events by time (to align recordings for different cameras at the
|
||||
// same time).
|
||||
return children.sort(sortYoungestToOldest);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -208,7 +212,7 @@ export const generateMediaViewerContextForChildren = (
|
||||
segment.cameraID === child.frigate?.cameraID &&
|
||||
segment.start >= start &&
|
||||
segment.end <= end,
|
||||
order: sortSegmentsOldestToYoungest,
|
||||
order: sortOldestToYoungest,
|
||||
});
|
||||
seekSeconds = getSeekTimeInSegments(
|
||||
// Recordings start from the top of the hour.
|
||||
|
||||
@@ -49,9 +49,9 @@ export interface RecordingSegmentsItem {
|
||||
* @param b The second item.
|
||||
* @returns -1, 0, 1 (standard array sort function configuration).
|
||||
*/
|
||||
export const sortTimelineItemsYoungestToOldest = (
|
||||
a: FrigateCardTimelineItem,
|
||||
b: FrigateCardTimelineItem,
|
||||
export const sortYoungestToOldest = (
|
||||
a: RecordingSegmentsItem | FrigateCardTimelineItem,
|
||||
b: RecordingSegmentsItem | FrigateCardTimelineItem,
|
||||
): number => {
|
||||
if (a.start < b.start) {
|
||||
return 1;
|
||||
@@ -68,9 +68,9 @@ export const sortTimelineItemsYoungestToOldest = (
|
||||
* @param b The second item.
|
||||
* @returns -1, 0, 1 (standard array sort function configuration).
|
||||
*/
|
||||
export const sortSegmentsOldestToYoungest = (
|
||||
a: RecordingSegmentsItem,
|
||||
b: RecordingSegmentsItem,
|
||||
export const sortOldestToYoungest = (
|
||||
a: RecordingSegmentsItem | FrigateCardTimelineItem,
|
||||
b: RecordingSegmentsItem | FrigateCardTimelineItem,
|
||||
): number => {
|
||||
if (a.start < b.start) {
|
||||
return -1;
|
||||
@@ -438,7 +438,7 @@ export class TimelineDataManager {
|
||||
this._cameras.forEach((_, cameraID) => {
|
||||
const segments = this._recordingSegments.get({
|
||||
filter: (item) => item.cameraID === cameraID,
|
||||
order: sortSegmentsOldestToYoungest,
|
||||
order: sortOldestToYoungest,
|
||||
});
|
||||
let current: RecordingSegmentsItem | null = null;
|
||||
for (let i = 0; i < segments.length; ++i) {
|
||||
|
||||
Reference in New Issue
Block a user