ha_devices_module.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import yaml
  2. import requests
  3. import os
  4. import json
  5. from utils.logger_config import logger
  6. class HADeviceController:
  7. def __init__(self, config_path='ha_config_prod.yaml'):
  8. self.config_path = config_path
  9. self.config = self._load_config()
  10. self.ha_config = self.config.get('home_assistant', {})
  11. self.base_url = self.ha_config.get('url', '').rstrip('/')
  12. self.token = self.ha_config.get('token', '')
  13. self.headers = {
  14. "Authorization": f"Bearer {self.token}",
  15. "Content-Type": "application/json",
  16. }
  17. self.devices = self.config.get('ha_devices', {})
  18. def _load_config(self):
  19. if not os.path.exists(self.config_path):
  20. logger.error(f"配置文件不存在: {self.config_path}")
  21. return {}
  22. try:
  23. with open(self.config_path, 'r', encoding='utf-8') as f:
  24. return yaml.safe_load(f) or {}
  25. except Exception as e:
  26. logger.error(f"加载配置文件失败: {e}")
  27. return {}
  28. def _get_device_state(self, entity_id):
  29. """获取设备当前状态"""
  30. if not self.base_url or not self.token:
  31. return None
  32. url = f"{self.base_url}/api/states/{entity_id}"
  33. try:
  34. logger.info(f"正在检查设备状态: {entity_id}")
  35. response = requests.get(url, headers=self.headers, timeout=5)
  36. if response.status_code == 200:
  37. data = response.json()
  38. state = data.get('state')
  39. logger.info(f"设备 {entity_id} 当前状态: {state}")
  40. return state
  41. else:
  42. logger.error(f"获取设备状态失败: {entity_id}, code={response.status_code}")
  43. return None
  44. except Exception as e:
  45. logger.error(f"获取设备状态异常: {entity_id}, {e}")
  46. return None
  47. def _call_ha_service(self, entity_id, service="turn_on", domain="switch"):
  48. if not self.base_url or not self.token:
  49. logger.error("Home Assistant 配置缺失 (url or token)")
  50. return False
  51. if not entity_id:
  52. logger.warning("未配置 entity_id")
  53. return False
  54. url = f"{self.base_url}/api/services/{domain}/{service}"
  55. payload = {"entity_id": entity_id}
  56. logger.info(f"准备调用HA接口: URL={url}, Entity={entity_id}, Service={domain}.{service}")
  57. try:
  58. response = requests.post(url, headers=self.headers, json=payload, timeout=5)
  59. if response.status_code in [200, 201]:
  60. logger.info(f"HA调用成功: {entity_id} -> {domain}.{service}, 响应: {response.text}")
  61. return True
  62. else:
  63. logger.error(f"HA调用失败: {response.status_code} - {response.text}")
  64. return False
  65. except Exception as e:
  66. logger.error(f"HA请求异常: {e}")
  67. return False
  68. def control_device(self, device_key, action="turn_on"):
  69. """
  70. 通用设备控制方法
  71. :param device_key: 配置文件 ha_devices 中的 key (如 'entrance_light_1')
  72. :param action: 动作 'turn_on' 或 'turn_off'
  73. """
  74. device_info = self.devices.get(device_key)
  75. if not device_info:
  76. logger.error(f"未找到设备配置: {device_key}")
  77. return False
  78. entity_id = device_info.get('entity_id')
  79. if not entity_id:
  80. logger.error(f"设备 {device_key} 未配置 entity_id")
  81. return False
  82. # 检查设备当前状态
  83. current_state = self._get_device_state(entity_id)
  84. if current_state:
  85. if action == "turn_on" and current_state == "on":
  86. logger.info(f"设备 {device_key} ({entity_id}) 已经是开启状态,跳过开启操作")
  87. return True
  88. if action == "turn_off" and current_state == "off":
  89. logger.info(f"设备 {device_key} ({entity_id}) 已经是关闭状态,跳过关闭操作")
  90. return True
  91. # 自动判断 domain
  92. domain = entity_id.split('.')[0]
  93. return self._call_ha_service(entity_id, service=action, domain=domain)
  94. # 具体设备控制方法
  95. def turn_on_entrance_lights(self):
  96. """打开一楼大门玄关顶灯 (全部)"""
  97. r1 = self.control_device('entrance_light_1', 'turn_on')
  98. r2 = self.control_device('entrance_light_2', 'turn_on')
  99. return r1 and r2
  100. def turn_off_entrance_lights(self):
  101. """关闭一楼大门玄关顶灯 (全部)"""
  102. r1 = self.control_device('entrance_light_1', 'turn_off')
  103. r2 = self.control_device('entrance_light_2', 'turn_off')
  104. return r1 and r2
  105. def turn_on_exhibition_spotlight(self):
  106. """打开一楼大门玄关射灯"""
  107. return self.control_device('exhibition_spotlight', 'turn_on')
  108. def turn_off_exhibition_spotlight(self):
  109. """关闭一楼大门玄关射灯"""
  110. return self.control_device('exhibition_spotlight', 'turn_off')
  111. def turn_on_exhibition_ceiling_light(self):
  112. """打开一楼展厅顶灯"""
  113. return self.control_device('exhibition_ceiling_light', 'turn_on')
  114. def turn_off_exhibition_ceiling_light(self):
  115. """关闭一楼展厅顶灯"""
  116. return self.control_device('exhibition_ceiling_light', 'turn_off')
  117. def turn_on_exhibition_desktop_switch(self):
  118. """打开展厅桌面的灯座总开关"""
  119. return self.control_device('exhibition_desktop_switch', 'turn_on')
  120. def turn_off_exhibition_desktop_switch(self):
  121. """关闭展厅桌面的灯座总开关"""
  122. return self.control_device('exhibition_desktop_switch', 'turn_off')
  123. def turn_on_exhibition_3d_fan(self):
  124. """打开展厅桌面3D风扇投影"""
  125. return self.control_device('exhibition_3d_fan', 'turn_on')
  126. def turn_off_exhibition_3d_fan(self):
  127. """关闭展厅桌面3D风扇投影"""
  128. return self.control_device('exhibition_3d_fan', 'turn_off')
  129. def turn_on_exhibition_stand_light_strip(self):
  130. """打开展台桌子灯带"""
  131. return self.control_device('exhibition_stand_light_strip', 'turn_on')
  132. def turn_off_exhibition_stand_light_strip(self):
  133. """关闭展台桌子灯带"""
  134. return self.control_device('exhibition_stand_light_strip', 'turn_off')
  135. def turn_on_all(self):
  136. """打开所有配置的HA设备"""
  137. results = []
  138. for key in self.devices:
  139. results.append(self.control_device(key, 'turn_on'))
  140. return all(results) if results else False
  141. def turn_off_all(self):
  142. """关闭所有配置的HA设备"""
  143. results = []
  144. for key in self.devices:
  145. results.append(self.control_device(key, 'turn_off'))
  146. return all(results) if results else False
  147. # 单例实例
  148. ha_device_controller = HADeviceController()
  149. # 模块级便捷函数
  150. def control_device(device_key, action="turn_on"):
  151. return ha_device_controller.control_device(device_key, action)
  152. def turn_on_entrance_lights():
  153. return ha_device_controller.turn_on_entrance_lights()
  154. def turn_off_entrance_lights():
  155. return ha_device_controller.turn_off_entrance_lights()
  156. def turn_on_exhibition_spotlight():
  157. return ha_device_controller.turn_on_exhibition_spotlight()
  158. def turn_off_exhibition_spotlight():
  159. return ha_device_controller.turn_off_exhibition_spotlight()
  160. def turn_on_exhibition_ceiling_light():
  161. return ha_device_controller.turn_on_exhibition_ceiling_light()
  162. def turn_off_exhibition_ceiling_light():
  163. return ha_device_controller.turn_off_exhibition_ceiling_light()
  164. def turn_on_exhibition_desktop_switch():
  165. return ha_device_controller.turn_on_exhibition_desktop_switch()
  166. def turn_off_exhibition_desktop_switch():
  167. return ha_device_controller.turn_off_exhibition_desktop_switch()
  168. def turn_on_exhibition_3d_fan():
  169. return ha_device_controller.turn_on_exhibition_3d_fan()
  170. def turn_off_exhibition_3d_fan():
  171. return ha_device_controller.turn_off_exhibition_3d_fan()
  172. def turn_on_exhibition_stand_light_strip():
  173. return ha_device_controller.turn_on_exhibition_stand_light_strip()
  174. def turn_off_exhibition_stand_light_strip():
  175. return ha_device_controller.turn_off_exhibition_stand_light_strip()
  176. def turn_on_all():
  177. return ha_device_controller.turn_on_all()
  178. def turn_off_all():
  179. return ha_device_controller.turn_off_all()