소스 검색

V2接口代码优化

zhangdongming 2 년 전
부모
커밋
a595908715
2개의 변경된 파일528개의 추가작업 그리고 261개의 파일을 삭제
  1. 83 261
      Controller/DetectControllerV2.py
  2. 445 0
      Service/DevicePushService.py

+ 83 - 261
Controller/DetectControllerV2.py

@@ -1,28 +1,22 @@
 import json
 import logging
 import os
-import threading
-import time
 
 import apns2
 import boto3
 import botocore
 import jpush as jpush
 from botocore import client
+from django.db import transaction
 from django.http import JsonResponse
 from django.views.generic.base import View
 from pyfcm import FCMNotification
 
 from AnsjerPush.config import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
 from AnsjerPush.config import JPUSH_CONFIG, FCM_CONFIG, APNS_CONFIG, BASE_DIR, APNS_MODE
-from AnsjerPush.config import SERVER_TYPE
-from Model.models import UidPushModel, SysMsgModel
-from Object.ETkObject import ETkObject
 from Object.RedisObject import RedisObject
-from Object.UidTokenObject import UidTokenObject
-from Object.utils import LocalDateTimeUtil
 from Service.CommonService import CommonService
-from Service.EquipmentInfoService import EquipmentInfoService
+from Service.DevicePushService import DevicePushService
 from Service.GatewayService import GatewayPushService
 
 
@@ -38,6 +32,17 @@ class NotificationV2View(View):
         return self.validation(request.POST)
 
     def validation(self, request_dict):
+        """
+        设备触发报警消息推送
+        @param request_dict:uidToken 加密uid
+        @param request_dict:etk 加密uid
+        @param request_dict:channel 设备通道号
+        @param request_dict:n_time 设备触发报警时间
+        @param request_dict:event_type 设备事件类型
+        @param request_dict:is_st 文件类型(0:无,1:图片,2:视频)
+        @param request_dict:region 文件存储区域(1:国外,2国内)
+        @param request_dict:electricity 电量值
+        """
         logger = logging.getLogger('info')
         logger.info("移动侦测V2接口参数:{}".format(request_dict))
         uidToken = request_dict.get('uidToken', None)
@@ -57,250 +62,71 @@ class NotificationV2View(View):
             return JsonResponse(status=200, data={'code': 404, 'msg': 'no region or is_st'})
 
         try:
