fix: Ignore startup triggers from cameras without the trigger capability (#2621)
- Closes: #2103
This commit is contained in:
@@ -71,6 +71,13 @@ export class CameraTriggersManager {
|
||||
.getCameraManager()
|
||||
.getStore()
|
||||
.getCameras()) {
|
||||
// A camera without the trigger capability never subscribes to its
|
||||
// configured trigger entities, so its already-on entities must not
|
||||
// synthesize a trigger here either.
|
||||
if (!camera.getCapabilities()?.has('trigger')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const entityID of camera.getConfig().triggers.entities) {
|
||||
if (isTriggeredState(hass?.states[entityID]?.state)) {
|
||||
triggered = true;
|
||||
|
||||
@@ -9,6 +9,7 @@ import { triggersSchema, type TriggersOptions } from '../../src/config/schema/vi
|
||||
import {
|
||||
createCameraConfig,
|
||||
createCameraManager,
|
||||
createCapabilities,
|
||||
createCardAPI,
|
||||
createConfig,
|
||||
createHASS,
|
||||
@@ -1566,6 +1567,90 @@ describe('CameraTriggersManager', () => {
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).not.toBeCalled();
|
||||
expect(api.getViewManager().setViewDefaultWithNewQuery).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should not trigger a camera without the trigger capability', async () => {
|
||||
const api = createTriggerAPI();
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera_1',
|
||||
capabilities: createCapabilities({ trigger: false }),
|
||||
config: createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const hass = createHASS({
|
||||
'binary_sensor.motion': createStateEntity({
|
||||
state: 'on',
|
||||
}),
|
||||
});
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(hass);
|
||||
|
||||
const manager = new CameraTriggersManager(api);
|
||||
const result = await manager.handleInitialCameraTriggers();
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
expect(manager.isTriggered()).toBeFalsy();
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should target the startup action at a camera that has the trigger capability', async () => {
|
||||
const api = createTriggerAPI({
|
||||
config: {
|
||||
actions: {
|
||||
trigger: 'live',
|
||||
},
|
||||
},
|
||||
});
|
||||
vi.mocked(api.getCameraManager().getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'substream',
|
||||
capabilities: createCapabilities({ substream: true, trigger: false }),
|
||||
config: createCameraConfig({
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
cameraID: 'camera_1',
|
||||
config: createCameraConfig({
|
||||
dependencies: {
|
||||
cameras: ['substream'],
|
||||
},
|
||||
triggers: {
|
||||
entities: ['binary_sensor.motion'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const hass = createHASS({
|
||||
'binary_sensor.motion': createStateEntity({
|
||||
state: 'on',
|
||||
}),
|
||||
});
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(hass);
|
||||
|
||||
const manager = new CameraTriggersManager(api);
|
||||
const result = await manager.handleInitialCameraTriggers();
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(manager.getTriggeredCameraIDs()).toEqual(new Set(['camera_1']));
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).toHaveBeenCalledWith({
|
||||
params: {
|
||||
view: 'live',
|
||||
camera: 'camera_1',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should take actions with human interactions when interaction mode is active', async () => {
|
||||
|
||||
@@ -381,6 +381,7 @@ export const createCapabilities = (capabilities?: CapabilitiesRaw): Capabilities
|
||||
recordings: false,
|
||||
seek: false,
|
||||
snapshots: false,
|
||||
trigger: true,
|
||||
...capabilities,
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user