Merge pull request 'feat: align keyboard LocalID to GlobalID and preserve server credentials' (#2) from feat/keyboard-localid-and-preserve-credentials into main
This commit is contained in:
@@ -1120,6 +1120,64 @@ def disable_keyboard_ptz(tree):
|
|||||||
return cleared
|
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):
|
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:
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ async def export_set(payload: dict):
|
|||||||
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)
|
geviset.disable_keyboard_ptz(tree)
|
||||||
|
geviset.align_keyboard_local_ids(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,
|
||||||
@@ -303,6 +304,7 @@ async def build_from_excel(
|
|||||||
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)
|
geviset.disable_keyboard_ptz(tree)
|
||||||
|
geviset.align_keyboard_local_ids(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"):
|
||||||
@@ -316,6 +318,8 @@ async def build_from_excel(
|
|||||||
s["id"] = str(idx)
|
s["id"] = str(idx)
|
||||||
bundle_gcore = geviset.extract_gcore(tree)
|
bundle_gcore = geviset.extract_gcore(tree)
|
||||||
bundle_gsc = geviset.extract_gsc(tree)
|
bundle_gsc = geviset.extract_gsc(tree)
|
||||||
|
geviset.preserve_server_credentials(gcore_list, bundle_gcore["servers"])
|
||||||
|
geviset.preserve_server_credentials(gsc_list, bundle_gsc["servers"])
|
||||||
bundle_gcore["servers"] = gcore_list
|
bundle_gcore["servers"] = gcore_list
|
||||||
bundle_gsc["servers"] = gsc_list
|
bundle_gsc["servers"] = gsc_list
|
||||||
geviset.apply_gcore(tree, bundle_gcore)
|
geviset.apply_gcore(tree, bundle_gcore)
|
||||||
|
|||||||
Reference in New Issue
Block a user