fix: make the Control view send PTZ to the monitor's own server (#5172)

The standalone Control view's controlCmd() still had its 2020
(control, event, xtell, ytell) signature, but ptzControls() binds the
buttons as data-on-mousedown/mouseup handlers that receive the event,
and it read the monitor id with $j('#mid').getAttribute(), which jQuery
objects don't have. Every PTZ button threw before sending anything.

Port the watch view's event-based controlCmd(): the button's value is
the command, mouseup sends moveStop, xge/yge come from data-xtell and
data-ytell. Send requests to the monitor's server (monitorUrl, from
Monitor::UrlToIndex() as on the watch view) instead of this server: on a
multi-server install only the owning server's zmcontrol.pl can drive
the camera, and relaying through Monitor::sendControlCommand() puts the
raw zmcontrol arguments into a daemonControl API path, which fails.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nicandClaude Opus 5.5 authored and GitHub committed 2026-10-04 08:52:10 -04:00
1 parent 72922bb459
commit f362efd23e
2 files changed
+31 -20

No files matched your search

+25 -20
View File
@@ -1,7 +1,7 @@
var form = $j('#controlForm');
function controlReq(data) {
$j.getJSON(zmAuth.appendTo(thisUrl + '?view=request&request=control'), data)
$j.getJSON(zmAuth.appendTo(monitorUrl + '?view=request&request=control'), data)
.done(getControlResponse)
.fail(logAjaxFail);
}
@@ -16,39 +16,44 @@ function getControlResponse(respObj, respText) {
}
}
function controlCmd( control, event, xtell, ytell ) {
var mid = $j('#mid').getAttribute('value');
// Bound by ptzControls() as data-on-mousedown/mouseup (or data-on-click):
// the button's value is the command, releasing a continuous move stops it.
function controlCmd(event) {
const button = event.currentTarget || event.target;
const control = (event.type == 'mouseup') ? 'moveStop' : button.getAttribute('value');
const xtell = button.getAttribute('data-xtell');
const ytell = button.getAttribute('data-ytell');
const data = {};
if ( event && (xtell || ytell) ) {
var data = {};
var target = $j(event.target);
var offset = target.offset();
var width = target.width();
var height = target.height();
if (xtell || ytell) {
const target = $j(button);
const offset = target.offset();
const width = target.width();
const height = target.height();
var x = event.pageX - offset.left;
var y = event.pageY - offset.top;
const x = event.pageX - offset.left;
const y = event.pageY - offset.top;
if ( xtell ) {
var xge = parseInt( (x*100)/width );
if ( xtell == -1 ) {
if (xtell) {
let xge = parseInt((x*100)/width);
if (xtell == -1) {
xge = 100 - xge;
} else if ( xtell == 2 ) {
} else if (xtell == 2) {
xge = 2*(50 - xge);
}
data.xge = xge;
}
if ( ytell ) {
var yge = parseInt( (y*100)/height );
if ( ytell == -1 ) {
if (ytell) {
let yge = parseInt((y*100)/height);
if (ytell == -1) {
yge = 100 - yge;
} else if ( ytell == 2 ) {
} else if (ytell == 2) {
yge = 2*(50 - yge);
}
data.yge = yge;
}
}
data.id = mid;
data.id = $j('#mid').val();
data.control = control;
controlReq(data);
}
@@ -0,0 +1,6 @@
<?php
global $monitor;
?>
// PTZ requests go to the server that runs the monitor, as on the watch view:
// only that server's zmcontrol.pl can drive the camera.
var monitorUrl = '<?php echo $monitor->UrlToIndex(ZM_MIN_STREAMING_PORT ? ($monitor->Id() + ZM_MIN_STREAMING_PORT) : '') ?>';