auto_switch_juyudeng.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. """
  4. @CreateTime: 2022/06/28 18:53
  5. @Author: lxc
  6. @LastEditTime:
  7. @Desctiption: 聚鱼灯
  8. """
  9. from event_storage import EventStorage
  10. from log import OutPutLog
  11. import time
  12. from datetime import datetime
  13. from utility import Utility
  14. import json
  15. class AutoSwitchJuyudeng:
  16. def __init__(self):
  17. self._storage = EventStorage()
  18. self._log = OutPutLog()
  19. def run(self):
  20. self._log.info("[AutoSwitchDevice] - AutoSwitchDevice module is running!")
  21. run_time = 0
  22. while True:
  23. this_time = time.time()
  24. self.now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  25. if this_time - run_time > 60:
  26. run_time = this_time
  27. self.check_status()
  28. self.update_juyudeng_status()
  29. def get_light_real_status(self):
  30. """
  31. 获取聚鱼灯的实时状态:光敏模式的状态、灯的开关状态
  32. :return: {'juyudeng_1#_guangmin': 0, 'juyudeng_2#_guangmin': 1, 'juyudeng_3#_guangmin': 0,
  33. 'juyudeng_4#_guangmin': 0, 'juyudeng_5#_guangmin': 0, 'juyudeng_6#_guangmin': 1, 'juyudeng_7#_guangmin': 1,
  34. 'juyudeng_8#_guangmin': 1, 'juyudeng_1#_status': 1, 'juyudeng_2#_status': 1, 'juyudeng_3#_status': 0,
  35. 'juyudeng_4#_status': 0, 'juyudeng_5#_status': 1, 'juyudeng_6#_status': 1, 'juyudeng_7#_status': 0,
  36. 'juyudeng_8#_status': 0}
  37. """
  38. sql_point_info = "SELECT serial_number,io_point_name " \
  39. "FROM `data_point_tbl` " \
  40. "WHERE `io_point_name` LIKE 'juyudeng_%_%';"
  41. point_info = self._storage.execute_sql(sql_point_info)
  42. read_real_list = []
  43. point_name_dict = {}
  44. for each in point_info:
  45. serial_number = "c"+str(each["serial_number"])
  46. read_real_list.append(serial_number)
  47. point_name_dict[serial_number] = each["io_point_name"]
  48. real_data_dict = self._storage.get_real_data(read_real_list)
  49. light_real_status = {}
  50. for k, v in real_data_dict.items():
  51. light_real_status[point_name_dict[k]] = v
  52. return light_real_status
  53. def get_light_his_status(self):
  54. """
  55. 获取聚鱼灯的历史状态信息
  56. :return: [{'station_name': 'juyudeng_12#', 'location': '1#', 'control_mode': 0, 'status': 0,
  57. 'definite_time': '[]', 'commands': '{"open_light": [{"res": 65280, "device_id": 1, "start_addr": 0,
  58. "output_value": 65280, "function_code": 5}], "close_light": [{"res": 0, "device_id": 1, "start_addr": 0,
  59. "output_value": 0, "function_code": 5}], "open_photosense": [{"res": 0, "device_id": 1, "start_addr": 2,
  60. "output_value": 0, "function_code": 5}], "close_photosense": [{"res": 65280, "device_id": 1, "start_addr": 2,
  61. "output_value": 65280, "function_code": 5}]}', 'conn_status': 1}, ...]
  62. """
  63. sql_his_info = "SELECT station_name,location,control_mode,status,definite_time,commands,conn_status " \
  64. "FROM `gather_fish_light_control`;"
  65. his_info = self._storage.execute_sql(sql_his_info)
  66. return his_info
  67. def check_status(self):
  68. # 获取聚鱼灯的实时状态:光敏模式的状态、灯的开关状态
  69. light_real_status = self.get_light_real_status()
  70. # print("light_real_status=", light_real_status)
  71. # 获取聚鱼灯的历史状态信息
  72. light_his_status = self.get_light_his_status()
  73. for each in light_his_status:
  74. # {'station_name': 'juyudeng_12#', 'location': '2#', 'control_mode': 1, 'status': 1, 'definite_time': '[["00:00:00,23:59:59"]]', 'commands': '{}', 'conn_status': 0}
  75. station_name = each['station_name'] # 聚鱼灯的站名
  76. location = each['location'] # 聚鱼灯的位置
  77. his_control_mode = each['control_mode'] # 历史控制模式(0=光敏控制 1=手动控制 2=定时控制)
  78. his_status = each['status'] # 历史状态(0=关 1=开,模式1需要获取该参数的值)
  79. his_conn_status = each['conn_status'] # 历史通讯状态(0=在线,1=不在线)
  80. command = json.loads(each['commands']) # 控制开关的指令
  81. guangmin_status = light_real_status[f"{station_name}_guangmin"] # 此刻光敏模式的状态(0=开 1=关)
  82. light_status = light_real_status[f"juyudeng_{location}_status"] # 此刻灯的状态(0=关 1=开)
  83. sql_update = False
  84. all_command = []
  85. # 对比现在的状态和断电之前的状态
  86. try:
  87. if light_status is not None and his_conn_status == 1:
  88. # 现在能读到聚鱼灯的状态且上一次读不到:将聚鱼灯的状态恢复至断电之前的状态,更新conn_status的状态
  89. print(f"{self.now}-[check_status]-{location}聚鱼灯 ({light_status},{guangmin_status}) 1路表示灯开关(0关 1开) 2路表示光敏模式开关(0开 1关)")
  90. if his_control_mode == 0:
  91. # 恢复至光敏模式
  92. if int(guangmin_status) == 1:
  93. # 当前是非光敏模式,需要改为光敏模式
  94. if light_status == 1:
  95. # 先关灯 ??????????关两个灯?????????
  96. all_command.extend(command['close_light'])
  97. print(f"{self.now}-[check_status]-{location}聚鱼灯 先关灯,再设为光敏模式")
  98. # 再开光敏
  99. all_command.extend(command['open_photosense'])
  100. print(f"{self.now}-[check_status]-{location}聚鱼灯 设为光敏模式")
  101. else:
  102. # 当前是光敏模式,不需要处理
  103. # print(f"{self.now}-[check_status]-{location}聚鱼灯 当前是光敏模式,不需要处理")
  104. pass
  105. elif his_control_mode == 1:
  106. # 恢复至手动模式
  107. if int(guangmin_status) == 0:
  108. # 先关闭光敏模式
  109. all_command.extend(command['close_photosense'])
  110. print(f"{self.now}-[check_status]-{location}聚鱼灯 先关闭光敏模式,再修改灯的状态为{his_status}")
  111. if light_status != his_status:
  112. # 聚鱼灯改为his_status的状态(0=关 1=开)
  113. if his_status == 0:
  114. all_command.extend(command['close_light'])
  115. elif his_status == 1:
  116. all_command.extend(command['open_light'])
  117. print(f"{self.now}-[check_status]-{location}聚鱼灯 修改灯的状态为{his_status}")
  118. else:
  119. # print(f"{self.now}-[check_status]-{location}聚鱼灯 状态相同{his_status},不需要处理")
  120. pass
  121. elif his_control_mode == 2:
  122. # 恢复至定时模式
  123. if int(guangmin_status) == 0:
  124. # 先关闭光敏模式
  125. all_command.extend(command['close_photosense'])
  126. print(f"{self.now}-[check_status]-{location}聚鱼灯 定时模式:先关闭光敏模式")
  127. # 判断开关灯在 command_polling 方法中
  128. # 更新conn_status的状态
  129. sql_update = f"UPDATE `gather_fish_light_control` SET conn_status=0 WHERE `location`='{location}';"
  130. elif light_status is None and his_conn_status == 0:
  131. # 现在读不到聚鱼灯的状态且上一次能读到:更新conn_status的状态
  132. sql_update = f"UPDATE `gather_fish_light_control` SET conn_status=1 WHERE location='{location}';"
  133. elif light_status is None and his_conn_status == 1:
  134. # print(f"{self.now}-[check_status]-{location}聚鱼灯一直处于离线状态,不做处理")
  135. pass
  136. elif light_status is not None and his_conn_status == 0:
  137. # 聚鱼灯一直处于在线状态
  138. if int(his_status) == int(light_status):
  139. # print(f"{self.now}-[check_status]-{location}聚鱼灯一直处于在线状态,status与当前状态一致!")
  140. pass
  141. else:
  142. # 更新status字段的状态(control_mode字段的状态由前端调接口修改)
  143. sql_update = f"UPDATE `gather_fish_light_control` SET status={light_status} WHERE `location`='{location}';"
  144. print(f"{self.now}-[check_status]-{location}聚鱼灯一直处于在线状态,保存当前模式status={light_status}")
  145. # 执行修改状态的指令
  146. if len(all_command) > 0:
  147. # jyd_connectors = Utility.available_connectors[f"juyudeng_{location}"]
  148. jyd_connectors = Utility.available_connectors[station_name]
  149. for each_command in all_command:
  150. print(f"{self.now}-[check_status]-{location}聚鱼灯 {each_command}")
  151. jyd_connectors.send_command(each_command)
  152. if sql_update:
  153. print(f"{self.now}-[check_status]-{location}聚鱼灯 {sql_update}")
  154. self._storage.execute_update_sql(sql_update)
  155. except Exception as e:
  156. print(f"{self.now}-[check_status]-{location}聚鱼灯 ERROR:{e}")
  157. self._log.error(e)
  158. def get_real_status(self):
  159. """
  160. 获取聚鱼灯的实时状态
  161. return:{'juyudeng_1#': '1', 'juyudeng_2#': None, 'juyudeng_3#': None,...}
  162. """
  163. juyudeng_point_sql = "SELECT serial_number,io_point_name FROM `data_point_tbl` WHERE `io_point_name` LIKE 'juyudeng_%_status';"
  164. juyudeng_point = self._storage.execute_sql(juyudeng_point_sql)
  165. read_real_list = []
  166. point_name_dict = {}
  167. for each in juyudeng_point:
  168. serial_number = "c"+str(each["serial_number"])
  169. read_real_list.append(serial_number)
  170. juyudeng_name = each["io_point_name"].replace("_status", "")
  171. point_name_dict[serial_number] = juyudeng_name
  172. real_data_dict = self._storage.get_real_data(read_real_list)
  173. light_real_status = {}
  174. for k,v in real_data_dict.items():
  175. light_real_status[point_name_dict[k]] = v
  176. return light_real_status
  177. def update_juyudeng_status(self):
  178. """判断聚鱼灯的状态是否需要修改"""
  179. # 获取聚鱼灯的实时状态
  180. all_light_real_status = self.get_real_status() # {'juyudeng_1#': '1', 'juyudeng_2#': None,...}
  181. # print(all_light_real_status)
  182. # 判断聚鱼灯的状态是否需要修改
  183. juyudeng_info_sql = "SELECT station_name,location,control_mode,definite_time,commands FROM `gather_fish_light_control`;"
  184. get_juyudeng_info = self._storage.execute_sql(juyudeng_info_sql)
  185. for juyudeng_info in get_juyudeng_info:
  186. # {'location': '1#', 'control_mode': 0, 'definite_time': '[["06:00:00,10:59:59"], ["00:03:00,03:50:59"]]', 'commands': None}
  187. control_mode = juyudeng_info["control_mode"] # 0:光敏控制,1:手动控制,2:定时控制
  188. if control_mode == 0:
  189. '''光敏模式:前端发送控制指令'''
  190. pass
  191. elif control_mode == 1:
  192. '''手动模式:前端发送控制指令'''
  193. pass
  194. elif control_mode == 2:
  195. '''定时模式'''
  196. light_status = 0 # 默认聚鱼灯处于关闭状态
  197. now_time = datetime.now().strftime("%H:%M:%S")
  198. definite_time = json.loads(juyudeng_info["definite_time"])
  199. # 依次判断每个时间段
  200. for time_list in definite_time:
  201. each_time = time_list[0].split(",")
  202. time1 = each_time[0]
  203. time2 = each_time[1]
  204. if time1 < time2:
  205. if time1 <= now_time <= time2:
  206. light_status = 1
  207. else:
  208. if time2 <= now_time <= time1:
  209. light_status = 1
  210. # 判断是否需要修改当前状态
  211. light_name = f"juyudeng_{juyudeng_info['location']}"
  212. station_name = juyudeng_info['station_name'] # 聚鱼灯的站名
  213. light_real_status = all_light_real_status[light_name]
  214. # print("///////////////////////",light_name, light_real_status, light_status)
  215. if light_real_status is None or int(light_status) != int(light_real_status):
  216. commands = json.loads(juyudeng_info["commands"])
  217. if int(light_status) == 0:
  218. # 关灯
  219. command = commands["close_light"]
  220. elif int(light_status) == 1:
  221. # 开灯
  222. command = commands["open_light"]
  223. # print(light_name, light_real_status. light_status, command)
  224. try:
  225. Utility.available_connectors[station_name].send_command(command)
  226. except Exception as e:
  227. self._log.error(e)
  228. """
  229. station_name:
  230. juyudeng_12#
  231. juyudeng_34#
  232. juyudeng_56#
  233. juyudeng_78#
  234. 开灯1/3/5/7:[{"res": 65280, "device_id": 1, "start_addr": 0, "output_value": 65280, "function_code": 5}]
  235. 关灯1/3/5/7:[{"res": 0, "device_id": 1, "start_addr": 0, "output_value": 0, "function_code": 5}]
  236. 开灯2/4/6/8:[{"res": 65280, "device_id": 1, "start_addr": 1, "output_value": 65280, "function_code": 5}]
  237. 关灯2/4/6/8:[{"res": 0, "device_id": 1, "start_addr": 1, "output_value": 0, "function_code": 5}]
  238. 开光敏1-8:[{"res": 0, "device_id": 1, "start_addr": 2, "output_value": 0, "function_code": 5}]
  239. 关光敏1-8:[{"res": 65280, "device_id": 1, "start_addr": 2, "output_value": 65280, "function_code": 5}]
  240. 1/3/5/7
  241. {"open_light": [{"res": 65280, "device_id": 1, "start_addr": 0, "output_value": 65280, "function_code": 5}],
  242. "close_light": [{"res": 0, "device_id": 1, "start_addr": 0, "output_value": 0, "function_code": 5}],
  243. "open_photosense": [{"res": 0, "device_id": 1, "start_addr": 2, "output_value": 0, "function_code": 5}],
  244. "close_photosense": [{"res": 65280, "device_id": 1, "start_addr": 2, "output_value": 65280, "function_code": 5}]}
  245. 2/4/6/8
  246. {"open_light": [{"res": 65280, "device_id": 1, "start_addr": 1, "output_value": 65280, "function_code": 5}],
  247. "close_light": [{"res": 0, "device_id": 1, "start_addr": 1, "output_value": 0, "function_code": 5}],
  248. "open_photosense": [{"res": 0, "device_id": 1, "start_addr": 2, "output_value": 0, "function_code": 5}],
  249. "close_photosense": [{"res": 65280, "device_id": 1, "start_addr": 2, "output_value": 65280, "function_code": 5}]}
  250. """