-            is_st = int(is_st)
-            region = int(region)
-
-            # 解密获取uid
-            if etk:
-                eto = ETkObject(etk)
-                uid = eto.uid
-            else:
-                uto = UidTokenObject(uidToken)
-                uid = uto.UID
-            # uid = request_dict.get('uid', None)     # 调试
-            # 判断uid长度
-            if len(uid) != 20 and len(uid) != 14:
-                return JsonResponse(status=200, data={'code': 404, 'msg': 'wrong uid'})
-            logger.info('调用推送接口的uid:{}'.format(uid))
-
-            pkey = '{uid}_{channel}_{event_type}_ptl'.format(uid=uid, channel=channel, event_type=event_type)
-            ykey = '{uid}_redis_qs'.format(uid=uid)
-            is_sys_msg = self.is_sys_msg(int(event_type))
-            if is_sys_msg:
-                dkey = '{uid}_{channel}_{event_type}_flag'.format(uid=uid, channel=channel, event_type=event_type)
-            else:
-                dkey = '{uid}_{channel}_flag'.format(uid=uid, channel=channel)
-
-            redisObj = RedisObject(db=6)
-            have_ykey = redisObj.get_data(key=ykey)  # uid_set 数据库缓存
-            have_pkey = redisObj.get_data(key=pkey)  # 一分钟限制key
-            have_dkey = redisObj.get_data(key=dkey)  # 推送消息时间间隔
-            logger.info('ykey:{}, pkey: {}, dkey: {}'.format(have_ykey, have_pkey, have_dkey))
-            # 一分钟内不推送
-            if have_pkey:
-                return JsonResponse(status=200, data={'code': 0, 'msg': 'Push again in one minute'})
-            redisObj.set_data(key=pkey, val=1, expire=60)
-
-            # 查询推送数据
-            uid_push_qs = UidPushModel.objects.filter(uid_set__uid=uid, uid_set__detect_status=1). \
-                values('token_val', 'app_type', 'appBundleId', 'm_code', 'push_type', 'userID_id', 'userID__NickName',
-                       'lang', 'm_code', 'tz', 'uid_set__nickname', 'uid_set__detect_interval', 'uid_set__detect_group',
-                       'uid_set__channel', 'uid_set__ai_type', 'uid_set__new_detect_interval')
-            if not uid_push_qs.exists():
-                logger.info('uid_push 数据不存在')
-                return JsonResponse(status=200, data={'code': 176, 'msg': 'no uid_push data'})
-            ai_type = uid_push_qs.first()['uid_set__ai_type']
-            event_type = self.get_combo_msg_type(ai_type, int(event_type))
-            redis_list = []
-            for qs in uid_push_qs:
-                redis_list.append(qs)
-            # 修改redis数据,并设置过期时间为10分钟
-            redisObj.set_data(key=ykey, val=str(redis_list), expire=600)
-
-            nickname = redis_list[0]['uid_set__nickname']
-            detect_interval = redis_list[0]['uid_set__detect_interval']
-            if not nickname:
-                nickname = uid
-            if not have_dkey:
-                # 设置推送消息的时间间隔
-                if SERVER_TYPE != 'Ansjer.cn_formal_settings':
-                    new_detect_interval = redis_list[0]['uid_set__new_detect_interval']
-                    detect_interval = new_detect_interval if new_detect_interval > 0 else detect_interval
-                    detect_interval = 60 if detect_interval < 60 else detect_interval
-                redisObj.set_data(key=dkey, val=1, expire=detect_interval - 5)
-                logger.info('APP消息推送间隔:{}s'.format(detect_interval))
-
-            if is_st == 1 or is_st == 3:  # 使用aws s3
-                aws_s3_client = s3_client(region=region)
-                bucket = 'foreignpush' if region == 1 else 'push'
-            kwag_args = {
-                'uid': uid,
-                'channel': channel,
-                'event_type': event_type,
-                'n_time': n_time,
-            }
-            sys_msg_list = []
-            userID_ids = []
-            do_apns_code = ''
-            do_fcm_code = ''
-            do_jpush_code = ''
-            logger.info('进入手机推送------')
-            logger.info('uid={}'.format(uid))
-            logger.info(redis_list)
-            new_device_info_list = []
-            local_date_time = ''
-            for up in redis_list:
-                push_type = up['push_type']
-                appBundleId = up['appBundleId']
-                token_val = up['token_val']
-                lang = up['lang']
-                tz = up['tz']
-                if tz is None or tz == '':
-                    tz = 0
-                # 发送标题
-                msg_title = self.get_msg_title(appBundleId=appBundleId, nickname=nickname)
-                # 发送内容
-                msg_text = self.get_msg_text(channel=channel, n_time=n_time, lang=lang, tz=tz,
-                                             event_type=event_type, electricity=electricity)
-                kwag_args['appBundleId'] = appBundleId
-                kwag_args['token_val'] = token_val
-                kwag_args['msg_title'] = msg_title
-                kwag_args['msg_text'] = msg_text
-                logger.info('推送要的数据: {}'.format(kwag_args))
-                local_date_time = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang='cn')
-                logger.info('<<<<<根据时区计算后日期={},时区={}'.format(local_date_time, tz))
-                local_date_time = local_date_time[0:10]
-                logger.info('<<<<<切片后的日期={}'.format(local_date_time))
-                # 以下是存库
-                userID_id = up["userID_id"]
-                if userID_id not in userID_ids:
-                    now_time = int(time.time())
-                    if is_sys_msg:
-                        sys_msg_text = self.get_msg_text(channel=channel, n_time=n_time, lang=lang, tz=tz,
-                                                         event_type=event_type, electricity=electricity, is_sys=1)
-                        sys_msg_list.append(SysMsgModel(
-                            userID_id=userID_id,
-                            msg=sys_msg_text,
-                            addTime=now_time,
-                            updTime=now_time,
-                            uid=uid,
-                            eventType=event_type))
-                    else:
-                        # start 根据设备侦测时间为准进行分表存储数据
-                        logger.info('分表存数据start------')
-                        new_device_info_list.append(EquipmentInfoService.get_equipment_info_obj(
-                            local_date_time,
-                            device_user_id=userID_id,
-                            event_time=n_time,
-                            event_type=event_type,
-                            device_uid=uid,
-                            device_nick_name=nickname,
-                            channel=channel,
-                            alarm='Motion \tChannel:{channel}'.format(channel=channel),
-                            is_st=is_st,
-                            receive_time=n_time,
-                            add_time=now_time,
-                            storage_location=2,
-                            border_coords='',
-                        ))
-                        # end
-                    userID_ids.append(userID_id)
-                try:
-                    # 推送消息
-                    if not have_dkey:
-                        logger.info('APP准备推送:{}, {}'.format(uid, request_dict))
-                        if (is_st == 1 or is_st == 3) and (push_type == 0 or push_type == 1):  # 推送显示图片
-                            if is_st == 1:
-                                key = '{}/{}/{}.jpeg'.format(uid, channel, n_time)
-                            else:
-                                key = '{}/{}/{}_0.jpeg'.format(uid, channel, n_time)
-                            push_thread = threading.Thread(target=self.push_thread_test, args=(
-                                push_type, aws_s3_client, bucket, key, uid, appBundleId, token_val, event_type, n_time,
-                                msg_title, msg_text, channel))
-                            push_thread.start()
-                        else:
-                            if push_type == 0:  # ios apns
-                                do_apns_code = self.do_apns(**kwag_args)
-                            elif push_type == 1:  # android gcm
-                                do_fcm_code = self.do_fcm(**kwag_args)
-                            elif push_type == 2:  # android jpush
-                                do_jpush_code = self.do_jpush(**kwag_args)
-                except Exception as e:
-                    logger.info(
-                        "errLine={errLine}, errMsg={errMsg}".format(errLine=e.__traceback__.tb_lineno, errMsg=repr(e)))
-                    continue
-            if is_sys_msg:
-                SysMsgModel.objects.bulk_create(sys_msg_list)
-            else:
-                # new 分表批量存储 设备信息
-                if new_device_info_list and len(new_device_info_list) > 0:
-                    # 根据日期获得星期几
-                    week = LocalDateTimeUtil.date_to_week(local_date_time)
-                    EquipmentInfoService.equipment_info_bulk_create(week, new_device_info_list)
-                    logger.info('设备信息分表批量保存end------')
-
-            if is_st == 0 or is_st == 2:
-                for up in redis_list:
-                    if up['push_type'] == 0:  # ios apns
-                        up['do_apns_code'] = do_apns_code
-                    elif up['push_type'] == 1:  # android gcm
-                        up['do_fcm_code'] = do_fcm_code
-                    elif up['push_type'] == 2:  # android jpush
-                        up['do_jpush_code'] = do_jpush_code
-                    del up['push_type']
-                    del up['userID_id']
-                    del up['userID__NickName']
-                    del up['lang']
-                    del up['tz']
-                    del up['uid_set__nickname']
-                    del up['uid_set__detect_interval']
-                    del up['uid_set__detect_group']
-                return JsonResponse(status=200, data={'code': 0, 'msg': 'success 0 or 2', 're_list': redis_list})
-
-            elif is_st == 1:
-                thumbspng = '{uid}/{channel}/{filename}.jpeg'.format(uid=uid, channel=channel, filename=n_time)
-                Params = {'Key': thumbspng}
-                if region == 2:  # 2:国内
-                    Params['Bucket'] = 'push'
-                else:  # 1:国外
-                    Params['Bucket'] = 'foreignpush'
-                response_url = generate_s3_url(aws_s3_client, Params)
-                for up in redis_list:
-                    up['do_apns_code'] = do_apns_code
-                    up['do_fcm_code'] = do_fcm_code
-                    up['do_jpush_code'] = do_jpush_code
-                    del up['push_type']
-                    del up['userID_id']
-                    del up['userID__NickName']
-                    del up['lang']
-                    del up['tz']
-                    del up['uid_set__nickname']
-                    del up['uid_set__detect_interval']
-                    del up['uid_set__detect_group']
-                res_data = {'code': 0, 'img_push': response_url, 'msg': 'success'}
-                return JsonResponse(status=200, data=res_data)
-
-            elif is_st == 3:
-                img_url_list = []
-                if region == 2:  # 2:国内
-                    Params = {'Bucket': 'push'}
-                else:  # 1:国外
-                    Params = {'Bucket': 'foreignpush'}
-                for i in range(is_st):
-                    thumbspng = '{uid}/{channel}/{filename}_{st}.jpeg'. \
-                        format(uid=uid, channel=channel, filename=n_time, st=i)
-                    Params['Key'] = thumbspng
-                    response_url = generate_s3_url(aws_s3_client, Params)
-                    img_url_list.append(response_url)
-
-                for up in redis_list:
-                    up['do_apns_code'] = do_apns_code
-                    up['do_fcm_code'] = do_fcm_code
-                    up['do_jpush_code'] = do_jpush_code
-                    del up['push_type']
-                    del up['userID_id']
-                    del up['userID__NickName']
-                    del up['lang']
-                    del up['tz']
-                    del up['uid_set__nickname']
-                    del up['uid_set__detect_interval']
-                    del up['uid_set__detect_group']
-                res_data = {'code': 0, 'img_url_list': img_url_list, 'msg': 'success 3'}
-                return JsonResponse(status=200, data=res_data)
+            with transaction.atomic():
+                is_st = int(is_st)
+                region = int(region)
+                uid = DevicePushService.decode_uid(etk, uidToken)  # 解密uid
+                if len(uid) != 20 and len(uid) != 14:
+                    return JsonResponse(status=200, data={'code': 404, 'msg': 'wrong uid'})
+                req_limiting = '{uid}_{channel}_{event_type}_ptl' \
+                    .format(uid=uid, channel=channel, event_type=event_type)
+                is_sys_msg = self.is_sys_msg(int(event_type))  # 判断事件类型是否是系统消息
+                if is_sys_msg:
+                    push_interval = '{uid}_{channel}_{event_type}_flag' \
+                        .format(uid=uid, channel=channel, event_type=event_type)
+                else:
+                    push_interval = '{uid}_{channel}_flag'.format(uid=uid, channel=channel)
+                redisObj = RedisObject(db=6)
+                cache_req_limiting = redisObj.get_data(key=req_limiting)  # 获取请求限流缓存数据
+                cache_app_push = redisObj.get_data(key=push_interval)  # 获取APP推送消息时间间隔缓存数据
+                logger.info('消息推送- 限流key: {}, 推送间隔key: {}'.
+                            format(cache_req_limiting, cache_app_push))
+                if cache_req_limiting:  # 限流存在则直接返回
+                    return JsonResponse(status=200, data={'code': 0, 'msg': 'Push again in one minute'})
+                redisObj.set_data(key=req_limiting, val=1, expire=60)  # 当缓存不存在限流数据 重新设置一分钟请求一次
+                uid_push_qs = DevicePushService.query_uid_push(uid)  # 查询uid_set与push数据列表
+                if not uid_push_qs.exists():
+                    logger.info('消息推送-uid_push 数据不存在')
+                    return JsonResponse(status=200, data={'code': 176, 'msg': 'no uid_push data'})
+                ai_type = uid_push_qs.first()['uid_set__ai_type']
+                event_type = self.get_combo_msg_type(ai_type, int(event_type))  # 解析消息事件类型看是否多类型组合
+                # 将uid_set以及uid_push 转数组列表
+                uid_set_push_list = DevicePushService.cache_uid_push(uid_push_qs)
+                nickname = uid_set_push_list[0]['uid_set__nickname']
+                nickname = uid if not nickname else nickname
+                # APP消息提醒推送间隔
+                detect_interval = uid_set_push_list[0]['uid_set__detect_interval']
+                if not cache_app_push:
+                    # 缓存APP提醒推送间隔 默认1分钟提醒一次
+                    DevicePushService.cache_push_detect_interval(redisObj, push_interval, detect_interval,
+                                                                 uid_set_push_list[0]['uid_set__new_detect_interval'])
+                bucket = ''
+                aws_s3_client = ''
+                if is_st == 1 or is_st == 3:  # 使用aws s3
+                    aws_s3_client = s3_client(region=region)
+                    bucket = 'foreignpush' if region == 1 else 'push'
+                kwag_args = {
+                    'uid': uid,
+                    'channel': channel,
+                    'event_type': event_type,
+                    'n_time': n_time,
+                }
+                params = {'nickname': nickname, 'uid': uid, 'kwag_args': kwag_args, 'is_st': is_st, 'region': region,
+                          'is_sys_msg': is_sys_msg, 'channel': channel, 'event_type': event_type, 'n_time': n_time,
+                          'electricity': electricity, 'bucket': bucket, 'aws_s3_client': aws_s3_client,
+                          'app_push': cache_app_push}
+                # APP消息推送与获取报警消息数据列表
+                result = DevicePushService.save_msg_push(uid_set_push_list, **params)
+                # 批量系统消息&报警消息数据存库
+                DevicePushService.save_sys_msg(is_sys_msg, result['local_date_time'],
+                                               result['sys_msg_list'], result['new_device_info_list'])
+                params['aws_s3_client'] = aws_s3_client
+                params['uid_set_push_list'] = uid_set_push_list
+                params['code_dict'] = result
+                result_dict = DevicePushService.get_push_url(**params)  # 获取S3对象上传链接
+                return JsonResponse(status=200, data=result_dict)
         except Exception as e:
