Browse Source

推送服务

chenjunkai 5 years ago
parent
commit
30653ffa5e
10 changed files with 715 additions and 295 deletions
  1. 1 0
      .gitignore
  2. 102 1
      AnsjerPush/config.py
  3. 7 27
      AnsjerPush/settings.py
  4. 196 154
      Controller/DetectController.py
  5. 133 108
      Model/models.py
  6. 68 0
      Object/ETkObject.py
  7. 0 4
      Object/RedisObject.py
  8. 6 0
      Object/UidTokenObject.py
  9. 202 0
      Service/CommonService.py
  10. 0 1
      requirements.txt

+ 1 - 0
.gitignore

@@ -13,3 +13,4 @@
 /Ansjer/test/__init__.py
 /sdk_install
 /DB/mydata4vipday2.ipdb
+/__pycache__/*.pyc

+ 102 - 1
AnsjerPush/config.py

@@ -14,6 +14,9 @@
 # 主要静态变量配置文件
 import datetime, os
 
+
+DEBUG_MODE = 'DEV'
+# MODE = 'PRO'
 # 阿里云发邮箱
 ALY_SES_ACCESS_NAME = 'message@dvema.com'
 ALY_SES_ACCESS_PAW = 'SMtp123456'
@@ -59,10 +62,108 @@ NGINX_RTMP_STAT = 'http://www.dvema.com/stat'
 SERVER_DOMAIN = 'http://www.dvema.com/'
 SERVER_DOMAIN_SSL = 'https://www.dvema.com/'
 DOMAIN_HOST = 'www.dvema.com'
-SERVER_HOST = 'localhost'
+SERVER_HOST = '192.168.136.45'
+# SERVER_HOST = 'localhost'
 PAYPAL_CRD = {
     "mode": "live",  # sandbox or live
     "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
     "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
 }
 DETECT_PUSH_DOMAIN = 'http://push.dvema.com/'
+
+
+JPUSH_CONFIG = {
+    'com.ansjer.accloud_ab': {
+        'Key': 'f0dc047e5e53fd14199de5b0',
+        'Secret': 'aa7f7db33e9f0a7f3871aa1c'},
+    'com.ansjer.adcloud_ab': {
+        'Key': '76d97b535185114985608234',
+        'Secret': 'c9a92b301043cc9c52778692'},
+    'com.ansjer.zccloud_ab': {
+        'Key': 'd9924f56d3cc7c6017965130',
+        'Secret': '869d832d126a232f158b5987'},
+    'com.ansjer.loocamccloud_ab': {
+        'Key': 'd1cc44797b4642b0e05304fe',
+        'Secret': 'c3e8b4ca8c576de61401e56a'},
+    'com.ansjer.loocamdcloud_ab': {
+        'Key': '76d97b535185114985608234',
+        'Secret': 'c9a92b301043cc9c52778692'},
+    'com.ansjer.zccloud_a': {
+        'Key': '57de2a80d68bf270fd6bdf5a',
+        'Secret': '3d354eb6a0b49c2610decf42'},
+    'com.ansjer.accloud_a': {
+        'Key': 'ff95ee685f49c0dc4013347b',
+        'Secret': 'de2c20959f5516fdeeafe78e'},
+    'com.ansjer.adcloud_a': {
+        'Key': '2e47eb1aee9b164460df3668',
+        'Secret': 'b9137d8d684bc248f1809b6d'},
+    'com.ansjer.loocamccloud_a': {
+        'Key': '23c9213215c7ca0ec945629b',
+        'Secret': '81e4b1e859cc8387e2e6c431'},
+    'com.ansjer.loocamdcloud_a': {
+        'Key': '1dbdd60a16e9892d6f68a073',
+        'Secret': '80a97690e7e043109059b403'},
+    'com.ansjer.customizedb_a': {
+        'Key': '9d79630aa49adfa291fe2568',
+        'Secret': '4d8ff52f88136561875a0212'},
+    'com.ansjer.customizedd_a': {
+        'Key': '8fc4f495685bde53341ee25d',
+        'Secret': 'f1da11fa466509fa2670fb66',
+    }
+}
+# type =1
+FCM_CONFIG = {
+    'com.ansjer.zccloud_a': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
+    'com.ansjer.loocamccloud_a': 'AAAAb9YP3rk:APA91bFCgd-kbVmpK4EVpfdHH_PJZQCYTkOGnTZdIuBWEz2r7aMRsJYHOH3sB-rwcbaRWgnufTyjX9nGQxb6KxQbWVk4ah_H-M3IqGh6Mb60WQQAuR33V6g_Jes5pGL6ViuIxGHqVMaR',
+    'com.ansjer.loocamdcloud_a': 'AAAAb9YP3rk:APA91bGw2I2KMD4i-5T7nZO_wB8kuAOuqgyqe5rxmY-W5qkpYEx9IL2IfmC_qf6B_xOyjIDDSjckvMo-RauN__SEoxvAkis7042GRkoKpw7cjZ_H8lC-d50PC0GclPzccrOGFusyKbFY',
+    'com.ansjer.customizedb_a': 'AAAAb9YP3rk:APA91bE7kI4vcm-9h_CJNFlOZfc-xwP4Btn6AnjOrwoKV6fgYN7fdarkO76sYxVZiAbDnxsFfOJyP7vQfwyan6mdjuyD5iHdt_XgO22VqniC0vA1V4GJiCS8Tp7LxIX8JVKZl9I_Powt',
+    'com.ansjer.customizeda_a': 'AAAAb9YP3rk:APA91bF0HzizVWDc6dKzobY9fsaKDK4veqkOZehDXshVXs8pEEvNWjR_YWbhP60wsRYCHCal8fWN5cECVOWNMMzDsfU88Ty2AUl8S5FtZsmeDTkoGntQOswBr8Ln7Fm_LAp1VqTf9CpM',
+    'com.ansjer.customizedd_a': 'AAAAb9YP3rk:APA91bHkxOozJWBrlv3eNT0PgwosYENI9aM4Zuzd418cX-iKkpa1zFNC5MkNDKApx1KH4fhmAfaJ6IMRZ0nj5GIxCpstDYCaZWwgC7-etqfSxG5JAq8LOwJx0o_1tUZqwjIic8ztsg0o',
+    'com.ansjer.adcloud_a': 'AAAAb9YP3rk:APA91bFm06w8b9OKQ0gz0iaWFuRqRIkvgAz6z7Gp3dBU_X-LNGJQd1hc1QR2W7QzBglF8SHtERA45a2lbdLRa5qv7hxfd6W_sJLBK7dA8jklsOQBvy505oUzTwMKWy4TwH-exps9KrhO',
+    'com.ansjer.accloud_a': 'AAAAb9YP3rk:APA91bFm06w8b9OKQ0gz0iaWFuRqRIkvgAz6z7Gp3dBU_X-LNGJQd1hc1QR2W7QzBglF8SHtERA45a2lbdLRa5qv7hxfd6W_sJLBK7dA8jklsOQBvy505oUzTwMKWy4TwH-exps9KrhO'
+}
+
+if DEBUG_MODE == 'DEV':
+    APNS_CONFIG = {
+        'com.ansjer.loocamccloud': {
+            'pem_path': 'Ansjer/file/apns_pem/lcc-dev.pem',
+        },
+        'com.ansjer.zosidcloud': {
+            'pem_path': 'Ansjer/file/apns_pem/zosidcloud-dev.pem',
+        },
+        'com.ansjer.customizedb': {
+            'pem_path': 'Ansjer/file/apns_pem/customizedb-dev.pem',
+        },
+        'com.ansjer.customizeda': {
+            'pem_path': 'Ansjer/file/apns_pem/customizeda-dev.pem',
+        },
+        'com.ansjer.zccloud': {
+            'pem_path': 'Ansjer/file/apns_pem/zccloud-dev.pem',
+        },
+        'com.ansjer.accloud': {
+            'pem_path': 'Ansjer/file/apns_pem/accloud-dev.pem',
+        }
+    }
+    APNS_MODE = 'dev'
+if DEBUG_MODE == 'PRO':
+    APNS_CONFIG = {
+        'com.ansjer.loocamccloud': {
+            'pem_path': 'Ansjer/file/apns_pem/lcc.pem',
+        },
+        'com.ansjer.zosidcloud': {
+            'pem_path': 'Ansjer/file/apns_pem/zosidcloud.pem',
+        },
+        'com.ansjer.customizedb': {
+            'pem_path': 'Ansjer/file/apns_pem/customizedb.pem',
+        },
+        'com.ansjer.customizeda': {
+            'pem_path': 'Ansjer/file/apns_pem/customizeda.pem',
+        },
+        'com.ansjer.zccloud': {
+            'pem_path': 'Ansjer/file/apns_pem/zccloud.pem',
+        },
+        'com.ansjer.accloud': {
+            'pem_path': 'Ansjer/file/apns_pem/accloud-dev.pem',
+        }
+    }
+    APNS_MODE = 'prod'

+ 7 - 27
AnsjerPush/settings.py

@@ -1,35 +1,10 @@
-"""
-Django settings for AnsjerPush project.
-
-Generated by 'django-admin startproject' using Django 2.1.4.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/2.1/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/2.1/ref/settings/
-"""
-
 import os
 
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
 SECRET_KEY = '$2hf5g$a%_^kk0-l25l$!o5)yc=dvtnfpc8(+$rh4fq4twa_xx'
-
-# SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True
-
 ALLOWED_HOSTS = ["*"]
 
-
-# Application definition
-
 INSTALLED_APPS = [
     'django.contrib.admin',
     'django.contrib.auth',
@@ -83,10 +58,15 @@ WSGI_APPLICATION = 'AnsjerPush.wsgi.application'
 # DATABASES_USER = 'ansjer'
 # DATABASES_PASS = '1234'
 # test
-DATABASE_DATA = 'AnsjerTest'
-SERVER_HOST = '13.56.215.252'
+# DATABASE_DATA = 'AnsjerTest'
+# SERVER_HOST = '13.56.215.252'
+# DATABASES_USER = 'ansjer'
+# DATABASES_PASS = '1234'
+DATABASE_DATA = 'AnsjerLocal'
+SERVER_HOST = '192.168.136.45'
 DATABASES_USER = 'ansjer'
 DATABASES_PASS = '1234'
+
 DATABASES = {'default': {
     'ENGINE': 'django.db.backends.mysql',
     'NAME': DATABASE_DATA,

+ 196 - 154
Controller/DetectController.py

@@ -11,7 +11,6 @@
 @file: DetectController.py
 @Contact: chanjunkai@163.com
 """
-
 import os
 import time
 
@@ -22,18 +21,20 @@ from django.http import JsonResponse
 from django.views.generic.base import View
 from pyfcm import FCMNotification
 
-from AnsjerPush.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, BASE_DIR
+from AnsjerPush.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, DETECT_PUSH_DOMAIN, JPUSH_CONFIG, \
+    FCM_CONFIG, APNS_CONFIG, BASE_DIR, APNS_MODE
 from Model.models import Equipment_Info, UidSetModel, UidPushModel
+from Object.ETkObject import ETkObject
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.UidTokenObject import UidTokenObject
+from Service.CommonService import CommonService
 
-
-# http://192.168.136.40:8077/notify/push?uidToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJUTjdNUEUzMjExVUU3NkFQMTExQSJ9.k501567VdnhFpn_ygzGRDat3Kqlz5CsEA9jAC2dDk_g&obj=12341234&n_time=1234561234
+# http://192.168.136.40:8099/notify/push?uidToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJWVkRIQ1ZCWURLRk1KUldBMTExQSIsImNoYW5uZWwiOiIxIn0.4Uyaw7_wPetBKn9LeO28eqLFivWE1gmny-n1j0Xm-Mk&obj=12341234&n_time=1234561234
 # http://test.dvema.com/notify/push?uidToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJQMldOR0pSRDJFSEE1RVU5MTExQSJ9.xOCI5lerk8JOs5OcAzunrKCfCrtuPIZ3AnkMmnd-bPY&n_time=1526845794&channel=1&event_type=51&is_st=0
-# 移动侦测接口
 
 
+# 移动侦测接口
 class NotificationView(View):
 
     def get(self, request, *args, **kwargs):
@@ -60,27 +61,31 @@ class NotificationView(View):
             # return response.json(444)
         utko = UidTokenObject(uidToken)
         uid = utko.UID
+        redisObj = RedisObject(db=6)
+        # pkey = '{uid}_{channel}_ptl'.format(uid=uid, channel=channel)
+        pkey = '{uid}_ptl'.format(uid=uid)
+        if redisObj.get_data(key=pkey):
+            res_data = {'code': 0, 'msg': 'success,!'}
+            return JsonResponse(status=200, data=res_data)
+        else:
+            # 设置推送间隔60秒一次
+            redisObj.set_data(key=pkey, val=1, expire=60)
         uid_set_qs = UidSetModel.objects.filter(uid=uid, detect_status=1)
         if uid_set_qs.exists():
             uid_set_id = uid_set_qs[0].id
             nickname = uid_set_qs[0].nickname
+            if not nickname:
+                nickname = uid
             uid_push_qs = UidPushModel.objects.filter(uid_set__id=uid_set_id). \
-                values('token_val', 'app_type', 'appBundleId', 'push_type', 'userID_id', 'userID__NickName', 'lang')
-            if uid_set_qs.exists():
-                redisObj = RedisObject(db=6)
-                pkey = '{uid}_{channel}_ptl'.format(uid=uid, channel=channel)
-                if redisObj.get_data(key=pkey):
-                    res_data = {'code': 0, 'msg': 'success,!'}
-                    return JsonResponse(status=200, data=res_data)
-                else:
-                    detect_interval = uid_set_qs[0].detect_interval
-                    if detect_interval:
-                        redisObj.set_data(key=pkey, val=1, expire=detect_interval)
+                values('token_val', 'app_type', 'appBundleId', 'push_type', 'userID_id', 'userID__NickName', 'lang',
+                       'tz')
+            if uid_push_qs.exists():
                 auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
                 bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
                 for up in uid_push_qs:
                     push_type = up['push_type']
                     # ios apns
+                    print(push_type)
                     if push_type == 0:
                         self.do_apns(request_dict, up, response, uid, channel, nickname)
                     # android gcm
@@ -95,13 +100,25 @@ class NotificationView(View):
                 self.do_bulk_create_info(uid_push_qs, n_time, channel, event_type, is_st, uid)
                 if is_st == '0' or is_st == '2':
                     return JsonResponse(status=200, data={'code': 0, 'msg': 'success'})
-                else:
+                elif is_st == '1':
                     # Endpoint以杭州为例,其它Region请按实际情况填写。
                     obj = '{uid}/{channel}/{filename}.jpeg'.format(uid=uid, channel=channel, filename=n_time)
                     # 设置此签名URL在60秒内有效。
                     url = bucket.sign_url('PUT', obj, 7200)
                     res_data = {'code': 0, 'img_push': url, 'msg': 'success'}
                     return JsonResponse(status=200, data=res_data)
+                elif is_st == '3':
+                    # 人形检测带动图
+                    # Endpoint以杭州为例,其它Region请按实际情况填写。
+                    img_url_list = []
+                    for i in range(int(is_st)):
+                        obj = '{uid}/{channel}/{filename}_{st}.jpeg'. \
+                            format(uid=uid, channel=channel, filename=n_time, st=i)
+                        # 设置此签名URL在60秒内有效。
+                        url = bucket.sign_url('PUT', obj, 7200)
+                        img_url_list.append(url)
+                    res_data = {'code': 0, 'img_url_list': img_url_list, 'msg': 'success'}
+                    return JsonResponse(status=200, data=res_data)
             else:
                 return JsonResponse(status=200, data={'code': 404, 'msg': 'data is not exist'})
         else:
@@ -109,53 +126,14 @@ class NotificationView(View):
 
     def do_jpush(self, request_dict, uaql, response, uid, channel, nickname):
         event_type = request_dict.get('event_type', None)
-        jpush_config = {
-            'com.ansjer.accloud_ab': {
-                'Key': 'f0dc047e5e53fd14199de5b0',
-                'Secret': 'aa7f7db33e9f0a7f3871aa1c'},
-            'com.ansjer.adcloud_ab': {
-                'Key': '76d97b535185114985608234',
-                'Secret': 'c9a92b301043cc9c52778692'},
-            'com.ansjer.zccloud_ab': {
-                'Key': 'd9924f56d3cc7c6017965130',
-                'Secret': '869d832d126a232f158b5987'},
-            'com.ansjer.loocamccloud_ab': {
-                'Key': 'd1cc44797b4642b0e05304fe',
-                'Secret': 'c3e8b4ca8c576de61401e56a'},
-            'com.ansjer.loocamdcloud_ab': {
-                'Key': '76d97b535185114985608234',
-                'Secret': 'c9a92b301043cc9c52778692'},
-            'com.ansjer.zccloud_a': {
-                'Key': '57de2a80d68bf270fd6bdf5a',
-                'Secret': '3d354eb6a0b49c2610decf42'},
-            'com.ansjer.accloud_a': {
-                'Key': 'ff95ee685f49c0dc4013347b',
-                'Secret': 'de2c20959f5516fdeeafe78e'},
-            'com.ansjer.adcloud_a': {
-                'Key': '2e47eb1aee9b164460df3668',
-                'Secret': 'b9137d8d684bc248f1809b6d'},
-            'com.ansjer.loocamccloud_a': {
-                'Key': '23c9213215c7ca0ec945629b',
-                'Secret': '81e4b1e859cc8387e2e6c431'},
-            'com.ansjer.loocamdcloud_a': {
-                'Key': '1dbdd60a16e9892d6f68a073',
-                'Secret': '80a97690e7e043109059b403'},
-            'com.ansjer.customizedb_a': {
-                'Key': '9d79630aa49adfa291fe2568',
-                'Secret': '4d8ff52f88136561875a0212'},
-            'com.ansjer.customizedd_a': {
-                'Key': '8fc4f495685bde53341ee25d',
-                'Secret': 'f1da11fa466509fa2670fb66',
-            }
-        }
         n_time = request_dict.get('n_time', None)
         appBundleId = uaql['appBundleId']
         token_val = uaql['token_val']
         lang = uaql['lang']
-
+        tz = uaql['tz']
         response = ResponseObject()
-        app_key = jpush_config[appBundleId]['Key']
-        master_secret = jpush_config[appBundleId]['Secret']
+        app_key = JPUSH_CONFIG[appBundleId]['Key']
+        master_secret = JPUSH_CONFIG[appBundleId]['Secret']
         # 此处换成各自的app_key和master_secre
         _jpush = jpush.JPush(app_key, master_secret)
         push = _jpush.create_push()
@@ -165,24 +143,8 @@ class NotificationView(View):
         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}
-        n_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(n_time)))
-        if lang == 'cn':
-            if nickname:
-                # message_title = "周视({nickname})".format(nickname=nickname)
-                message_title = self.get_message_title(appBundleId=appBundleId, nickname=nickname)
-            else:
-                # message_title = "周视({uid})".format(uid=uid)
-                message_title = self.get_message_title(appBundleId=appBundleId, nickname=uid)
-            send_text = '通道:{channel} 日期:{date}'.format(channel=channel, date=n_date)
-        else:
-            if nickname:
-                message_title = self.get_message_title(appBundleId=appBundleId, nickname=nickname)
-                # message_title = "zosi({nickname})".format(nickname=nickname)
-            else:
-                message_title = self.get_message_title(appBundleId=appBundleId, nickname=uid)
-
-                # message_title = "zosi({uid})".format(uid=uid)
-            send_text = 'channel:{channel} date:{date}'.format(channel=channel, date=n_date)
+        message_title = self.get_message_title(appBundleId=appBundleId, nickname=nickname)
+        send_text = self.get_send_text(channel=channel, n_time=n_time, lang=lang, tz=tz,event_type=event_type)
         android = jpush.android(alert=send_text, priority=1, style=1, alert_type=7,
                                 big_text=send_text, title=message_title,
                                 extras=push_data)
@@ -200,66 +162,52 @@ class NotificationView(View):
         else:
             return response.json(0)
 
-
     def get_message_title(self, 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',
+            '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+')'
+            return package_title_config[appBundleId] + '(' + nickname + ')'
         else:
             return nickname
 
+    def get_send_text(self, channel, n_time, lang, tz, event_type):
+        n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz)
+        msg_type = ''
+        if int(event_type) == 704:
+            msg_type = 'battery is too low'
+            if lang == 'cn':
+                msg_type = '电池电量过低'
+        send_text = '{msg_type}channel:{channel} date:{date}'.format(msg_type=msg_type, channel=channel, date=n_date)
+        if lang == 'cn':
+            send_text = '{msg_type}通道:{channel} 日期:{date}'.format(msg_type=msg_type, channel=channel, date=n_date)
+        return send_text
+
     def do_fcm(self, request_dict, uaql, response, uid, channel, nickname):
         n_time = request_dict.get('n_time')
         appBundleId = uaql['appBundleId']
         token_val = uaql['token_val']
         lang = uaql['lang']
-        fcm_config = {
-            'com.ansjer.zccloud_a': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
-            'com.ansjer.loocamccloud_a': 'AAAAb9YP3rk:APA91bFCgd-kbVmpK4EVpfdHH_PJZQCYTkOGnTZdIuBWEz2r7aMRsJYHOH3sB-rwcbaRWgnufTyjX9nGQxb6KxQbWVk4ah_H-M3IqGh6Mb60WQQAuR33V6g_Jes5pGL6ViuIxGHqVMaR',
-            'com.ansjer.loocamdcloud_a': 'AAAAb9YP3rk:APA91bGw2I2KMD4i-5T7nZO_wB8kuAOuqgyqe5rxmY-W5qkpYEx9IL2IfmC_qf6B_xOyjIDDSjckvMo-RauN__SEoxvAkis7042GRkoKpw7cjZ_H8lC-d50PC0GclPzccrOGFusyKbFY',
-            'com.ansjer.customizedb_a': 'AAAAb9YP3rk:APA91bE7kI4vcm-9h_CJNFlOZfc-xwP4Btn6AnjOrwoKV6fgYN7fdarkO76sYxVZiAbDnxsFfOJyP7vQfwyan6mdjuyD5iHdt_XgO22VqniC0vA1V4GJiCS8Tp7LxIX8JVKZl9I_Powt',
-            'com.ansjer.customizeda_a': 'AAAAb9YP3rk:APA91bF0HzizVWDc6dKzobY9fsaKDK4veqkOZehDXshVXs8pEEvNWjR_YWbhP60wsRYCHCal8fWN5cECVOWNMMzDsfU88Ty2AUl8S5FtZsmeDTkoGntQOswBr8Ln7Fm_LAp1VqTf9CpM',
-            'com.ansjer.customizedd_a': 'AAAAb9YP3rk:APA91bHkxOozJWBrlv3eNT0PgwosYENI9aM4Zuzd418cX-iKkpa1zFNC5MkNDKApx1KH4fhmAfaJ6IMRZ0nj5GIxCpstDYCaZWwgC7-etqfSxG5JAq8LOwJx0o_1tUZqwjIic8ztsg0o',
-            'com.ansjer.adcloud_a': 'AAAAb9YP3rk:APA91bFm06w8b9OKQ0gz0iaWFuRqRIkvgAz6z7Gp3dBU_X-LNGJQd1hc1QR2W7QzBglF8SHtERA45a2lbdLRa5qv7hxfd6W_sJLBK7dA8jklsOQBvy505oUzTwMKWy4TwH-exps9KrhO',
-            'com.ansjer.accloud_a': 'AAAAb9YP3rk:APA91bFm06w8b9OKQ0gz0iaWFuRqRIkvgAz6z7Gp3dBU_X-LNGJQd1hc1QR2W7QzBglF8SHtERA45a2lbdLRa5qv7hxfd6W_sJLBK7dA8jklsOQBvy505oUzTwMKWy4TwH-exps9KrhO'
-        }
+        tz = uaql['tz']
         try:
-            serverKey = fcm_config[appBundleId]
+            serverKey = FCM_CONFIG[appBundleId]
         except Exception as e:
             return response.json(404)
         event_type = request_dict.get('event_type', None)
         push_service = FCMNotification(api_key=serverKey)
         registration_id = token_val
-        n_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(n_time)))
-        if lang == 'cn':
-            if nickname:
-                # message_title = "周视({nickname})".format(nickname=nickname)
-                message_title = self.get_message_title(appBundleId=appBundleId,nickname=nickname)
-            else:
-                # message_title = "周视({uid})".format(uid=uid)
-                message_title = self.get_message_title(appBundleId=appBundleId,nickname=uid)
-            send_text = '通道:{channel} 日期:{date}'.format(channel=channel, date=n_date)
-        else:
-            if nickname:
-                message_title = self.get_message_title(appBundleId=appBundleId,nickname=nickname)
-                # message_title = "zosi({nickname})".format(nickname=nickname)
-            else:
-                message_title = self.get_message_title(appBundleId=appBundleId,nickname=uid)
-
-                # message_title = "zosi({uid})".format(uid=uid)
-            send_text = 'channel:{channel} date:{date}'.format(channel=channel, date=n_date)
+        message_title = self.get_message_title(appBundleId=appBundleId, nickname=nickname)
+        send_text = self.get_send_text(channel=channel, n_time=n_time, lang=lang, tz=tz,event_type=event_type)
         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=registration_id, message_title=message_title,
@@ -278,28 +226,15 @@ class NotificationView(View):
         lang = uaql['lang']
         n_time = request_dict.get('n_time')
         appBundleId = uaql['appBundleId']
-        apns_config = {
-            'com.ansjer.loocamccloud': {
-                'pem_path': os.path.join(BASE_DIR, 'Ansjer/file/apns_pem/apns-dev-test.pem'),
-                'password': '111111'
-            }
-        }
-        n_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(n_time)))
-        if lang == 'cn':
-            if nickname:
-                message_title = "周视({nickname})".format(nickname=nickname)
-            else:
-                message_title = "周视({uid})".format(uid=uid)
-            send_text = '通道:{channel} 日期:{date}'.format(channel=channel, date=n_date)
-        else:
-            if nickname:
-                message_title = "zosi({nickname})".format(nickname=nickname)
-            else:
-                message_title = "zosi({uid})".format(uid=uid)
-            send_text = 'channel:{channel} date:{date}'.format(channel=channel, date=n_date)
+        tz = uaql['tz']
+        message_title = self.get_message_title(appBundleId=appBundleId, nickname=nickname)
+        send_text = self.get_send_text(channel=channel, n_time=n_time, lang=lang, tz=tz,event_type=event_type)
         try:
-            cli = apns2.APNSClient(mode="dev", client_cert=apns_config[appBundleId]['pem_path'],
-                                   password=apns_config[appBundleId]['password'])
+            print('---')
+
+            cli = apns2.APNSClient(mode=APNS_MODE,
+                                   client_cert=os.path.join(BASE_DIR, APNS_CONFIG[appBundleId]['pem_path']))
+            # password=APNS_CONFIG[appBundleId]['password'])
             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}
             # body = json.dumps(push_data)
@@ -309,11 +244,14 @@ class NotificationView(View):
             res = cli.push(n=n, device_token=token_val, topic=appBundleId)
             # assert res.status_code == 200, res.reason
             # assert res.apns_id
+            print('========')
+            print(res.status_code)
             if res.status_code == 200:
                 return response.json(0)
             else:
                 return response.json(404, res.reason)
         except Exception as e:
+            print(repr(e))
             return response.json(10, repr(e))
 
     def do_bulk_create_info(self, uaqs, n_time, channel, event_type, is_st, uid):
@@ -321,24 +259,128 @@ class NotificationView(View):
         qs_list = []
         nowTime = int(time.time())
         # 设备昵称
-
+        userID_ids = []
         for dv in uaqs:
-            add_data = {
-                'userID_id': dv["userID_id"],
-                'eventTime': n_time,
-                'eventType': event_type,
-                'devUid': uid,
-                'devNickName': uid,
-                'Channel': channel,
-                'alarm': 'Motion \tChannel:{channel}'.format(channel=channel),
-                'is_st': int(is_st),
-                'receiveTime': n_time,
-                'addTime': nowTime
-            }
-            qs_list.append(Equipment_Info(**add_data))
+            userID_id = dv["userID_id"]
+            if userID_id not in userID_ids:
+                add_data = {
+                    'userID_id': dv["userID_id"],
+                    'eventTime': n_time,
+                    'eventType': event_type,
+                    'devUid': uid,
+                    'devNickName': uid,
+                    'Channel': channel,
+                    'alarm': 'Motion \tChannel:{channel}'.format(channel=channel),
+                    'is_st': int(is_st),
+                    'receiveTime': n_time,
+                    'addTime': nowTime
+                }
+                qs_list.append(Equipment_Info(**add_data))
+                userID_ids.append(userID_id)
         if qs_list:
             print(1)
             Equipment_Info.objects.bulk_create(qs_list)
             return True
         else:
             return False
+
+
+# http://test.dvema.com/detect/add?uidToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJQMldOR0pSRDJFSEE1RVU5MTExQSJ9.xOCI5lerk8JOs5OcAzunrKCfCrtuPIZ3AnkMmnd-bPY&n_time=1526845794&channel=1&event_type=51&is_st=0
+# 移动侦测接口
+class PushNotificationView(View):
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        # operation = kwargs.get('operation')
+        return self.validation(request.GET)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        # operation = kwargs.get('operation')
+        return self.validation(request.POST)
+
+    def validation(self, request_dict):
+        etk = request_dict.get('etk', None)
+        channel = request_dict.get('channel', '1')
+        n_time = request_dict.get('n_time', None)
+        event_type = request_dict.get('event_type', None)
+        is_st = request_dict.get('is_st', None)
+        eto = ETkObject(etk)
+        uid = eto.uid
+        if len(uid) == 20:
+            redisObj = RedisObject(db=6)
+            # pkey = '{uid}_{channel}_ptl'.format(uid=uid, channel=channel)
+            pkey = '{uid}_ptl'.format(uid=uid)
+            # 推送时间限制
+            if redisObj.get_data(key=pkey):
+                res_data = {'code': 0, 'msg': 'success,!'}
+                return JsonResponse(status=200, data=res_data)
+            else:
+                redisObj.set_data(key=pkey, val=1, expire=60)
+            uid_set_qs = UidSetModel.objects.filter(uid=uid, detect_status=1)
+            if uid_set_qs.exists():
+                uid_set_id = uid_set_qs[0].id
+                uid_push_qs = UidPushModel.objects.filter(uid_set__id=uid_set_id). \
+                    values('token_val', 'app_type', 'appBundleId', 'push_type',
+                           'userID_id', 'userID__NickName', 'lang', 'tz')
+                if uid_set_qs.exists():
+                    auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+                    bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+                    self.do_bulk_create_info(uid_push_qs, n_time, channel, event_type, is_st, uid)
+                    if is_st == '0' or is_st == '2':
+                        return JsonResponse(status=200, data={'code': 0, 'msg': 'success'})
+                    elif is_st == '1':
+                        # Endpoint以杭州为例,其它Region请按实际情况填写。
+                        obj = '{uid}/{channel}/{filename}.jpeg'.format(uid=uid, channel=channel, filename=n_time)
+                        # 设置此签名URL在60秒内有效。
+                        url = bucket.sign_url('PUT', obj, 7200)
+                        res_data = {'code': 0, 'img_push': url, 'msg': 'success'}
+                        return JsonResponse(status=200, data=res_data)
+                    elif is_st == '3':
+                        # 人形检测带动图
+                        img_url_list = []
+                        for i in range(int(is_st)):
+                            obj = '{uid}/{channel}/{filename}_{st}.jpeg'. \
+                                format(uid=uid, channel=channel, filename=n_time, st=i)
+                            # 设置此签名URL在60秒内有效。
+                            url = bucket.sign_url('PUT', obj, 7200)
+                            img_url_list.append(url)
+                        res_data = {'code': 0, 'img_url_list': img_url_list, 'msg': 'success'}
+                        return JsonResponse(status=200, data=res_data)
+
+                else:
+                    return JsonResponse(status=200, data={'code': 404, 'msg': 'data is not exist'})
+            else:
+                return JsonResponse(status=200, data={'code': 404, 'msg': 'data is not exist'})
+        else:
+            return JsonResponse(status=200, data={'code': 404, 'msg': 'wrong etk'})
+
+    def do_bulk_create_info(self, uaqs, n_time, channel, event_type, is_st, uid):
+        #
+        qs_list = []
+        nowTime = int(time.time())
+        # 设备昵称
+        userID_ids = []
+        for dv in uaqs:
+            userID_id = dv["userID_id"]
+            if userID_id not in userID_ids:
+                add_data = {
+                    'userID_id': dv["userID_id"],
+                    'eventTime': n_time,
+                    'eventType': event_type,
+                    'devUid': uid,
+                    'devNickName': uid,
+                    'Channel': channel,
+                    'alarm': 'Motion \tChannel:{channel}'.format(channel=channel),
+                    'is_st': int(is_st),
+                    'receiveTime': n_time,
+                    'addTime': nowTime
+                }
+                qs_list.append(Equipment_Info(**add_data))
+                userID_ids.append(userID_id)
+        if qs_list:
+            print(1)
+            Equipment_Info.objects.bulk_create(qs_list)
+            return True
+        else:
+            return False

+ 133 - 108
Model/models.py

@@ -1,12 +1,13 @@
 from itertools import chain
 
-from django.contrib.auth.models import AbstractBaseUser,BaseUserManager
+from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
 from django.db import models
+from django.utils import six
+from django.utils.encoding import python_2_unicode_compatible
 from imagekit.models import ProcessedImageField
 from imagekit.processors import ResizeToFill
+
 from AnsjerPush.config import SERVER_DOMAIN
-from django.utils.encoding import python_2_unicode_compatible
-from django.utils import six
 
 
 class PermissionsManager(models.Manager):
@@ -28,6 +29,35 @@ class RoleManager(models.Manager):
         return self.get(roleName=roleName)
 
 
+class UserManager(BaseUserManager):
+
+    def create_user(self, username, password, userID, is_active,
+                    user_isValid, **extra_fields):
+        user = self.model(
+            username=username,
+            userID=userID,
+            is_active=is_active,
+            user_isValid=user_isValid,
+            **extra_fields
+        )
+        user.set_password(password)
+        user.save(using=self._db)
+
+        role = Role.objects.get(rid=1)
+        user.role.add(role)
+        return user
+
+    def create_superuser(self, username, password, userID, is_active,
+                         user_isValid, **extra_fields):
+        # extra_fields.setdefault('is_superuser', is_superuser)
+        is_superuser = extra_fields.get('is_superuser', None)
+        if is_superuser != 100 and is_superuser != 1:
+            raise ValueError('Superuser must have is_superuser=1 or 100.')
+
+        return self.create_user(username, password, userID, is_active,
+                                user_isValid, **extra_fields)
+
+
 @python_2_unicode_compatible
 class Permissions(models.Model):
     permName = models.CharField(blank=True, null=True, max_length=32, unique=True, verbose_name=u'权限名称')
@@ -89,34 +119,6 @@ class Role(models.Model):
             return permslist
 
 
-class UserManager(BaseUserManager):
-
-    def create_user(self, username, password, userID, is_active,
-                    user_isValid, **extra_fields):
-        user = self.model(
-            username=username,
-            userID=userID,
-            is_active=is_active,
-            user_isValid=user_isValid,
-            **extra_fields
-        )
-        user.set_password(password)
-        user.save(using=self._db)
-
-        role = Role.objects.get(rid=1)
-        user.role.add(role)
-        return user
-
-    def create_superuser(self, username, password, userID, is_active,
-                         user_isValid, **extra_fields):
-        # extra_fields.setdefault('is_superuser', is_superuser)
-        is_superuser = extra_fields.get('is_superuser', None)
-        if is_superuser != 100 and is_superuser != 1:
-            raise ValueError('Superuser must have is_superuser=1 or 100.')
-
-        return self.create_user(username, password, userID, is_active,
-                                user_isValid, **extra_fields)
-
 class Device_User(AbstractBaseUser):
     userID = models.CharField(blank=True, max_length=32, primary_key=True,
                               verbose_name=u'用户ID', unique=True)
@@ -198,75 +200,6 @@ class Device_User(AbstractBaseUser):
         return self.is_superuser
 
 
-# 设备表是建项目开发者设计的,自己看着办
-class Device_Info(models.Model):
-    id = models.CharField(blank=True, max_length=32, primary_key=True)
-    userID = models.ForeignKey(Device_User, blank=True, to_field='userID', on_delete=models.CASCADE)
-    NickName = models.CharField(blank=True, max_length=32, verbose_name=u'设备名称')
-    UID = models.CharField(blank=True, max_length=32, verbose_name=u'设备UID', default='')
-    SID = models.CharField(blank=True, max_length=32, verbose_name=u'服务器ID', default='')
-    View_Account = models.CharField(blank=True, max_length=32, verbose_name=u'设备用户名称', default='')
-    View_Password = models.CharField(blank=True, max_length=32, verbose_name=u'设备密码', default='')
-    AudioFormat = models.IntegerField(blank=True, default=1, verbose_name=u'初始化影像')
-    EventNotification = models.IntegerField(blank=True, verbose_name=u'报警类型', default=0)
-    ChannelIndex = models.IntegerField(blank=True, verbose_name=u'通道号', default=0)
-    Online = models.BooleanField(blank=True, default=False, verbose_name=u'设备是否在线')
-    mMonitorIndex = models.IntegerField(blank=True, default=-1)
-    Type = models.IntegerField(blank=True, verbose_name='设备类型')
-    DebugMode = models.IntegerField(blank=True, verbose_name=u'调试模式', default=0)
-    NotificationMode = models.IntegerField(blank=True, verbose_name=u'是否报警', default=0)
-    qvgaLevel = models.BooleanField(blank=True, verbose_name=u'SD与HD画面', default=0,
-                                    help_text=u'0代表:SD、1代表:HD')
-    isShare = models.BooleanField(blank=True, verbose_name=u'共享设备',
-                                  help_text=u'是否为共享获取的设备', default=False)
-    primaryUserID = models.CharField(blank=True, verbose_name='主用户id', max_length=32, default='')
-    primaryMaster = models.CharField(max_length=64, verbose_name=u'主用户名', default='')
-    data_joined = models.DateTimeField(blank=True, verbose_name=u'设备添加时间', auto_now_add=True)
-    update_time = models.DateTimeField(blank=True, verbose_name=u'更新时间', auto_now=True, null=True)
-
-    ip = models.CharField(blank=True, max_length=20, default='', verbose_name=u'设备区域ip')
-    area = models.CharField(blank=True, max_length=100, default='', verbose_name=u'设备区域area')
-    # ios要求新增字段
-    version = models.CharField(blank=True, max_length=20, default='', verbose_name=u'版本号')
-    SpaceUsable = models.CharField(blank=True, max_length=20, default='', verbose_name=u'可用空间')
-    SpaceSum = models.CharField(blank=True, max_length=20, default='', verbose_name=u'总空间')
-    WIFIName = models.CharField(blank=True, max_length=50, default='', verbose_name=u'无线名称')
-    WIFIIP = models.CharField(blank=True, max_length=20, default='', verbose_name=u'无线ip')
-    WIFIPwd = models.CharField(blank=True, max_length=50, default='', verbose_name=u'无线密码')
-    isDetector = models.BooleanField(blank=True, verbose_name=u'侦测开关0:关闭,1:开启)', default=False)
-    DetectorRank = models.IntegerField(blank=True, default=0, verbose_name=u'侦测灵敏度 1:低,2:中,3:高4:最高')
-    iSNotification = models.BooleanField(blank=True, verbose_name=u'报警通知 0:关闭,1:开启)', default=False)
-    MirrorType = models.IntegerField(blank=True, default=0, verbose_name=u'镜像类型 0:关闭镜像,1:上下镜像,2:左右镜像,3:上下左右镜像')
-    RecordType = models.IntegerField(blank=True, default=0, verbose_name=u'录像模式(0:关闭,1:全是录像,3:报警录像)')
-    TimeZone = models.CharField(blank=True, max_length=50, default='', verbose_name=u'时区')
-    isVod = models.SmallIntegerField(blank=True, default=0, verbose_name='是否支持云存')  # 是否支持云存设备
-    isExist = models.SmallIntegerField(blank=True, default=1, verbose_name='是否被删除')  # 是否被删除了(需主用户交互) 1存在,0不存在
-    ###
-    REQUIRED_FIELDS = []
-
-    def __str__(self):
-        return self.NickName
-
-    def model_to_dict(self, fields=None, exclude=None):
-        opts = self._meta
-        data = {}
-        for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many):
-            if not getattr(f, 'editable', False):
-                continue
-            if fields and f.name not in fields:
-                continue
-            if exclude and f.name in exclude:
-                continue
-            data[f.name] = f.value_from_object(self)
-        return data
-
-    class Meta:
-        db_table = 'device_info'
-        ordering = ('-data_joined',)
-        verbose_name = u'用户设备信息表'
-        verbose_name_plural = verbose_name
-
-
 class Equipment_Info(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
     devUid = models.CharField(default='', blank=True, max_length=32, verbose_name=u'设备ID')
@@ -291,31 +224,121 @@ class Equipment_Info(models.Model):
         ordering = ('-id',)
 
 
+# 存储通表
+class VodBucketModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='主键')
+    bucket = models.CharField(max_length=30, verbose_name='设备UID')
+    storeDay = models.IntegerField(default=0, verbose_name='存储生命周期(天)')
+    content = models.TextField(verbose_name='描述')
+    endpoint = models.CharField(max_length=125, default='', verbose_name='存储节点')
+    area = models.CharField(max_length=16, default='', verbose_name='区域')
+    region = models.CharField(max_length=16, default='', verbose_name='regionID')
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+    updTime = models.IntegerField(verbose_name='更新时间', default=0)
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'vod_bucket'
+        verbose_name = u'存储通信息'
+        verbose_name_plural = verbose_name
+        ordering = ('-id',)
+
+
+class VodHlsModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='回放列表主键')
+    uid = models.CharField(max_length=20, verbose_name='设备UID')
+    channel = models.SmallIntegerField(default=0, verbose_name='通道')
+    time = models.IntegerField(verbose_name='播放列表名字时间戳', default=0, db_index=True)
+    endTime = models.IntegerField(verbose_name='删除时间', default=0)
+    sec = models.IntegerField(verbose_name='秒数', default=0)
+    bucket = models.ForeignKey(VodBucketModel, blank=True, to_field='id', on_delete=models.CASCADE, default=1,
+                               verbose_name='存储空间')
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'vod_hls'
+        verbose_name = u'云存回放信息表'
+        verbose_name_plural = verbose_name
+        ordering = ('-id',)
+
+
+class OssCrdModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='主键')
+    uid = models.CharField(max_length=20, verbose_name='设备UID')
+    channel = models.SmallIntegerField(default=0, verbose_name='通道')
+    data = models.TextField(verbose_name='设备sts')
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+    bucket = models.ForeignKey(VodBucketModel, blank=True, to_field='id', on_delete=models.CASCADE, default=1,
+                               verbose_name='存储空间')
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'osscrd'
+        verbose_name = u'设备证书'
+        verbose_name_plural = verbose_name
+        ordering = ('-id',)
+
+
+class UID_Bucket(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    uid = models.CharField(max_length=20, verbose_name='设备UID')
+    channel = models.SmallIntegerField(default=0, verbose_name='通道')
+    bucket = models.ForeignKey(VodBucketModel, blank=True, to_field='id', on_delete=models.CASCADE, verbose_name='存储空间')
+    status = models.SmallIntegerField(default=0, verbose_name='状态[0:开启,1:关闭]')
+    endTime = models.IntegerField(verbose_name='结束时间', default=0)
+
+    class Meta:
+        db_table = 'vod_uid_bucket'
+        verbose_name = u'设备关联套餐表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class UID_Preview(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    uid = models.CharField(default='', max_length=20, db_index=True, verbose_name='设备UID')
+    channel = models.SmallIntegerField(verbose_name=u'通道号', default=0)
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+    updTime = models.IntegerField(verbose_name='更新时间', default=0)
+
+    class Meta:
+        db_table = 'uid_preview'
+        verbose_name = '设备预览图'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
 # 设备推送重构
 # 设备配置表,新
 class UidSetModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
-    uid = models.CharField(max_length=20, verbose_name='设备UID')
+    uid = models.CharField(max_length=20, db_index=True, unique=True, verbose_name='设备UID')
     channel = models.SmallIntegerField(default=0, verbose_name='通道数量')  #
     detect_status = models.SmallIntegerField(default=0, verbose_name='推送开关')  # 状态[0:关闭,1:开启,2:用户解绑]
-    detect_interval = models.IntegerField(verbose_name='推送间隔', default=0)  # 秒
+    detect_interval = models.IntegerField(verbose_name='推送间隔', default=60)  # 秒
     addTime = models.IntegerField(verbose_name='添加时间', default=0)
     updTime = models.IntegerField(verbose_name='更新时间', default=0)
-    # addTime 2019年 05月 27日 星期一 16:52:55 CST
     ucode = models.CharField(max_length=32, verbose_name='设备产品码', default='')
     version = models.CharField(max_length=32, verbose_name='设备版本', default='')
     p2p_region = models.CharField(max_length=16, verbose_name='设备区域', default='ALL')  # ALL CN EU US
-    # addTime Thu Jun 27 02:32:45 UTC 2019
     cloud_vod = models.SmallIntegerField(default=2, verbose_name='云存开关')  # 0,关闭,1开启,2,不支持
-    tz = models.CharField(default='', max_length=16, verbose_name='设备时区')  # utc+8
+    tz = models.CharField(default='', max_length=16, verbose_name='设备时区')  # +8
     video_code = models.SmallIntegerField(default=0, verbose_name='编码类型')  # 0:264,1:265
-
     nickname = models.CharField(default='', max_length=64, verbose_name='设备昵称')
-    ip = models.CharField(blank=True, max_length=20, default='', verbose_name=u'设备ip')
+    ip = models.CharField(max_length=20, default='', verbose_name=u'设备ip')
+    pwd = models.CharField(max_length=32, default='', verbose_name=u'设备密码')
+    # 设备重置后第一次启动时间
+    resetTime = models.IntegerField(default=0, verbose_name='设备重置时间')
 
     class Meta:
         db_table = 'uid_set'
-        verbose_name = u'设备配置'
+        verbose_name = u'设备配置'
         verbose_name_plural = verbose_name
         ordering = ('id',)
 
@@ -333,9 +356,11 @@ class UidPushModel(models.Model):
     addTime = models.IntegerField(verbose_name='添加时间', default=0)
     updTime = models.IntegerField(verbose_name='更新时间', default=0)
     lang = models.CharField(max_length=8, verbose_name='推送语言类型', default='en')  # en英文 cn中文
+    tz = models.CharField(max_length=8, verbose_name='utc时区', default='0')
 
     class Meta:
         db_table = 'uid_push'
         verbose_name = '设备绑定'
         verbose_name_plural = verbose_name
         ordering = ('-id',)
+

+ 68 - 0
Object/ETkObject.py

@@ -0,0 +1,68 @@
+#!/usr/bin/env python3  
+# -*- coding: utf-8 -*-  
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: AnsjerFormal
+@software: PyCharm
+@DATE: 2019/6/1 17:25
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: ETkObject.py
+@Contact: chanjunkai@163.com
+"""
+
+import base64
+import urllib.parse
+from random import Random
+
+
+class ETkObject(object):
+    def __init__(self, etk):
+        self.uid = ''
+        self.parseUid(etk)
+
+    def parseUid(self, etk):
+        try:
+            c = base64.b64decode(etk)
+            c = c[2:-2]
+            c = urllib.parse.unquote(c.decode('utf-8'))
+            c = base64.b64decode(c)
+            uid = c.decode('utf-8')
+            if len(uid) == 20:
+                self.uid = uid
+                print(uid)
+        except Exception as e:
+            print(repr(e))
+
+    def encrypt(self,data):
+        s = data.encode()
+        s = base64.b64encode(s)
+        startStr = self.randomParam()
+        endStr = self.randomParam()
+        s = '{startStr}{s}{endStr}'.format(startStr=startStr,s=s.decode('utf-8'),endStr=endStr)
+        s = base64.b64encode(s.encode())
+        s=s.decode('utf-8')
+        return s
+
+    def randomParam(self):
+        characterSet = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsT' \
+                       'tUuVvWwXxYyZz0123456789'
+        length = len(characterSet) - 1
+
+        random = Random()
+        ss = ''
+        for index in range(2):
+            ss += characterSet[random.randint(0, length)]
+        return ss
+
+
+# etkObj = ETkObject(etk='')
+# PP = etkObj.encrypt('jLBDSU9547NTRSMF111A')
+# print('encode_data:')
+# print(PP)
+# print('decode_data:')
+# eobj = ETkObject(etk=PP)
+# uid = eobj.uid
+# print(uid)
+

+ 0 - 4
Object/RedisObject.py

@@ -14,7 +14,6 @@
 import redis
 
 from AnsjerPush.config import SERVER_HOST
-from AnsjerPush.config import SERVER_TYPE
 
 # SERVER_HOST = '192.168.136.45'
 
@@ -26,9 +25,6 @@ db=3  -> 统计在线人数用
 class RedisObject:
 
     def __init__(self, db=0):
-        if db == 3:
-            if SERVER_TYPE != 'Ansjer.formal_settings':
-                db = 4
         self.POOL = redis.ConnectionPool(host=SERVER_HOST, port=6379, db=db)
         self.CONN = redis.Redis(connection_pool=self.POOL)
 

+ 6 - 0
Object/UidTokenObject.py

@@ -13,6 +13,7 @@
 """
 from AnsjerPush.config import UID_TOKEN_KEY
 import jwt
+# UID_TOKEN_KEY = 'c+565*j@%^'
 
 
 class UidTokenObject:
@@ -40,3 +41,8 @@ class UidTokenObject:
         token = jwt.encode(data, UID_TOKEN_KEY, algorithm='HS256').decode('utf-8')
         self.token=token
         return token
+#
+# uto = UidTokenObject()
+# res = uto.generate(data={'uid':'VVDHCVBYDKFMJRWA111A','channel':'1'})
+# print('---')
+# print(res)

+ 202 - 0
Service/CommonService.py

@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+import datetime
+import time
+from pathlib import Path
+from random import Random
+import ipdb
+import simplejson as json
+from django.core import serializers
+from django.utils import timezone
+from pyipip import IPIPDatabase
+
+from AnsjerPush.config import BASE_DIR
+
+
+# 复用性且公用较高封装代码在这
+class CommonService:
+
+    # 添加模糊搜索
+    @staticmethod
+    def get_kwargs(data={}):
+        kwargs = {}
+        for (k, v) in data.items():
+            if v is not None and v != u'':
+                kwargs[k + '__icontains'] = v
+        return kwargs
+
+    # 定义静态方法
+    # 格式化query_set转dict
+    @staticmethod
+    def qs_to_dict(query_set):
+        sqlJSON = serializers.serialize('json', query_set)
+        sqlList = json.loads(sqlJSON)
+        sqlDict = dict(zip(["datas"], [sqlList]))
+        return sqlDict
+
+    # 获取文件大小
+    @staticmethod
+    def get_file_size(file_path='', suffix_type='', decimal_point=0):
+
+        # for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
+        # path = Path() / 'D:/TestServer/123444.mp4'
+        path = Path() / file_path
+        size = path.stat().st_size
+        mb_size = 0.0
+        if suffix_type == 'MB':
+            mb_size = size / 1024.0 / 1024.0
+        if decimal_point != 0:
+            mb_size = round(mb_size, decimal_point)
+        return mb_size
+
+    @staticmethod
+    def get_param_flag(data=[]):
+        # print(data)
+        flag = True
+        for v in data:
+            if v is None:
+                flag = False
+                break
+        return flag
+
+    @staticmethod
+    def get_ip_address(request):
+        """
+        获取ip地址
+        :param request:
+        :return:
+        """
+        try:
+            real_ip = request.META['HTTP_X_FORWARDED_FOR']
+            clientIP = real_ip.split(",")[0]
+        except:
+            try:
+                clientIP = request.META['REMOTE_ADDR']
+            except Exception as e:
+                clientIP = ''
+        return clientIP
+
+    # @获取一天每个小时的datetime.datetime
+    @staticmethod
+    def getTimeDict(times):
+        time_dict = {}
+        t = 0
+        for x in range(24):
+            if x < 10:
+                x = '0' + str(x)
+            else:
+                x = str(x)
+            a = times.strftime("%Y-%m-%d") + " " + x + ":00:00"
+            time_dict[t] = timezone.datetime.strptime(a, '%Y-%m-%d %H:%M:%S')
+            t += 1
+        return time_dict
+
+    # 根据ip获取地址
+    @staticmethod
+    def getAddr(ip):
+        base_dir = BASE_DIR
+        # ip数据库
+        db = IPIPDatabase(base_dir + '/DB/17monipdb.dat')
+        addr = db.lookup(ip)
+        ts = addr.split('\t')[0]
+        return ts
+
+    # 通过ip检索ipip指定信息 lang为CN或EN
+    @staticmethod
+    def getIpIpInfo(ip, lang, update=False):
+        ipbd_dir = BASE_DIR + "/DB/mydata4vipday2.ipdb"
+        db = ipdb.City(ipbd_dir)
+        if update:
+            from var_dump import var_dump
+            var_dump('is_update')
+            rr = db.reload(ipbd_dir)
+            var_dump(rr)
+        info = db.find_map(ip, lang)
+        return info
+
+    @staticmethod
+    def getUserID(userPhone='13800138000', getUser=True, setOTAID=False, μs=True):
+        if μs == True:
+            if getUser == True:
+                timeID = str(round(time.time() * 1000000))
+                userID = timeID + userPhone
+
+                return userID
+            else:
+                if setOTAID == False:
+                    timeID = str(round(time.time() * 1000000))
+                    ID = userPhone + timeID
+
+                    return ID
+                else:
+                    timeID = str(round(time.time() * 1000000))
+                    eID = '13800' + timeID + '138000'
+                    return eID
+        else:
+            if getUser == True:
+                timeID = str(round(time.time() * 1000))
+                userID = timeID + userPhone
+
+                return userID
+            else:
+                if setOTAID == False:
+                    timeID = str(round(time.time() * 1000))
+                    ID = userPhone + timeID
+
+                    return ID
+                else:
+                    timeID = str(round(time.time() * 1000))
+                    eID = '13800' + timeID + '138000'
+                    return eID
+
+    # 生成随机数
+    @staticmethod
+    def RandomStr(randomlength=8, number=True):
+        str = ''
+        if number == False:
+            characterSet = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsT' \
+                           'tUuVvWwXxYyZz0123456789'
+        else:
+            characterSet = '0123456789'
+
+        length = len(characterSet) - 1
+
+        random = Random()
+        for index in range(randomlength):
+            str += characterSet[random.randint(0, length)]
+        return str
+
+    # 生成订单好
+    @staticmethod
+    def createOrderID():
+        random_id = CommonService.RandomStr(6, True)
+        order_id = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + str(random_id)
+        print('orderID:')
+        print(order_id)
+        return order_id
+
+    # qs转换list datetime处理
+    @staticmethod
+    def qs_to_list(qs):
+        res = []
+        # print(qs)
+        for ps in qs:
+            if 'add_time' in ps:
+                ps['add_time'] = ps['add_time'].strftime("%Y-%m-%d %H:%M:%S")
+            if 'update_time' in ps:
+                ps['update_time'] = ps['update_time'].strftime("%Y-%m-%d %H:%M:%S")
+            if 'end_time' in ps:
+                ps['end_time'] = ps['end_time'].strftime("%Y-%m-%d %H:%M:%S")
+            if 'data_joined' in ps:
+                if ps['data_joined']:
+                    ps['data_joined'] = ps['data_joined'].strftime("%Y-%m-%d %H:%M:%S")
+                else:
+                    ps['data_joined'] = ''
+            res.append(ps)
+        return res
+
+    # 获取当前时间
+    @staticmethod
+    def get_now_time_str(n_time, tz):
+        n_time = n_time + 3600 * float(tz)
+        n_date = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(int(n_time)))
+        return n_date

+ 0 - 1
requirements.txt

@@ -1,5 +1,4 @@
 Django > 2
-
 django-cors-headers
 django-imagekit
 django-guardian