// Room Camera Catalog // Purpose: Loads and normalizes configured room camera entries and emits update events when roster data changes. // Scope: Owns camera identity/url normalization and read-only accessors for room camera metadata. const EventEmitter = require('events'); const logger = require('../../globals/logger').child('roomCameraService'); const { loadConfig } = require('../../helpers/configLoader'); const { getRoomCameraEntries } = require('../../helpers/features'); const events = new EventEmitter(); const config = loadConfig(); const cameraMap = new Map(); function normalizeCamera(camera) { if (!camera) return null; const id = camera.id || camera.name; if (!id) { logger.warn('Room camera missing id', camera); return null; } if (!camera.url && !camera.streamUrl && !camera.mjpegUrl) { logger.warn('Room camera missing url/streamUrl', { id, camera }); return null; } return { id: String(id), name: camera.name || camera.id || String(id), description: camera.description || null, url: camera.url || null, streamUrl: camera.streamUrl || camera.mjpegUrl || null, }; } function getRoomCameras() { return Array.from(cameraMap.values()); } function getRoomCamera(id) { if (!id) return null; return cameraMap.get(String(id)) || null; } function loadFromConfig() { cameraMap.clear(); const list = getRoomCameraEntries(config); list.forEach((camera) => { const normalized = normalizeCamera(camera); if (normalized) cameraMap.set(normalized.id, normalized); }); logger.info('Loaded room cameras', { count: cameraMap.size }); events.emit('update', getRoomCameras()); } module.exports = { loadFromConfig, getRoomCameras, getRoomCamera, roomCameraEvents: events, };