kodi_alive_thread.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import threading
  2. import time
  3. from utils.logger_config import logger
  4. from hardware.kodi_module import KodiClientManager
  5. class KodiAliveThreadSingleton:
  6. """Kodi心跳检测线程单例类,每秒检查一次心跳,如果检测不到Kodi在线则启动Kodi应用"""
  7. _instance = None
  8. _lock = threading.Lock()
  9. def __new__(cls):
  10. if cls._instance is None:
  11. with cls._lock:
  12. if cls._instance is None:
  13. cls._instance = super(KodiAliveThreadSingleton, cls).__new__(cls)
  14. return cls._instance
  15. def __init__(self):
  16. # 避免重复初始化
  17. if hasattr(self, '_initialized'):
  18. return
  19. self._initialized = True
  20. self.thread = None
  21. self.is_running = False
  22. self._should_stop = False
  23. self.manager: KodiClientManager = None
  24. # 配置参数
  25. self.check_interval_seconds = 1 # 每秒检查一次
  26. # 启动工作线程
  27. self._start_worker_thread()
  28. def _start_worker_thread(self):
  29. """启动工作线程"""
  30. if self.thread is None or not self.thread.is_alive():
  31. self.is_running = True
  32. self._should_stop = False
  33. self.thread = threading.Thread(target=self._worker_loop, daemon=True)
  34. self.thread.start()
  35. logger.info("Kodi心跳检测线程已启动")
  36. def _initialize_manager(self):
  37. """初始化KodiClientManager"""
  38. if self.manager is None:
  39. self.manager = KodiClientManager()
  40. logger.info("KodiClientManager 初始化成功")
  41. def _worker_loop(self):
  42. """工作线程主循环"""
  43. logger.info("Kodi心跳检测线程开始运行,每秒检查一次心跳")
  44. try:
  45. # 确保Manager已初始化
  46. self._initialize_manager()
  47. while self.is_running and not self._should_stop:
  48. try:
  49. # 检查所有Kodi客户端是否在线
  50. offline_client_indices = self.manager.check_all_kodi_clients_online()
  51. if offline_client_indices:
  52. # 检测到不在线的客户端,启动对应的Kodi应用
  53. logger.warning(f"检测到 {len(offline_client_indices)} 个Kodi客户端不在线,索引: {offline_client_indices},尝试启动Kodi应用")
  54. for offline_client_index in offline_client_indices:
  55. try:
  56. # 根据client_index获取对应的客户端并启动
  57. if offline_client_index < len(self.manager.kodi_clients):
  58. client = self.manager.kodi_clients[offline_client_index]
  59. result = client.start_kodi()
  60. logger.info(f"已尝试启动客户端 {offline_client_index} 的Kodi应用,响应: {result}")
  61. else:
  62. logger.error(f"客户端索引 {offline_client_index} 超出范围,客户端总数: {len(self.manager.kodi_clients)}")
  63. except Exception as e:
  64. logger.error(f"启动客户端 {offline_client_index} 的Kodi应用时发生异常: {e}")
  65. else:
  66. # 所有客户端都在线
  67. logger.debug("所有Kodi客户端在线")
  68. # 等待指定时间后再次检查
  69. time.sleep(self.check_interval_seconds)
  70. if self._should_stop:
  71. logger.info("收到停止信号,退出循环")
  72. break
  73. except Exception as e:
  74. logger.error(f"工作线程循环异常: {e}")
  75. time.sleep(self.check_interval_seconds)
  76. except Exception as e:
  77. logger.error(f"工作线程异常: {e}")
  78. finally:
  79. self.is_running = False
  80. logger.info("Kodi心跳检测线程结束")
  81. def stop(self):
  82. """停止线程"""
  83. self._should_stop = True
  84. self.is_running = False
  85. logger.info("停止Kodi心跳检测线程")
  86. # 全局单例实例
  87. _kodi_alive_thread = KodiAliveThreadSingleton()
  88. def start_kodi_alive_check() -> bool:
  89. """
  90. 启动Kodi心跳检测
  91. 启动后,线程会每秒自动检查所有Kodi客户端的心跳
  92. 如果检测到不在线的客户端,会自动尝试启动对应的Kodi应用
  93. Returns:
  94. bool: 启动是否成功
  95. """
  96. if not _kodi_alive_thread.is_running:
  97. _kodi_alive_thread._start_worker_thread()
  98. return _kodi_alive_thread.is_running
  99. def stop_kodi_alive_check() -> bool:
  100. """
  101. 停止Kodi心跳检测
  102. Returns:
  103. bool: 停止是否成功
  104. """
  105. _kodi_alive_thread.stop()
  106. return True
  107. def is_alive_check_running() -> bool:
  108. """
  109. 检查心跳检测线程是否正在运行
  110. Returns:
  111. bool: 线程是否正在运行
  112. """
  113. return _kodi_alive_thread.is_running