fix: Honor configured home preset / merge presets. (#2553)
- Closes: https://github.com/dermotduffy/advanced-camera-card/issues/2525
This commit is contained in:
committed by
dermotduffy
parent
d833edb65b
commit
5c97e55a56
@@ -21,7 +21,7 @@ import {
|
||||
getGo2RTCMetadataEndpoint,
|
||||
getGo2RTCStreamEndpoint,
|
||||
} from '../utils/go2rtc/endpoint';
|
||||
import { getPTZCapabilitiesFromCameraConfig } from '../utils/ptz';
|
||||
import { getPTZCapabilitiesFromCameraConfig, mergePTZCapabilities } from '../utils/ptz';
|
||||
import { getPTZInfo } from './requests';
|
||||
import {
|
||||
FRIGATE_SEVERITY_MAP,
|
||||
@@ -217,8 +217,7 @@ export class FrigateCamera extends Camera {
|
||||
|
||||
const frigatePTZ = await this._getPTZCapabilities(hass, config);
|
||||
const configPTZ = getPTZCapabilitiesFromCameraConfig(config);
|
||||
const combinedPTZ: PTZCapabilities | null =
|
||||
configPTZ || frigatePTZ ? { ...frigatePTZ, ...configPTZ } : null;
|
||||
const combinedPTZ = mergePTZCapabilities(frigatePTZ, configPTZ);
|
||||
|
||||
const birdseye = isBirdseye(config);
|
||||
return {
|
||||
|
||||
@@ -18,7 +18,7 @@ import type { Camera, CameraInitializationOptions } from '../camera';
|
||||
import { EntityCamera } from '../entity-camera';
|
||||
import { ReolinkInitializationError } from '../error';
|
||||
import type { CameraEndpointsContext, CameraProxyConfig } from '../types';
|
||||
import { getPTZCapabilitiesFromCameraConfig } from '../utils/ptz';
|
||||
import { getPTZCapabilitiesFromCameraConfig, mergePTZCapabilities } from '../utils/ptz';
|
||||
|
||||
// Reolink channels are zero indexed.
|
||||
const REOLINK_DEFAULT_CHANNEL = 0;
|
||||
@@ -194,8 +194,7 @@ export class ReolinkCamera extends EntityCamera {
|
||||
? this._entitiesToCapabilities(hass, this._ptzEntities)
|
||||
: null;
|
||||
|
||||
const combinedPTZ: PTZCapabilities | null =
|
||||
configPTZ || reolinkPTZ ? { ...reolinkPTZ, ...configPTZ } : null;
|
||||
const combinedPTZ = mergePTZCapabilities(reolinkPTZ, configPTZ);
|
||||
|
||||
return {
|
||||
...(await super._getRawCapabilities(hass, options)),
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from '../../types';
|
||||
import type { CameraInitializationOptions } from '../camera';
|
||||
import { EntityCamera } from '../entity-camera';
|
||||
import { getPTZCapabilitiesFromCameraConfig } from '../utils/ptz';
|
||||
import { getPTZCapabilitiesFromCameraConfig, mergePTZCapabilities } from '../utils/ptz';
|
||||
|
||||
interface TPLinkCameraInitializationOptions extends CameraInitializationOptions {
|
||||
entityRegistryManager: EntityRegistryManager;
|
||||
@@ -43,8 +43,7 @@ export class TPLinkCamera extends EntityCamera {
|
||||
? this._entitiesToCapabilities(this._ptzEntities)
|
||||
: null;
|
||||
|
||||
const combinedPTZ: PTZCapabilities | null =
|
||||
configPTZ || tplinkPTZ ? { ...tplinkPTZ, ...configPTZ } : null;
|
||||
const combinedPTZ = mergePTZCapabilities(tplinkPTZ, configPTZ);
|
||||
|
||||
return {
|
||||
...(await super._getRawCapabilities(hass, options)),
|
||||
|
||||
@@ -54,6 +54,32 @@ export const getConfiguredPTZMovementType = (
|
||||
: null;
|
||||
};
|
||||
|
||||
// Combine engine-detected and configured PTZ capabilities. Configured movement
|
||||
// actions override their engine equivalents, but presets from both sources are
|
||||
// kept (configured first) so that configuring a preset does not erase the
|
||||
// auto-detected ones.
|
||||
export const mergePTZCapabilities = (
|
||||
enginePTZ: PTZCapabilities | null,
|
||||
configPTZ: PTZCapabilities | null,
|
||||
): PTZCapabilities | null => {
|
||||
if (!enginePTZ && !configPTZ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const presets = [
|
||||
...(configPTZ?.presets ?? []),
|
||||
...(enginePTZ?.presets ?? []).filter(
|
||||
(preset) => !configPTZ?.presets?.includes(preset),
|
||||
),
|
||||
];
|
||||
|
||||
return {
|
||||
...enginePTZ,
|
||||
...configPTZ,
|
||||
...(presets.length ? { presets } : {}),
|
||||
};
|
||||
};
|
||||
|
||||
export const getPTZCapabilitiesFromCameraConfig = (
|
||||
cameraConfig: CameraConfig,
|
||||
): PTZCapabilities | null => {
|
||||
|
||||
@@ -56,7 +56,18 @@ export class PTZAction extends AdvancedCameraCardAction<PTZActionConfig> {
|
||||
}
|
||||
|
||||
if (!action.ptz_action) {
|
||||
if (ptzCapabilities.presets && ptzCapabilities.presets.length >= 1) {
|
||||
// A configured `home` preset takes precedence over the first
|
||||
// auto-detected preset. Without this, engines that auto-detect presets
|
||||
// (e.g. Reolink) populate `capabilities.presets` from a `select` entity
|
||||
// and the home button always targets `presets[0]`, ignoring the
|
||||
// configured action. See:
|
||||
// https://github.com/dermotduffy/advanced-camera-card/issues/2525
|
||||
if (ptzConfiguration.presets?.['home']) {
|
||||
await api.getCameraManager().executePTZAction(ptzCameraID, 'preset', {
|
||||
phase: action.ptz_phase,
|
||||
preset: 'home',
|
||||
});
|
||||
} else if (ptzCapabilities.presets && ptzCapabilities.presets.length >= 1) {
|
||||
await api.getCameraManager().executePTZAction(ptzCameraID, 'preset', {
|
||||
phase: action.ptz_phase,
|
||||
preset: ptzCapabilities.presets[0],
|
||||
|
||||
Reference in New Issue
Block a user