import base64 import json import logging import os import threading import time import boto3 from django.views.generic.base import View from AnsjerPush.config import BASE_DIR from Model.models import UidPushModel, AiService, Device_Info from Object.ETkObject import ETkObject from Object.AiImageObject import ImageProcessingObject from Object.ResponseObject import ResponseObject from Object.utils import LocalDateTimeUtil from Service.CommonService import CommonService from Service.EquipmentInfoService import EquipmentInfoService from Service.PushService import PushObject class AiView(View): def get(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') return self.validation(request.GET, operation) def post(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') return self.validation(request.POST, operation) def validation(self, request_dict, operation): response = ResponseObject() if operation == 'identification': # ai识别推送 return self.identification(request_dict, response) else: return response.json(414) def identification(self, request_dict, response): """ ai识别推送 @param request_dict: 请求数据 @request_dict etk: uid token @request_dict n_time: 设备的当前时间 @request_dict channel: 通道 @request_dict fileOne: 图片一 @request_dict fileTwo: 图片二 @request_dict fileThree: 图片三 @param response: 响应 @return: response """ etk = request_dict.get('etk', None) n_time = request_dict.get('n_time', None) channel = request_dict.get('channel', '1') file_one = request_dict.get('fileOne', None) file_two = request_dict.get('fileTwo', None) file_three = request_dict.get('fileThree', None) if not all([etk, n_time]): return response.json(444) # 解密etk并判断uid长度 eto = ETkObject(etk) uid = eto.uid logger = logging.getLogger('info') logger.info('---进入ai识别推送接口--- etk:{}, uid:{}'.format(etk, uid)) receive_time = int(time.time()) file_list = [file_one, file_two, file_three] # 查询设备是否有使用中的ai服务 ai_service_qs = AiService.objects.filter(uid=uid, detect_status=1, use_status=1, endTime__gt=receive_time). \ values('detect_group') if not ai_service_qs.exists(): return response.json(173) # 查询推送相关数据 uid_push_qs = UidPushModel.objects.filter(uid_set__uid=uid). \ values('push_type', 'appBundleId', 'token_val', 'm_code', 'lang', 'tz', 'userID_id') if not uid_push_qs.exists(): return response.json(173) # 查询设备数据 device_info_qs = Device_Info.objects.filter(UID=uid).first() nickname = uid if device_info_qs is None else device_info_qs.NickName now_time = int(time.time()) detect_group = ai_service_qs[0]['detect_group'] try: dir_path = os.path.join(BASE_DIR, 'static/ai/' + uid + '/' + str(n_time)) if not os.path.exists(dir_path): os.makedirs(dir_path) file_path_list = [] for i, val in enumerate(file_list): val = val.replace(' ', '+') val = base64.b64decode(val) file_path = "{dir_path}/{n_time}_{i}.jpg".format(dir_path=dir_path, n_time=n_time, i=i) file_path_list.append(file_path) with open(file_path, 'wb') as f: f.write(val) f.close() image_size = 0 # 每张小图片的大小,等于0是按原图大小进行合并 image_row = 1 # 合并成一张图后,一行有几个小图 image_processing_obj = ImageProcessingObject(dir_path, image_size, image_row) image_processing_obj.merge_images() photo = open(dir_path + '.jpg', 'rb') # 打开合成图 # 识别合成图片 maxLabels = 50 # 最大标签 minConfidence = 80 # 置信度 client = boto3.client( 'rekognition', aws_access_key_id='AKIA2E67UIMD6JD6TN3J', aws_secret_access_key='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', region_name='us-east-1') # doc: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rekognition.html#Rekognition.Client.detect_labels rekognition_res = client.detect_labels( Image={'Bytes': photo.read()}, MaxLabels=maxLabels, MinConfidence=minConfidence) photo.close() if rekognition_res['ResponseMetadata']['HTTPStatusCode'] != 200: return response.json(5) label_dict = image_processing_obj.handle_rekognition_res(detect_group, rekognition_res) if not label_dict['label_list']: # 需要删除图片 # photo.close() # self.del_path(os.path.join(BASE_DIR, 'static/ai/' + uid)) return response.json(0) event_type = label_dict['event_type'] label_str = ','.join(label_dict['label_list']) new_bounding_box_dict = label_dict['new_bounding_box_dict'] # 上传缩略图到s3 file_dict = {} for i, val in enumerate(file_path_list): # 封面图 file_dict[val] = '{}/{}/{}_{}.jpeg'.format(uid, channel, n_time, i) upload_images_thread = threading.Thread(target=CommonService.upload_images, args=(file_dict, dir_path)) upload_images_thread.start() # 存储消息以及推送 uid_push_list = [uid_push for uid_push in uid_push_qs] eq_list = [] user_id_list = [] local_date_time = '' for up in uid_push_list: # 保存推送数据 tz = up['tz'] if tz is None or tz == '': tz = 0 local_date_time = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang='cn')[:10] user_id = up['userID_id'] if user_id not in user_id_list: eq_list.append(EquipmentInfoService.get_equipment_info_obj( local_date_time, device_user_id=user_id, event_time=n_time, event_type=event_type, device_uid=uid, device_nick_name=nickname, channel=channel, alarm='检查到{} \tChannel:{}'.format(label_str, channel), is_st=3, receive_time=receive_time, add_time=now_time, storage_location=2, border_coords=json.dumps(new_bounding_box_dict) )) user_id_list.append(user_id) # 推送 push_type = up['push_type'] appBundleId = up['appBundleId'] token_val = up['token_val'] lang = up['lang'] # 推送标题和推送内容 msg_title = PushObject.get_msg_title(app_bundle_id=appBundleId, nickname=nickname) msg_text = PushObject.get_ai_msg_text(channel=channel, n_time=n_time, lang=lang, tz=tz, label=label_str) kwargs = { 'nickname': nickname, 'app_bundle_id': appBundleId, 'token_val': token_val, 'n_time': n_time, 'event_type': event_type, 'msg_title': msg_title, 'msg_text': msg_text, 'uid': uid, 'channel': channel, } try: # 推送消息 if push_type == 0: # ios apns PushObject.ios_apns_push(**kwargs) elif push_type == 1: # android gcm PushObject.android_fcm_push(**kwargs) elif push_type == 2: # android jpush PushObject.android_jpush(**kwargs) except Exception as e: logger.info('ai推送消息异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) continue week = LocalDateTimeUtil.date_to_week(local_date_time) EquipmentInfoService.equipment_info_bulk_create(week, eq_list) return response.json(0) except Exception as e: logger.info('---ai识别推送异常---:{}'.format(repr(e))) data = { 'errLine': e.__traceback__.tb_lineno, 'errMsg': repr(e) } return response.json(48, data)