SmartSceneController.py 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Author : Rocky
  4. @Time : 2022/6/29 9:31
  5. @File :SmartSceneController.py
  6. """
  7. import json
  8. import time
  9. from django.core.exceptions import ObjectDoesNotExist
  10. from django.db import transaction
  11. from django.db.models import F, Q, Count
  12. from django.views import View
  13. from Ansjer.Config.gatewaySensorConfig import SMART_SCENE_TOPIC, SENSOR_TYPE, EVENT_TYPE, SCENE_EVENT_CREATE, \
  14. SCENE_EVENT_EDIT, SCENE_EVENT_DELETE, SCENE_STATUS_ON, SCENE_STATUS_OFF, SCENE_EVENT_EDIT_STATUS
  15. from Model.models import FamilyRoomDevice, GatewaySubDevice, FamilyRoom, SmartScene, EffectiveTime, Device_Info, \
  16. SceneLog
  17. from Object.ResponseObject import ResponseObject
  18. from Service.CommonService import CommonService
  19. class SmartSceneView(View):
  20. def get(self, request, *args, **kwargs):
  21. request.encoding = 'utf-8'
  22. operation = kwargs.get('operation')
  23. return self.validation(request.GET, request, operation)
  24. def post(self, request, *args, **kwargs):
  25. request.encoding = 'utf-8'
  26. operation = kwargs.get('operation')
  27. return self.validation(request.POST, request, operation)
  28. def validation(self, request_dict, request, operation):
  29. if operation == 'get-scene': # 设备获取智能场景数据
  30. return self.get_scene_data(request_dict, ResponseObject('cn'))
  31. token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
  32. if token_code != 0:
  33. return response.json(token_code)
  34. if operation == 'condition-devices': # 添加条件-查询设备
  35. return self.condition_devices(request_dict, response)
  36. elif operation == 'task-devices': # 添加任务-查询设备
  37. return self.task_devices(request_dict, response)
  38. elif operation == 'create': # 创建智能场景
  39. return self.create_smart_scene(request_dict, user_id, response)
  40. elif operation == 'scene-list': # 查询智能场景列表
  41. return self.scene_list(request_dict, user_id, response)
  42. elif operation == 'smart-button-scene-list': # 查询智能按钮场景列表
  43. return self.smart_button_scene_list(request_dict, user_id, response)
  44. elif operation == 'update-status': # 更新智能场景状态
  45. return self.update_status(request_dict, response)
  46. elif operation == 'detail': # 查询智能场景详情
  47. return self.scene_detail(request_dict, response)
  48. elif operation == 'edit': # 编辑智能场景
  49. return self.edit_smart_scene(request_dict, user_id, response)
  50. elif operation == 'delete': # 删除智能场景
  51. return self.delete_smart_scene(request_dict, response)
  52. elif operation == 'log': # 查询智能场景日志
  53. return self.scene_log(request_dict, response)
  54. elif operation == 'log-date': # 查询智能场景日志日期
  55. return self.scene_log_date(request_dict, response)
  56. elif operation == 'voice-audition': # 智能场景音频试听
  57. return self.voice_audition(request_dict, response)
  58. else:
  59. return response.json(414)
  60. @classmethod
  61. def condition_devices(cls, request_dict, response):
  62. """
  63. 添加条件-查询设备
  64. @param request_dict: 请求参数
  65. @request_dict deviceId: 网关设备id
  66. @request_dict subDeviceId: 子设备id
  67. @param response: 响应对象
  68. @return: response
  69. """
  70. device_id = request_dict.get('deviceId', None)
  71. sub_device_id = request_dict.get('subDeviceId', None)
  72. if not any([device_id, sub_device_id]):
  73. return response.json(444, {'error param': 'deviceId or subDeviceId'})
  74. try:
  75. if sub_device_id:
  76. device_id = GatewaySubDevice.objects.get(id=sub_device_id).device_id
  77. gateway_sub_device_qs = GatewaySubDevice.objects.filter(device_id=device_id)
  78. if not gateway_sub_device_qs.exists():
  79. return response.json(173)
  80. res = cls.get_sub_device_room_name(gateway_sub_device_qs)
  81. return response.json(0, res)
  82. except Exception as e:
  83. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  84. @classmethod
  85. def task_devices(cls, request_dict, response):
  86. """
  87. 添加任务-查询设备
  88. @param request_dict: 请求参数
  89. @request_dict deviceId: 网关设备id
  90. @param response: 响应对象
  91. @return: response
  92. """
  93. sub_device_id = request_dict.get('subDeviceId', None)
  94. device_id = request_dict.get('deviceId', None)
  95. if not any([device_id, sub_device_id]):
  96. return response.json(444, {'error param': 'deviceId or subDeviceId'})
  97. try:
  98. if device_id:
  99. res = [cls.get_gateway_data(device_id)]
  100. else:
  101. sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device_id', 'device_type')
  102. device_id = sub_device_qs[0]['device_id']
  103. device_type = sub_device_qs[0]['device_type']
  104. if device_type != SENSOR_TYPE['smart_button']: # 非智能按钮只返回网关
  105. res = [cls.get_gateway_data(device_id)]
  106. else: # 智能按钮返回网关,门磁和人体传感器(如果存在)
  107. gateway_data = cls.get_gateway_data(device_id)
  108. sub_device_qs = GatewaySubDevice.objects.filter(
  109. Q(Q(device_id=device_id) & Q(device_type=SENSOR_TYPE['door_magnet'])) |
  110. Q(Q(device_id=device_id) & Q(device_type=SENSOR_TYPE['body_sensor']))
  111. ).values('id', 'nickname', 'status', 'device_type')
  112. if sub_device_qs.exists():
  113. res = cls.get_sub_device_room_name(sub_device_qs, gateway_data)
  114. else:
  115. res = [gateway_data]
  116. return response.json(0, res)
  117. except Exception as e:
  118. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  119. @staticmethod
  120. def get_sub_device_room_name(sub_device_qs, gateway_data=None):
  121. """
  122. 获取房间名称
  123. @param sub_device_qs: 子设备信息
  124. @param gateway_data: 网关参数
  125. @return: sub_device_list
  126. """
  127. sub_device_list = []
  128. if gateway_data:
  129. sub_device_list.append(gateway_data)
  130. sub_device_qs = sub_device_qs.annotate(gatewaySubId=F('id'),
  131. deviceType=F('device_type'),
  132. deviceNickName=F('nickname')). \
  133. values('gatewaySubId', 'deviceType', 'deviceNickName', 'status')
  134. for sub_device in sub_device_qs:
  135. family_room_device_qs = FamilyRoomDevice.objects.filter(sub_device=sub_device['gatewaySubId']). \
  136. values('room_id')
  137. if not family_room_device_qs.exists():
  138. sub_device['roomName'] = ''
  139. else:
  140. room_id = family_room_device_qs[0]['room_id']
  141. try:
  142. sub_device['roomName'] = FamilyRoom.objects.get(id=room_id).name
  143. except ObjectDoesNotExist:
  144. sub_device['roomName'] = ''
  145. sub_device_list.append(sub_device)
  146. return sub_device_list
  147. @staticmethod
  148. def get_gateway_data(device_id):
  149. """
  150. 获取网关数据
  151. @param device_id: 网关设备id
  152. @return: res
  153. """
  154. device_info_qs = Device_Info.objects.filter(id=device_id).values('NickName', 'Type', 'serial_number')
  155. nickname = device_info_qs[0]['NickName']
  156. device_type = device_info_qs[0]['Type']
  157. serial_number = device_info_qs[0]['serial_number']
  158. room_id = FamilyRoomDevice.objects.filter(device_id=device_id).values('room_id')[0]['room_id']
  159. room_id_qs = FamilyRoom.objects.filter(id=room_id).values('name')
  160. room_name = room_id_qs.first()['name'] if room_id_qs.exists() else ''
  161. res = {
  162. 'serialNumber': serial_number,
  163. 'deviceNickName': nickname,
  164. 'deviceType': device_type,
  165. 'roomName': room_name,
  166. 'status': 1,
  167. }
  168. return res
  169. @staticmethod
  170. def create_smart_scene(request_dict, user_id, response):
  171. """
  172. 创建智能场景
  173. @param request_dict: 请求参数
  174. @param user_id: 用户id
  175. @request_dict deviceId: 网关设备id
  176. @request_dict subDeviceId: 子设备id
  177. @request_dict sceneName: 场景名称
  178. @request_dict conditions: 条件
  179. @request_dict tasks: 任务
  180. @request_dict isAllDay: 是否全天执行
  181. @request_dict startTime: 开始时间
  182. @request_dict endTime: 结束时间
  183. @request_dict repeat: 重复周期
  184. @param response: 响应对象
  185. @return: response
  186. """
  187. device_id = request_dict.get('deviceId', None)
  188. sub_device_id = request_dict.get('subDeviceId', None)
  189. scene_name = request_dict.get('sceneName', None)
  190. conditions = request_dict.get('conditions', None)
  191. tasks = request_dict.get('tasks', None)
  192. is_all_day = request_dict.get('isAllDay', None)
  193. if not all([scene_name, conditions, tasks]):
  194. return response.json(444, {'error param': 'scene_name and conditions and tasks'})
  195. now_time = int(time.time())
  196. conditions_dict = eval(conditions)
  197. tasks_list = eval(tasks)
  198. try:
  199. # 判断是否已存在该场景名
  200. smart_scene_qs = SmartScene.objects.filter(user_id=user_id, scene_name=scene_name)
  201. if smart_scene_qs.exists():
  202. return response.json(179)
  203. smart_scene_dict = {
  204. 'user_id': user_id,
  205. 'scene_name': scene_name,
  206. 'conditions': conditions,
  207. 'tasks': tasks,
  208. 'created_time': now_time,
  209. 'updated_time': now_time,
  210. }
  211. msg = {
  212. 'scene_event': SCENE_EVENT_CREATE,
  213. 'scene_status': SCENE_STATUS_ON
  214. }
  215. # 处理设置时间
  216. if is_all_day is not None:
  217. is_all_day = int(is_all_day)
  218. smart_scene_dict['is_all_day'] = is_all_day
  219. # 处理传网关设备id和子设备id的情况
  220. if conditions_dict['type'] == 1: # 网关设置时间
  221. if not device_id:
  222. return response.json(444, {'error param': 'deviceId'})
  223. smart_scene_dict['device_id'] = device_id
  224. device_info_qs = Device_Info.objects.filter(id=device_id).values('serial_number')
  225. if not device_info_qs.exists():
  226. return response.json(173)
  227. serial_number = device_info_qs[0]['serial_number']
  228. else: # 子设备设置场景
  229. if not sub_device_id:
  230. return response.json(444, {'error param': 'subDeviceId'})
  231. device_type = int(conditions_dict['sensor']['device_type'])
  232. # 智能按钮不能创建触发条件相同的场景
  233. if device_type == SENSOR_TYPE['smart_button']:
  234. event_type = conditions_dict['sensor']['eventValues'][0]['event_type']
  235. smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id,
  236. conditions__contains=event_type)
  237. if smart_scene_qs.exists():
  238. return response.json(180)
  239. # 温湿度传感器返回温湿度
  240. elif device_type == SENSOR_TYPE['tem_hum_sensor']:
  241. event_values = conditions_dict['sensor']['eventValues'][0]
  242. if '≥' in event_values['value']:
  243. replace_str = '≥ '
  244. msg['sensor_symbol'] = 2
  245. else:
  246. replace_str = '≤ '
  247. msg['sensor_symbol'] = 1
  248. value = event_values['value'].replace(replace_str, '')
  249. msg['sensor_data'] = float(value)
  250. smart_scene_dict['sub_device_id'] = sub_device_id
  251. sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device__serial_number',
  252. 'ieee_addr')
  253. if not sub_device_qs.exists():
  254. return response.json(173)
  255. serial_number = sub_device_qs[0]['device__serial_number']
  256. msg['sensor_type'] = int(conditions_dict['sensor']['device_type'])
  257. msg['sensor_ieee_addr'] = sub_device_qs[0]['ieee_addr']
  258. msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
  259. with transaction.atomic():
  260. if is_all_day is None: # 不设置时间
  261. smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
  262. # 设备的time数据,分钟转为秒
  263. time_dict = {
  264. 'start_time': conditions_dict['time']['minutes'] * 60,
  265. 'repeat': conditions_dict['time']['repeat']
  266. }
  267. elif is_all_day == 1: # 全天
  268. smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
  269. # 设备的time数据
  270. time_dict = {
  271. 'is_all_day': is_all_day
  272. }
  273. elif is_all_day == 2: # 非全天
  274. start_time = int(request_dict.get('startTime', None))
  275. end_time = int(request_dict.get('endTime', None))
  276. repeat = int(request_dict.get('repeat', None))
  277. effective_time_qs = EffectiveTime.objects.filter(start_time=start_time, end_time=end_time,
  278. repeat=repeat).values('id')
  279. if effective_time_qs.exists():
  280. effective_time_id = effective_time_qs[0]['id']
  281. else:
  282. effective_time_id = EffectiveTime.objects.create(start_time=start_time, end_time=end_time,
  283. repeat=repeat).id
  284. smart_scene_dict['effective_time_id'] = effective_time_id
  285. smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
  286. # 设备的time数据,分钟转为秒
  287. time_dict = {
  288. 'is_all_day': is_all_day,
  289. 'start_time': start_time * 60,
  290. 'end_time': end_time * 60,
  291. 'repeat': repeat
  292. }
  293. else:
  294. return response.json(444, {'error param': 'invalid isAllDay'})
  295. msg['time'] = time_dict
  296. msg['scene_id'] = smart_scene_qs.id
  297. task_list = []
  298. for task in tasks_list:
  299. sensor_type = int(task['device_type'])
  300. task_temp = {
  301. 'sensor_type': sensor_type
  302. }
  303. if sensor_type != -1: # 不为-1时需要其他数据
  304. task_temp['sensor_action'] = int(task['event_type'])
  305. # 延时
  306. if 'delay_time' in task and task['delay_time'] != 0:
  307. task_temp['sensor_delay'] = task['delay_time']
  308. # 子设备返回长地址
  309. sub_device_id = task.get('subDeviceId', None)
  310. if sub_device_id:
  311. sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('ieee_addr').first()
  312. task_temp['sensor_ieee_addr'] = sub_device_qs['ieee_addr']
  313. # 网关添加报警类型数据
  314. else:
  315. task_temp['voice_type'] = task.get('voice_type')
  316. task_temp['voice_id'] = task.get('voice_id')
  317. task_temp['count'] = task.get('count')
  318. task_temp['delay_time'] = task.get('delay_time')
  319. task_temp['duration'] = task.get('duration')
  320. task_temp['value_type'] = task.get('value_type')
  321. task_list.append(task_temp)
  322. msg['task'] = task_list
  323. smart_scene_qs.device_data = json.dumps(msg)
  324. smart_scene_qs.save()
  325. # 发布MQTT消息通知网关设备
  326. thing_name = serial_number
  327. topic_name = SMART_SCENE_TOPIC.format(serial_number)
  328. success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg)
  329. try:
  330. assert success
  331. except AssertionError:
  332. return response.json(10044)
  333. return response.json(0)
  334. except Exception as e:
  335. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  336. @staticmethod
  337. def scene_list(request_dict, user_id, response):
  338. """
  339. 查询智能场景列表
  340. @param request_dict: 请求参数
  341. @param user_id: 用户id
  342. @request_dict deviceId: 网关设备id
  343. @request_dict subDeviceId: 子设备id
  344. @param response: 响应对象
  345. @return: response
  346. """
  347. device_id = request_dict.get('deviceId', None)
  348. sub_device_id = request_dict.get('subDeviceId', None)
  349. if not any([device_id, sub_device_id]):
  350. return response.json(444, {'error param': 'deviceId or subDeviceId'})
  351. try:
  352. if device_id:
  353. sub_device_id = GatewaySubDevice.objects.filter(device_id=device_id).values('id')
  354. smart_scene_qs = SmartScene.objects.filter(
  355. Q(user_id=user_id) & Q(device_id=device_id) | Q(sub_device_id__in=sub_device_id))
  356. else:
  357. smart_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id)
  358. if not smart_scene_qs.exists():
  359. return response.json(173)
  360. smart_scene_qs = smart_scene_qs.values('id', 'scene_name', 'is_enable', 'device_id', 'sub_device_id')
  361. smart_scene_list = []
  362. for item in smart_scene_qs:
  363. smart_scene_dict = {
  364. 'id': item['id'],
  365. 'scene_name': item['scene_name'],
  366. 'is_enable': item['is_enable']
  367. }
  368. if item['device_id']:
  369. device_qs = Device_Info.objects.filter(id=item['device_id'], userID=user_id).values('NickName',
  370. 'Type')
  371. smart_scene_dict['device_type'] = device_qs[0]['Type'] if device_qs.exists() else ''
  372. smart_scene_dict['device_nickname'] = device_qs[0]['NickName'] if device_qs.exists() else ''
  373. else:
  374. device_qs = GatewaySubDevice.objects.filter(id=item['sub_device_id']).values('device_type',
  375. 'nickname')
  376. smart_scene_dict['device_type'] = device_qs[0]['device_type'] if device_qs.exists() else ''
  377. smart_scene_dict['device_nickname'] = device_qs[0]['nickname'] if device_qs.exists() else ''
  378. smart_scene_list.append(smart_scene_dict)
  379. return response.json(0, smart_scene_list)
  380. except Exception as e:
  381. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  382. @staticmethod
  383. def smart_button_scene_list(request_dict, user_id, response):
  384. """
  385. 查询智能按钮场景列表
  386. @param request_dict: 请求参数
  387. @param user_id: 用户id
  388. @request_dict subDeviceId: 子设备id
  389. @param response: 响应对象
  390. @return: response
  391. """
  392. sub_device_id = request_dict.get('subDeviceId', None)
  393. if not sub_device_id:
  394. return response.json(444, {'error param': 'subDeviceId'})
  395. try:
  396. click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
  397. conditions__contains=str(
  398. EVENT_TYPE['smart_button_click'])).values('id', 'scene_name',
  399. 'is_enable')
  400. double_click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
  401. conditions__contains=str(
  402. EVENT_TYPE['smart_button_double_click'])). \
  403. values('id', 'scene_name', 'is_enable')
  404. three_click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
  405. conditions__contains=str(
  406. EVENT_TYPE['smart_button_three_click'])). \
  407. values('id', 'scene_name', 'is_enable')
  408. scene_list = []
  409. if click_scene_qs.exists():
  410. scene_list.append({
  411. 'trigger_type': 1,
  412. 'id': click_scene_qs[0]['id'],
  413. 'scene_name': click_scene_qs[0]['scene_name'],
  414. 'is_enable': click_scene_qs[0]['is_enable']
  415. })
  416. if double_click_scene_qs.exists():
  417. scene_list.append({
  418. 'trigger_type': 2,
  419. 'id': double_click_scene_qs[0]['id'],
  420. 'scene_name': double_click_scene_qs[0]['scene_name'],
  421. 'is_enable': double_click_scene_qs[0]['is_enable']
  422. })
  423. if three_click_scene_qs.exists():
  424. scene_list.append({
  425. 'trigger_type': 3,
  426. 'id': three_click_scene_qs[0]['id'],
  427. 'scene_name': three_click_scene_qs[0]['scene_name'],
  428. 'is_enable': three_click_scene_qs[0]['is_enable']
  429. })
  430. return response.json(0, scene_list)
  431. except Exception as e:
  432. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  433. @staticmethod
  434. def update_status(request_dict, response):
  435. """
  436. 更新智能场景状态
  437. @param request_dict: 请求参数
  438. @request_dict smartSceneId: 智能场景id
  439. @request_dict isEnable: 状态,True or False
  440. @param response: 响应对象
  441. @return: response
  442. """
  443. smart_scene_id = request_dict.get('smartSceneId', None)
  444. is_enable = request_dict.get('isEnable', None)
  445. if not all([smart_scene_id, is_enable]):
  446. return response.json(444, {'error param': 'smartSceneId and status'})
  447. try:
  448. smart_scene_id = int(smart_scene_id)
  449. scene_status = SCENE_STATUS_ON if is_enable == 'True' else SCENE_STATUS_OFF
  450. msg = {
  451. 'scene_event': SCENE_EVENT_EDIT_STATUS,
  452. 'scene_id': smart_scene_id,
  453. 'scene_status': scene_status
  454. }
  455. # 查询序列号
  456. smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('device_id', 'sub_device_id')
  457. device_id = smart_scene_qs[0]['device_id']
  458. if device_id:
  459. serial_number = Device_Info.objects.filter(id=device_id).values('serial_number')[0]['serial_number']
  460. else:
  461. sub_device_id = smart_scene_qs[0]['sub_device_id']
  462. serial_number = GatewaySubDevice.objects.filter(id=sub_device_id).values('device__serial_number')[0][
  463. 'device__serial_number']
  464. topic_name = SMART_SCENE_TOPIC.format(serial_number)
  465. with transaction.atomic():
  466. SmartScene.objects.filter(id=smart_scene_id).update(is_enable=is_enable)
  467. # 通过mqtt发送设备数据
  468. success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  469. try:
  470. assert success
  471. except AssertionError:
  472. return response.json(10044)
  473. return response.json(0)
  474. except Exception as e:
  475. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  476. @staticmethod
  477. def scene_detail(request_dict, response):
  478. """
  479. 查询智能场景详情
  480. @param request_dict: 请求参数
  481. @request_dict smartSceneId: 智能场景id
  482. @param response: 响应对象
  483. @return: response
  484. """
  485. smart_scene_id = request_dict.get('smartSceneId', None)
  486. if not smart_scene_id:
  487. return response.json(444, {'error param': 'smartSceneId'})
  488. try:
  489. smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('id', 'scene_name', 'conditions',
  490. 'tasks', 'effective_time_id',
  491. 'is_all_day')
  492. if not smart_scene_qs.exists():
  493. return response.json(173)
  494. res = {
  495. 'scene_name': smart_scene_qs[0]['scene_name'],
  496. 'condition': eval(smart_scene_qs[0]['conditions']),
  497. 'task': eval(smart_scene_qs[0]['tasks']),
  498. }
  499. # 如果存在关联的时间数据,组织时间数据
  500. is_all_day = smart_scene_qs[0]['is_all_day']
  501. effectiveTime = {}
  502. if is_all_day != 0:
  503. effectiveTime['isAllDay'] = is_all_day
  504. if is_all_day == 2:
  505. try:
  506. effective_time_qs = EffectiveTime.objects.get(id=smart_scene_qs[0]['effective_time_id'])
  507. effectiveTime['startTime'] = effective_time_qs.start_time
  508. effectiveTime['endTime'] = effective_time_qs.end_time
  509. effectiveTime['repeat'] = effective_time_qs.repeat
  510. except ObjectDoesNotExist:
  511. return response.json(0, res)
  512. res['effectiveTime'] = effectiveTime
  513. return response.json(0, res)
  514. except Exception as e:
  515. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  516. @staticmethod
  517. def edit_smart_scene(request_dict, user_id, response):
  518. """
  519. 编辑智能场景
  520. @param request_dict: 请求参数
  521. @param user_id: 用户id
  522. @request_dict smartSceneId: 智能场景id
  523. @param response: 响应对象
  524. @return: response
  525. """
  526. smart_scene_id = int(request_dict.get('smartSceneId', None))
  527. device_id = request_dict.get('deviceId', None)
  528. sub_device_id = request_dict.get('subDeviceId', None)
  529. scene_name = request_dict.get('sceneName', None)
  530. conditions = request_dict.get('conditions', None)
  531. tasks = request_dict.get('tasks', None)
  532. is_all_day = request_dict.get('isAllDay', None)
  533. conditions_dict = eval(conditions)
  534. tasks_list = eval(tasks)
  535. now_time = int(time.time())
  536. smart_scene_qs = SmartScene.objects.filter(user_id=user_id, scene_name=scene_name).filter(~Q(id=smart_scene_id))
  537. if smart_scene_qs.exists():
  538. return response.json(179)
  539. res = {
  540. 'scene_name': scene_name,
  541. 'conditions': conditions_dict,
  542. 'tasks': tasks_list
  543. }
  544. effective_time = {}
  545. if is_all_day:
  546. is_all_day = int(is_all_day)
  547. effective_time['is_all_day'] = is_all_day
  548. if not all([smart_scene_id, scene_name, conditions, tasks]):
  549. return response.json(444, {'error param': 'smartSceneId,sceneName,conditions or tasks'})
  550. try:
  551. smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id)
  552. if not smart_scene_qs.exists():
  553. return response.json(173)
  554. scene_status = 1 if smart_scene_qs[0].is_enable else 0
  555. msg = {
  556. 'scene_id': smart_scene_id,
  557. 'scene_event': SCENE_EVENT_EDIT,
  558. 'scene_status': scene_status
  559. }
  560. if conditions_dict['type'] == 2: # 条件为选择子设备
  561. if not sub_device_id:
  562. return response.json(444, {'error param': 'subDeviceId'})
  563. device_type = int(conditions_dict['sensor']['device_type'])
  564. # 智能按钮不能创建触发条件相同的场景
  565. if device_type == SENSOR_TYPE['smart_button']:
  566. event_type = conditions_dict['sensor']['eventValues'][0]['event_type']
  567. smart_scene_temp_qs = SmartScene.objects.filter(Q(sub_device_id=sub_device_id),
  568. ~Q(id=smart_scene_id),
  569. conditions__contains=event_type)
  570. if smart_scene_temp_qs.exists():
  571. return response.json(180)
  572. # 温湿度传感器返回温湿度
  573. elif device_type == SENSOR_TYPE['tem_hum_sensor']:
  574. event_values = conditions_dict['sensor']['eventValues'][0]
  575. if '≥' in event_values['value']:
  576. replace_str = '≥ '
  577. msg['sensor_symbol'] = 2
  578. else:
  579. replace_str = '≤ '
  580. msg['sensor_symbol'] = 1
  581. value = event_values['value'].replace(replace_str, '')
  582. msg['sensor_data'] = float(value)
  583. device_id = ''
  584. sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('ieee_addr',
  585. 'device__serial_number')
  586. if not sub_device_qs.exists():
  587. return response.json(173)
  588. serial_number = sub_device_qs[0]['device__serial_number']
  589. msg['sensor_type'] = int(conditions_dict['sensor']['device_type'])
  590. msg['sensor_ieee_addr'] = sub_device_qs[0]['ieee_addr']
  591. msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
  592. else:
  593. if not device_id:
  594. return response.json(444, {'error param': 'deviceId'})
  595. sub_device_id = 0
  596. device_qs = Device_Info.objects.filter(id=device_id).values('serial_number')
  597. if not device_qs.exists():
  598. return response.json(173)
  599. serial_number = device_qs[0]['serial_number']
  600. task_list = []
  601. for task in tasks_list:
  602. sensor_type = int(task['device_type'])
  603. task_temp = {
  604. 'sensor_type': sensor_type
  605. }
  606. if sensor_type != -1: # 不为-1时需要其他数据
  607. task_temp['sensor_action'] = int(task['event_type'])
  608. # 延时
  609. if 'delay_time' in task and task['delay_time'] != 0:
  610. task_temp['sensor_delay'] = task['delay_time']
  611. # 子设备返回长地址
  612. task_sub_device_id = task.get('subDeviceId', None)
  613. if task_sub_device_id:
  614. sub_device_qs = GatewaySubDevice.objects.filter(id=task_sub_device_id).values('ieee_addr').first()
  615. task_temp['sensor_ieee_addr'] = sub_device_qs['ieee_addr']
  616. # 网关添加报警类型数据
  617. else:
  618. task_temp['voice_type'] = task.get('voice_type')
  619. task_temp['voice_id'] = task.get('voice_id')
  620. task_temp['count'] = task.get('count')
  621. task_temp['delay_time'] = task.get('delay_time')
  622. task_temp['duration'] = task.get('duration')
  623. task_temp['value_type'] = task.get('value_type')
  624. task_list.append(task_temp)
  625. msg['task'] = task_list
  626. with transaction.atomic():
  627. smart_scene_qs.update(scene_name=scene_name, conditions=conditions, tasks=tasks,
  628. device_data=json.dumps(msg), updated_time=now_time, device_id=device_id,
  629. sub_device_id=sub_device_id)
  630. if is_all_day is None: # 不设置时间或全天
  631. smart_scene_qs.update(effective_time_id=0, is_all_day=0)
  632. time_dict = {
  633. 'start_time': conditions_dict['time']['minutes'] * 60,
  634. 'repeat': conditions_dict['time']['repeat']
  635. }
  636. elif is_all_day == 1:
  637. smart_scene_qs.update(effective_time_id=0, is_all_day=is_all_day)
  638. time_dict = {
  639. 'is_all_day': is_all_day
  640. }
  641. else:
  642. start_time = int(request_dict.get('startTime', None))
  643. end_time = int(request_dict.get('endTime', None))
  644. repeat = int(request_dict.get('repeat', None))
  645. effective_time_qs = EffectiveTime.objects.filter(start_time=start_time, end_time=end_time,
  646. repeat=repeat).values('id')
  647. if effective_time_qs.exists():
  648. effective_time_id = effective_time_qs[0]['id']
  649. else:
  650. effective_time_id = EffectiveTime.objects.create(start_time=start_time, end_time=end_time,
  651. repeat=repeat).id
  652. smart_scene_qs.update(effective_time_id=effective_time_id, is_all_day=is_all_day)
  653. time_dict = {
  654. 'is_all_day': is_all_day,
  655. 'start_time': start_time * 60,
  656. 'end_time': end_time * 60,
  657. 'repeat': repeat
  658. }
  659. effective_time = {
  660. 'isAllDay': is_all_day,
  661. 'startTime': start_time,
  662. 'endTime': end_time,
  663. 'repeat': repeat
  664. }
  665. msg['time'] = time_dict
  666. # 通过mqtt发送设备数据
  667. thing_name = serial_number
  668. topic_name = SMART_SCENE_TOPIC.format(serial_number)
  669. success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg)
  670. try:
  671. assert success
  672. except AssertionError:
  673. return response.json(10044)
  674. res['effectiveTime'] = effective_time
  675. return response.json(0, res)
  676. except Exception as e:
  677. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  678. @staticmethod
  679. def delete_smart_scene(request_dict, response):
  680. """
  681. 删除智能场景
  682. @param request_dict: 请求参数
  683. @request_dict smartSceneIds: 智能场景id
  684. @param response: 响应对象
  685. @return: response
  686. """
  687. smart_scene_ids = request_dict.get('smartSceneIds', None)
  688. if not smart_scene_ids:
  689. return response.json(444, {'error param': 'smartSceneIds'})
  690. try:
  691. smart_scene_id_list = smart_scene_ids.split(',')
  692. # 获取序列号
  693. smart_scene_id = smart_scene_id_list[0]
  694. smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('device_id', 'sub_device_id')
  695. device_id = smart_scene_qs[0]['device_id']
  696. if device_id:
  697. serial_number = Device_Info.objects.filter(id=device_id).values('serial_number')[0]['serial_number']
  698. else:
  699. serial_number = GatewaySubDevice.objects.filter(id=smart_scene_qs[0]['sub_device_id']). \
  700. values('device__serial_number')[0]['device__serial_number']
  701. topic_name = SMART_SCENE_TOPIC.format(serial_number)
  702. with transaction.atomic():
  703. SmartScene.objects.filter(id__in=smart_scene_id_list).delete()
  704. for smart_scene_id in smart_scene_id_list:
  705. # 通知设备删除场景id
  706. msg = {
  707. 'scene_event': SCENE_EVENT_DELETE,
  708. 'scene_id': int(smart_scene_id)
  709. }
  710. success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  711. try:
  712. assert success
  713. except AssertionError:
  714. return response.json(10044)
  715. time.sleep(0.3)
  716. return response.json(0)
  717. except Exception as e:
  718. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  719. @staticmethod
  720. def scene_log(request_dict, response):
  721. """
  722. 查询场景日志
  723. @param request_dict: 请求参数
  724. @request_dict deviceId: 网关id
  725. @request_dict subDeviceId: 子设备id
  726. @request_dict page: 页数
  727. @request_dict size: 条数
  728. @request_dict startTime: 开始时间
  729. @request_dict endTime: 结束时间
  730. @param response: 响应对象
  731. @return: response
  732. """
  733. family_id = request_dict.get('familyId', None)
  734. device_id = request_dict.get('deviceId', None)
  735. sub_device_id = request_dict.get('subDeviceId', None)
  736. page = request_dict.get('page', None)
  737. size = request_dict.get('size', None)
  738. start_time = request_dict.get('startTime', None)
  739. end_time = request_dict.get('endTime', None)
  740. if not all([family_id, page, size]):
  741. return response.json(444, {'error param': 'familyId or page or size'})
  742. device_list = []
  743. sub_device_list = []
  744. if not device_id and not sub_device_id:
  745. family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id).values('device', 'sub_device')
  746. for device in family_room_device_qs:
  747. if device['device'] not in device_list:
  748. device_list.append(device['device'])
  749. if device['sub_device']:
  750. sub_device_list.append(device['sub_device'])
  751. elif sub_device_id: # 查询子设备
  752. family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id,
  753. sub_device=sub_device_id).values('device_id')
  754. for device in family_room_device_qs:
  755. device_list.append(device['device_id'])
  756. sub_device_list.append(sub_device_id)
  757. else: # 查询网关
  758. family_room_device_qs = FamilyRoomDevice.objects.filter(Q(family_id=family_id) & Q(device=device_id) &
  759. ~Q(sub_device=0)).values(
  760. 'sub_device')
  761. device_list.append(device_id)
  762. for device in family_room_device_qs:
  763. sub_device_list.append(device['sub_device'])
  764. try:
  765. page, size = int(page), int(size)
  766. scene_log_qs = SceneLog.objects.filter(Q(device_id__in=device_list) | Q(sub_device_id__in=sub_device_list))
  767. if start_time and end_time:
  768. scene_log_qs = scene_log_qs.filter(created_time__range=(start_time, end_time)).values(
  769. 'status',
  770. 'created_time',
  771. 'device_id',
  772. 'sub_device_id',
  773. 'scene_name',
  774. 'tasks').order_by(
  775. '-created_time')[(page - 1) * size:page * size]
  776. else:
  777. scene_log_qs = scene_log_qs.values('status', 'created_time', 'device_id', 'sub_device_id', 'scene_name',
  778. 'tasks').order_by(
  779. '-created_time')[(page - 1) * size:page * size]
  780. if not scene_log_qs.exists():
  781. return response.json(0, [])
  782. for item in scene_log_qs:
  783. if not device_id and not sub_device_id:
  784. if not item['sub_device_id']:
  785. device_qs = Device_Info.objects.filter(id=item['device_id']).values('Type')
  786. item['device_type'] = device_qs[0]['Type'] if device_qs.exists() else ''
  787. else:
  788. device_qs = GatewaySubDevice.objects.filter(id=item['sub_device_id']).values('device_type')
  789. item['device_type'] = device_qs[0]['device_type'] if device_qs.exists() else ''
  790. elif sub_device_id:
  791. device_qs = GatewaySubDevice.objects.filter(id=item['sub_device_id']).values('device_type')
  792. item['device_type'] = device_qs[0]['device_type'] if device_qs.exists() else ''
  793. else:
  794. device_qs = Device_Info.objects.filter(id=item['device_id']).values('Type')
  795. item['device_type'] = device_qs[0]['Type'] if device_qs.exists() else ''
  796. if item['tasks'] != '':
  797. item['tasks'] = eval(item['tasks'])
  798. scene_log_list = list(scene_log_qs)
  799. return response.json(0, scene_log_list)
  800. except Exception as e:
  801. print('error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  802. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  803. @staticmethod
  804. def scene_log_date(request_dict, response):
  805. """
  806. 查询场景日志日期
  807. @param request_dict: 请求参数
  808. @request_dict deviceId: 网关id
  809. @request_dict subDeviceId: 子设备id
  810. @param response: 响应对象
  811. @return: response
  812. """
  813. family_id = request_dict.get('familyId', None)
  814. device_id = request_dict.get('deviceId', None)
  815. sub_device_id = request_dict.get('subDeviceId', None)
  816. if not family_id:
  817. return response.json(444, {'error param': 'familyId'})
  818. device_list = []
  819. sub_device_list = []
  820. if not device_id and not sub_device_id:
  821. family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id).values('device', 'sub_device')
  822. for device in family_room_device_qs:
  823. if device['device'] not in device_list:
  824. device_list.append(device['device'])
  825. if device['sub_device']:
  826. sub_device_list.append(device['sub_device'])
  827. elif sub_device_id:
  828. family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, sub_device=sub_device_id)
  829. sub_device_list.append(sub_device_id)
  830. else:
  831. family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, device=device_id).values(
  832. 'sub_device')
  833. device_list.append(device_id)
  834. for device in family_room_device_qs:
  835. sub_device_list.append(device['sub_device'])
  836. if not family_room_device_qs.exists():
  837. return response.json(173)
  838. try:
  839. scene_log_qs = SceneLog.objects.extra(
  840. select={'date': "FROM_UNIXTIME(created_time,'%%Y-%%m-%%d')"}).values('date'). \
  841. filter(Q(device_id__in=device_list) | Q(sub_device_id__in=sub_device_list)). \
  842. annotate(count=Count('created_time')). \
  843. order_by('-date')[:31]
  844. log_date_list = []
  845. for scene_log in scene_log_qs:
  846. log_date_list.append({
  847. 'timestamp': CommonService.str_to_timestamp(scene_log['date'], '%Y-%m-%d'),
  848. 'count': scene_log['count'],
  849. 'format': scene_log['date'],
  850. })
  851. return response.json(0, log_date_list)
  852. except Exception as e:
  853. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  854. @staticmethod
  855. def get_scene_data(request_dict, response):
  856. """
  857. 设备获取智能场景数据
  858. @param request_dict: 请求参数
  859. @request_dict serial_number: 序列号
  860. @param response: 响应对象
  861. @return: response
  862. """
  863. serial_number = request_dict.get('serial_number', None)
  864. if not serial_number:
  865. return response.json(444, {'error param': 'serial_number'})
  866. try:
  867. device_info_qs = Device_Info.objects.filter(serial_number=serial_number).values('id')
  868. if not device_info_qs.exists():
  869. return response.json(173)
  870. device_id = device_info_qs[0]['id']
  871. sub_device_id_list = GatewaySubDevice.objects.filter(device_id=device_id).values_list('id', flat=True)
  872. if sub_device_id_list:
  873. smart_scene_qs = SmartScene.objects.filter(
  874. Q(device_id=device_id) | Q(sub_device_id__in=sub_device_id_list))
  875. else:
  876. smart_scene_qs = SmartScene.objects.filter(device_id=device_id)
  877. if not smart_scene_qs.exists():
  878. return response.json(173)
  879. # 下发智能场景数据
  880. smart_scene_qs = smart_scene_qs.values('device_data')
  881. topic_name = SMART_SCENE_TOPIC.format(serial_number)
  882. for smart_scene in smart_scene_qs:
  883. msg = eval(smart_scene['device_data'])
  884. success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  885. try:
  886. assert success
  887. except AssertionError:
  888. return response.json(10044)
  889. time.sleep(2)
  890. # 下发智能按钮数据
  891. smart_button_qs = GatewaySubDevice.objects.filter(device_id=device_id,
  892. device_type=SENSOR_TYPE['smart_button']).values(
  893. 'ieee_addr', 'is_tampered')
  894. if smart_button_qs.exists():
  895. sos_count = smart_button_qs.count()
  896. for index, smart_button in enumerate(smart_button_qs):
  897. msg = {
  898. 'sos_count': sos_count, # 该网关下的智能按钮数量
  899. 'sos_num': index + 1, # 第几个按钮
  900. 'sensor_ieee_addr': smart_button['ieee_addr'],
  901. 'sos_select': smart_button['is_tampered']
  902. }
  903. success = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
  904. try:
  905. assert success
  906. except AssertionError:
  907. return response.json(10044)
  908. time.sleep(2)
  909. return response.json(0)
  910. except Exception as e:
  911. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  912. @classmethod
  913. def voice_audition(cls, request_dict, response):
  914. """
  915. 智能场景音频试听
  916. @param request_dict: 请求参数
  917. @request_dict deviceId: 网关设备id
  918. @request_dict subDeviceId: 子设备id
  919. @request_dict voiceId: 音频id
  920. @param response: 响应对象
  921. @return: response
  922. """
  923. device_id = request_dict.get('deviceId', None)
  924. sub_device_id = request_dict.get('subDeviceId', None)
  925. voice_id = request_dict.get('voiceId', None)
  926. if not any([device_id, sub_device_id]) or voice_id is None:
  927. return response.json(444)
  928. try:
  929. if sub_device_id:
  930. device_id = GatewaySubDevice.objects.get(id=sub_device_id).device_id
  931. gateway_sub_device_qs = GatewaySubDevice.objects.filter(device_id=device_id)
  932. if not gateway_sub_device_qs.exists():
  933. return response.json(173)
  934. # 查询序列号
  935. return response.json(0)
  936. except Exception as e:
  937. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  938. #
  939. # ___====-_ _-====___
  940. # _--^^^#####// \\#####^^^--_
  941. # _-^##########// ( ) \\##########^-_
  942. # -############// |\^^/| \\############-
  943. # _/############// (@::@) \\############\_
  944. # /#############(( \\// ))#############\
  945. # -###############\\ (oo) //###############-
  946. # -#################\\ / VV \ //#################-
  947. # -###################\\/ \//###################-
  948. # _#/|##########/\######( /\ )######/\##########|\#_
  949. # |/ |#/\#/\#/\/ \#/\##\ | | /##/\#/ \/\#/\#/\#| \|
  950. # ` |/ V V ` V \#\| | | |/#/ V ' V V \| '
  951. # ` ` ` ` / | | | | \ ' ' ' '
  952. # ( | | | | )
  953. # __\ | | | | /__
  954. # (vvv(VVV)(VVV)vvv)
  955. # 神兽保佑
  956. # 代码无BUG!
  957. #