AiController.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import base64
  2. import json
  3. import logging
  4. import os
  5. import threading
  6. import time
  7. import boto3
  8. from django.views.generic.base import View
  9. from AnsjerPush.config import BASE_DIR
  10. from Model.models import UidPushModel, AiService, Device_Info
  11. from Object.ETkObject import ETkObject
  12. from Object.AiImageObject import ImageProcessingObject
  13. from Object.ResponseObject import ResponseObject
  14. from Object.utils import LocalDateTimeUtil
  15. from Service.CommonService import CommonService
  16. from Service.EquipmentInfoService import EquipmentInfoService
  17. from Service.PushService import PushObject
  18. class AiView(View):
  19. def get(self, request, *args, **kwargs):
  20. request.encoding = 'utf-8'
  21. operation = kwargs.get('operation')
  22. return self.validation(request.GET, operation)
  23. def post(self, request, *args, **kwargs):
  24. request.encoding = 'utf-8'
  25. operation = kwargs.get('operation')
  26. return self.validation(request.POST, operation)
  27. def validation(self, request_dict, operation):
  28. response = ResponseObject()
  29. if operation == 'identification': # ai识别推送
  30. return self.identification(request_dict, response)
  31. else:
  32. return response.json(414)
  33. def identification(self, request_dict, response):
  34. """
  35. ai识别推送
  36. @param request_dict: 请求数据
  37. @request_dict etk: uid token
  38. @request_dict n_time: 设备的当前时间
  39. @request_dict channel: 通道
  40. @request_dict fileOne: 图片一
  41. @request_dict fileTwo: 图片二
  42. @request_dict fileThree: 图片三
  43. @param response: 响应
  44. @return: response
  45. """
  46. etk = request_dict.get('etk', None)
  47. n_time = request_dict.get('n_time', None)
  48. channel = request_dict.get('channel', '1')
  49. file_one = request_dict.get('fileOne', None)
  50. file_two = request_dict.get('fileTwo', None)
  51. file_three = request_dict.get('fileThree', None)
  52. if not all([etk, n_time]):
  53. return response.json(444)
  54. # 解密etk并判断uid长度
  55. eto = ETkObject(etk)
  56. uid = eto.uid
  57. logger = logging.getLogger('info')
  58. logger.info('---进入ai识别推送接口--- etk:{}, uid:{}'.format(etk, uid))
  59. receive_time = int(time.time())
  60. file_list = [file_one, file_two, file_three]
  61. # 查询设备是否有使用中的ai服务
  62. ai_service_qs = AiService.objects.filter(uid=uid, detect_status=1, use_status=1, endTime__gt=receive_time). \
  63. values('detect_group')
  64. if not ai_service_qs.exists():
  65. return response.json(173)
  66. # 查询推送相关数据
  67. uid_push_qs = UidPushModel.objects.filter(uid_set__uid=uid). \
  68. values('push_type', 'appBundleId', 'token_val', 'm_code', 'lang', 'tz', 'userID_id')
  69. if not uid_push_qs.exists():
  70. return response.json(173)
  71. # 查询设备数据
  72. device_info_qs = Device_Info.objects.filter(UID=uid).first()
  73. nickname = uid if device_info_qs is None else device_info_qs.NickName
  74. now_time = int(time.time())
  75. detect_group = ai_service_qs[0]['detect_group']
  76. try:
  77. dir_path = os.path.join(BASE_DIR, 'static/ai/' + uid + '/' + str(n_time))
  78. if not os.path.exists(dir_path):
  79. os.makedirs(dir_path)
  80. file_path_list = []
  81. for i, val in enumerate(file_list):
  82. val = val.replace(' ', '+')
  83. val = base64.b64decode(val)
  84. file_path = "{dir_path}/{n_time}_{i}.jpg".format(dir_path=dir_path, n_time=n_time, i=i)
  85. file_path_list.append(file_path)
  86. with open(file_path, 'wb') as f:
  87. f.write(val)
  88. f.close()
  89. image_size = 0 # 每张小图片的大小,等于0是按原图大小进行合并
  90. image_row = 1 # 合并成一张图后,一行有几个小图
  91. image_processing_obj = ImageProcessingObject(dir_path, image_size, image_row)
  92. image_processing_obj.merge_images()
  93. photo = open(dir_path + '.jpg', 'rb') # 打开合成图
  94. # 识别合成图片
  95. maxLabels = 50 # 最大标签
  96. minConfidence = 80 # 置信度
  97. client = boto3.client(
  98. 'rekognition',
  99. aws_access_key_id='AKIA2E67UIMD6JD6TN3J',
  100. aws_secret_access_key='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',
  101. region_name='us-east-1')
  102. # doc: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html#Rekognition.Client.detect_labels
  103. rekognition_res = client.detect_labels(
  104. Image={'Bytes': photo.read()},
  105. MaxLabels=maxLabels,
  106. MinConfidence=minConfidence)
  107. photo.close()
  108. if rekognition_res['ResponseMetadata']['HTTPStatusCode'] != 200:
  109. return response.json(5)
  110. label_dict = image_processing_obj.handle_rekognition_res(detect_group, rekognition_res)
  111. if not label_dict['label_list']:
  112. # 需要删除图片
  113. # photo.close()
  114. # self.del_path(os.path.join(BASE_DIR, 'static/ai/' + uid))
  115. return response.json(0)
  116. event_type = label_dict['event_type']
  117. label_str = ','.join(label_dict['label_list'])
  118. new_bounding_box_dict = label_dict['new_bounding_box_dict']
  119. # 上传缩略图到s3
  120. file_dict = {}
  121. for i, val in enumerate(file_path_list):
  122. # 封面图
  123. file_dict[val] = '{}/{}/{}_{}.jpeg'.format(uid, channel, n_time, i)
  124. upload_images_thread = threading.Thread(target=CommonService.upload_images, args=(file_dict, dir_path))
  125. upload_images_thread.start()
  126. # 存储消息以及推送
  127. uid_push_list = [uid_push for uid_push in uid_push_qs]
  128. eq_list = []
  129. user_id_list = []
  130. local_date_time = ''
  131. for up in uid_push_list:
  132. # 保存推送数据
  133. tz = up['tz']
  134. if tz is None or tz == '':
  135. tz = 0
  136. local_date_time = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang='cn')[:10]
  137. user_id = up['userID_id']
  138. if user_id not in user_id_list:
  139. eq_list.append(EquipmentInfoService.get_equipment_info_obj(
  140. local_date_time,
  141. device_user_id=user_id,
  142. event_time=n_time,
  143. event_type=event_type,
  144. device_uid=uid,
  145. device_nick_name=nickname,
  146. channel=channel,
  147. alarm='检查到{} \tChannel:{}'.format(label_str, channel),
  148. is_st=3,
  149. receive_time=receive_time,
  150. add_time=now_time,
  151. storage_location=2,
  152. border_coords=json.dumps(new_bounding_box_dict)
  153. ))
  154. user_id_list.append(user_id)
  155. # 推送
  156. push_type = up['push_type']
  157. appBundleId = up['appBundleId']
  158. token_val = up['token_val']
  159. lang = up['lang']
  160. # 推送标题和推送内容
  161. msg_title = PushObject.get_msg_title(app_bundle_id=appBundleId, nickname=nickname)
  162. msg_text = PushObject.get_ai_msg_text(channel=channel, n_time=n_time, lang=lang, tz=tz, label=label_str)
  163. kwargs = {
  164. 'nickname': nickname,
  165. 'app_bundle_id': appBundleId,
  166. 'token_val': token_val,
  167. 'n_time': n_time,
  168. 'event_type': event_type,
  169. 'msg_title': msg_title,
  170. 'msg_text': msg_text,
  171. 'uid': uid,
  172. 'channel': channel,
  173. }
  174. try:
  175. # 推送消息
  176. if push_type == 0: # ios apns
  177. PushObject.ios_apns_push(**kwargs)
  178. elif push_type == 1: # android gcm
  179. PushObject.android_fcm_push(**kwargs)
  180. elif push_type == 2: # android jpush
  181. PushObject.android_jpush(**kwargs)
  182. except Exception as e:
  183. logger.info('ai推送消息异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  184. continue
  185. week = LocalDateTimeUtil.date_to_week(local_date_time)
  186. EquipmentInfoService.equipment_info_bulk_create(week, eq_list)
  187. return response.json(0)
  188. except Exception as e:
  189. logger.info('---ai识别推送异常---:{}'.format(repr(e)))
  190. data = {
  191. 'errLine': e.__traceback__.tb_lineno,
  192. 'errMsg': repr(e)
  193. }
  194. return response.json(48, data)