mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
wawa
This commit is contained in:
@@ -106,6 +106,7 @@ let motionWatchdogTimer = null;
|
|||||||
let panTiltRenewTimer = null;
|
let panTiltRenewTimer = null;
|
||||||
let zoomRepeatTimer = null;
|
let zoomRepeatTimer = null;
|
||||||
let desiredMotion = STOP_MOTION;
|
let desiredMotion = STOP_MOTION;
|
||||||
|
let pendingFullStopCommand = false;
|
||||||
let pendingPanTiltCommand = false;
|
let pendingPanTiltCommand = false;
|
||||||
let pendingZoomCommand = false;
|
let pendingZoomCommand = false;
|
||||||
let motionCommandPromise = null;
|
let motionCommandPromise = null;
|
||||||
@@ -1143,10 +1144,14 @@ function panTiltMatches(left = STOP_MOTION, right = STOP_MOTION) {
|
|||||||
return left.pan === right.pan && left.tilt === right.tilt;
|
return left.pan === right.pan && left.tilt === right.tilt;
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestMotionCommands({ panTilt = false, zoom = false } = {}) {
|
function requestMotionCommands({ fullStop = false, panTilt = false, zoom = false } = {}) {
|
||||||
|
pendingFullStopCommand = pendingFullStopCommand || fullStop;
|
||||||
pendingPanTiltCommand = pendingPanTiltCommand || panTilt;
|
pendingPanTiltCommand = pendingPanTiltCommand || panTilt;
|
||||||
pendingZoomCommand = pendingZoomCommand || zoom;
|
pendingZoomCommand = pendingZoomCommand || zoom;
|
||||||
if (motionCommandPromise || (!pendingPanTiltCommand && !pendingZoomCommand)) {
|
if (
|
||||||
|
motionCommandPromise ||
|
||||||
|
(!pendingFullStopCommand && !pendingPanTiltCommand && !pendingZoomCommand)
|
||||||
|
) {
|
||||||
return motionCommandPromise || Promise.resolve();
|
return motionCommandPromise || Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1157,7 +1162,27 @@ function requestMotionCommands({ panTilt = false, zoom = false } = {}) {
|
|||||||
building a delayed command backlog that would continue after release.
|
building a delayed command backlog that would continue after release.
|
||||||
*/
|
*/
|
||||||
motionCommandPromise = (async () => {
|
motionCommandPromise = (async () => {
|
||||||
while (pendingPanTiltCommand || pendingZoomCommand) {
|
while (pendingFullStopCommand || pendingPanTiltCommand || pendingZoomCommand) {
|
||||||
|
const sendFullStop = pendingFullStopCommand;
|
||||||
|
pendingFullStopCommand = false;
|
||||||
|
if (sendFullStop) {
|
||||||
|
try {
|
||||||
|
await initialize();
|
||||||
|
/*
|
||||||
|
Reserve ONVIF Stop for real all-axis safety events. The TrackMix
|
||||||
|
appears to treat even an axis-filtered Stop as global, so ordinary
|
||||||
|
user releases below use zero velocity instead.
|
||||||
|
*/
|
||||||
|
await callOnvif('stop', {
|
||||||
|
profileToken: state.profileToken,
|
||||||
|
panTilt: true,
|
||||||
|
zoom: true,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn('PTZ full stop command failed', { error: getErrorMessage(err) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const sendPanTilt = pendingPanTiltCommand;
|
const sendPanTilt = pendingPanTiltCommand;
|
||||||
pendingPanTiltCommand = false;
|
pendingPanTiltCommand = false;
|
||||||
if (sendPanTilt) {
|
if (sendPanTilt) {
|
||||||
@@ -1166,12 +1191,17 @@ function requestMotionCommands({ panTilt = false, zoom = false } = {}) {
|
|||||||
try {
|
try {
|
||||||
await initialize();
|
await initialize();
|
||||||
if (!pan && !tilt) {
|
if (!pan && !tilt) {
|
||||||
// Stop only pan/tilt. Omitting Zoom is essential because a zoom
|
/*
|
||||||
// finger/key may still be held while direction returns to neutral.
|
Zero pan/tilt velocity stops only that axis under ContinuousMove.
|
||||||
await callOnvif('stop', {
|
Do not use ONVIF Stop here: this TrackMix ignores the requested
|
||||||
|
axis filter and can also stop zoom that is still being held.
|
||||||
|
*/
|
||||||
|
await callOnvif('continuousMove', {
|
||||||
profileToken: state.profileToken,
|
profileToken: state.profileToken,
|
||||||
panTilt: true,
|
x: 0,
|
||||||
zoom: false,
|
y: 0,
|
||||||
|
onlySendPanTilt: true,
|
||||||
|
timeout: PAN_TILT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await callOnvif('continuousMove', {
|
await callOnvif('continuousMove', {
|
||||||
@@ -1194,12 +1224,16 @@ function requestMotionCommands({ panTilt = false, zoom = false } = {}) {
|
|||||||
try {
|
try {
|
||||||
await initialize();
|
await initialize();
|
||||||
if (!zoom) {
|
if (!zoom) {
|
||||||
// Stop only zoom so repeated zoom release cannot interrupt a smooth
|
/*
|
||||||
// pan/tilt ContinuousMove that is already running on the camera.
|
Zero zoom velocity is the axis-local release. The camera's Stop
|
||||||
await callOnvif('stop', {
|
implementation is over-broad and halts pan/tilt even when the
|
||||||
|
request includes only Zoom=true.
|
||||||
|
*/
|
||||||
|
await callOnvif('continuousMove', {
|
||||||
profileToken: state.profileToken,
|
profileToken: state.profileToken,
|
||||||
panTilt: false,
|
zoom: 0,
|
||||||
zoom: true,
|
onlySendZoom: true,
|
||||||
|
timeout: ZOOM_PULSE_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@@ -1223,7 +1257,9 @@ function requestMotionCommands({ panTilt = false, zoom = false } = {}) {
|
|||||||
})().finally(() => {
|
})().finally(() => {
|
||||||
motionCommandPromise = null;
|
motionCommandPromise = null;
|
||||||
// Cover an intent arriving between the loop check and promise cleanup.
|
// Cover an intent arriving between the loop check and promise cleanup.
|
||||||
if (pendingPanTiltCommand || pendingZoomCommand) requestMotionCommands();
|
if (pendingFullStopCommand || pendingPanTiltCommand || pendingZoomCommand) {
|
||||||
|
requestMotionCommands();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return motionCommandPromise;
|
return motionCommandPromise;
|
||||||
@@ -1295,14 +1331,15 @@ function acceptMotionIntent(socket, payload = {}) {
|
|||||||
|
|
||||||
function forceMotionStop(reason = 'safety-stop') {
|
function forceMotionStop(reason = 'safety-stop') {
|
||||||
/*
|
/*
|
||||||
Lifecycle stops force both axis-specific Stop commands even when local state
|
Lifecycle stops force a real all-axis ONVIF Stop even when local state is
|
||||||
is already zero. The browser may have lost its final packet, or the camera
|
already zero. The browser may have lost its final packet, or the camera may
|
||||||
may have accepted a command whose response has not returned, so deduplicating
|
have accepted a command whose response has not returned, so deduplicating a
|
||||||
a safety stop would trust precisely the state we are trying to recover from.
|
safety stop would trust precisely the state we are trying to recover from.
|
||||||
*/
|
*/
|
||||||
clearPanTiltRenewal();
|
clearPanTiltRenewal();
|
||||||
clearZoomRepeat();
|
clearZoomRepeat();
|
||||||
queueMotionIntent(STOP_MOTION, reason, { forceAxes: true });
|
queueMotionIntent(STOP_MOTION, reason);
|
||||||
|
requestMotionCommands({ fullStop: true });
|
||||||
return motionCommandPromise || Promise.resolve();
|
return motionCommandPromise || Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user