fix: Stop a released PTZ key ending another held key's movement (#2675)
- Closes: #2668
This commit is contained in:
@@ -19,7 +19,7 @@ import {
|
||||
} from '../utils/action-state';
|
||||
import { AdvancedCameraCardAction } from './base';
|
||||
|
||||
const STEP_DELAY_SECONDS = 0.1;
|
||||
export const STEP_DELAY_SECONDS = 0.1;
|
||||
const STEP_ZOOM = 0.1;
|
||||
export const STEP_PAN = 5;
|
||||
|
||||
@@ -77,6 +77,10 @@ export class PTZDigitalAction extends AdvancedCameraCardAction<PTZDigitialAction
|
||||
this._stopped = false;
|
||||
await replaceInProgressForThisTarget(targetID, this._context, 'ptzDigital', this);
|
||||
|
||||
if (this._stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._stepChange(api, targetID);
|
||||
|
||||
// The steps are repeated only once the first step returns, and only if
|
||||
@@ -87,7 +91,19 @@ export class PTZDigitalAction extends AdvancedCameraCardAction<PTZDigitialAction
|
||||
);
|
||||
}
|
||||
} else if (action.ptz_phase === 'stop') {
|
||||
await clearInProgressForThisTarget(targetID, this._context, 'ptzDigital');
|
||||
// A stop only stops the movement it names, as another movement may have
|
||||
// replaced the one this stop was issued for. An undefined ptz_action
|
||||
// stops any movement.
|
||||
await clearInProgressForThisTarget(
|
||||
targetID,
|
||||
this._context,
|
||||
'ptzDigital',
|
||||
action.ptz_action
|
||||
? (incumbent) =>
|
||||
incumbent instanceof PTZDigitalAction &&
|
||||
incumbent._getAction().ptz_action === action.ptz_action
|
||||
: undefined,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,10 +114,21 @@ export class PTZAction extends AdvancedCameraCardAction<PTZActionConfig> {
|
||||
}
|
||||
};
|
||||
|
||||
await singleStep();
|
||||
if (!this._stopped) {
|
||||
await singleStep();
|
||||
}
|
||||
} else if (action.ptz_phase === 'stop') {
|
||||
// Scenario: Asked to stop continuous move, camera only supports relative moves natively.
|
||||
await clearInProgressForThisTarget(ptzCameraID, this._context, 'ptz');
|
||||
// A stop only stops the movement it names, as another movement may have
|
||||
// replaced the one this stop was issued for.
|
||||
await clearInProgressForThisTarget(
|
||||
ptzCameraID,
|
||||
this._context,
|
||||
'ptz',
|
||||
(incumbent) =>
|
||||
incumbent instanceof PTZAction &&
|
||||
incumbent._getAction().ptz_action === action.ptz_action,
|
||||
);
|
||||
} else {
|
||||
this._stopped = false;
|
||||
|
||||
|
||||
@@ -31,14 +31,20 @@ export const replaceInProgressForThisTarget = async (
|
||||
await replaced?.stop();
|
||||
};
|
||||
|
||||
// The removal is made before the stop is awaited, so an action that registers
|
||||
// for this target meanwhile is left in place.
|
||||
// `matcher` decides whether the in-progress action is one this caller may
|
||||
// stop; on a mismatch the action is left running. Without a matcher, whatever
|
||||
// is in progress is stopped. The removal is made before the stop is awaited,
|
||||
// so an action that registers for this target meanwhile is left in place.
|
||||
export const clearInProgressForThisTarget = async (
|
||||
targetID: string,
|
||||
context: ActionContext,
|
||||
contextKey: keyof ActionContext,
|
||||
matcher?: (incumbent: Action) => boolean,
|
||||
): Promise<void> => {
|
||||
const stopped = context[contextKey]?.[targetID]?.inProgressAction;
|
||||
if (!stopped || (matcher && !matcher(stopped))) {
|
||||
return;
|
||||
}
|
||||
delete context[contextKey]?.[targetID];
|
||||
await stopped?.stop();
|
||||
await stopped.stop();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user