gatewayController.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Author : Rocky
  4. @Time : 2022/5/9 10:51
  5. @File :gatewayController.py
  6. """
  7. import threading
  8. import time
  9. from django.views.generic.base import View
  10. from AnsjerPush.Config.gatewaySensorConfig import SENSOR_TYPE, EVENT_TYPE
  11. from AnsjerPush.config import LOGGER
  12. from Model.models import SensorRecord, GatewaySubDevice, GatewayPush, Device_Info, SceneLog, SmartScene, CountryModel
  13. from Object.ResponseObject import ResponseObject
  14. from Service.EquipmentInfoService import EquipmentInfoService
  15. from Service.HuaweiPushService.HuaweiPushService import HuaweiPushObject
  16. from Service.PushService import PushObject
  17. class GatewayView(View):
  18. def get(self, request, *args, **kwargs):
  19. request.encoding = 'utf-8'
  20. operation = kwargs.get('operation')
  21. return self.validation(request.GET, operation)
  22. def post(self, request, *args, **kwargs):
  23. request.encoding = 'utf-8'
  24. operation = kwargs.get('operation')
  25. return self.validation(request.POST, operation)
  26. def validation(self, request_dict, operation):
  27. response = ResponseObject()
  28. if operation == 'gatewayPush': # 网关推送
  29. return self.gateway_push(request_dict, response)
  30. elif operation == 'sceneLogPush': # 场景日志推送
  31. return self.scene_log_push(request_dict, response)
  32. elif operation == 'socketPush': # 插座推送
  33. return self.socket_msg_push(request_dict, response)
  34. else:
  35. return response.json(414)
  36. @classmethod
  37. def gateway_push(cls, request_dict, response):
  38. """
  39. 网关推送
  40. @param request_dict: 请求参数
  41. @request_dict serial_number: 序列号
  42. @request_dict ieee_addr: 长地址
  43. @request_dict sensor_type: 传感器类型
  44. @request_dict event_type: 事件类型
  45. @request_dict defense: 防御状态,0:撤防,1:防御
  46. @request_dict sensor_status: 拆动状态,拆动时传参
  47. @param response: 响应对象
  48. @return: response
  49. """
  50. serial_number = request_dict.get('serial_number', None)
  51. ieee_addr = request_dict.get('ieee_addr', None)
  52. sensor_type = int(request_dict.get('sensor_type', None))
  53. event_type = int(request_dict.get('event_type', None))
  54. defense = int(request_dict.get('defense', None))
  55. LOGGER.info('---调用网关推送接口--- request_dict:{}'.format(request_dict))
  56. if not all([serial_number, ieee_addr, sensor_type, event_type]):
  57. return response.json(444)
  58. n_time = int(time.time())
  59. try:
  60. # 查询子设备表id
  61. gateway_sub_device_qs = GatewaySubDevice.objects.filter(device__serial_number=serial_number,
  62. device_type=sensor_type, ieee_addr=ieee_addr). \
  63. values('id', 'nickname', 'device__userID__region_country')
  64. if not gateway_sub_device_qs.exists():
  65. return response.json(173)
  66. country_id = gateway_sub_device_qs[0]['device__userID__region_country']
  67. lang = cls.confirm_lang(country_id)
  68. alarm = cls.get_alarm(lang, event_type)
  69. gateway_sub_device_id = gateway_sub_device_qs[0]['id']
  70. nickname = gateway_sub_device_qs[0]['nickname']
  71. sensor_record_dict = {
  72. 'gateway_sub_device_id': gateway_sub_device_id,
  73. 'alarm': alarm,
  74. 'event_type': event_type,
  75. 'created_time': n_time,
  76. }
  77. # 处理温湿度,不推送
  78. if sensor_type == SENSOR_TYPE['tem_hum_sensor'] and (
  79. event_type == EVENT_TYPE['temperature'] or event_type == EVENT_TYPE['humidity']):
  80. num = request_dict.get('num', None)
  81. num = str(int(num) / 100)
  82. sensor_record_dict['alarm'] = num
  83. SensorRecord.objects.create(**sensor_record_dict)
  84. return response.json(0)
  85. SensorRecord.objects.create(**sensor_record_dict)
  86. # 门磁被拆动/拆动恢复,修改拆动状态
  87. if event_type == 2156:
  88. gateway_sub_device_qs.update(is_tampered=1)
  89. elif event_type == 2152:
  90. gateway_sub_device_qs.update(is_tampered=0)
  91. # 撤防状态不推送
  92. if defense == 0:
  93. return response.json(0)
  94. device_info_qs = Device_Info.objects.filter(serial_number=serial_number).values('userID_id')
  95. if not device_info_qs.exists():
  96. return response.json(173)
  97. equipment_info_list = []
  98. equipment_info_model = EquipmentInfoService.randoms_choice_equipment_info()
  99. # 推送表存储数据
  100. equipment_info_kwargs = {
  101. 'device_uid': serial_number,
  102. 'device_nick_name': nickname,
  103. 'event_type': event_type,
  104. 'event_time': n_time,
  105. 'add_time': n_time,
  106. 'alarm': alarm
  107. }
  108. for device_info in device_info_qs:
  109. user_id = device_info['userID_id']
  110. equipment_info_kwargs['device_user_id'] = user_id
  111. equipment_info_list.append(equipment_info_model(**equipment_info_kwargs))
  112. # 开启异步推送
  113. push_kwargs = {
  114. 'user_id': user_id,
  115. 'n_time': n_time,
  116. 'event_type': event_type,
  117. 'nickname': nickname,
  118. 'alarm': alarm,
  119. }
  120. push_thread = threading.Thread(
  121. target=cls.gateway_push_msg,
  122. kwargs=push_kwargs)
  123. push_thread.start()
  124. if equipment_info_list:
  125. equipment_info_model.objects.bulk_create(equipment_info_list)
  126. return response.json(0)
  127. except Exception as e:
  128. LOGGER.info('---网关推送接口异常--- {}'.format(repr(e)))
  129. return response.json(500, 'error_ine:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  130. @staticmethod
  131. def confirm_lang(country_id):
  132. """
  133. 根据country_id确定语言
  134. @param country_id: 国家id
  135. @return lang: 语言
  136. """
  137. country_qs = CountryModel.objects.filter(id=country_id).values('country_code')
  138. if not country_qs.exists():
  139. lang = 'NA'
  140. else:
  141. lang = country_qs[0]['country_code']
  142. return lang
  143. @staticmethod
  144. def get_alarm(lang, event_type):
  145. """
  146. 根据语言和事件类型确定警报内容
  147. @param lang: 语言
  148. @param event_type: 事件类型
  149. @return alarm: 警报内容
  150. """
  151. alarm = ''
  152. if lang == 'CN':
  153. # 门磁
  154. if event_type == 2150:
  155. alarm = '门磁开'
  156. elif event_type == 2151:
  157. alarm = '门磁关'
  158. elif event_type == 2156:
  159. alarm = '被拆动'
  160. elif event_type == 2152:
  161. alarm = '拆动恢复'
  162. # 智能按钮
  163. elif event_type == 2160:
  164. alarm = '紧急按钮按下'
  165. elif event_type == 2161:
  166. alarm = '单击'
  167. elif event_type == 2162:
  168. alarm = '双击'
  169. elif event_type == 2163:
  170. alarm = '长按'
  171. # 水浸
  172. elif event_type == 2170:
  173. alarm = '水浸触发'
  174. elif event_type == 2171:
  175. alarm = '水浸恢复'
  176. # 烟雾
  177. elif event_type == 2180:
  178. alarm = '烟雾触发'
  179. elif event_type == 2181:
  180. alarm = '烟雾恢复'
  181. # 人体红外
  182. elif event_type == 2190:
  183. alarm = '有人移动'
  184. elif event_type == 2191:
  185. alarm = '无人移动'
  186. # 低电量
  187. elif event_type in (2153, 2164, 2172, 2182, 2193):
  188. alarm = '低电量'
  189. else:
  190. # 门磁
  191. if event_type == 2150:
  192. alarm = 'Door magnetic opening'
  193. elif event_type == 2151:
  194. alarm = 'Door magnetic closing'
  195. elif event_type == 2156:
  196. alarm = 'Be dismantled'
  197. elif event_type == 2152:
  198. alarm = 'Dismantling recovery'
  199. # 智能按钮
  200. elif event_type == 2160:
  201. alarm = 'Emergency button pressed'
  202. elif event_type == 2161:
  203. alarm = 'Single click'
  204. elif event_type == 2162:
  205. alarm = 'Double click'
  206. elif event_type == 2163:
  207. alarm = 'Long press'
  208. # 水浸
  209. elif event_type == 2170:
  210. alarm = 'Water immersion trigger'
  211. elif event_type == 2171:
  212. alarm = 'Water immersion recovery'
  213. # 烟雾
  214. elif event_type == 2180:
  215. alarm = 'Smoke triggering'
  216. elif event_type == 2181:
  217. alarm = 'Smoke recovery'
  218. # 人体红外
  219. elif event_type == 2190:
  220. alarm = 'Someone moving'
  221. elif event_type == 2191:
  222. alarm = 'Unmanned movement'
  223. # 低电量
  224. elif event_type in (2153, 2164, 2172, 2182, 2193):
  225. alarm = 'LOW BATTERY'
  226. return alarm
  227. @classmethod
  228. def scene_log_push(cls, request_dict, response):
  229. """
  230. 网关智能场景日志推送
  231. @param request_dict: 请求参数
  232. @request_dict sceneId: 场景id
  233. @request_dict status: 状态
  234. @param response: 响应对象
  235. @return: response
  236. """
  237. scene_id = request_dict.get('sceneId', None)
  238. status = request_dict.get('status', None)
  239. LOGGER.info('---场景日志推送接口--- request_dict:{}'.format(request_dict))
  240. if not all([scene_id, status]):
  241. return response.json(444)
  242. smart_scene_qs = SmartScene.objects.filter(id=scene_id).values('scene_name', 'conditions', 'tasks', 'device_id',
  243. 'sub_device_id', 'user_id')
  244. if not smart_scene_qs.exists():
  245. return response.json(173)
  246. scene_name = smart_scene_qs[0]['scene_name']
  247. tasks = smart_scene_qs[0]['tasks']
  248. device_id = smart_scene_qs[0]['device_id']
  249. sub_device_id = smart_scene_qs[0]['sub_device_id']
  250. n_time = int(time.time())
  251. user_id = smart_scene_qs[0]['user_id']
  252. if sub_device_id:
  253. gateway_sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('nickname')
  254. nickname = gateway_sub_device_qs[0]['nickname'] if gateway_sub_device_qs.exists() else ''
  255. else:
  256. device_qs = Device_Info.objects.filter(id=device_id).values('NickName')
  257. nickname = device_qs[0]['NickName'] if device_qs.exists() else ''
  258. log_dict = {
  259. 'scene_id': scene_id,
  260. 'scene_name': scene_name,
  261. 'tasks': tasks,
  262. 'status': status,
  263. 'device_id': device_id,
  264. 'sub_device_id': sub_device_id,
  265. 'created_time': n_time,
  266. }
  267. tasks = eval(tasks)
  268. try:
  269. SceneLog.objects.create(**log_dict)
  270. # 推送日志
  271. gateway_push_qs = GatewayPush.objects.filter(user_id=user_id, logout=False). \
  272. values('user_id', 'app_bundle_id', 'app_type', 'push_type', 'token_val', 'm_code', 'lang', 'm_code',
  273. 'tz')
  274. if not gateway_push_qs.exists():
  275. return response.json(174)
  276. # 开启异步推送
  277. push_kwargs = {
  278. 'tasks': tasks,
  279. 'n_time': n_time,
  280. 'nickname': nickname,
  281. 'gateway_push_qs': gateway_push_qs
  282. }
  283. push_thread = threading.Thread(
  284. target=cls.scene_msg_push,
  285. kwargs=push_kwargs)
  286. push_thread.start()
  287. return response.json(0)
  288. except Exception as e:
  289. LOGGER.info('---场景日志推送接口异常--- {}'.format(repr(e)))
  290. return response.json(500, 'error_ine:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  291. @classmethod
  292. def gateway_push_msg(cls, **push_kwargs):
  293. user_id = push_kwargs['user_id']
  294. # 查询推送配置数据
  295. gateway_push_qs = GatewayPush.objects.filter(user_id=user_id, logout=False). \
  296. values('user_id', 'app_bundle_id', 'app_type', 'push_type', 'token_val', 'm_code', 'lang', 'm_code',
  297. 'tz')
  298. if gateway_push_qs.exists():
  299. n_time = push_kwargs['n_time']
  300. event_type = push_kwargs['event_type']
  301. nickname = push_kwargs['nickname']
  302. alarm = push_kwargs['alarm']
  303. kwargs = {
  304. 'n_time': n_time,
  305. 'event_type': event_type,
  306. 'nickname': nickname,
  307. }
  308. # 推送到每台登录账号的手机
  309. for gateway_push in gateway_push_qs:
  310. app_bundle_id = gateway_push['app_bundle_id']
  311. push_type = gateway_push['push_type']
  312. token_val = gateway_push['token_val']
  313. lang = gateway_push['lang']
  314. tz = gateway_push['tz'] if gateway_push['tz'] else 0
  315. # 获取推送所需数据
  316. msg_title = PushObject.get_msg_title(nickname)
  317. msg_text = PushObject.get_gateway_msg_text(n_time, tz, lang, alarm)
  318. kwargs['msg_title'] = msg_title
  319. kwargs['msg_text'] = msg_text
  320. kwargs['app_bundle_id'] = app_bundle_id
  321. kwargs['token_val'] = token_val
  322. try:
  323. # 推送消息
  324. cls.push_msg(push_type, **kwargs)
  325. except Exception as e:
  326. LOGGER.info('网关推送消息异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  327. continue
  328. @classmethod
  329. def scene_msg_push(cls, **push_kwargs):
  330. tasks = push_kwargs['tasks']
  331. n_time = push_kwargs['n_time']
  332. nickname = push_kwargs['nickname']
  333. gateway_push_qs = push_kwargs['gateway_push_qs']
  334. for task in tasks:
  335. event_type = task['event_type']
  336. if event_type == '1001':
  337. kwargs = {
  338. 'n_time': n_time,
  339. 'event_type': event_type,
  340. 'nickname': nickname,
  341. }
  342. event_info = task['value']
  343. # 推送到每台登录账号的手机
  344. for gateway_push in gateway_push_qs:
  345. app_bundle_id = gateway_push['app_bundle_id']
  346. push_type = gateway_push['push_type']
  347. token_val = gateway_push['token_val']
  348. kwargs['msg_title'] = PushObject.get_msg_title(nickname)
  349. kwargs['msg_text'] = event_info
  350. kwargs['app_bundle_id'] = app_bundle_id
  351. kwargs['token_val'] = token_val
  352. try:
  353. # 推送消息
  354. cls.push_msg(push_type, **kwargs)
  355. except Exception as e:
  356. LOGGER.info(
  357. '场景日志推送消息异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  358. continue
  359. @staticmethod
  360. def push_msg(push_type, **kwargs):
  361. """
  362. 发送推送消息
  363. @param push_type: 推送类型
  364. @param kwargs: 推送参数
  365. @return: None
  366. """
  367. if push_type == 0: # ios apns
  368. PushObject.ios_apns_push(**kwargs)
  369. elif push_type == 1: # android gcm
  370. PushObject.android_fcm_push_v1(**kwargs)
  371. elif push_type == 2: # android 极光推送
  372. PushObject.android_jpush(**kwargs)
  373. elif push_type == 3:
  374. huawei_push_object = HuaweiPushObject()
  375. huawei_push_object.send_push_notify_message(**kwargs)
  376. elif push_type == 4: # android 小米推送
  377. channel_id = 104551
  378. PushObject.android_xmpush(channel_id=channel_id, **kwargs)
  379. elif push_type == 5: # android vivo推送
  380. PushObject.android_vivopush(**kwargs)
  381. elif push_type == 6: # android oppo推送
  382. channel_id = 'DEVICE_REMINDER'
  383. PushObject.android_oppopush(channel_id=channel_id, **kwargs)
  384. elif push_type == 7: # android 魅族推送
  385. PushObject.android_meizupush(**kwargs)
  386. @classmethod
  387. def socket_msg_push(cls, request_dict, response):
  388. """
  389. 智能插座开关状态推送
  390. """
  391. try:
  392. serial_number = request_dict.get('serialNumber', None)
  393. device_time = request_dict.get('deviceTime', None)
  394. status = request_dict.get('status', None)
  395. if not all([serial_number, status, device_time]):
  396. return response.json(444)
  397. status = int(status)
  398. now_time = int(device_time) if device_time else int(time.time())
  399. # 获取主用户设备id
  400. log_dict = {
  401. 'status': status,
  402. 'device_id': serial_number,
  403. 'created_time': now_time,
  404. }
  405. SceneLog.objects.create(**log_dict)
  406. LOGGER.info('成功接收并保存,插座序列号{},状态:{}'.format(serial_number, status))
  407. return response.json(0)
  408. except Exception as e:
  409. print(repr(e))
  410. LOGGER.info('---插座开关日志推送接口异常--- {}'.format(repr(e)))
  411. return response.json(500, repr(e))