feat: align keyboard LocalID to GlobalID and preserve server credentials
Two operator requirements for MBeg keyboards and server connections: 1. align_keyboard_local_ids(): on every keyboard interface under Clients/GeViIO/GeViIO_01, set each video input/output LocalID equal to its GlobalID so operators can address cameras/monitors by global id. Virtual decoders/servers under GeViIO_Virtual keep their sequential local ids. Runs after prune in /api/set/export and /api/batch/build. 2. preserve_server_credentials(): server User/Password are entered by hand and must survive re-importing the server list from Excel. Matched by alias, an existing non-empty credential overrides the imported value. Applied to G-Core and GeViScope servers in /api/batch/build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1120,6 +1120,64 @@ def disable_keyboard_ptz(tree):
|
||||
return cleared
|
||||
|
||||
|
||||
def align_keyboard_local_ids(tree):
|
||||
"""Make LocalID equal GlobalID for every video input and output on every
|
||||
MBeg keyboard interface (Clients/GeViIO/GeViIO_01).
|
||||
|
||||
Operators address cameras/monitors on the keyboards by their global id,
|
||||
so the local id must match it. Other interfaces (virtual decoders and
|
||||
servers under GeViIO_Virtual) keep their own sequential local ids.
|
||||
"""
|
||||
geviio = _find_folder(tree, ["Clients", "GeViIO", "GeViIO_01"])
|
||||
if not geviio:
|
||||
return 0
|
||||
changed = 0
|
||||
for interface in geviio.get("children", []):
|
||||
if not isinstance(interface, dict) or interface.get("type") != "folder":
|
||||
continue
|
||||
for sub in ("VideoInputs", "VideoOutputs"):
|
||||
container = _child_by_name(interface, sub)
|
||||
if container is None:
|
||||
continue
|
||||
for entry in container.get("children", []):
|
||||
if entry.get("type") != "folder":
|
||||
continue
|
||||
local_node = _child_by_name(entry, "LocalID")
|
||||
global_node = _child_by_name(entry, "GlobalID")
|
||||
if local_node is None or global_node is None:
|
||||
continue
|
||||
global_id = global_node.get("value")
|
||||
if isinstance(global_id, int) and local_node.get("value") != global_id:
|
||||
local_node["value"] = global_id
|
||||
changed += 1
|
||||
return changed
|
||||
|
||||
|
||||
def preserve_server_credentials(new_servers, existing_servers):
|
||||
"""Keep User/Password that were already entered on the matching server.
|
||||
|
||||
Server credentials are filled in by hand and must not be wiped when the
|
||||
server list is re-imported from Excel. Servers are matched by alias; an
|
||||
existing non-empty user or password overrides the imported value.
|
||||
"""
|
||||
by_alias = {}
|
||||
for server in existing_servers or []:
|
||||
alias = str(server.get("alias", "")).strip()
|
||||
if alias:
|
||||
by_alias[alias] = server
|
||||
preserved = 0
|
||||
for server in new_servers or []:
|
||||
old = by_alias.get(str(server.get("alias", "")).strip())
|
||||
if not old:
|
||||
continue
|
||||
if old.get("user"):
|
||||
server["user"] = old["user"]
|
||||
if old.get("password"):
|
||||
server["password"] = old["password"]
|
||||
preserved += 1
|
||||
return preserved
|
||||
|
||||
|
||||
def prune_video_inputs(tree, global_ids):
|
||||
target_ids = {int(x) for x in global_ids if isinstance(x, int) and x > 0}
|
||||
if not target_ids:
|
||||
|
||||
Reference in New Issue
Block a user