问题描述: - 当sync_mode=full且incoming_ids为空时,条件判断失败 - 导致旧的孤儿ROI配置残留在本地数据库 - 后续配置更新时尝试启动孤儿ROI对应的摄像头,产生警告 根本原因: - line 889: if self._db_manager and incoming_ids: - 当incoming_ids为空列表时,条件判断为False - 跳过了清理旧配置的逻辑 修复方案: - 移除incoming_ids的条件判断 - 全量同步时始终执行清理逻辑 - incoming_ids为空时,清除所有旧配置(符合全量同步语义) - incoming_ids不为空时,清除不在列表中的旧配置 附加工具: - cleanup_orphan_rois.py: 清理当前残留的孤儿ROI记录 影响: - 修复配置同步逻辑bug - 避免孤儿ROI警告 - 提高配置同步的可靠性 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
122 lines
3.8 KiB
Python
122 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
清理孤儿ROI配置
|
|
- 删除没有对应摄像头配置的ROI记录
|
|
- 删除关联的算法绑定记录
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
|
|
from core.config_sync import get_config_sync_manager
|
|
|
|
def main():
|
|
print("=== Orphan ROI Cleanup Tool ===\n")
|
|
|
|
config_manager = get_config_sync_manager()
|
|
|
|
# 1. Get all cameras and ROIs
|
|
cameras = config_manager.get_cameras()
|
|
camera_ids = {c.camera_id for c in cameras}
|
|
|
|
rois = config_manager.get_roi_configs(force_refresh=True)
|
|
binds = config_manager.get_bindings()
|
|
|
|
print(f"Current Status:")
|
|
print(f" - Total cameras: {len(cameras)}")
|
|
print(f" - Total ROIs: {len(rois)}")
|
|
print(f" - Total bindings: {len(binds)}")
|
|
|
|
# 2. Find orphan ROIs
|
|
orphan_rois = [roi for roi in rois if roi.camera_id not in camera_ids]
|
|
|
|
if not orphan_rois:
|
|
print("\n[OK] No orphan ROIs found. Database is clean!")
|
|
return
|
|
|
|
print(f"\n[PROBLEM] Found {len(orphan_rois)} orphan ROIs:")
|
|
for roi in orphan_rois:
|
|
print(f" - ROI ID: {roi.roi_id}")
|
|
print(f" Camera ID: {roi.camera_id} (MISSING)")
|
|
print(f" ROI Type: {roi.roi_type if hasattr(roi, 'roi_type') else 'N/A'}")
|
|
print()
|
|
|
|
# 3. Find orphan bindings
|
|
orphan_roi_ids = {roi.roi_id for roi in orphan_rois}
|
|
orphan_binds = [b for b in binds if b.roi_id in orphan_roi_ids]
|
|
|
|
if orphan_binds:
|
|
print(f"Related orphan bindings: {len(orphan_binds)}")
|
|
for bind in orphan_binds:
|
|
print(f" - Bind ID: {bind.bind_id}")
|
|
print(f" ROI ID: {bind.roi_id}")
|
|
print(f" Algorithm: {bind.algo_code}")
|
|
print()
|
|
|
|
# 4. Ask for confirmation
|
|
print("=" * 50)
|
|
print("Cleanup Plan:")
|
|
print(f" 1. Delete {len(orphan_rois)} orphan ROI records")
|
|
print(f" 2. Delete {len(orphan_binds)} orphan binding records")
|
|
print("=" * 50)
|
|
|
|
response = input("\nProceed with cleanup? (yes/no): ").strip().lower()
|
|
|
|
if response != 'yes':
|
|
print("\n[CANCELLED] Cleanup aborted by user")
|
|
return
|
|
|
|
# 5. Perform cleanup
|
|
print("\n[EXECUTING] Cleanup in progress...")
|
|
|
|
# Initialize database manager
|
|
config_manager._init_database()
|
|
db_manager = config_manager._db_manager
|
|
|
|
if not db_manager:
|
|
print("[ERROR] Database manager not available")
|
|
return
|
|
|
|
deleted_rois = 0
|
|
deleted_binds = 0
|
|
|
|
# Delete orphan bindings first (foreign key constraint)
|
|
for bind in orphan_binds:
|
|
try:
|
|
db_manager.delete_binding(bind.bind_id)
|
|
deleted_binds += 1
|
|
print(f" [OK] Deleted binding: {bind.bind_id}")
|
|
except Exception as e:
|
|
print(f" [FAIL] Failed to delete binding {bind.bind_id}: {e}")
|
|
|
|
# Delete orphan ROIs
|
|
for roi in orphan_rois:
|
|
try:
|
|
db_manager.delete_roi(roi.roi_id)
|
|
deleted_rois += 1
|
|
print(f" [OK] Deleted ROI: {roi.roi_id}")
|
|
except Exception as e:
|
|
print(f" [FAIL] Failed to delete ROI {roi.roi_id}: {e}")
|
|
|
|
# 6. Invalidate cache
|
|
config_manager.invalidate_all_cache()
|
|
|
|
# 7. Summary
|
|
print("\n" + "=" * 50)
|
|
print("Cleanup Summary")
|
|
print("=" * 50)
|
|
print(f"Deleted ROIs: {deleted_rois}/{len(orphan_rois)}")
|
|
print(f"Deleted bindings: {deleted_binds}/{len(orphan_binds)}")
|
|
|
|
if deleted_rois == len(orphan_rois) and deleted_binds == len(orphan_binds):
|
|
print("\n[SUCCESS] All orphan records cleaned up!")
|
|
print("\nNext steps:")
|
|
print(" 1. Restart the Edge service to apply changes")
|
|
print(" 2. Warnings should disappear from logs")
|
|
else:
|
|
print("\n[WARNING] Some records failed to delete")
|
|
print(" Please check error messages above")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|