DetectControllerV2.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import json
  2. import logging
  3. import threading
  4. from django.http import JsonResponse
  5. from django.views.generic.base import View
  6. from AnsjerPush.config import CONFIG_EUR, CONFIG_INFO, CONFIG_US, UNRESTRICTED_FREQUENCY_PUSH_EVENT_TYPE_LIST, \
  7. CONFIG_TEST, CONFIG_CN
  8. from Object.RedisObject import RedisObject
  9. from Object.enums.RedisKeyConstant import RedisKeyConstant
  10. from Service.DevicePushService import DevicePushService
  11. TIME_LOGGER = logging.getLogger('time')
  12. ERROR_INFO_LOGGER = logging.getLogger('error_info')
  13. # 移动侦测V2接口
  14. class NotificationV2View(View):
  15. def get(self, request, *args, **kwargs):
  16. request.encoding = 'utf-8'
  17. return self.validation(request.GET)
  18. def post(self, request, *args, **kwargs):
  19. request.encoding = 'utf-8'
  20. return self.validation(request.POST)
  21. @staticmethod
  22. def validation(request_dict):
  23. """
  24. 设备触发报警消息推送
  25. @param request_dict:uidToken 加密uid
  26. @param request_dict:etk 加密uid
  27. @param request_dict:channel 设备通道号
  28. @param request_dict:n_time 设备触发报警时间
  29. @param request_dict:event_type 设备事件类型
  30. @param request_dict:is_st 文件类型(0,2:无图, 1:单张图片, 3:三张图片)
  31. @param request_dict:region 文件存储区域(1:国外, 2:国内)
  32. @param request_dict:electricity 电量值
  33. @param request_dict:time_token 时间戳token
  34. @param request_dict:uid uid
  35. @param request_dict:dealings_type 往来检测 1:来,2:离开
  36. @param request_dict:detection 检测类型 0:普通,1:算法
  37. """
  38. uidToken = request_dict.get('uidToken', None)
  39. etk = request_dict.get('etk', None)
  40. channel = request_dict.get('channel', '1')
  41. n_time = request_dict.get('n_time', None)
  42. event_type = request_dict.get('event_type', None)
  43. is_st = request_dict.get('is_st', None)
  44. region = request_dict.get('region', None)
  45. electricity = request_dict.get('electricity', '')
  46. dealings_type = int(request_dict.get('dealingsType', 0))
  47. detection = int(request_dict.get('detection', 0))
  48. button = request_dict.get('button', '1')
  49. storage_location = request_dict.get('storage_location', None)
  50. uid = request_dict.get('uid', None)
  51. # 参数校验
  52. if not all([channel, n_time]):
  53. return JsonResponse(status=200, data={'code': 444, 'msg': 'param is wrong'})
  54. if not region or not is_st:
  55. return JsonResponse(status=200, data={'code': 404, 'msg': 'no region or is_st'})
  56. is_st = int(is_st)
  57. region = int(region)
  58. event_type = int(event_type)
  59. redis_obj = RedisObject()
  60. try:
  61. if uid is None:
  62. uid = DevicePushService.decode_uid(etk, uidToken)
  63. if len(uid) != 20 and len(uid) != 14:
  64. return JsonResponse(status=200, data={'code': 404, 'msg': 'wrong uid'})
  65. TIME_LOGGER.info('开始推送,uid:{},参数:{}'.format(uid, request_dict))
  66. # 判断是否为系统消息
  67. is_sys_msg = DevicePushService.judge_sys_msg(event_type)
  68. if is_sys_msg:
  69. push_interval = '{}_{}_{}_flag'.format(uid, channel, event_type)
  70. else:
  71. push_interval = '{}_{}_flag'.format(uid, channel)
  72. req_limiting = '{}_{}_{}_ptl'.format(uid, channel, event_type)
  73. cache_req_limiting = redis_obj.get_data(key=req_limiting) # 获取请求限流缓存数据
  74. cache_app_push = redis_obj.get_data(key=push_interval) # 获取APP推送消息时间间隔缓存数据
  75. if event_type not in UNRESTRICTED_FREQUENCY_PUSH_EVENT_TYPE_LIST:
  76. if cache_req_limiting: # 限流存在则直接返回
  77. return JsonResponse(status=200, data={'code': 0, 'msg': 'Push again in one minute'})
  78. redis_obj.set_data(key=req_limiting, val=1, expire=60) # 当缓存不存在限流数据 重新设置一分钟请求一次
  79. # OZI定制客户儿童保护模式
  80. child_protection = event_type == 1023 and detection == 0
  81. # 查询uid_push和uid_set数据
  82. if child_protection:
  83. uid_push_qs = DevicePushService.get_uid_push_by_uid(uid) # 查主用户
  84. else:
  85. uid_push_qs = DevicePushService.query_uid_push(uid, event_type, button)
  86. if uid_push_qs is None:
  87. return JsonResponse(status=200, data={'code': 175, 'msg': 'device_info数据不存在'})
  88. if not uid_push_qs.exists():
  89. TIME_LOGGER.info('推送响应,uid:{},uid_push数据不存在!'.format(uid))
  90. return JsonResponse(status=200, data={'code': 176, 'msg': 'uid_push数据不存在'})
  91. ai_type = 0 if child_protection else uid_push_qs.first()['uid_set__ai_type']
  92. device_type = uid_push_qs.first()['uid_set__device_type']
  93. # uid_push_qs转存列表
  94. uid_set_push_list = DevicePushService.qs_to_list(uid_push_qs)
  95. nickname = uid_set_push_list[0]['uid_set__nickname']
  96. nickname = uid if not nickname else nickname
  97. # APP消息提醒推送间隔
  98. detect_interval = uid_set_push_list[0]['uid_set__detect_interval']
  99. if event_type not in UNRESTRICTED_FREQUENCY_PUSH_EVENT_TYPE_LIST:
  100. if not cache_app_push:
  101. # 缓存APP提醒推送间隔 默认1分钟提醒一次
  102. DevicePushService.cache_push_detect_interval(redis_obj, push_interval, detect_interval,
  103. uid_set_push_list[0]['uid_set__new_detect_interval'])
  104. else:
  105. cache_app_push = ''
  106. bucket = ''
  107. aws_s3_client = ''
  108. # 推图,初始化s3 client
  109. if is_st == 1 or is_st == 3:
  110. aws_s3_client = DevicePushService.get_s3_client(region=region)
  111. bucket = 'foreignpush' if region == 1 else 'push'
  112. # 推送相关参数
  113. push_kwargs = {
  114. 'uid': uid,
  115. 'channel': channel,
  116. 'event_type': event_type,
  117. 'n_time': n_time,
  118. }
  119. # 对象存储区域, 测试/国内: 旧:aws(2),新:阿里云(1),华为云(5),设备传参, 美洲: oci凤凰城(3), 欧洲: oci伦敦(4)
  120. if CONFIG_INFO == CONFIG_US:
  121. storage_location = 3
  122. elif CONFIG_INFO == CONFIG_EUR:
  123. storage_location = 4
  124. try:
  125. config_key = RedisKeyConstant.PUSH_STORAGE_CONFIG_UID.value + uid
  126. config_value = redis_obj.get_data(key=config_key)
  127. if config_value: # 有配置则使用配置
  128. storage_location = int(config_value)
  129. except Exception as e:
  130. TIME_LOGGER.error('获取缓存推送存储位置异常uid:{},error:{}'.format(uid, repr(e)))
  131. elif CONFIG_INFO in [CONFIG_TEST, CONFIG_CN]:
  132. # 测试/国内服: 优先使用设备传参,否则默认阿里云
  133. if storage_location is not None:
  134. storage_location = int(storage_location)
  135. else:
  136. storage_location = 1 # 默认阿里云
  137. else:
  138. if storage_location is not None:
  139. storage_location = int(storage_location)
  140. else:
  141. storage_location = 1
  142. params = {'nickname': nickname, 'uid': uid, 'push_kwargs': push_kwargs, 'is_st': is_st, 'region': region,
  143. 'is_sys_msg': is_sys_msg, 'channel': channel, 'event_type': event_type, 'n_time': n_time,
  144. 'electricity': electricity, 'bucket': bucket, 'aws_s3_client': aws_s3_client,
  145. 'app_push': cache_app_push, 'storage_location': storage_location, 'ai_type': ai_type,
  146. 'device_type': device_type,
  147. 'dealings_type': dealings_type, 'detection': detection,
  148. 'app_push_config': uid_set_push_list[0]['uid_set__msg_notify'],
  149. 'uid_set_push_list': uid_set_push_list, 'redis_obj': redis_obj}
  150. # 异步推送消息和保存数据
  151. push_thread = threading.Thread(
  152. target=push_and_save_data,
  153. kwargs=params)
  154. push_thread.start()
  155. # 视频通话不返回图片链接
  156. if event_type in [607, 1022]:
  157. TIME_LOGGER.info('推送响应,uid:{},n_time:{},事件类型:{}'.format(uid, n_time, event_type))
  158. return JsonResponse(status=200, data={'code': 0, 'msg': 'success'})
  159. # 获取S3对象上传链接
  160. kwargs = {
  161. 'is_st': is_st,
  162. 'uid': uid,
  163. 'channel': channel,
  164. 'n_time': n_time,
  165. 'region': region,
  166. 'aws_s3_client': aws_s3_client,
  167. 'storage_location': storage_location
  168. }
  169. res_data = DevicePushService.get_res_data(**kwargs)
  170. TIME_LOGGER.info('推送响应,uid:{},n_time:{},事件类型:{},响应:{}'.format(
  171. uid, n_time, event_type, json.dumps(res_data)))
  172. return JsonResponse(status=200, data=res_data)
  173. except Exception as e:
  174. ERROR_INFO_LOGGER.info('V2推送接口异常,uid:{},etk:{},error_line:{},error_msg:{}'.
  175. format(uid, etk, e.__traceback__.tb_lineno, repr(e)))
  176. data = {
  177. 'error_line': e.__traceback__.tb_lineno,
  178. 'error_msg': repr(e)
  179. }
  180. return JsonResponse(status=200, data=json.dumps(data), safe=False)
  181. def push_and_save_data(**params):
  182. uid = params['uid']
  183. try:
  184. TIME_LOGGER.info('{}开始异步存表和推送'.format(uid))
  185. # 异步推送消息
  186. push_thread = threading.Thread(
  187. target=DevicePushService.push_msg,
  188. kwargs=params)
  189. push_thread.start()
  190. # 保存推送数据
  191. result = DevicePushService.save_msg_push(**params)
  192. TIME_LOGGER.info('{}存表结果:{}'.format(uid, result))
  193. except Exception as e:
  194. ERROR_INFO_LOGGER.info(
  195. 'V2推送第一个线程异常{},error_line:{},error_msg:{}'.format(uid, e.__traceback__.tb_lineno, repr(e)))