Compare commits

..

2 Commits

Author SHA1 Message Date
3b38a5c6d9 Merge pull request 'fix: clear PTZ flag on all MBeg keyboard video inputs' (#1) from fix/disable-keyboard-ptz into main 2026-05-28 21:34:49 +00:00
Docker Config Backup
18084ec9d7 fix: clear PTZ flag on all MBeg keyboard video inputs
Keyboard interfaces under Clients/GeViIO/GeViIO_01 should never have the
PTZ flag set on their video inputs. Previously PTZ cameras (e.g. 101027)
were exported with PTZ=True on every keyboard, unlike fixed cameras.

Adds geviset.disable_keyboard_ptz() and runs it at the end of the video
input pipeline in both /api/set/export and /api/batch/build. Only the
keyboard interfaces are touched; virtual decoders/servers under
GeViIO_Virtual keep their PTZ flags so PTZ control still works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-28 23:33:14 +02:00
2 changed files with 30 additions and 0 deletions

View File

@@ -1092,6 +1092,34 @@ def ensure_global_video_inputs(tree, global_ids, ptz_by_id=None):
) )
def disable_keyboard_ptz(tree):
"""Force PTZ off for every video input on every MBeg keyboard interface.
Keyboards live directly under Clients/GeViIO/GeViIO_01 (each is an
interface folder with its own VideoInputs). PTZ control on the keyboard
side is never wanted, so the PTZ flag of each video input is cleared.
Virtual decoders/servers under GeViIO_Virtual are left untouched.
"""
geviio = _find_folder(tree, ["Clients", "GeViIO", "GeViIO_01"])
if not geviio:
return 0
cleared = 0
for interface in geviio.get("children", []):
if not isinstance(interface, dict) or interface.get("type") != "folder":
continue
video_inputs = _child_by_name(interface, "VideoInputs")
if video_inputs is None:
continue
for entry in video_inputs.get("children", []):
if entry.get("type") != "folder":
continue
ptz_node = _child_by_name(entry, "PTZ")
if ptz_node is not None and ptz_node.get("value") is not False:
ptz_node["value"] = False
cleared += 1
return cleared
def prune_video_inputs(tree, global_ids): def prune_video_inputs(tree, global_ids):
target_ids = {int(x) for x in global_ids if isinstance(x, int) and x > 0} target_ids = {int(x) for x in global_ids if isinstance(x, int) and x > 0}
if not target_ids: if not target_ids:

View File

@@ -110,6 +110,7 @@ async def export_set(payload: dict):
geviset.ensure_global_video_inputs(tree, camera_ids, ptz_by_id) geviset.ensure_global_video_inputs(tree, camera_ids, ptz_by_id)
geviset.ensure_vx3_video_inputs(tree, camera_ids, ptz_by_id) geviset.ensure_vx3_video_inputs(tree, camera_ids, ptz_by_id)
geviset.prune_video_inputs(tree, camera_ids) geviset.prune_video_inputs(tree, camera_ids)
geviset.disable_keyboard_ptz(tree)
print( print(
f"EXPORT camera_ids={len(camera_ids)} contains_101027={101027 in camera_ids}", f"EXPORT camera_ids={len(camera_ids)} contains_101027={101027 in camera_ids}",
flush=True, flush=True,
@@ -301,6 +302,7 @@ async def build_from_excel(
geviset.ensure_global_video_inputs(tree, camera_ids, ptz_by_id) geviset.ensure_global_video_inputs(tree, camera_ids, ptz_by_id)
geviset.ensure_vx3_video_inputs(tree, camera_ids, ptz_by_id) geviset.ensure_vx3_video_inputs(tree, camera_ids, ptz_by_id)
geviset.prune_video_inputs(tree, camera_ids) geviset.prune_video_inputs(tree, camera_ids)
geviset.disable_keyboard_ptz(tree)
if servers and servers.filename: if servers and servers.filename:
if not servers.filename.lower().endswith(".xlsx"): if not servers.filename.lower().endswith(".xlsx"):