SmartSocketController.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : SmartSocketController.py
  4. @Time : 2023/3/17 11:52
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import logging
  10. import time
  11. from django.db import transaction
  12. from django.http import QueryDict
  13. from django.views import View
  14. from Model.models import SocketInfo, SocketSchedule, Device_Info
  15. from Object.ResponseObject import ResponseObject
  16. from Object.TokenObject import TokenObject
  17. from Service.CommonService import CommonService
  18. LOGGER = logging.getLogger('info')
  19. SOCKET_TOPIC_NAME = 'loocam/smart-socket/{}' # 插座发布消息主题(因设备当前版本只能订阅一个主题)
  20. class SmartSocketView(View):
  21. def get(self, request, *args, **kwargs):
  22. request.encoding = 'utf-8'
  23. operation = kwargs.get('operation')
  24. return self.validation(request.GET, request, operation)
  25. def post(self, request, *args, **kwargs):
  26. request.encoding = 'utf-8'
  27. operation = kwargs.get('operation')
  28. return self.validation(request.POST, request, operation)
  29. def delete(self, request, *args, **kwargs):
  30. request.encoding = 'utf-8'
  31. operation = kwargs.get('operation')
  32. delete = QueryDict(request.body)
  33. if not delete:
  34. delete = request.GET
  35. return self.validation(delete, request, operation)
  36. def put(self, request, *args, **kwargs):
  37. request.encoding = 'utf-8'
  38. operation = kwargs.get('operation')
  39. put = QueryDict(request.body)
  40. return self.validation(put, request, operation)
  41. def validation(self, request_dict, request, operation):
  42. token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
  43. lang = request_dict.get('lang', 'cn')
  44. response = ResponseObject(lang)
  45. if token.code != 0:
  46. return response.json(token.code)
  47. if operation == 'addSwitch': # 添加插座开关
  48. return self.add_switch(request_dict, response)
  49. elif operation == 'addCountDown': # 添加插座倒计时
  50. return self.add_count_down(request_dict, response)
  51. elif operation == 'addSchedule': # 添加插座排程
  52. return self.save_socket_schedule(request_dict, response)
  53. return response.json(404)
  54. @staticmethod
  55. def get_serial_number_by_device_id(deviceId):
  56. """
  57. 根据设备ID获取序列号
  58. """
  59. device_info = Device_Info.objects.get(id=deviceId)
  60. return device_info.serial_number
  61. @classmethod
  62. def add_switch(cls, request_dict, response):
  63. """
  64. 添加开关
  65. """
  66. device_id = request_dict.get('deviceId', None)
  67. status = request_dict.get('status', None)
  68. if not all([device_id, status]):
  69. return response.json(444)
  70. serial_number = cls.get_serial_number_by_device_id(device_id)
  71. # 保存数据库并下发MQTT消息到插座设备
  72. result = cls.save_socket_switch(device_id, serial_number, int(status))
  73. if not result:
  74. return response.json(177)
  75. return response.json(0)
  76. @staticmethod
  77. def save_socket_switch(device_id, serial_number, status, type_switch=0):
  78. """
  79. 保存插座开关信息
  80. @param device_id: 设备ID
  81. @param serial_number: 序列号
  82. @param status: 状态 0关,1开
  83. @param type_switch: 0:总开关,1倒计时开关
  84. @return: True | False
  85. """
  86. if not device_id:
  87. return False
  88. socket_info_qs = SocketInfo.objects.filter(device_id=device_id, type_switch=type_switch)
  89. now_time = int(time.time())
  90. try:
  91. with transaction.atomic():
  92. # 创建插座开关信息
  93. if not socket_info_qs.exists():
  94. socket_dict = {"device_id": device_id,
  95. "serial_number": serial_number,
  96. "status": status,
  97. "type_switch": type_switch,
  98. "created_time": now_time,
  99. "updated_time": now_time,
  100. "online": True}
  101. SocketInfo.objects.create(**socket_dict)
  102. return True
  103. if socket_info_qs.first().status == status:
  104. return True
  105. socket_info_qs.update(status=status, updated_time=now_time)
  106. # 主题名称
  107. topic_name = SOCKET_TOPIC_NAME.format(serial_number)
  108. # 发布消息内容
  109. msg = {'type': 1, 'data': {'deviceSwitch': status}}
  110. result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  111. LOGGER.info('智能插座开关设置发布MQTT消息结果{}'.format(result))
  112. return True
  113. except Exception as e:
  114. LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  115. return False
  116. @classmethod
  117. def add_count_down(cls, request_dict, response):
  118. """
  119. 添加倒计时
  120. """
  121. device_id = request_dict.get('deviceId', None)
  122. status = request_dict.get('status', None)
  123. start = request_dict.get('start', None)
  124. count_down_time = request_dict.get('countDownTime', None)
  125. if not all([device_id, status, count_down_time]):
  126. return response.json(444)
  127. serial_number = cls.get_serial_number_by_device_id(device_id)
  128. # 保存数据库并下发MQTT消息到插座设备
  129. result = cls.save_socket_count_down(device_id, serial_number, int(status), int(start), int(count_down_time))
  130. if not result:
  131. return response.json(177)
  132. return response.json(0)
  133. @staticmethod
  134. def save_socket_count_down(device_id, serial_number, status, start, count_down_time, type_switch=1):
  135. """
  136. 保存插座倒计时信息
  137. @param count_down_time: 倒计时时间戳
  138. @param start: 是否启动倒计时 0:关闭,1:开始
  139. @param device_id: 设备ID
  140. @param serial_number: 序列号
  141. @param status: 倒计时电源状态 0关,1开
  142. @param type_switch: 0:总开关,1倒计时开关
  143. @return:
  144. """
  145. if not device_id:
  146. return False
  147. socket_info_qs = SocketInfo.objects.filter(device_id=device_id, type_switch=type_switch)
  148. now_time = int(time.time())
  149. try:
  150. with transaction.atomic():
  151. # 创建插座倒计时信息
  152. if not socket_info_qs.exists():
  153. socket_dict = {"device_id": device_id,
  154. "serial_number": serial_number,
  155. "status": status,
  156. "type_switch": type_switch,
  157. "created_time": now_time,
  158. "updated_time": now_time,
  159. "online": True,
  160. "count_down_time": count_down_time}
  161. socket_info_qs = SocketInfo.objects.create(**socket_dict)
  162. count_down_id = socket_info_qs.id
  163. else:
  164. socket_info_qs.update(status=status, count_down_time=count_down_time,
  165. updated_time=now_time)
  166. count_down_id = socket_info_qs.first().id
  167. # 主题名称
  168. topic_name = SOCKET_TOPIC_NAME.format(serial_number)
  169. # 发布消息内容
  170. msg = {'type': 2,
  171. 'data': {'powerType': status,
  172. 'countDownId': count_down_id,
  173. 'time': count_down_time,
  174. 'start': start}}
  175. result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  176. LOGGER.info('智能插座倒计时发布MQTT消息结果{}'.format(result))
  177. return True
  178. except Exception as e:
  179. LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  180. return False
  181. @classmethod
  182. def save_socket_schedule(cls, request_dict, response):
  183. """
  184. 插座添加排程
  185. """
  186. try:
  187. device_id = request_dict.get('deviceId', None)
  188. task_type = request_dict.get('timeType', None)
  189. start_time = request_dict.get('startTime', None)
  190. end_time = request_dict.get('endTime', None)
  191. repeat = request_dict.get('repeat', None)
  192. task_id = request_dict.get('taskId', None)
  193. device_switch = request_dict.get('deviceSwitch', None)
  194. task_switch = request_dict.get('taskSwitch', None)
  195. if not all([task_type, start_time, repeat, device_switch, task_switch]):
  196. return response.json(444)
  197. device_switch = int(device_switch)
  198. task_switch = int(task_switch)
  199. now_time = int(time.time())
  200. data = {'time_type': int(task_type), 'start_time': int(start_time), 'repeat': int(repeat),
  201. 'switch_status': True if device_switch == 1 else False,
  202. 'task_status': True if task_switch == 1 else False}
  203. serial_number = cls.get_serial_number_by_device_id(device_id)
  204. if task_id: # 修改排程
  205. task_id = int(task_id)
  206. socket_schedule_qs = SocketSchedule.objects.filter(id=task_id)
  207. if not socket_schedule_qs.exists():
  208. return response.json(174)
  209. if end_time:
  210. data['end_time'] = int(end_time)
  211. data['updated_time'] = now_time
  212. socket_schedule_qs.update(**data)
  213. else:
  214. # 添加排程
  215. data['device_id'] = device_id
  216. data['serial_number'] = serial_number
  217. data['updated_time'] = now_time
  218. data['created_time'] = now_time
  219. socket_schedule = SocketSchedule.objects.create(**data)
  220. task_id = socket_schedule.id
  221. # 讲排程任务下发给设备
  222. cls.send_socket_schedule(serial_number, task_id, int(task_type), int(start_time),
  223. int(end_time), int(repeat), device_switch,
  224. task_switch)
  225. return response.json(0)
  226. except Exception as e:
  227. LOGGER.info('智能插座异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  228. return False
  229. @staticmethod
  230. def send_socket_schedule(serial_number, task_id, time_type, start_time, end_time, repeat, device_switch,
  231. task_switch):
  232. """
  233. 排程下发设备
  234. @param serial_number: 序列号
  235. @param task_id: 当前排程任务id
  236. @param time_type: 任务类型 0:设定时间,1:设定时间段
  237. @param start_time: 开启时间
  238. @param end_time: 结束时间
  239. @param repeat: 重复日期
  240. @param device_switch: 任务执行后期望设备状态,0:关闭,1:开启
  241. @param task_switch: 任务执行状态 0:不执行,1:执行
  242. @return: True | False
  243. """
  244. msg = {
  245. 'type': 3,
  246. 'data': {'taskId': task_id, 'timeType': time_type,
  247. 'startTime': start_time, 'endTime': end_time,
  248. 'repeat': repeat,
  249. 'deviceSwitch': device_switch,
  250. 'taskSwitch': task_switch}
  251. }
  252. # 主题名称
  253. topic_name = SOCKET_TOPIC_NAME.format(serial_number)
  254. result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  255. LOGGER.info('智能插座排程任务发布MQTT消息结果{}'.format(result))
  256. return result