group_state.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. """各摄像头组运行时共享状态."""
  2. import copy
  3. import logging
  4. import threading
  5. from typing import Any, Dict
  6. class GroupState:
  7. def __init__(self):
  8. self._data: Dict[str, Dict[str, Any]] = {}
  9. self._lock = threading.Lock()
  10. def reset(self):
  11. """重置所有状态(主要用于测试)."""
  12. with self._lock:
  13. self._data.clear()
  14. def init_group(self, group_id: str, panorama_rtsp: str, ptz_rtsp: str, ptz_config: Dict):
  15. with self._lock:
  16. if group_id in self._data:
  17. raise ValueError(f"Group {group_id} already initialized")
  18. self._data[group_id] = {
  19. "panorama_rtsp": panorama_rtsp,
  20. "ptz_rtsp": ptz_rtsp,
  21. "ptz_position": {"pan": 0.0, "tilt": 0.0, "zoom": 1},
  22. "polling_state": "idle", # idle|scanning|polling|paused
  23. "scan_progress": {"total": 0, "current": 0, "state": "idle"},
  24. "last_detection": None,
  25. "logs": [],
  26. }
  27. def get(self, group_id: str) -> Dict[str, Any]:
  28. with self._lock:
  29. return copy.deepcopy(self._data.get(group_id, {}))
  30. def list_groups(self) -> list:
  31. with self._lock:
  32. return list(self._data.keys())
  33. def update(self, group_id: str, key: str, value: Any):
  34. with self._lock:
  35. if group_id not in self._data:
  36. logging.warning("Cannot update unknown group: %s", group_id)
  37. return
  38. self._data[group_id][key] = value
  39. def compare_and_update(
  40. self, group_id: str, key: str, expected: Any, new_value: Any
  41. ) -> bool:
  42. with self._lock:
  43. if group_id not in self._data:
  44. return False
  45. if self._data[group_id].get(key) != expected:
  46. return False
  47. self._data[group_id][key] = new_value
  48. return True
  49. def update_nested(self, group_id: str, key: str, sub_key: str, value: Any):
  50. with self._lock:
  51. if group_id not in self._data:
  52. raise KeyError(f"Group {group_id} not initialized")
  53. if key not in self._data[group_id] or not isinstance(self._data[group_id][key], dict):
  54. raise KeyError(f"Key {key} is not a dict")
  55. self._data[group_id][key][sub_key] = value
  56. def append_log(self, group_id: str, message: str):
  57. with self._lock:
  58. if group_id not in self._data:
  59. logging.warning("Cannot append log to unknown group: %s", group_id)
  60. return
  61. logs = self._data[group_id]["logs"]
  62. logs.append(message)
  63. self._data[group_id]["logs"] = logs[-200:]
  64. # 全局单例(保持 import 兼容性;测试可调用 reset() 重置)
  65. group_state = GroupState()