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 { 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()), this._resolvedMediaCache, new RequestCache(), eventCallback, ); } return cameraManagerEngine; } public async getEngineForCamera( hass: HomeAssistant, cameraConfig: CameraConfig, ): Promise { 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; } }