| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 | # -*- encoding: utf-8 -*-"""@File    : CronCloudPhotoController.py@Time    : 2022/10/24 15:48@Author  : stephen@Email   : zhangdongming@asj6.wecom.work@Software: PyCharm"""import datetimeimport loggingimport osimport timeimport tracebackimport cv2from django.db import transactionfrom django.views import Viewfrom Ansjer.config import PUSH_CLOUD_PHOTO, ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME, PUSH_BUCKETfrom Model.models import UidSetModel, DeviceCloudPhotoInfo, DevicePicturePushInfofrom Object.AWS.AmazonS3Util import AmazonS3Utilfrom Object.RedisObject import RedisObjectfrom Object.ResponseObject import ResponseObjectfrom Object.utils import LocalDateTimeUtilfrom Service.EquipmentInfoService import EquipmentInfoServiceLOGGER = logging.getLogger('info')UID_KEY = 'ANSJER:UID:SET:INFO'class CronCloudPhotoView(View):    def get(self, request, *args, **kwargs):        request.encoding = 'utf-8'        operation = kwargs.get('operation')        return self.validation(request.GET, request, operation)    def post(self, request, *args, **kwargs):        request.encoding = 'utf-8'        operation = kwargs.get('operation')        return self.validation(request.POST, request, operation)    def validation(self, request_dict, request, operation):        response = ResponseObject()        if operation == 'get-photo':            return self.get_photo(response)        elif operation == 'cache-uid-set':            return self.cache_photo_uid_set(response)        elif operation == 'generate-video':            return self.generate_video(response)        else:            return response.json(404)    @classmethod    def get_photo(cls, response):        """        定时获取设备消息推送图        """        try:            now_time = int(time.time())            LOGGER.info('进入缓存uid进行获取消息推送图片进行对象copy:{}'.format(now_time))            redis = RedisObject().CONN            uid_set_cache = redis.lrange(UID_KEY, 0, -1)            if not uid_set_cache:                return response.json(0)            uid_set_cache = list(uid_set_cache)            today = datetime.date.today()            time_stamp = cls.get_month_stamp()            s3 = AmazonS3Util(ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME)            for item in uid_set_cache:                try:                    eq_qs = EquipmentInfoService.get_equipment_info_model(str(today))                    item = str(item, encoding="utf-8")                    last_date = LocalDateTimeUtil.get_cur_month_end()                    start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(last_date, '%Y-%m-%d')                    eq_qs = eq_qs.filter(event_time__gt=time_stamp, event_time__lt=end_time, is_st=1, device_uid=item) \                        .values('device_uid', 'channel', 'event_time', 'device_nick_name')                    count = eq_qs.count()                    page = int(count / 2) if count > 1 else count                    redis.lrem(UID_KEY, 0, item)                    if page == 0:                        continue                    eq_qs = eq_qs[(page - 1) * 1:page * 1]                    eq_vo = eq_qs[0]                    file_path = '{uid}/{channel}/{event_time}.jpeg'.format(uid=eq_vo['device_uid'],                                                                           channel=eq_vo['channel'],                                                                           event_time=eq_vo['event_time'])                    s3.copy_obj(PUSH_BUCKET, PUSH_CLOUD_PHOTO, file_path)                    push_data = {'type': 0, 'uid': eq_vo['device_uid'], 'channel': eq_vo['channel'],                                 'event_time': eq_vo['event_time'], 'updated_time': now_time, 'created_time': now_time,                                 'device_nick_name': eq_vo['device_nick_name']}                    DevicePicturePushInfo.objects.create(**push_data)                except Exception as e:                    LOGGER.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))                    redis.lrem(UID_KEY, 0, item)                    continue            return response.json(0)        except Exception as e:            print(e)            LOGGER.info('--->抽取推送图片异常:{}'.format(traceback.format_exc()))            return response.json(177, repr(e))    @classmethod    def cache_photo_uid_set(cls, response):        """        缓存uid_set信息        """        try:            now_time = int(time.time())            LOGGER.info('进入读取开启云相册用户并把UID存在redis:{}'.format(now_time))            photo_qs = DeviceCloudPhotoInfo.objects.filter(status=1).values('uid')            if not photo_qs.exists():                return response.json(0)            redis = RedisObject()            for item in photo_qs:                uid_set_qs = UidSetModel.objects.filter(uid=item['uid'], detect_status=1)                if not uid_set_qs:                    continue                redis.CONN.rpush(UID_KEY, item['uid'])            return response.json(0)        except Exception as e:            print(e)            LOGGER.info('--->获取uid_set信息异常:{}'.format(traceback.format_exc()))            return response.json(177, repr(e))    @classmethod    def generate_video(cls, response):        """        生成视频并存库        """        try:            now_time = int(time.time())            LOGGER.info('进入云相册开启用户,进行消息推送图进行合成视频:{}'.format(now_time))            photo_qs = DeviceCloudPhotoInfo.objects.filter(status=1).values('uid', 'user_id')            if not photo_qs.exists():                return response.json(0)            # 获取当前项目路径            poj_path = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))            time_stamp = cls.get_month_stamp()            s3 = AmazonS3Util(ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME)            for item in photo_qs:                try:                    with transaction.atomic():                        last_date = LocalDateTimeUtil.get_cur_month_end()                        start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(last_date, '%Y-%m-%d')                        picture_qs = DevicePicturePushInfo.objects.filter(uid=item['uid'],                                                                          event_time__gt=time_stamp,                                                                          event_time__lt=end_time,                                                                          type=0) \                            .values('uid', 'channel', 'event_time', 'device_nick_name')                        if not picture_qs.exists():                            continue                        device_nickname = picture_qs[0]['device_nick_name']                        pic_list = cls.download_push_picture(s3, item['uid'], poj_path, picture_qs)                        video_path = poj_path + r'\Ansjer\file\video.mp4'  # 输出视频的保存路径                        cls.picture_synthesis_video(video_path, poj_path, pic_list)  # 图片合成视频                        video_name = datetime.datetime.now().strftime('%Y%m')                        data = open(video_path, 'rb')                        key = '{}/video/{}.mp4'.format(item['uid'], video_name)                        s3.upload_file_obj(PUSH_CLOUD_PHOTO, key, data)  # 将视频资源上传至S3保存                        os.remove(video_path)  # 上传完成删除本地资源                        push_data = {'type': 1, 'uid': item['uid'], 'channel': 1,                                     'event_time': int(video_name), 'updated_time': now_time, 'created_time': now_time,                                     'device_nick_name': device_nickname, 'user_id': item['user_id']}                        DevicePicturePushInfo.objects.create(**push_data)                except Exception as e:                    LOGGER.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))                    continue            return response.json(0)        except Exception as e:            print(e)            LOGGER.info('--->图片合成视频异常:{}'.format(traceback.format_exc()))            return response.json(177)    @staticmethod    def download_push_picture(s3, uid, dir_url, picture_qs):        """        下载推送图片,讲下载资源保存到项目本地        @param s3: s3对象        @param uid: 设备uid        @param dir_url: 项目文件路径        @param picture_qs: 消息推送图片对象        @return: pic_list 图片文件名集合        """        pic_list = []        for pic in picture_qs:            path = dir_url + r'\Ansjer\file\{}.jpeg'.format(pic['event_time'])            s3_key = '{}/{}/{}.jpeg'.format(uid, pic['channel'], pic['event_time'])            s3.download_object(PUSH_CLOUD_PHOTO, s3_key, path)            pic_list.append('{}.jpeg'.format(pic['event_time']))        return pic_list    @staticmethod    def picture_synthesis_video(video_path, poj_path, pic_list):        """        图片合成视频        @param video_path: 输出视频的保存路径        @param poj_path: 项目路径        @param pic_list: 图片文件名集合        @return:        """        if not pic_list:            raise Exception('this pic_list is null.')        fps = 1  # 帧率        img_path = poj_path + r'\Ansjer\file\{}'.format(pic_list[0])        image = cv2.imread(img_path)        size = image.shape        w = size[1]  # 宽度        h = size[0]  # 高度        img_size = (w, h)  # 图片尺寸        fourcc = cv2.VideoWriter_fourcc(*"mp4v")        video_writer = cv2.VideoWriter(video_path, fourcc, fps, img_size)        for item in pic_list:            img_path = poj_path + r'\Ansjer\file\{}'.format(item)            frame = cv2.imread(img_path)            if frame is None:                continue            frame = cv2.resize(frame, img_size)  # 生成视频   图片尺寸和设定尺寸相同            video_writer.write(frame)  # 将图片写进视频里            os.remove(img_path)        video_writer.release()  # 释放资源    @staticmethod    def get_month_stamp():        """        获取当月开始时间戳        """        now_month = LocalDateTimeUtil.get_cur_month_start()        start_time = "{} 00:00:00".format(str(now_month))        time_array = time.strptime(start_time, "%Y-%m-%d %H:%M:%S")        # 转换为时间戳        return int(time.mktime(time_array))
 |