diff --git a/docs/configuration/cameras/README.md b/docs/configuration/cameras/README.md index 78c2556e..19b2f83a 100644 --- a/docs/configuration/cameras/README.md +++ b/docs/configuration/cameras/README.md @@ -203,6 +203,11 @@ to allow for precise/smooth controls, and if unavailable will translate multiple `relative` steps with optional delays between each step. Manually configured [actions](../actions/README.md) may be configured to call either variety. +When PTZ actions are manually set in the config, they will replace the +auto-detected actions. For example if `actions_left` is set for a Frigate +camera, it will be used for all `left` PTZ actions even though Frigate cameras +natively support continuous actions (`actions_left_start`, `actions_left_stop`). + ?> Frigate auto-detected PTZ actions will always be `continuous` as this is what the integration currently offers. diff --git a/src/camera-manager/frigate/camera.ts b/src/camera-manager/frigate/camera.ts index 3dd992d6..34012192 100644 --- a/src/camera-manager/frigate/camera.ts +++ b/src/camera-manager/frigate/camera.ts @@ -4,10 +4,7 @@ import { StateWatcherSubscriptionInterface } from '../../card-controller/hass/st import { CameraConfig } from '../../config/types'; import { localize } from '../../localize/localize'; import { PTZCapabilities, PTZMovementType } from '../../types'; -import { - errorToConsole, - recursivelyMergeObjectsConcatenatingArraysUniquely, -} from '../../utils/basic'; +import { errorToConsole } from '../../utils/basic'; import { EntityRegistryManager } from '../../utils/ha/entity-registry'; import { Entity } from '../../utils/ha/entity-registry/types'; import { Camera, CameraInitializationOptions } from '../camera'; @@ -125,13 +122,13 @@ export class FrigateCamera extends Camera { const configPTZCapabilities = getPTZCapabilitiesFromCameraConfig(this.getConfig()); const frigatePTZCapabilities = await this._getPTZCapabilities(hass, config); - const combinedPTZCapabilities = + + const combinedPTZCapabilities: PTZCapabilities | null = configPTZCapabilities || frigatePTZCapabilities - ? recursivelyMergeObjectsConcatenatingArraysUniquely( - {}, - configPTZCapabilities, - frigatePTZCapabilities, - ) + ? { + ...frigatePTZCapabilities, + ...configPTZCapabilities, + } : null; const birdseye = isBirdseye(config); diff --git a/src/camera-manager/utils/ptz.ts b/src/camera-manager/utils/ptz.ts index 78a6ccd0..c7cb3158 100644 --- a/src/camera-manager/utils/ptz.ts +++ b/src/camera-manager/utils/ptz.ts @@ -70,13 +70,15 @@ export const getPTZCapabilitiesFromCameraConfig = ( zoomOut?.length || presets?.length ? { - left: left ?? undefined, - right: right ?? undefined, - up: up ?? undefined, - down: down ?? undefined, - zoomIn: zoomIn ?? undefined, - zoomOut: zoomOut ?? undefined, - presets: presets, + // Only return keys with some capability (to aid with action merging + // later). + ...(left ? { left } : {}), + ...(right ? { right } : {}), + ...(up ? { up } : {}), + ...(down ? { down } : {}), + ...(zoomIn ? { zoomIn } : {}), + ...(zoomOut ? { zoomOut } : {}), + ...(presets ? { presets } : {}), } : null; }; diff --git a/tests/camera-manager/frigate/camera.test.ts b/tests/camera-manager/frigate/camera.test.ts index 3ec504aa..470d0b65 100644 --- a/tests/camera-manager/frigate/camera.test.ts +++ b/tests/camera-manager/frigate/camera.test.ts @@ -210,8 +210,9 @@ describe('FrigateCamera', () => { entityRegistryManager: mock(), stateWatcher: mock(), frigateEventWatcher: mock(), - }), - expect(camera.getCapabilities()?.has('ptz')).toBeFalsy(); + }); + + expect(camera.getCapabilities()?.has('ptz')).toBeFalsy(); expect(camera.getCapabilities()?.hasPTZCapability()).toBeFalsy(); expect(consoleSpy).toBeCalled(); }); diff --git a/tests/camera-manager/utils/ptz.test.ts b/tests/camera-manager/utils/ptz.test.ts index a7bafc34..3e0659be 100644 --- a/tests/camera-manager/utils/ptz.test.ts +++ b/tests/camera-manager/utils/ptz.test.ts @@ -163,11 +163,9 @@ describe('getPTZCapabilitiesFromCameraConfig', () => { }, }), ), - )?.toEqual( - expect.objectContaining({ - [capabilityName]: ['relative'], - }), - ); + )?.toEqual({ + [capabilityName]: ['relative'], + }); }); }); @@ -182,10 +180,8 @@ describe('getPTZCapabilitiesFromCameraConfig', () => { }, }), ), - )?.toEqual( - expect.objectContaining({ - presets: ['window'], - }), - ); + )?.toEqual({ + presets: ['window'], + }); }); }); diff --git a/tests/utils/ptz.test.ts b/tests/utils/ptz.test.ts index de085886..9d3b3ddb 100644 --- a/tests/utils/ptz.test.ts +++ b/tests/utils/ptz.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { Capabilities } from '../../src/camera-manager/capabilities'; import { getPTZTarget,