-            logger.info('移动侦测接口异常: {}'.format(e))
-            logger.info('错误文件', e.__traceback__.tb_frame.f_globals['__file__'])
-            logger.info('错误行号', e.__traceback__.tb_lineno)
+            logger.info('消息推送-异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
             data = {
                 'errLine': e.__traceback__.tb_lineno,
                 'errMsg': repr(e),
@@ -387,7 +213,12 @@ class NotificationV2View(View):
         else:
             return nickname
 
-    def is_sys_msg(self, event_type):
+    @staticmethod
+    def is_sys_msg(event_type):
+        """
+        判断是否属于系统消息
+        @return: True | False
+        """
         event_type_list = [702, 703, 704]
         if event_type in event_type_list:
             return True
@@ -521,12 +352,3 @@ def s3_client(region):
             region_name='us-east-1'
         )
     return aws_s3_client
-
-
-def generate_s3_url(aws_s3_client, Params):
-    response_url = aws_s3_client.generate_presigned_url(
-        ClientMethod='put_object',
-        Params=Params,
-        ExpiresIn=3600
-    )
-    return response_url

+ 445 - 0
Service/DevicePushService.py

@@ -0,0 +1,445 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : DevicePushService.py
+@Time    : 2022/11/23 11:40
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import logging
+import os
+import threading
+import time
+
+import apns2
+import jpush as jpush
+from pyfcm import FCMNotification
+
+from AnsjerPush.config import JPUSH_CONFIG, FCM_CONFIG, APNS_CONFIG, BASE_DIR, APNS_MODE
+from AnsjerPush.config import SERVER_TYPE
+from Model.models import UidPushModel, SysMsgModel
+from Object.ETkObject import ETkObject
+from Object.UidTokenObject import UidTokenObject
+from Object.utils import LocalDateTimeUtil
+from Service.CommonService import CommonService
+from Service.EquipmentInfoService import EquipmentInfoService
+from Service.GatewayService import GatewayPushService
+
+LOGGING = logging.getLogger('info')
+
+
+class DevicePushService:
+
+    @staticmethod
+    def decode_uid(etk, uidToken):
+        """
+        解密UID,优先解密etk 否则判断uidToken
+        """
+        # 解密获取uid
+        if etk:
+            eto = ETkObject(etk)
+            uid = eto.uid
+        else:
+            uto = UidTokenObject(uidToken)
+            uid = uto.UID
+        LOGGING.info('消息推送-当前UID:{}'.format(uid))
+        return uid
+
+    @classmethod
+    def query_uid_push(cls, uid):
+        """
+        查询uid_set与push数据列表
+        """
+        uid_push_qs = UidPushModel.objects.filter(uid_set__uid=uid, uid_set__detect_status=1). \
+            values('token_val', 'app_type', 'appBundleId', 'm_code', 'push_type', 'userID_id', 'userID__NickName',
+                   'lang', 'm_code', 'tz', 'uid_set__nickname', 'uid_set__detect_interval', 'uid_set__detect_group',
+                   'uid_set__channel', 'uid_set__ai_type', 'uid_set__new_detect_interval')
+        return uid_push_qs
+
+    @staticmethod
+    def cache_uid_push(uid_push_qs):
+        """
+        将uid_push 信息进行缓存
+        @param uid_push_qs: uid_set & uid_push 列表对象
+        @return: uid_set_list
+        """
+        uid_set_list = []
+        for qs in uid_push_qs:
+            uid_set_list.append(qs)
+        # redis_obj.set_data(key=name, val=str(redis_list), expire=expire)
+        return uid_set_list
+
+    @staticmethod
+    def cache_push_detect_interval(redis_obj, name, detect_interval, new_detect_interval):
+        """
+        缓存设置推送消息的时间间隔
+        @param redis_obj: redis对象
+        @param name: redis key
+        @param detect_interval: 原推送时间间隔
+        @param new_detect_interval: 新推送时间间隔
+        """
+        if SERVER_TYPE != 'Ansjer.cn_formal_settings':
+            detect_interval = new_detect_interval if new_detect_interval > 0 else detect_interval
+            detect_interval = 60 if detect_interval < 60 else detect_interval
+        redis_obj.set_data(key=name, val=1, expire=detect_interval - 5)
+        LOGGING.info('消息推送-缓存设置APP推送间隔:{}s'.format(detect_interval))
+
+    @classmethod
+    def save_msg_push(cls, uid_set_push_list, **params):
+        """
+        APP消息推送以及报警消息存库
+        @nickname 设备名称
+        @channel 通道
+        @event_type 事件类型
+        """
+        new_device_info_list = []
+        sys_msg_list = []
+        userID_ids = []
+        kwag_args = params['kwag_args']
+        code_data = {'do_apns_code': '', 'do_fcm_code': '', 'do_jpush_code': ''}
+        local_date_time = ''
+        for up in uid_set_push_list:
+            appBundleId = up['appBundleId']
+            token_val = up['token_val']
+            lang = up['lang']
+            tz = up['tz']
+            if tz is None or tz == '':
+                tz = 0
+            # 发送标题
+            msg_title = cls.get_msg_title(appBundleId=appBundleId, nickname=params['nickname'])
+            # 发送内容
+            msg_text = cls.get_msg_text(channel=params['channel'], n_time=params['n_time'], lang=lang,
+                                        tz=tz, event_type=params['event_type'],
+                                        electricity=params['electricity'])
+            kwag_args['appBundleId'] = appBundleId
+            kwag_args['token_val'] = token_val
+            kwag_args['msg_title'] = msg_title
+            kwag_args['msg_text'] = msg_text
+            LOGGING.info('推送要的数据: {}'.format(kwag_args))
+            local_date_time = CommonService.get_now_time_str(n_time=params['n_time'], tz=tz, lang='cn')
+            LOGGING.info('<<<<<根据时区计算后日期={},时区={}'.format(local_date_time, tz))
+            local_date_time = local_date_time[0:10]
+            LOGGING.info('<<<<<切片后的日期={}'.format(local_date_time))
+            # 以下是存库
+            userID_id = up["userID_id"]
+            if userID_id not in userID_ids:
+                now_time = int(time.time())
+                if params['is_sys_msg']:
+                    sys_msg_text = cls.get_msg_text(channel=params['channel'], n_time=params['n_time'], lang=lang,
+                                                    tz=tz,
+                                                    event_type=params['event_type'], electricity=params['electricity'],
+                                                    is_sys=1)
+                    sys_msg_list.append(SysMsgModel(userID_id=userID_id, msg=sys_msg_text, addTime=now_time,
+                                                    updTime=now_time, uid=params['uid'],
+                                                    eventType=params['event_type']))
+                else:
+                    LOGGING.info('分表存数据start------')
+                    params['userID_id'] = userID_id
+                    new_device_info_list.append(cls.created_device_vo(local_date_time, **params))
+                userID_ids.append(userID_id)
+            params['appBundleId'] = appBundleId
+            params['token_val'] = token_val
+            params['lang'] = lang
+            params['tz'] = tz
+            params['kwag_args'] = kwag_args
+            code_data = cls.send_app_msg_push(up['push_type'], **params)
+        return {'code_date': code_data, 'new_device_info_list': new_device_info_list, 'sys_msg_list': sys_msg_list,
+                'local_date_time': local_date_time}
+
+    @classmethod
+    def send_app_msg_push(cls, push_type, **param):
+        """
+        发送app消息推送
+        """
+        try:
+            kwag_args = param['kwag_args']
+            result = {'do_apns_code': '', 'do_fcm_code': '', 'do_jpush_code': ''}
+            # 判断是否进行APP消息推送,如app_push不为空,则不进行推送
+            if not param['app_push']:
+                LOGGING.info('APP准备推送:{}, {}'.format(param['uid'], param))
+                if (param['is_st'] == 1 or param['is_st'] == 3) and (push_type == 0 or push_type == 1):  # 推送显示图片
+                    if param['is_st'] == 1:
+                        key = '{}/{}/{}.jpeg'.format(param['uid'], param['channel'], param['n_time'])
+                    else:
+                        key = '{}/{}/{}_0.jpeg'.format(param['uid'], param['channel'], param['n_time'])
+                    push_thread = threading.Thread(target=cls.async_send_picture_push, args=(
+                        push_type, param['aws_s3_client'], param['bucket'], key, param['uid'], param['appBundleId'],
+                        param['token_val'], param['event_type'], param['n_time'],
+                        param['msg_title'], param['msg_text'], param['channel']))
+                    push_thread.start()
+                else:
+                    if push_type == 0:  # ios apns
+                        result['do_apns_code'] = cls.do_apns(**kwag_args)
+                    elif push_type == 1:  # android gcm
+                        result['do_fcm_code'] = cls.do_fcm(**kwag_args)
+                    elif push_type == 2:  # android jpush
+                        result['do_jpush_code'] = cls.do_jpush(**kwag_args)
+            return result
+        except Exception as e:
+            LOGGING.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return None
+
+    @classmethod
+    def save_sys_msg(cls, is_sys_msg, local_date_time, sys_msg_list, new_device_info_list):
+        """
+        保存系统消息&设备推送消息存库
+        """
+        if is_sys_msg:
+            SysMsgModel.objects.bulk_create(sys_msg_list)
+        else:
+            # new 分表批量存储 设备信息
+            if new_device_info_list and len(new_device_info_list) > 0:
+                # 根据日期获得星期几
+                week = LocalDateTimeUtil.date_to_week(local_date_time)
+                EquipmentInfoService.equipment_info_bulk_create(week, new_device_info_list)
+                LOGGING.info('设备信息分表批量保存end------')
+        return True
+
+    @classmethod
+    def created_device_vo(cls, local_date_time, **params):
+        """
+        获取设备推送表对象
+        """
+        return EquipmentInfoService.get_equipment_info_obj(
+            local_date_time,
+            device_user_id=params['userID_id'],
+            event_time=params['n_time'],
+            event_type=params['event_type'],
+            device_uid=params['uid'],
+            device_nick_name=params['nickname'],
+            channel=params['channel'],
+            alarm='Motion \tChannel:{channel}'.format(channel=params['channel']),
+            is_st=params['is_st'],
+            receive_time=params['n_time'],
+            add_time=int(time.time()),
+            storage_location=2,
+            border_coords='',
+        )
+
+    @staticmethod
+    def get_msg_title(appBundleId, nickname):
+        """
+        获取消息标题
+        """""
+        package_title_config = {
+            'com.ansjer.customizedd_a': 'DVS',
+            'com.ansjer.zccloud_a': 'ZosiSmart',
+            'com.ansjer.zccloud_ab': '周视',
+            'com.ansjer.adcloud_a': 'ADCloud',
+            'com.ansjer.adcloud_ab': 'ADCloud',
+            'com.ansjer.accloud_a': 'ACCloud',
+            'com.ansjer.loocamccloud_a': 'Loocam',
+            'com.ansjer.loocamdcloud_a': 'Anlapus',
+            'com.ansjer.customizedb_a': 'COCOONHD',
+            'com.ansjer.customizeda_a': 'Guardian365',
+            'com.ansjer.customizedc_a': 'PatrolSecure',
+        }
+        if appBundleId in package_title_config.keys():
+            return package_title_config[appBundleId] + '(' + nickname + ')'
+        else:
+            return nickname
+
+    @staticmethod
+    def get_msg_text(channel, n_time, lang, tz, event_type, electricity='', is_sys=0):
+        """
+        获取消息文本
+        """
+        n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
+        etype = int(event_type)
+        if lang == 'cn':
+            if etype == 704:
+                msg_type = '剩余电量:' + electricity
+            elif etype == 702:
+                msg_type = '摄像头休眠'
+            elif etype == 703:
+                msg_type = '摄像头唤醒'
+            else:
+                msg_type = ''
+            if is_sys:
+                send_text = '{msg_type} 通道:{channel}'.format(msg_type=msg_type, channel=channel)
+            else:
+                send_text = '{msg_type} 通道:{channel} 日期:{date}'.format(msg_type=msg_type, channel=channel, date=n_date)
+        else:
+            if etype == 704:
+                msg_type = 'Battery remaining:' + electricity
+            elif etype == 702:
+                msg_type = 'Camera sleep'
+            elif etype == 703:
+                msg_type = 'Camera wake'
+            else:
+                msg_type = ''
+            if is_sys:
+                send_text = '{msg_type} channel:{channel}'. \
+                    format(msg_type=msg_type, channel=channel)
+            else:
+                send_text = '{msg_type} channel:{channel} date:{date}'. \
+                    format(msg_type=msg_type, channel=channel, date=n_date)
+        return send_text
+
+    @staticmethod
+    def do_jpush(uid, channel, appBundleId, token_val, event_type, n_time,
+                 msg_title, msg_text):
+        """
+        android 国内极光APP消息提醒推送
+        """
+        app_key = JPUSH_CONFIG[appBundleId]['Key']
+        master_secret = JPUSH_CONFIG[appBundleId]['Secret']
+        _jpush = jpush.JPush(app_key, master_secret)
+        push = _jpush.create_push()
+        push.audience = jpush.registration_id(token_val)
+        push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
+                     "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1", "channel": channel}
+        android = jpush.android(alert=msg_text, priority=1, style=1, alert_type=7,
+                                big_text=msg_text, title=msg_title,
+                                extras=push_data)
+        push.notification = jpush.notification(android=android)
+        push.platform = jpush.all_
+        res = push.send()
+        print(res)
+        return res.status_code
+
+    @staticmethod
+    def do_fcm(uid, channel, appBundleId, token_val, event_type, n_time, msg_title, msg_text):
+        """
+        android 谷歌APP消息提醒推送
+        """
+        try:
+            serverKey = FCM_CONFIG[appBundleId]
+        except Exception as e:
+            LOGGING.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return 'serverKey abnormal'
+        push_service = FCMNotification(api_key=serverKey)
+        data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
+                "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1", "channel": channel}
+        result = push_service.notify_single_device(registration_id=token_val, message_title=msg_title,
+                                                   message_body=msg_text, data_message=data,
+                                                   extra_kwargs={
+                                                       'default_vibrate_timings': True,
+                                                       'default_sound': True,
+                                                       'default_light_settings': True
+                                                   })
+        return result
+
+    @staticmethod
+    def do_apns(uid, channel, appBundleId, token_val, event_type, n_time, msg_title,
+                msg_text):
+        """
+        ios 消息提醒推送
+        """
+        LOGGING.info("进来do_apns函数了")
+        LOGGING.info(token_val)
+        LOGGING.info(APNS_MODE)
+        LOGGING.info(os.path.join(BASE_DIR, APNS_CONFIG[appBundleId]['pem_path']))
+        try:
+            cli = apns2.APNSClient(
+                mode=APNS_MODE, client_cert=os.path.join(BASE_DIR, APNS_CONFIG[appBundleId]['pem_path']))
+
+            push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
+                         "received_at": n_time, "sound": "", "uid": uid, "zpush": "1", "channel": channel}
+            alert = apns2.PayloadAlert(body=msg_text, title=msg_title)
+            payload = apns2.Payload(alert=alert, custom=push_data, sound="default")
+
+            # return uid, channel, appBundleId, str(token_val), event_type, n_time, msg_title,msg_text
+            n = apns2.Notification(payload=payload, priority=apns2.PRIORITY_LOW)
+            res = cli.push(n=n, device_token=token_val, topic=appBundleId)
+            print(res.status_code)
+            LOGGING.info("apns_推送状态:")
+            LOGGING.info(res.status_code)
+
+            if res.status_code == 200:
+                return res.status_code
+            else:
+                print('apns push fail')
+                print(res.reason)
+                LOGGING.info('apns push fail')
+                LOGGING.info(res.reason)
+                return res.status_code
+        except (ValueError, ArithmeticError):
+            return 'The program has a numeric format exception, one of the arithmetic exceptions'
+        except Exception as e:
+            print(repr(e))
+            print('do_apns函数错误行号', e.__traceback__.tb_lineno)
+            LOGGING.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return repr(e)
+
+    @classmethod
+    def async_send_picture_push(cls, push_type, aws_s3_client, bucket, key, uid, appBundleId,
+                                token_val, event_type, n_time, msg_title, msg_text, channel):
+        """
+        异步APP图片推送
+        """
+        try:
+            image_url = aws_s3_client.generate_presigned_url('get_object', Params={'Bucket': bucket, 'Key': key},
+                                                             ExpiresIn=300)
+            LOGGING.info('推送图片url:{}'.format(image_url))
+            if push_type == 0:
+                GatewayPushService.ios_apns_push(uid, appBundleId, token_val, n_time, event_type, msg_title, msg_text,
+                                                 uid, channel, image_url)
+            elif push_type == 1:
+                GatewayPushService.android_fcm_push(uid, appBundleId, token_val, n_time, event_type, msg_title,
+                                                    msg_text, uid, channel, image_url)
+        except Exception as e:
+            LOGGING.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def get_push_url(**params):
+        """
+        获取推送URL,设备根本当前返回结果进行数据上传
+        @return: re_data
+        """
+        re_data = {'code': 0, 'msg': 'success'}
+        if params['is_st'] == 0 or params['is_st'] == 2:
+            re_data['msg'] = 'success 0 or 2'
+            for up in params['uid_set_push_list']:
+                if up['push_type'] == 0:  # ios apns
+                    up['do_apns_code'] = params['code_dict']['do_apns_code']
+                elif up['push_type'] == 1:  # android gcm
+                    up['do_fcm_code'] = params['code_dict']['do_fcm_code']
+                elif up['push_type'] == 2:  # android jpush
+                    up['do_jpush_code'] = params['code_dict']['do_jpush_code']
+                del up['push_type']
+                del up['userID_id']
+                del up['userID__NickName']
+                del up['lang']
+                del up['tz']
+                del up['uid_set__nickname']
+                del up['uid_set__detect_interval']
+                del up['uid_set__detect_group']
+            re_data['re_list'] = params['uid_set_push_list']
+        elif params['is_st'] == 1:
+            key_name = '{uid}/{channel}/{filename}.jpeg' \
+                .format(uid=params['uid'], channel=params['channel'], filename=params['n_time'])
+            re_args = {'Key': key_name}
+            if params['region'] == 2:  # 2:国内
+                re_args['Bucket'] = 'push'
+            else:  # 1:国外
+                re_args['Bucket'] = 'foreignpush'
+            response_url = DevicePushService.generate_s3_url(params['aws_s3_client'], re_args)
+            re_data['img_push'] = response_url
+        elif params['is_st'] == 3:
+            img_url_list = []
+            if params['region'] == 2:  # 2:国内
+                re_args = {'Bucket': 'push'}
+            else:  # 1:国外
+                re_args = {'Bucket': 'foreignpush'}
+            for i in range(params['is_st']):
+                key_name = '{uid}/{channel}/{filename}_{st}.jpeg'. \
+                    format(uid=params['uid'], channel=params['channel'], filename=params['n_time'], st=i)
+                re_args['Key'] = key_name
+                response_url = DevicePushService.generate_s3_url(params['aws_s3_client'], re_args)
+                img_url_list.append(response_url)
+            re_data['img_url_list'] = img_url_list
+            re_data['msg'] = 'success 3'
+        return re_data
+
+    @staticmethod
+    def generate_s3_url(aws_s3_client, params):
+        """
+        获取S3对象URL
+        """
+        response_url = aws_s3_client.generate_presigned_url(
+            ClientMethod='put_object',
+            Params=params,
+            ExpiresIn=3600
+        )
+        return response_url