dev_mng.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import threading
  2. from threading import Lock
  3. import queue
  4. import json
  5. import traceback
  6. from collections import deque
  7. from common.sys_comm import LOGDBG, LOGINFO, LOGWARN, LOGERR
  8. from common.sys_comm import get_utc_time_ms, utc_to_bj_s, get_bj_time_ms, get_bj_time_s
  9. from common.sys_comm import g_sys_conf, g_sys_conf_mtx
  10. g_dev_map_lock = threading.Lock()
  11. g_dev_map = {} # <dev_id: str, device: Device>
  12. # 跟踪区域类
  13. class TrackingRegion:
  14. def __init__(self, x1=0, y1=0, z1=0, x2=0, y2=0, z2=0):
  15. # 线程锁
  16. self.lock_ = threading.Lock()
  17. self.start_x: int = x1
  18. self.start_y: int = y1
  19. self.start_z: int = z1
  20. self.stop_x: int = x2
  21. self.stop_y: int = y2
  22. self.stop_z: int = z2
  23. def __repr__(self):
  24. return (f"TrackingRegion(start=({self.start_x}, {self.start_y}, {self.start_z}), "
  25. f"stop=({self.stop_x}, {self.stop_y}, {self.stop_z}))")
  26. # 安装参数类
  27. class InstallParam:
  28. def __init__(self, mount_plain="", height=0, tracking_region=None):
  29. # 线程锁
  30. self.lock_ = threading.Lock()
  31. self.mount_plain: str = mount_plain
  32. self.isCeiling: int = 1
  33. self.height = height
  34. self.tracking_region = tracking_region if tracking_region else TrackingRegion()
  35. self.north_angle_: float = 0
  36. def __repr__(self):
  37. return (f"InstallParam(mount_plain='{self.mount_plain}', isCeiling={self.isCeiling}, "
  38. f"height={self.height}, north_angle={self.north_angle_}, "
  39. f"tracking_region={repr(self.tracking_region)})")
  40. # 网络参数类
  41. class Network:
  42. def __init__(self, ssid="", password="", ip=""):
  43. # 线程锁
  44. self.lock_ = threading.Lock()
  45. self.ssid = ssid
  46. self.password = password
  47. self.ip = ip
  48. def set_ssid(self, ssid:str):
  49. with self.lock_:
  50. self.ssid = ssid
  51. def set_password(self, password:str):
  52. with self.lock_:
  53. self.password = password
  54. def set_ip(self, ip:str):
  55. with self.lock_:
  56. self.ip = ip
  57. def __repr__(self):
  58. return f"Network(ssid='{self.ssid}', password='{self.password}' , ip='{self.ip}')"
  59. class Device():
  60. def __init__(self,
  61. dev_id: str = "",
  62. dev_name: str = "",
  63. online: int = 0,
  64. dev_type: str = "",
  65. network: Network = None,
  66. install_param: InstallParam = None):
  67. # 线程锁
  68. self.lock_ = Lock()
  69. # 基本属性
  70. self.dev_id_ = dev_id
  71. self.dev_name_ = dev_name
  72. self.online_ = online
  73. self.dev_type_ = dev_type
  74. self.network_ = network if network else Network()
  75. self.install_param_ = install_param if install_param else InstallParam()
  76. # 实时数据队列
  77. self.rtd_len_: int = 100
  78. self.rtd_que_: deque = deque(maxlen=self.rtd_len_)
  79. """
  80. {
  81. "timestamp": 1727323744093,
  82. "pose": 2,
  83. "target_point": [
  84. [
  85. 0.15537149991307939,
  86. -0.17245136840002878,
  87. 0.5702038151877267,
  88. 1
  89. ],
  90. [
  91. 0.15537149991307939,
  92. -0.17245136840002878,
  93. 0.5702038151877267,
  94. 2
  95. ]
  96. ]
  97. }
  98. """
  99. # 插入新的rtd单元
  100. def put_rtd_unit(self, rtd_unit: object):
  101. """
  102. 插入新的点云数据,超过最大长度自动丢弃旧数据
  103. """
  104. with self.lock_:
  105. self.rtd_que_.append(rtd_unit)
  106. # 获取最新的rtd_que_
  107. def get_last_rtd_que(self) -> list:
  108. """
  109. 获取当前最新的点云数据(全部缓存)
  110. """
  111. with self.lock_:
  112. return list(self.rtd_que_)
  113. # 获取rtd单元
  114. def get_rtd_unit(self, index: int):
  115. with self.lock_:
  116. if not self.rtd_que_:
  117. return None
  118. try:
  119. return self.rtd_que_[index]
  120. except IndexError:
  121. return None
  122. # 获取最新的rtd单元
  123. def get_last_rtd_unit(self) -> object:
  124. with self.lock_:
  125. if self.rtd_que_:
  126. return self.rtd_que_[-1]
  127. return None
  128. # 获取 rtd_que_ 的副本
  129. def get_rtd_que_copy(self) -> list:
  130. with self.lock_:
  131. return list(self.rtd_que_)
  132. def update_dev_info(dev_id:str, dev_instance:Device):
  133. with g_dev_map_lock:
  134. if dev_id in g_dev_map:
  135. g_dev_map[dev_id] = None
  136. LOGDBG(f"update dev: {dev_id}")
  137. else:
  138. LOGDBG(f"new dev: {dev_id}")
  139. # todo 更新设备保活时间(伪)
  140. # dev_instance.set_keepalive(get_utc_time_ms())
  141. g_dev_map[dev_id] = dev_instance
  142. # 回调函数,处理查询结果:查询所有的设备信息
  143. def cb_handle_query_all_dev_info(result):
  144. try:
  145. if result:
  146. for row in result:
  147. dev_id = row["client_id"]
  148. dev_instance = Device(
  149. dev_id=row["client_id"],
  150. dev_name=row["dev_name"],
  151. online=row["online"],
  152. dev_type=row["dev_type"]
  153. )
  154. # 更新设备信息
  155. update_dev_info(dev_id, dev_instance)
  156. LOGDBG(f"cb_handle_query_all_dev_info succeed")
  157. else:
  158. LOGDBG("cb_handle_query_all_dev_info, invalid result")
  159. except json.JSONDecodeError as e:
  160. tb_info = traceback.extract_tb(e.__traceback__)
  161. for frame in tb_info:
  162. LOGERR(f"[{frame.filename}:{frame.lineno}] @{frame.name}(), error:{e}, {e.doc}")
  163. except Exception as e:
  164. tb_info = traceback.extract_tb(e.__traceback__)
  165. for frame in tb_info:
  166. LOGERR(f"[{frame.filename}:{frame.lineno}] @{frame.name}(), error: {e}")
  167. def dev_map_push(dev_id: str, device: Device) -> None:
  168. with g_dev_map_lock:
  169. g_dev_map[dev_id] = device
  170. def dev_map_pop(dev_id: str) -> Device:
  171. with g_dev_map_lock:
  172. return g_dev_map.pop(dev_id, None)
  173. def dev_map_find(dev_id: str) -> Device:
  174. with g_dev_map_lock:
  175. return g_dev_map.get(dev_id, None)
  176. def dev_map_delete(dev_id: str) -> bool:
  177. with g_dev_map_lock:
  178. if dev_id in g_dev_map:
  179. del g_dev_map[dev_id]
  180. return True
  181. return False