diff --git a/src/camera-manager/reolink/camera.ts b/src/camera-manager/reolink/camera.ts index a6ad535d..dd848b10 100644 --- a/src/camera-manager/reolink/camera.ts +++ b/src/camera-manager/reolink/camera.ts @@ -104,9 +104,7 @@ export class ReolinkCamera extends EntityCamera { // and must only be taken from the user config instead. const match = uniqueID - ? String(uniqueID).match( - /^(?[A-Za-z0-9]+)_(?[A-Za-z0-9]+)_/, - ) + ? String(uniqueID).match(/^(?[^_]+)_(?[^_]+)_/) : null; const hostid = match?.groups?.hostid ?? null; diff --git a/tests/camera-manager/reolink/camera.test.ts b/tests/camera-manager/reolink/camera.test.ts index efd54c38..e121c6c3 100644 --- a/tests/camera-manager/reolink/camera.test.ts +++ b/tests/camera-manager/reolink/camera.test.ts @@ -5,8 +5,8 @@ import { ReolinkCamera } from '../../../src/camera-manager/reolink/camera'; import { CameraProxyConfig } from '../../../src/camera-manager/types'; import { ActionsExecutor } from '../../../src/card-controller/actions/types'; import { StateWatcher } from '../../../src/card-controller/hass/state-watcher'; -import { EntityRegistryManagerLive } from '../../../src/ha/registry/entity'; import { DeviceRegistryManager } from '../../../src/ha/registry/device'; +import { EntityRegistryManagerLive } from '../../../src/ha/registry/entity'; import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock'; import { createCameraConfig, @@ -122,6 +122,7 @@ describe('ReolinkCamera', () => { await camera.initialize({ hass: createHASS(), entityRegistryManager, + deviceRegistryManager: mock(), stateWatcher: mock(), }), ).rejects.toThrowError('Could not initialize Reolink camera'); @@ -151,29 +152,6 @@ describe('ReolinkCamera', () => { ).rejects.toThrowError('Could not initialize Reolink camera'); }); - it('successfully with an NVR-connected camera without user-specified channel', async () => { - const config = createCameraConfig({ - camera_entity: 'camera.office_reolink', - }); - const camera = new ReolinkCamera(config, mock()); - const entityRegistryManager = new EntityRegistryManagerMock([ - createRegistryEntity({ - entity_id: 'camera.office_reolink', - unique_id: '9527000HXU4V1VHZ_9527000I7E5F1GYU_main', - platform: 'reolink', - }), - ]); - - await camera.initialize({ - hass: createHASS(), - entityRegistryManager, - deviceRegistryManager: mock(), - stateWatcher: mock(), - }); - - expect(camera.getChannel()).toBe(0); - }); - it('successfully with a directly connected camera', async () => { const config = createCameraConfig({ camera_entity: 'camera.office_reolink', @@ -223,6 +201,75 @@ describe('ReolinkCamera', () => { expect(camera.getChannel()).toBe(3); }); + it('successfully with hyphenated host id', async () => { + const config = createCameraConfig({ + camera_entity: 'camera.office_reolink', + }); + const camera = new ReolinkCamera(config, mock()); + const entityRegistryManager = new EntityRegistryManagerMock([ + createRegistryEntity({ + entity_id: 'camera.office_reolink', + unique_id: 'host-id_7_main', + platform: 'reolink', + }), + ]); + + await camera.initialize({ + hass: createHASS(), + entityRegistryManager, + deviceRegistryManager: mock(), + stateWatcher: mock(), + }); + + expect(camera.getChannel()).toBe(7); + }); + + it('successfully with a default fallback channel', async () => { + const config = createCameraConfig({ + camera_entity: 'camera.office_reolink', + }); + const camera = new ReolinkCamera(config, mock()); + const entityRegistryManager = new EntityRegistryManagerMock([ + createRegistryEntity({ + entity_id: 'camera.office_reolink', + unique_id: 'hostid_channel-uid_main', + platform: 'reolink', + }), + ]); + + await camera.initialize({ + hass: createHASS(), + entityRegistryManager, + deviceRegistryManager: mock(), + stateWatcher: mock(), + }); + + expect(camera.getChannel()).toBe(0); + }); + + it('successfully with colon in host id', async () => { + const config = createCameraConfig({ + camera_entity: 'camera.office_reolink', + }); + const camera = new ReolinkCamera(config, mock()); + const entityRegistryManager = new EntityRegistryManagerMock([ + createRegistryEntity({ + entity_id: 'camera.office_reolink', + unique_id: 'host:id_7_main', + platform: 'reolink', + }), + ]); + + await camera.initialize({ + hass: createHASS(), + entityRegistryManager, + deviceRegistryManager: mock(), + stateWatcher: mock(), + }); + + expect(camera.getChannel()).toBe(7); + }); + describe('should detect channel from configuration URL', () => { it('should return null if device_id is missing', async () => { const config = createCameraConfig({