Files
advanced-camera-card/src/camera-manager/engine-factory.ts
T

115 lines
4.0 KiB
TypeScript

import { HomeAssistant } from '@dermotduffy/custom-card-helpers';
import { CameraConfig } from '../config/types';
import { localize } from '../localize/localize';
import { BrowseMediaManager } from '../utils/ha/browse-media/browse-media-manager';
import { BrowseMedia } from '../utils/ha/browse-media/types';
import { EntityRegistryManager } from '../utils/ha/entity-registry';
import { Entity } from '../utils/ha/entity-registry/types';
import { ResolvedMediaCache } from '../utils/ha/resolved-media';
import { MemoryRequestCache, RecordingSegmentsCache, RequestCache } from './cache';
import { CameraManagerEngine } from './engine';
import { CameraInitializationError } from './error';
import { CameraEventCallback, Engine } from './types';
import { getCameraEntityFromConfig } from './utils/camera-entity-from-config';
export class CameraManagerEngineFactory {
protected _entityRegistryManager: EntityRegistryManager;
protected _resolvedMediaCache: ResolvedMediaCache;
constructor(
entityRegistryManager: EntityRegistryManager,
resolvedMediaCache: ResolvedMediaCache,
) {
this._entityRegistryManager = entityRegistryManager;
this._resolvedMediaCache = resolvedMediaCache;
}
public async createEngine(
engine: Engine,
eventCallback?: CameraEventCallback,
): Promise<CameraManagerEngine> {
let cameraManagerEngine: CameraManagerEngine;
switch (engine) {
case Engine.Generic:
const { GenericCameraManagerEngine } = await import('./generic/engine-generic');
cameraManagerEngine = new GenericCameraManagerEngine(eventCallback);
break;
case Engine.Frigate:
const { FrigateCameraManagerEngine } = await import('./frigate/engine-frigate');
cameraManagerEngine = new FrigateCameraManagerEngine(
new RecordingSegmentsCache(),
new RequestCache(),
eventCallback,
);
break;
case Engine.MotionEye:
const { MotionEyeCameraManagerEngine } = await import(
'./motioneye/engine-motioneye'
);
cameraManagerEngine = new MotionEyeCameraManagerEngine(
new BrowseMediaManager(new MemoryRequestCache<string, BrowseMedia>()),
this._resolvedMediaCache,
new RequestCache(),
eventCallback,
);
}
return cameraManagerEngine;
}
public async getEngineForCamera(
hass: HomeAssistant,
cameraConfig: CameraConfig,
): Promise<Engine | null> {
let engine: Engine | null = null;
if (cameraConfig.engine === 'frigate') {
engine = Engine.Frigate;
} else if (cameraConfig.engine === 'motioneye') {
engine = Engine.MotionEye;
} else if (cameraConfig.engine === 'generic') {
engine = Engine.Generic;
} else {
const cameraEntity = getCameraEntityFromConfig(cameraConfig);
if (cameraEntity) {
let entity: Entity | null;
try {
entity = await this._entityRegistryManager.getEntity(hass, cameraEntity);
} catch (e) {
// If the camera is not in the registry, but is in the HA states it is
// assumed to be a generic camera.
if (hass.states[cameraEntity]) {
return Engine.Generic;
}
// Otherwise, it's probably a typo so throw an exception.
throw new CameraInitializationError(
localize('error.no_camera_entity'),
cameraConfig,
);
}
switch (entity?.platform) {
case 'frigate':
engine = Engine.Frigate;
break;
case 'motioneye':
engine = Engine.MotionEye;
break;
default:
engine = Engine.Generic;
}
} else if (cameraConfig.frigate.camera_name) {
// Frigate technically does not need an entity, if the camera name is
// manually set the camera is assumed to be Frigate.
engine = Engine.Frigate;
} else if (
cameraConfig.webrtc_card?.url ||
(cameraConfig.go2rtc?.url && cameraConfig.go2rtc?.stream)
) {
engine = Engine.Generic;
}
}
return engine;
}
}