Parcourir la source

更新为测试服代码

locky il y a 4 ans
Parent
commit
08d6d497fa
60 fichiers modifiés avec 4243 ajouts et 538 suppressions
  1. 4 0
      .gitignore
  2. 123 0
      Ansjer/cn_config/config_formal.py
  3. 134 0
      Ansjer/cn_config/config_test.py
  4. 254 0
      Ansjer/cn_config/formal_settings.py
  5. 16 0
      Ansjer/cn_config/formal_wsgi.py
  6. 274 0
      Ansjer/cn_config/test_settings.py
  7. 16 0
      Ansjer/cn_config/test_wsgi.py
  8. 17 6
      Ansjer/config.py
  9. 15 2
      Ansjer/urls.py
  10. 123 0
      Ansjer/us_config/config_formal.py
  11. 67 0
      Ansjer/us_config/config_local.py
  12. 134 0
      Ansjer/us_config/config_test.py
  13. 254 0
      Ansjer/us_config/formal_settings.py
  14. 16 0
      Ansjer/us_config/formal_wsgi.py
  15. 457 0
      Ansjer/us_config/local_settings.py
  16. 16 0
      Ansjer/us_config/local_wsgi.py
  17. 274 0
      Ansjer/us_config/test_settings.py
  18. 16 0
      Ansjer/us_config/test_wsgi.py
  19. 3 3
      Controller/Alexa.py
  20. 4 1
      Controller/CloudStorage.py
  21. 44 69
      Controller/CompanyController.py
  22. 44 1
      Controller/DeviceConfirmRegion.py
  23. 75 0
      Controller/DeviceDebug.py
  24. 15 36
      Controller/EquipmentManager.py
  25. 3 1
      Controller/EquipmentManagerV2.py
  26. 13 12
      Controller/EquipmentManagerV3.py
  27. 5 1
      Controller/EquipmentStatus.py
  28. 0 1
      Controller/FAQController.py
  29. 22 15
      Controller/IotCoreController.py
  30. 1 1
      Controller/LogManager.py
  31. 5 3
      Controller/OrderContrller.py
  32. 611 0
      Controller/PcInfo.py
  33. 360 0
      Controller/PctestController.py
  34. 201 202
      Controller/SerialNumberController.py
  35. 3 1
      Controller/ShadowController.py
  36. 62 47
      Controller/TestApi.py
  37. 16 0
      Controller/UIDController.py
  38. 2 0
      Controller/UidSetController.py
  39. 3 1
      Controller/UidUser.py
  40. 42 28
      Controller/UserController.py
  41. 40 15
      Controller/VPGController.py
  42. 22 15
      Controller/VoicePromptController.py
  43. 27 0
      CrontabTask/formal_statistics_push_day_task.py
  44. 27 0
      CrontabTask/formal_statistics_push_month_task.py
  45. 49 0
      CrontabTask/formal_zositech_help_weekly_task.py
  46. 31 0
      CrontabTask/test_statistics_push_day_task.py
  47. 31 0
      CrontabTask/test_statistics_push_month_task.py
  48. 52 0
      CrontabTask/test_zositech_help_weekly_task.py
  49. 128 5
      Model/models.py
  50. 15 20
      Object/AWS/S3Email.py
  51. 4 2
      Object/ResponseObject.py
  52. 3 3
      Service/CloudLogs.py
  53. 1 1
      Service/MiscellService.py
  54. 0 40
      Service/ModelService.py
  55. 8 5
      Service/middleware.py
  56. 15 0
      cn_formal_manage.py
  57. 15 0
      cn_test_manage.py
  58. 1 1
      local_manage.py
  59. 15 0
      us_formal_manage.py
  60. 15 0
      us_test_manage.py

+ 4 - 0
.gitignore

@@ -15,4 +15,8 @@
 /sdk_install
 /DB/mydata4vipday2.ipdb
 /venv
+/local_manage.py
+/Controller/TestApi.py
 
+/PushModel/
+/SerialModel/

+ 123 - 0
Ansjer/cn_config/config_formal.py

@@ -0,0 +1,123 @@
+#!/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/10/16 9:45
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: config_formal.py
+@Contact: chanjunkai@163.com
+"""
+import os
+
+NGINX_RTMP_STAT = 'http://www.dvema.com/stat'
+SERVER_DOMAIN_SSL = 'https://www.dvema.com/'
+SERVER_DOMAIN = 'http://www.dvema.com/'
+DOMAIN_HOST = 'www.dvema.com'
+SERVER_HOST = 'localhost'
+# PAYPAL_CRD = {
+#     "mode": "live",  # sandbox or live
+#     "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
+#     "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
+# }
+PAYPAL_CRD = {
+    "mode": "sandbox",  # sandbox or live
+    "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
+    "client_secret": "EO8kRc8yioDk0i2Qq-QMcVFfwkmyMJorTvBSLDTnxDJJ_wb9VoM_0jkUY9iEng2Flp1ze8wQOGpH5nB2"
+}
+
+DETECT_PUSH_DOMAIN = 'http://push.dvema.com/'
+DETECT_PUSH_DOMAINS = 'https://push.dvema.com/'
+DETECT_PUSH_DOMAIN_JIUAN = 'http://jiuan.push.dvema.com/'
+DETECT_PUSH_DOMAINS_JIUAN = 'https://jiuan.push.dvema.com/'
+# 数据库dyanamo品牌日志数据库
+USER_BRAND = 'user_brand'
+USER_BRAND_ALL = 'user_brand_all'
+
+# type =2
+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',
+    'com.ansjer.zccloud_ab': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
+}
+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',
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
+    'com.ansjer.customizedc': {
+        'pem_path': 'Ansjer/file/apns_pem/customizedc.pem',
+    }
+}
+APNS_MODE = 'prod'
+# 根路径
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+SERVER_TYPE = os.environ.get('DJANGO_SETTINGS_MODULE')
+
+TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 134 - 0
Ansjer/cn_config/config_test.py

@@ -0,0 +1,134 @@
+#!/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/10/16 9:45
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: config_test.py
+@Contact: chanjunkai@163.com
+"""
+import os
+
+NGINX_RTMP_STAT = 'http://test.zositechc.cn/stat/'
+SERVER_DOMAIN = 'http://test.zositechc.cn/'
+SERVER_DOMAIN_SSL = 'https://test.zositechc.cn/'
+
+
+# token的secret
+OAUTH_ACCESS_TOKEN_SECRET = 'test_a+jbgnw%@1%zy^=@dn62%'
+OAUTH_REFRESH_TOKEN_SECRET = 'test_r+jbgnw%@1%zy^=@dn62%'
+
+DOMAIN_HOST = 'test.zositechc.cn'
+SERVER_HOST = 'localhost'
+PAYPAL_CRD = {
+    # "mode": "live",  # sandbox or live
+    # "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
+    # "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
+    # "mode": "sandbox",  # sandbox or live
+    # "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",
+    # "client_secret": "EGkMCB3RWTcUGJGDYahJ9mCO0AQzEn2AvFfx1GAFjfyyn7-8a0NObcZks89QorlFpvNWTsDXVa2INRNM"
+    "mode": "sandbox",  # sandbox or live
+    "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
+    "client_secret": "EO8kRc8yioDk0i2Qq-QMcVFfwkmyMJorTvBSLDTnxDJJ_wb9VoM_0jkUY9iEng2Flp1ze8wQOGpH5nB2"
+}
+# PAYPAL_CRD = {
+#     "mode": "sandbox",  # sandbox or live
+#     "client_id": "ATXTpWs8sajNYeU46jNs1yzpy4H_o3RRrGVIJ8Tscc312BjMx12cpRgCucfWX07a4G6GbK8hzElB04Pd",
+#     "client_secret": "EHcnfrpL1o1ev9WnlQ-C1uymeRKDoJ6li6Y0d6iHoRGj4u8Sx5lSEEH774XphP4LQZ0DrDUdvxbux0T2"
+# }
+DETECT_PUSH_DOMAIN = 'http://test.push.dvema.com/'
+DETECT_PUSH_DOMAINS = 'https://test.push.dvema.com/'
+DETECT_PUSH_DOMAIN_JIUAN = 'http://jiuan.push.dvema.com/'
+DETECT_PUSH_DOMAINS_JIUAN = 'https://jiuan.push.dvema.com/'
+# 数据库dyanamo品牌日志数据库
+USER_BRAND = 'test_user_brand'
+USER_BRAND_ALL = 'test_user_brand_all'
+
+# type =2
+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',
+    'com.ansjer.zccloud_ab': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
+}
+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',
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
+    'com.ansjer.customizedc': {
+        'pem_path': 'Ansjer/file/apns_pem/customizedc.pem',
+    }
+}
+# 根路径
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+APNS_MODE = 'dev'
+SERVER_TYPE = os.environ.get('DJANGO_SETTINGS_MODULE')
+
+TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 254 - 0
Ansjer/cn_config/formal_settings.py

@@ -0,0 +1,254 @@
+import os
+from Ansjer.config import BASE_DIR
+
+SECRET_KEY = 'c7ki2_gkg4#sjfm-u1%$s#&n#szf01f*v69rwv2qsf#-zmm@tl'
+# DEBUG = True
+DEBUG = False
+ALLOWED_HOSTS = ['*']
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'Service.middleware.StatisticsUrlMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'corsheaders.middleware.CorsPostCsrfMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django_global_request.middleware.GlobalRequestMiddleware',
+]
+
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.ModelBackend',  # django default backend
+    'guardian.backends.ObjectPermissionBackend',
+)
+
+ADDR_URL = []
+ANONYMOUS_USER_ID = -1  # 支持匿名用户.
+
+STATIC_URL = '/static/'
+
+# 上传路径根目录
+MEDIA_ROOT = os.path.join(BASE_DIR, 'static/Upgrate')
+# 在浏览器上访问该上传文件的url的前缀
+MEDIA_URL = '/static/Upgrate/'
+ROOT_URLCONF = 'Ansjer.urls'
+LOGIN_URL = '/account/login'
+AUTH_USER_MODEL = 'Model.Device_User'  # 自定义Model
+APPEND_SLASH = False
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # 'DIRS': [BASE_DIR + '/static/templates', ],
+        'DIRS': [BASE_DIR + '/templates', ],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'Ansjer.cn_config.formal_wsgi.application'
+
+
+# 服务器类型
+DATABASE_DATA = 'Ansjer81'
+SERVER_HOST = 'business-server.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
+DATABASES_USER = 'azrds'
+DATABASES_PASS = 'UKv78ezQhiGMmSef5U5s'
+
+DATABASE_DATA2 = 'Ansjer81'
+SERVER_HOST2 = 'ansjerpush.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+DATABASES_USER2 = 'azrds'
+DATABASES_PASS2 = 'azrds.x.x'
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA,
+        'USER': DATABASES_USER,
+        'PASSWORD': DATABASES_PASS,
+        'HOST': SERVER_HOST,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    'mysql02': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA2,
+        'USER': DATABASES_USER2,
+        'PASSWORD': DATABASES_PASS2,
+        'HOST': SERVER_HOST2,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    }
+}
+DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
+DATABASE_APPS_MAPPING = {
+    'Model': 'default',
+    'db2': 'mysql02',
+}
+
+
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+LANGUAGE_CODE = 'en-us'
+TIME_ZONE = 'Asia/Shanghai'
+# TIME_ZONE = 'UTC'
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+# CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)
+
+#########################################
+'''
+增加错误信息推送到管理员邮箱
+'''
+# 管理员邮箱
+ADMINS = (
+    ('admin', 'sonalh@foxmail.com'),
+)
+
+# 非空链接,却发生404错误,发送通知MANAGERS
+SEND_BROKEN_LINK_EMAILS = True
+MANAGERS = ADMINS
+
+# Email设置
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'smtp.163.com'  # QQ邮箱SMTP服务器(邮箱需要开通SMTP服务)
+EMAIL_PORT = 25  # QQ邮箱SMTP服务端口
+EMAIL_HOST_USER = 'chanjunkai@163.com'  # 我的邮箱帐号
+EMAIL_HOST_PASSWORD = 'cjk1234'  # 授权码
+EMAIL_SUBJECT_PREFIX = 'website'  # 为邮件标题的前缀,默认是'[django]'
+EMAIL_USE_TLS = True  # 开启安全链接
+DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER  # 设置发件人
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'formatters': {
+        'error_format': {
+            # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
+            'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
+        },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+
+    },
+    'filters': {
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'class': 'django.utils.log.AdminEmailHandler',
+            'include_html': True,
+        },
+        'default': {
+            'level': 'ERROR',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/error/error.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'error_format',
+        },
+        'console': {
+            'level': 'ERROR',
+            'class': 'logging.StreamHandler',
+            'formatter': 'error_format'
+        },
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['default', 'console'],
+            # 'handlers': ['mail_admins','default','console'],
+            # 'level': 'ERROR',
+            'level': 'ERROR',
+            'propagate': False
+        },
+        # log 调用时需要当作参数传入
+        'info': {
+            'handlers': ['info'],
+            'level':'INFO',
+            'propagate': False
+        }
+        # 'django.db.backends': {
+        #     'handlers': ['console'],
+        #     'propagate': True,
+        #     'level': 'DEBUG',
+        # },
+    }
+}

+ 16 - 0
Ansjer/cn_config/formal_wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for Ansjer project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.cn_config.formal_settings")
+
+application = get_wsgi_application()

+ 274 - 0
Ansjer/cn_config/test_settings.py

@@ -0,0 +1,274 @@
+import os
+from Ansjer.config import BASE_DIR
+
+
+SECRET_KEY = 'c7ki2_gkg4#sjfm-u1%$s#&n#szf01f*v69rwv2qsf#-zmm@tl'
+DEBUG = True
+# DEBUG = False
+ALLOWED_HOSTS = ['*']
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model',
+    'PushModel',
+    'SerialModel',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'Service.middleware.StatisticsUrlMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'corsheaders.middleware.CorsPostCsrfMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django_global_request.middleware.GlobalRequestMiddleware',
+]
+
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.ModelBackend',  # django default backend
+    'guardian.backends.ObjectPermissionBackend',
+)
+
+ADDR_URL = []
+ANONYMOUS_USER_ID = -1  # 支持匿名用户
+
+STATIC_URL = '/static/'
+
+# 上传路径根目录
+MEDIA_ROOT = os.path.join(BASE_DIR, 'static/Upgrate')
+# 在浏览器上访问该上传文件的url的前缀
+MEDIA_URL = '/static/Upgrate/'
+ROOT_URLCONF = 'Ansjer.urls'
+LOGIN_URL = '/account/login'
+AUTH_USER_MODEL = 'Model.Device_User'  # 自定义Model
+APPEND_SLASH = False
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # 'DIRS': [BASE_DIR + '/static/templates', ],
+        'DIRS': [BASE_DIR + '/templates', ],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'Ansjer.cn_config.test_wsgi.application'
+
+
+# 服务器类型
+#国内宁夏测试业务数据库
+DATABASE_DATA = 'AnsjerTest'
+SERVER_HOST = 'business-server.cvp7gfpnmziz.rds.cn-northwest-1.amazonaws.com.cn'
+DATABASES_USER = 'azrds'
+DATABASES_PASS = 'UKv78ezQhiGMmSef5U5s'
+
+#推送数据库
+DATABASE_DATA2 = 'AnsjerTest'
+SERVER_HOST2 = 'ansjerpush.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+DATABASES_USER2 = 'azrds'
+DATABASES_PASS2 = 'azrds.x.x'
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA,
+        'USER': DATABASES_USER,
+        'PASSWORD': DATABASES_PASS,
+        'HOST': SERVER_HOST,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    'mysql02': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA2,
+        'USER': DATABASES_USER2,
+        'PASSWORD': DATABASES_PASS2,
+        'HOST': SERVER_HOST2,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+}
+
+DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
+DATABASE_APPS_MAPPING = {
+    'Model': 'default',
+    'db2': 'mysql02',
+}
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+LANGUAGE_CODE = 'en-us'
+# TIME_ZONE = 'Asia/Shanghai'
+TIME_ZONE = 'UTC'
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+# CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)
+
+#########################################
+'''
+增加错误信息推送到管理员邮箱
+'''
+# 管理员邮箱
+ADMINS = (
+    ('admin', 'sonalh@foxmail.com'),
+)
+
+# 非空链接,却发生404错误,发送通知MANAGERS
+SEND_BROKEN_LINK_EMAILS = True
+MANAGERS = ADMINS
+
+# Email设置
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'smtp.163.com'  # QQ邮箱SMTP服务器(邮箱需要开通SMTP服务)
+EMAIL_PORT = 25  # QQ邮箱SMTP服务端口
+EMAIL_HOST_USER = 'chanjunkai@163.com'  # 我的邮箱帐号
+EMAIL_HOST_PASSWORD = 'cjk1234'  # 授权码
+EMAIL_SUBJECT_PREFIX = 'website'  # 为邮件标题的前缀,默认是'[django]'
+EMAIL_USE_TLS = True  # 开启安全链接
+DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER  # 设置发件人
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'formatters': {
+        'error_format': {
+            # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
+            'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
+        },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+
+    },
+    'filters': {
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'class': 'django.utils.log.AdminEmailHandler',
+            'include_html': True,
+        },
+        'default': {
+            'level': 'ERROR',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/error/error.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'error_format',
+        },
+        'console': {
+            'level': 'ERROR',
+            'class': 'logging.StreamHandler',
+            'formatter': 'error_format'
+        },
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+        'device_info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/device_info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['default', 'console'],
+            # 'handlers': ['mail_admins','default','console'],
+            # 'level': 'ERROR',
+            'level': 'ERROR',
+            'propagate': False
+        },
+        # log 调用时需要当作参数传入
+        'info': {
+            'handlers': ['info'],
+            'level':'INFO',
+            'propagate': False
+        },
+
+        'device_info':{
+            'handlers': ['device_info'],
+            'level':'INFO',
+            'propagate': False
+        }
+        # 'django.db.backends': {
+        #     'handlers': ['console'],
+        #     'propagate': True,
+        #     'level': 'DEBUG',
+        # },
+    }
+}

+ 16 - 0
Ansjer/cn_config/test_wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for Ansjer project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.cn_config.test_settings")
+
+application = get_wsgi_application()

+ 17 - 6
Ansjer/config.py

@@ -57,6 +57,7 @@ AuthCode_Expire = 600
 RTMP_PUSH_URL = 'http://13.56.215.252:8091/hls'
 # 根路径
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ADDR_URL = []
 # uid token key
 UID_TOKEN_KEY = 'c+565*j@%^'
 
@@ -74,13 +75,23 @@ AWS_ACCESS_KEY_ID = ['AKIA2MMWBR4DSFG67DTG','AKIA2E67UIMD45Y3HL53']  #0国内,
 AWS_SECRET_ACCESS_KEY = ['aI9gxcAKPmiGgPy9axrtFKzjYGbvpuytEX4xWweL','ckYLg4Lo9ZXJIcJEAKkzf2rWvs8Xth1FCjqiAqUw']
 AWS_ARN = ['arn:aws-cn:s3','arn:aws:s3']
 
+#尚云服务器CRCKey
+CRCKey = {'AUS':'CRCKey', 'ACN':'CRCKey'}   #{平台名:CRCKey值}
+
 # 不同环境配置
-if SERVER_TYPE == 'Ansjer.local_settings':
-    from Ansjer.config_local import *
-elif SERVER_TYPE == 'Ansjer.test_settings':
-    from Ansjer.config_test import *
-elif SERVER_TYPE == 'Ansjer.formal_settings':
-    from Ansjer.config_formal import *
+#美国
+if SERVER_TYPE == 'Ansjer.us_config.local_settings':
+    from Ansjer.us_config.config_local import *
+elif SERVER_TYPE == 'Ansjer.us_config.test_settings':
+    from Ansjer.us_config.config_test import *
+elif SERVER_TYPE == 'Ansjer.us_config.formal_settings':
+    from Ansjer.us_config.config_formal import *
+
+#国内
+elif SERVER_TYPE == 'Ansjer.cn_config.formal_settings':
+    from Ansjer.cn_config.config_formal import *
+elif SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+    from Ansjer.cn_config.config_test import *
 
 
 DEVICE_TYPE = {

+ 15 - 2
Ansjer/urls.py

@@ -18,7 +18,7 @@ from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppIn
     VerifyCodeController, FileController, UIDController, LogController, SalesController, \
     OrderTaskController, HistoryUIDController, UIDManageUserController, SerialNumberController, CompanyController, \
     RegionController, VPGController, LanguageController, TestController, DeviceConfirmRegion, S3GetStsController, \
-    DetectControllerV2, ShadowController, TestDetectController
+    DetectControllerV2, ShadowController, TestDetectController, PcInfo, PctestController, DeviceDebug
 
 urlpatterns = [
     url(r'^testApi/(?P<operation>.*)$', TestApi.testView.as_view()),
@@ -281,6 +281,8 @@ urlpatterns = [
 
     #云存服务统计
     url(r'^Cloudsum/(?P<operation>.*)$', Cloudsum.Cloudsum.as_view()),
+    # 设备ip地区统计
+    url(r'^device/StatisticsIpRegion$', DeviceConfirmRegion.StatisticsIpRegion.as_view()),
 
     #Iot Core
     url(r'iot/(?P<operation>.*)$', IotCoreController.IotCoreView.as_view()),
@@ -293,7 +295,7 @@ urlpatterns = [
     re_path('user/(?P<operation>.*)', UIDManageUserController.UserView.as_view()),
     re_path('uid/(?P<operation>.*)', UIDController.UIDView.as_view()),
     re_path('history/(?P<operation>.*)', HistoryUIDController.HistoryUIDView.as_view()),
-    re_path('log/(?P<operation>.*)', LogController.LogView.as_view()),
+    re_path('^log/(?P<operation>.*)', LogController.LogView.as_view()),
     re_path('orderTask/(?P<operation>.*)', OrderTaskController.OrderTaskView.as_view()),
     path('upload', FileController.UploadUIDFileView.as_view()),
     path('download', FileController.DownloadUIDFileView.as_view()),
@@ -321,6 +323,17 @@ urlpatterns = [
     #设备确定分配地区
     url(r'^device/confirmRegion$', DeviceConfirmRegion.ConfirmRegion.as_view()),
 
+    # pc端软件信息
+    url(r'^pcInfo/(?P<operation>.*)$', PcInfo.PcInfo.as_view()),
+
+    # pc端测试软件
+    url(r'^pcTest/(?P<operation>.*)$', PctestController.PcTest.as_view()),
+
+    # 设备debug
+    # url(r'^deviceDebug/(?P<operation>.*)$', DeviceDebug.DeviceDebug.as_view()),
+    re_path('deviceDebug/(?P<operation>.*)', DeviceDebug.DeviceDebug.as_view()),
+
+
     re_path('(?P<path>.*)', LogManager.errorPath),
 
 

+ 123 - 0
Ansjer/us_config/config_formal.py

@@ -0,0 +1,123 @@
+#!/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/10/16 9:45
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: config_formal.py
+@Contact: chanjunkai@163.com
+"""
+import os
+
+NGINX_RTMP_STAT = 'http://www.dvema.com/stat'
+SERVER_DOMAIN_SSL = 'https://www.dvema.com/'
+SERVER_DOMAIN = 'http://www.dvema.com/'
+DOMAIN_HOST = 'www.dvema.com'
+SERVER_HOST = 'localhost'
+# PAYPAL_CRD = {
+#     "mode": "live",  # sandbox or live
+#     "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
+#     "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
+# }
+PAYPAL_CRD = {
+    "mode": "sandbox",  # sandbox or live
+    "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
+    "client_secret": "EO8kRc8yioDk0i2Qq-QMcVFfwkmyMJorTvBSLDTnxDJJ_wb9VoM_0jkUY9iEng2Flp1ze8wQOGpH5nB2"
+}
+
+DETECT_PUSH_DOMAIN = 'http://push.dvema.com/'
+DETECT_PUSH_DOMAINS = 'https://push.dvema.com/'
+DETECT_PUSH_DOMAIN_JIUAN = 'http://jiuan.push.dvema.com/'
+DETECT_PUSH_DOMAINS_JIUAN = 'https://jiuan.push.dvema.com/'
+# 数据库dyanamo品牌日志数据库
+USER_BRAND = 'user_brand'
+USER_BRAND_ALL = 'user_brand_all'
+
+# type =2
+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',
+    'com.ansjer.zccloud_ab': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
+}
+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',
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
+    'com.ansjer.customizedc': {
+        'pem_path': 'Ansjer/file/apns_pem/customizedc.pem',
+    }
+}
+APNS_MODE = 'prod'
+# 根路径
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+SERVER_TYPE = os.environ.get('DJANGO_SETTINGS_MODULE')
+
+TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 67 - 0
Ansjer/us_config/config_local.py

@@ -0,0 +1,67 @@
+#!/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/10/16 9:45
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: config_local.py
+@Contact: chanjunkai@163.com
+"""
+import os
+
+# token的secret
+OAUTH_ACCESS_TOKEN_SECRET = 'local_a+jbgnw%@1%zy^=@dn62%'
+OAUTH_REFRESH_TOKEN_SECRET = 'local_r+jbgnw%@1%zy^=@dn62%'
+
+NGINX_RTMP_STAT = 'http://127.0.0.1:8077/stat'
+SERVER_DOMAIN = 'http://127.0.0.1:8077/'
+SERVER_DOMAIN_SSL = 'http://127.0.0.1:8077/'
+SERVER_HOST = '127.0.0.1'
+DOMAIN_HOST = '127.0.0.1'
+# SERVER_HOST = '127.0.0.1'
+# DOMAIN_HOST = '127.0.0.1'
+RTMP_PUSH_URL = 'rtmp://127.0.0.1:1935/hls'
+PAYPAL_CRD = {
+    "mode": "sandbox",  # sandbox or live
+    "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",
+    "client_secret": "EGkMCB3RWTcUGJGDYahJ9mCO0AQzEn2AvFfx1GAFjfyyn7-8a0NObcZks89QorlFpvNWTsDXVa2INRNM"
+}
+DETECT_PUSH_DOMAIN = 'http://test.push.dvema.com/'
+DETECT_PUSH_DOMAINS = 'https://test.push.dvema.com/'
+DETECT_PUSH_DOMAIN_JIUAN = 'http://jiuan.push.dvema.com/'
+DETECT_PUSH_DOMAINS_JIUAN = 'https://jiuan.push.dvema.com/'
+# 数据库dyanamo品牌日志数据库
+USER_BRAND = 'test_user_brand'
+USER_BRAND_ALL = 'test_user_brand_all'
+
+
+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',
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
+}
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+APNS_MODE = 'dev'
+TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 134 - 0
Ansjer/us_config/config_test.py

@@ -0,0 +1,134 @@
+#!/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/10/16 9:45
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: config_test.py
+@Contact: chanjunkai@163.com
+"""
+import os
+
+NGINX_RTMP_STAT = 'http://test.dvema.com/stat'
+SERVER_DOMAIN = 'http://test.dvema.com/'
+SERVER_DOMAIN_SSL = 'https://test.dvema.com/'
+
+
+# token的secret
+OAUTH_ACCESS_TOKEN_SECRET = 'test_a+jbgnw%@1%zy^=@dn62%'
+OAUTH_REFRESH_TOKEN_SECRET = 'test_r+jbgnw%@1%zy^=@dn62%'
+
+DOMAIN_HOST = 'test.dvema.com'
+SERVER_HOST = 'localhost'
+PAYPAL_CRD = {
+    # "mode": "live",  # sandbox or live
+    # "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
+    # "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
+    # "mode": "sandbox",  # sandbox or live
+    # "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",
+    # "client_secret": "EGkMCB3RWTcUGJGDYahJ9mCO0AQzEn2AvFfx1GAFjfyyn7-8a0NObcZks89QorlFpvNWTsDXVa2INRNM"
+    "mode": "sandbox",  # sandbox or live
+    "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
+    "client_secret": "EO8kRc8yioDk0i2Qq-QMcVFfwkmyMJorTvBSLDTnxDJJ_wb9VoM_0jkUY9iEng2Flp1ze8wQOGpH5nB2"
+}
+# PAYPAL_CRD = {
+#     "mode": "sandbox",  # sandbox or live
+#     "client_id": "ATXTpWs8sajNYeU46jNs1yzpy4H_o3RRrGVIJ8Tscc312BjMx12cpRgCucfWX07a4G6GbK8hzElB04Pd",
+#     "client_secret": "EHcnfrpL1o1ev9WnlQ-C1uymeRKDoJ6li6Y0d6iHoRGj4u8Sx5lSEEH774XphP4LQZ0DrDUdvxbux0T2"
+# }
+DETECT_PUSH_DOMAIN = 'http://test.push.dvema.com/'
+DETECT_PUSH_DOMAINS = 'https://test.push.dvema.com/'
+DETECT_PUSH_DOMAIN_JIUAN = 'http://jiuan.push.dvema.com/'
+DETECT_PUSH_DOMAINS_JIUAN = 'https://jiuan.push.dvema.com/'
+# 数据库dyanamo品牌日志数据库
+USER_BRAND = 'test_user_brand'
+USER_BRAND_ALL = 'test_user_brand_all'
+
+# type =2
+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',
+    'com.ansjer.zccloud_ab': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
+}
+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',
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
+    'com.ansjer.customizedc': {
+        'pem_path': 'Ansjer/file/apns_pem/customizedc.pem',
+    }
+}
+# 根路径
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+APNS_MODE = 'dev'
+SERVER_TYPE = os.environ.get('DJANGO_SETTINGS_MODULE')
+
+TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 254 - 0
Ansjer/us_config/formal_settings.py

@@ -0,0 +1,254 @@
+import os
+from Ansjer.config import BASE_DIR
+
+SECRET_KEY = 'c7ki2_gkg4#sjfm-u1%$s#&n#szf01f*v69rwv2qsf#-zmm@tl'
+# DEBUG = True
+DEBUG = False
+ALLOWED_HOSTS = ['*']
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'Service.middleware.StatisticsUrlMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'corsheaders.middleware.CorsPostCsrfMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django_global_request.middleware.GlobalRequestMiddleware',
+]
+
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.ModelBackend',  # django default backend
+    'guardian.backends.ObjectPermissionBackend',
+)
+
+ADDR_URL = []
+ANONYMOUS_USER_ID = -1  # 支持匿名用户.
+
+STATIC_URL = '/static/'
+
+# 上传路径根目录
+MEDIA_ROOT = os.path.join(BASE_DIR, 'static/Upgrate')
+# 在浏览器上访问该上传文件的url的前缀
+MEDIA_URL = '/static/Upgrate/'
+ROOT_URLCONF = 'Ansjer.urls'
+LOGIN_URL = '/account/login'
+AUTH_USER_MODEL = 'Model.Device_User'  # 自定义Model
+APPEND_SLASH = False
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # 'DIRS': [BASE_DIR + '/static/templates', ],
+        'DIRS': [BASE_DIR + '/templates', ],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'Ansjer.us_config.formal_wsgi.application'
+
+
+# 服务器类型
+DATABASE_DATA = 'Ansjer81'
+SERVER_HOST = 'database-2.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+DATABASES_USER = 'azrds'
+DATABASES_PASS = 'azrds.x.x'
+
+DATABASE_DATA2 = 'Ansjer81'
+SERVER_HOST2 = 'ansjerpush.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+DATABASES_USER2 = 'azrds'
+DATABASES_PASS2 = 'azrds.x.x'
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA,
+        'USER': DATABASES_USER,
+        'PASSWORD': DATABASES_PASS,
+        'HOST': SERVER_HOST,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    'mysql02': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA2,
+        'USER': DATABASES_USER2,
+        'PASSWORD': DATABASES_PASS2,
+        'HOST': SERVER_HOST2,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    }
+}
+DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
+DATABASE_APPS_MAPPING = {
+    'Model': 'default',
+    'db2': 'mysql02',
+}
+
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+LANGUAGE_CODE = 'en-us'
+TIME_ZONE = 'Asia/Shanghai'
+# TIME_ZONE = 'UTC'
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+# CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)
+
+#########################################
+'''
+增加错误信息推送到管理员邮箱
+'''
+# 管理员邮箱
+ADMINS = (
+    ('admin', 'sonalh@foxmail.com'),
+)
+
+# 非空链接,却发生404错误,发送通知MANAGERS
+SEND_BROKEN_LINK_EMAILS = True
+MANAGERS = ADMINS
+
+# Email设置
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'smtp.163.com'  # QQ邮箱SMTP服务器(邮箱需要开通SMTP服务)
+EMAIL_PORT = 25  # QQ邮箱SMTP服务端口
+EMAIL_HOST_USER = 'chanjunkai@163.com'  # 我的邮箱帐号
+EMAIL_HOST_PASSWORD = 'cjk1234'  # 授权码
+EMAIL_SUBJECT_PREFIX = 'website'  # 为邮件标题的前缀,默认是'[django]'
+EMAIL_USE_TLS = True  # 开启安全链接
+DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER  # 设置发件人
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'formatters': {
+        'error_format': {
+            # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
+            'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
+        },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+
+    },
+    'filters': {
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'class': 'django.utils.log.AdminEmailHandler',
+            'include_html': True,
+        },
+        'default': {
+            'level': 'ERROR',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/error/error.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'error_format',
+        },
+        'console': {
+            'level': 'ERROR',
+            'class': 'logging.StreamHandler',
+            'formatter': 'error_format'
+        },
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['default', 'console'],
+            # 'handlers': ['mail_admins','default','console'],
+            # 'level': 'ERROR',
+            'level': 'ERROR',
+            'propagate': False
+        },
+        # log 调用时需要当作参数传入
+        'info': {
+            'handlers': ['info'],
+            'level':'INFO',
+            'propagate': False
+        }
+        # 'django.db.backends': {
+        #     'handlers': ['console'],
+        #     'propagate': True,
+        #     'level': 'DEBUG',
+        # },
+    }
+}

+ 16 - 0
Ansjer/us_config/formal_wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for Ansjer project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.us_config.formal_settings")
+
+application = get_wsgi_application()

+ 457 - 0
Ansjer/us_config/local_settings.py

@@ -0,0 +1,457 @@
+import os
+from Ansjer.config import BASE_DIR
+
+
+SECRET_KEY = 'c7ki2_gkg4#sjfm-u1%$s#&n#szf01f*v69rwv2qsf#-zmm@tl'
+DEBUG = True
+# DEBUG = False
+ALLOWED_HOSTS = ['*']
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'Service.middleware.StatisticsUrlMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'corsheaders.middleware.CorsPostCsrfMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    # 'django_global_request.middleware.GlobalRequestMiddleware',
+]
+
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.ModelBackend',  # django default backend
+    'guardian.backends.ObjectPermissionBackend',
+)
+
+ADDR_URL = []
+ANONYMOUS_USER_ID = -1  # 支持匿名用户
+
+STATIC_URL = '/static/'
+STATICFILES_DIRS = (os.path.join(BASE_DIR,'static'),)
+
+# 上传路径根目录
+MEDIA_ROOT = os.path.join(BASE_DIR, 'static/Upgrate')
+# 在浏览器上访问该上传文件的url的前缀
+MEDIA_URL = '/static/Upgrate/'
+ROOT_URLCONF = 'Ansjer.urls'
+LOGIN_URL = '/account/login'
+AUTH_USER_MODEL = 'Model.Device_User'  # 自定义Model
+APPEND_SLASH = False
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # 'DIRS': [BASE_DIR + '/static/templates', ],
+        'DIRS': [BASE_DIR + '/templates'],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'Ansjer.us_config.local_wsgi.application'
+
+# 服务器类型
+DATABASE_DATA = 'ansjertest'
+SERVER_HOST = '127.0.0.1'
+DATABASES_USER = 'root'
+DATABASES_PASS = '123456'
+
+# DATABASE_DATA2 = 'ansjerpush'
+# SERVER_HOST2 = '127.0.0.1'
+# DATABASES_USER2 = 'root'
+# DATABASES_PASS2 = '123456'
+
+
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA,
+        'USER': DATABASES_USER,
+        'PASSWORD': DATABASES_PASS,
+        'HOST': SERVER_HOST,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    # 'mysql02': {
+    #     'ENGINE': 'django.db.backends.mysql',
+    #     'NAME': DATABASE_DATA2,
+    #     'USER': DATABASES_USER2,
+    #     'PASSWORD': DATABASES_PASS2,
+    #     'HOST': SERVER_HOST2,
+    #     'PORT': '3306',
+    #     'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+    #     'AUTOCOMMIT': True
+    # }
+}
+DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
+DATABASE_APPS_MAPPING = {
+    'Model': 'default',
+    'db2': 'mysql02',
+}
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+LANGUAGE_CODE = 'en-us'
+TIME_ZONE = 'Asia/Shanghai'
+# TIME_ZONE = 'UTC'
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+# CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)
+
+#########################################
+'''
+增加错误信息推送到管理员邮箱
+'''
+# 管理员邮箱
+ADMINS = (
+    ('admin', 'chanjunkai@163.com'),
+    ('admin', '1379072853@qq.com'),
+)
+
+# 非空链接,却发生404错误,发送通知MANAGERS
+SEND_BROKEN_LINK_EMAILS = True
+MANAGERS = ADMINS
+
+# Email设置
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'smtp.163.com'  # QQ邮箱SMTP服务器(邮箱需要开通SMTP服务)
+EMAIL_PORT = 25  # QQ邮箱SMTP服务端口
+EMAIL_HOST_USER = 'chanjunkai@163.com'  # 我的邮箱帐号
+EMAIL_HOST_PASSWORD = 'cjk1234'  # 授权码
+EMAIL_SUBJECT_PREFIX = 'website'  # 为邮件标题的前缀,默认是'[django]'
+EMAIL_USE_TLS = True  # 开启安全链接
+DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER  # 设置发件人
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model',
+    'PushModel',
+    'SerialModel',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'Service.middleware.StatisticsUrlMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'corsheaders.middleware.CorsPostCsrfMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    # 'django_global_request.middleware.GlobalRequestMiddleware',
+]
+
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.ModelBackend',  # django default backend
+    'guardian.backends.ObjectPermissionBackend',
+)
+
+ADDR_URL = []
+ANONYMOUS_USER_ID = -1  # 支持匿名用户
+
+STATIC_URL = '/static/'
+
+# 上传路径根目录
+MEDIA_ROOT = os.path.join(BASE_DIR, 'static/Upgrate')
+# 在浏览器上访问该上传文件的url的前缀
+MEDIA_URL = '/static/Upgrate/'
+ROOT_URLCONF = 'Ansjer.urls'
+LOGIN_URL = '/account/login'
+AUTH_USER_MODEL = 'Model.Device_User'  # 自定义Model
+APPEND_SLASH = False
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # 'DIRS': [BASE_DIR + '/static/templates', ],
+        'DIRS': [BASE_DIR + '/templates'],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'Ansjer.local_wsgi.application'
+
+# 服务器类型
+#业务数据库
+DATABASE_DATA = 'ansjertest'
+SERVER_HOST = '127.0.0.1'
+DATABASES_USER = 'root'
+DATABASES_PASS = 'root'
+
+#推送数据库
+DATABASE_DATA2 = 'ansjerpush'
+SERVER_HOST2 = '127.0.0.1'
+DATABASES_USER2 = 'root'
+DATABASES_PASS2 = 'root'
+
+#序列号公共数据库
+DATABASE_DATA3 = 'serial'
+SERVER_HOST3 = '127.0.0.1'
+DATABASES_USER3 = 'root'
+DATABASES_PASS3 = 'root'
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA,
+        'USER': DATABASES_USER,
+        'PASSWORD': DATABASES_PASS,
+        'HOST': SERVER_HOST,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    'mysql02': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA2,
+        'USER': DATABASES_USER2,
+        'PASSWORD': DATABASES_PASS2,
+        'HOST': SERVER_HOST2,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    'mysql03': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA3,
+        'USER': DATABASES_USER3,
+        'PASSWORD': DATABASES_PASS3,
+        'HOST': SERVER_HOST3,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+}
+DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
+DATABASE_APPS_MAPPING = {
+    'Model': 'default',
+    'PushModel': 'mysql02',
+    'SerialModel': 'mysql03',
+}
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+LANGUAGE_CODE = 'en-us'
+TIME_ZONE = 'Asia/Shanghai'
+# TIME_ZONE = 'UTC'
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+# CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)
+
+#########################################
+'''
+增加错误信息推送到管理员邮箱
+'''
+# 管理员邮箱
+ADMINS = (
+    ('admin', 'sonalh@foxmail.com'),
+)
+
+# 非空链接,却发生404错误,发送通知MANAGERS
+SEND_BROKEN_LINK_EMAILS = True
+MANAGERS = ADMINS
+
+# Email设置
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'smtp.163.com'  # QQ邮箱SMTP服务器(邮箱需要开通SMTP服务)
+EMAIL_PORT = 25  # QQ邮箱SMTP服务端口
+EMAIL_HOST_USER = 'chanjunkai@163.com'  # 我的邮箱帐号
+EMAIL_HOST_PASSWORD = 'cjk1234'  # 授权码
+EMAIL_SUBJECT_PREFIX = 'website'  # 为邮件标题的前缀,默认是'[django]'
+EMAIL_USE_TLS = True  # 开启安全链接
+DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER  # 设置发件人
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'formatters': {
+        'error_format': {
+            # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
+            'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
+        },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+
+    },
+    'filters': {
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'class': 'django.utils.log.AdminEmailHandler',
+            'include_html': True,
+        },
+        'default': {
+            'level': 'ERROR',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/error/error.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'error_format',
+        },
+        'console': {
+            'level': 'ERROR',
+            'class': 'logging.StreamHandler',
+            'formatter': 'error_format'
+        },
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['default', 'console'],
+            # 'handlers': ['mail_admins','default','console'],
+            # 'level': 'ERROR',
+            'level': 'ERROR',
+            'propagate': False
+        },
+        # log 调用时需要当作参数传入
+        'info': {
+            'handlers': ['info'],
+            'level':'INFO',
+            'propagate': False
+        }
+        # 'django.db.backends': {
+        #     'handlers': ['console'],
+        #     'propagate': True,
+        #     'level': 'DEBUG',
+        # },
+    }
+}

+ 16 - 0
Ansjer/us_config/local_wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for Ansjer project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.us_config.local_settings")
+
+application = get_wsgi_application()

+ 274 - 0
Ansjer/us_config/test_settings.py

@@ -0,0 +1,274 @@
+import os
+from Ansjer.config import BASE_DIR
+
+
+SECRET_KEY = 'c7ki2_gkg4#sjfm-u1%$s#&n#szf01f*v69rwv2qsf#-zmm@tl'
+DEBUG = True
+# DEBUG = False
+ALLOWED_HOSTS = ['*']
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model',
+    'PushModel',
+    'SerialModel',
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'Service.middleware.StatisticsUrlMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'corsheaders.middleware.CorsPostCsrfMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django_global_request.middleware.GlobalRequestMiddleware',
+]
+
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.ModelBackend',  # django default backend
+    'guardian.backends.ObjectPermissionBackend',
+)
+
+ADDR_URL = []
+ANONYMOUS_USER_ID = -1  # 支持匿名用户
+
+STATIC_URL = '/static/'
+
+# 上传路径根目录
+MEDIA_ROOT = os.path.join(BASE_DIR, 'static/Upgrate')
+# 在浏览器上访问该上传文件的url的前缀
+MEDIA_URL = '/static/Upgrate/'
+ROOT_URLCONF = 'Ansjer.urls'
+LOGIN_URL = '/account/login'
+AUTH_USER_MODEL = 'Model.Device_User'  # 自定义Model
+APPEND_SLASH = False
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # 'DIRS': [BASE_DIR + '/static/templates', ],
+        'DIRS': [BASE_DIR + '/templates', ],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'Ansjer.us_config.test_wsgi.application'
+
+
+# 服务器类型
+#业务数据库
+DATABASE_DATA = 'AnsjerTest'
+SERVER_HOST = 'database-2.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+DATABASES_USER = 'azrds'
+DATABASES_PASS = 'azrds.x.x'
+
+#推送数据库
+DATABASE_DATA2 = 'AnsjerTest'
+SERVER_HOST2 = 'ansjerpush.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+DATABASES_USER2 = 'azrds'
+DATABASES_PASS2 = 'azrds.x.x'
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA,
+        'USER': DATABASES_USER,
+        'PASSWORD': DATABASES_PASS,
+        'HOST': SERVER_HOST,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+    'mysql02': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA2,
+        'USER': DATABASES_USER2,
+        'PASSWORD': DATABASES_PASS2,
+        'HOST': SERVER_HOST2,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    },
+}
+
+DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
+DATABASE_APPS_MAPPING = {
+    'Model': 'default',
+    'db2': 'mysql02',
+}
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+LANGUAGE_CODE = 'en-us'
+# TIME_ZONE = 'Asia/Shanghai'
+TIME_ZONE = 'UTC'
+USE_I18N = True
+USE_L10N = True
+USE_TZ = True
+
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+# CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)
+
+#########################################
+'''
+增加错误信息推送到管理员邮箱
+'''
+# 管理员邮箱
+ADMINS = (
+    ('admin', 'sonalh@foxmail.com'),
+)
+
+# 非空链接,却发生404错误,发送通知MANAGERS
+SEND_BROKEN_LINK_EMAILS = True
+MANAGERS = ADMINS
+
+# Email设置
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'smtp.163.com'  # QQ邮箱SMTP服务器(邮箱需要开通SMTP服务)
+EMAIL_PORT = 25  # QQ邮箱SMTP服务端口
+EMAIL_HOST_USER = 'chanjunkai@163.com'  # 我的邮箱帐号
+EMAIL_HOST_PASSWORD = 'cjk1234'  # 授权码
+EMAIL_SUBJECT_PREFIX = 'website'  # 为邮件标题的前缀,默认是'[django]'
+EMAIL_USE_TLS = True  # 开启安全链接
+DEFAULT_FROM_EMAIL = SERVER_EMAIL = EMAIL_HOST_USER  # 设置发件人
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'formatters': {
+        'error_format': {
+            # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
+            'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
+        },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+
+    },
+    'filters': {
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'class': 'django.utils.log.AdminEmailHandler',
+            'include_html': True,
+        },
+        'default': {
+            'level': 'ERROR',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/error/error.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'error_format',
+        },
+        'console': {
+            'level': 'ERROR',
+            'class': 'logging.StreamHandler',
+            'formatter': 'error_format'
+        },
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+        'device_info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.TimedRotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/device_info/info.log',
+            'backupCount': 30,
+            'when': 'D',
+            'formatter': 'standard',
+            'encoding': 'utf-8',
+        },
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['default', 'console'],
+            # 'handlers': ['mail_admins','default','console'],
+            # 'level': 'ERROR',
+            'level': 'ERROR',
+            'propagate': False
+        },
+        # log 调用时需要当作参数传入
+        'info': {
+            'handlers': ['info'],
+            'level':'INFO',
+            'propagate': False
+        },
+
+        'device_info':{
+            'handlers': ['device_info'],
+            'level':'INFO',
+            'propagate': False
+        }
+        # 'django.db.backends': {
+        #     'handlers': ['console'],
+        #     'propagate': True,
+        #     'level': 'DEBUG',
+        # },
+    }
+}

+ 16 - 0
Ansjer/us_config/test_wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for Ansjer project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.us_config.test_settings")
+
+application = get_wsgi_application()

+ 3 - 3
Controller/Alexa.py

@@ -88,9 +88,9 @@ class AlexaConnectNum(TemplateView):
         res = []
         #最近三十天每天最高连接数
         if operation == 'thirtyDays':
-            query_num = AlexaConnectStatisticsModel.objects. \
-                            extra(select={"month_day_time": "FROM_UNIXTIME(data_time, '%%m-%%d')"}). \
-                            values('num', 'month_day_time').order_by('-data_time')[:30]
+            query_num = AlexaConnectStatisticsModel.objects.\
+                extra(select={"month_day_time": "FROM_UNIXTIME(data_time, '%%m-%%d')"}).\
+                values('num', 'month_day_time').order_by('-data_time')[:30]
             res = list(query_num)
 
         #最近十二个月每月最高连接数

+ 4 - 1
Controller/CloudStorage.py

@@ -34,7 +34,6 @@ from django.db import transaction
 from django.views.generic.base import View
 import jwt
 from pyfcm import FCMNotification
-
 from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, SERVER_DOMAIN, PAYPAL_CRD, \
     SERVER_DOMAIN_SSL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_ARN, APNS_MODE, APNS_CONFIG, BASE_DIR, \
     JPUSH_CONFIG, FCM_CONFIG, OAUTH_ACCESS_TOKEN_SECRET
@@ -1492,6 +1491,10 @@ class CloudStorageView(View):
     def do_vod_msg_end(self, request_dict):
         response = ResponseObject()
         now_time = int(time.time())
+        # 过期前第365天提示一次,测试用
+        list = UID_Bucket.objects.filter(Q(endTime__gt=now_time + 3600 * 8736) & Q(endTime__lte=(now_time + 3600 * 8760))).values('id','uid','bucket__area','channel','endTime')
+        self.do_vod_msg(now_time,list)
+
         # 过期前第7天提示一次
         list = UID_Bucket.objects.filter(Q(endTime__gt=now_time + 3600 * 144) & Q(endTime__lte=(now_time + 3600 * 168))).values('id','uid','bucket__area','channel','endTime')
         self.do_vod_msg(now_time,list)

+ 44 - 69
Controller/CompanyController.py

@@ -29,10 +29,12 @@ class CompanyView(View):
 
     def validate(self, request_dict, operation):
 
-        token = TokenObject(request_dict.get('token', None))
-
         response = uidManageResponseObject()
 
+        if operation == 'createSerial':
+            return self.do_create_serial(request_dict, response)
+
+        token = TokenObject(request_dict.get('token', None))
         if token.code != 0:
             return response.json(token.code)
 
@@ -44,8 +46,6 @@ class CompanyView(View):
             return self.do_delete(token.userID, request_dict, response)
         elif operation == 'list':
             return self.do_list(token.userID, request_dict, response)
-        elif operation == 'createSerial':
-            return self.do_create_serial(token.userID, request_dict, response)
         else:
             return response.json(404)
 
@@ -124,80 +124,55 @@ class CompanyView(View):
         else:
             return response.json(444)
 
-    @transaction.atomic
-    def do_create_serial(self, userID, request_dict, response):
+    def do_create_serial(self, request_dict, response):
         # perm = ModelService.check_perm_uid_manage(userID, 0)
         # if not perm:
         #     return response.json(309)
 
         id = request_dict.get('id', None)
         quantity = request_dict.get('quantity', None)
-        p2p = request_dict.get('p2p', None)
-        if id and quantity:
-            company_qs = CompanyModel.objects.filter(id=id)
 
-            if not company_qs.exists():
-                return response.json(444)
-            p2p_sum_Serial = SerialNumberModel.objects.filter(p2p=p2p).count()
-            p2p_sum_Serial_company = CompanySerialModel.objects.filter(p2p=p2p).count()
-            p2p_sum_bind = p2p_sum_Serial - p2p_sum_Serial_company
-            if int(quantity) > int(p2p_sum_bind):
-                return response.json(10041)
-
-            savePoint = transaction.savepoint()
-            try:
-                try:
-
-                    company = company_qs[0]
-                    # start = company.quantity
-                    # start = int(start)
-                    # end = start + int(quantity)
-                    # serial_qs = SerialNumberModel.objects.filter(p2p=p2p)[start:end]
-                    start_1 = p2p_sum_Serial_company
-                    end_1 = int(start_1) + int(quantity)
-                    serial_qs = SerialNumberModel.objects.filter(p2p=p2p)[start_1:end_1]
-                    if serial_qs.exists():
-                        data = []
-                        now_time = int(time.time())
-                        for item in serial_qs:
-                            data.append(CompanySerialModel(
-                                company_id=company.id,
-                                serial_number=item.serial_number,
-                                add_time=now_time,
-                                update_time=now_time,
-                                p2p=p2p
-                            ))
-
-                            if len(data) == 5000:
-                                CompanySerialModel.objects.bulk_create(data)
-                                data.clear()
-                        if len(data) > 0:
-                            CompanySerialModel.objects.bulk_create(data)
-                            data.clear()
-
-                        # company.quantity = company.quantity + end - start
-                        company.quantity =CompanySerialModel.objects.filter(company_id=id).count()
-                        company.save()
-                        return response.json(0)
-                    else:
-                        return response.json(173)
-                except Exception as e:
-                    # print('--------------------------error 5000')
-                    # print(repr(e))
-                    if savePoint:
-                        transaction.rollback(savePoint)
-                    djangoLogger = logging.getLogger('django')
-                    djangoLogger.exception(repr(e))
-                    return response.json(176, str(e))
-            except Exception as e:
-                # print('--------------------------error 5001')
-                # print(repr(e))
-                djangoLogger = logging.getLogger('django')
-                djangoLogger.exception(repr(e))
-                return response.json(176, str(e))
-        else:
+        if not all([id, quantity]):
             return response.json(444)
 
+        company_qs = CompanyModel.objects.filter(id=id)
+        if not company_qs.exists():
+            return response.json(444)
+
+        sum_Serial = SerialNumberModel.objects.filter().count()
+        sum_Serial_company = CompanySerialModel.objects.filter().count()
+        sum_bind = sum_Serial - sum_Serial_company  # 剩余可绑定的序列号
+        if int(quantity) > int(sum_bind):
+            return response.json(10041)
+
+        try:
+            company = company_qs[0]
+            start_1 = sum_Serial_company
+            end_1 = int(start_1) + int(quantity)
+            serial_qs = SerialNumberModel.objects.filter()[start_1:end_1]
+            if serial_qs.exists():
+                company_serial_bulk = []
+                now_time = int(time.time())
+                for item in serial_qs:
+                    company_serial_bulk.append(CompanySerialModel(
+                        status=1,
+                        add_time=now_time,
+                        update_time=now_time,
+                        company_id=company.id,
+                        serial_number=item.serial_number,
+                    ))
+                with transaction.atomic():
+                    CompanySerialModel.objects.bulk_create(company_serial_bulk)
+                    company.quantity = CompanySerialModel.objects.filter(company_id=id).count()
+                    company.save()
+                return response.json(0)
+            else:
+                return response.json(173)
+        except Exception as e:
+            djangoLogger = logging.getLogger('django')
+            djangoLogger.exception(repr(e))
+            return response.json(176, str(e))
+
     def do_list(self, userID, request_dict, response):
         # perm = ModelService.check_perm_uid_manage(userID, 0)
         # if not perm:

+ 44 - 1
Controller/DeviceConfirmRegion.py

@@ -26,7 +26,7 @@ from ratelimit.decorators import ratelimit
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
-    UserAppFrequencyModel, CountryIPModel, CountryModel, RegionModel
+    UserAppFrequencyModel, CountryIPModel, CountryModel, RegionModel, P2PIpModel
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
@@ -78,6 +78,8 @@ class Device_Region(object):
     def get_device_region(self, ip):
 
         ipInfo = CommonService.getIpIpInfo(ip, "CN")
+
+        #暂时测试国外
         if ipInfo['country_code']:
             device_request_url = CountryModel.objects.filter(country_code=ipInfo['country_code']).values("region__api","region__id")
             if device_request_url.exists():
@@ -87,3 +89,44 @@ class Device_Region(object):
         return api[0]['id']
 
 
+# 根据p2p的ip统计设备所在地区
+class StatisticsIpRegion(TemplateView):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(StatisticsIpRegion, self).dispatch(*args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        return self.ipRegion(request.GET)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        return self.ipRegion(request.POST)
+
+    def ipRegion(self, request_dict):
+        response = ResponseObject()
+        ip = request_dict.get('ip', None)
+        uid = request_dict.get('uid', None)
+
+        if not all([ip, uid]):
+            return response.json(444)
+
+        try:
+            # 判断uid是否已记录过ip信息
+            p2p_ip_qs = P2PIpModel.objects.filter(uid=uid)
+            if p2p_ip_qs.exists():
+                return response.json(174)
+
+            # 根据ip确定位置信息
+            ip_info = CommonService.getIpIpInfo(ip, 'CN')
+            # 获取国家,地区,城市
+            country_name = ip_info['country_name']
+            region_name = ip_info['region_name']
+            city_name = ip_info['city_name']
+            P2PIpModel.objects.create(uid=uid, ip=ip, country_name=country_name, region_name=region_name,
+                                      city_name=city_name, add_time=int(time.time()))
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+

+ 75 - 0
Controller/DeviceDebug.py

@@ -0,0 +1,75 @@
+#!/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: 2021/07/06 11:17
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+"""
+import json
+import time
+import urllib
+import uuid
+import boto3
+import threading
+import logging
+from boto3.session import Session
+from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
+from django.views.generic.base import View
+from Model.models import Device_Info
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Object.UidTokenObject import UidTokenObject
+from Service.CommonService import CommonService
+from django.db.models import Q, F
+from time import strftime
+
+
+class DeviceDebug(View):
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        response = ResponseObject()
+        if not operation:
+            return response.json(444,'operation')
+        uidToken = request_dict.get('uidToken', None)
+        if uidToken is not None:
+            utko = UidTokenObject(uidToken)
+            if utko.flag is False:
+                return response.json(444, 'uidToken')
+            uid = utko.UID
+            if uid is not None:
+                if operation == 'singleDebug':
+                    return self.single_debug(request, request_dict, uid, response)
+            return response.json(444, 'operation')
+        else:
+            return response.json(309)
+
+    def single_debug(self,request, request_dict, uid, response):
+        ip = CommonService.get_ip_address(request)
+        device_info = logging.getLogger('device_info')
+        device_info.info("----------------------------------------------------------------------------------")
+        device_info.info("----------------------------------------------------------------------------------")
+        device_info.info("----------------------------------------------------------------------------------")
+        device_info.info("----------------------------------------------------------------------------------")
+        device_info.info("----------------------------------------------------------------------------------")
+        device_info.info("----------------------------------------------------------------------------------")
+        device_info.info("debug----------------------------------------------------------------------------------start")
+        device_info.info("uid:"+uid)
+        device_info.info(strftime("%Y-%m-%d %H:%M:%S"))
+        device_info.info("ip:"+ip)
+        device_info.info(request_dict.get('debug_log'))
+        device_info.info("debug------------------------------------------------------------------------------------end")
+        return response.json(0,'debug success')
+                # return response.json(10, '生成失败')

+ 15 - 36
Controller/EquipmentManager.py

@@ -8,7 +8,7 @@ import requests
 import simplejson as json
 from django.utils import timezone
 from Model.models import Device_User, Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel, \
-    UIDCompanySerialModel, iotdeviceInfoModel, UIDMainUser, UidChannelSetModel
+    UIDCompanySerialModel, iotdeviceInfoModel, UIDMainUser
 from django.db.models import Q
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -253,16 +253,8 @@ def modifyUserEquipmentInterface(request):
                 }
                 UidSetModel.objects.create(**uid_set_create_dict)
             Device_Info.objects.filter(UID=uid).update(NickName=nickname)
-            if deviceData.__contains__('NickName') and us_qs[0].is_alexa == 1:
-                encrypt_pwd = ''
-                if deviceData.__contains__('View_Password'):
-                    encrypt_pwd = ModelService.encrypt_pwd(deviceData['View_Password'])
-                # 请求Alexa服务器更新事件网关
-                url = 'https://www.zositech.xyz/deviceStatus/addOrUpdateV2'
-                data_list = [{'userID': userID, 'UID': uid, 'uid_nick': nickname, 'password': encrypt_pwd}]
-                data_list = json.dumps(data_list)
-                data = {'data_list': data_list}
-                requests.post(url, data=data, timeout=2)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
         return response.json(0, res)
 
 
@@ -378,7 +370,6 @@ def addInterface(request):
     version = request_dict.get('version', '')
     isCheckMainUser = request_dict.get('isCheckMainUser', None)
     isMainUserExists = False
-    encrypt_password = ModelService.encrypt_pwd(View_Password)
     if all([UID, NickName, View_Account, Type, ChannelIndex]):
         tko = TokenObject(token)
         response.lang = tko.lang
@@ -493,28 +484,14 @@ def addInterface(request):
                     else:
                         Device_Info.objects.filter(UID=UID).update(vodPrimaryUserID=vodPrimaryUserID,
                                                                    vodPrimaryMaster=vodPrimaryMaster)
-                    if not us_qs.exists():
-                        us_qs = UidSetModel.objects.filter(uid=UID)
-
-                    if us_qs.exists() and us_qs[0].is_alexa == 1:
-                        if us_qs[0].channel > 1:
-                            data_list = []
-                            uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id). \
-                                values('channel', 'channel_name')
-                            if uid_channel_set_qs.exists():
-                                # 多通道设备名为 UidChannelSetModel 的 channel_name
-                                for uid_channel_set in uid_channel_set_qs:
-                                    data_list.append(
-                                        {'userID': userID, 'UID': UID, 'uid_nick': uid_channel_set['channel_name'],
-                                         'channel': uid_channel_set['channel'], 'password': encrypt_password})
-                        else:
-                            data_list = [{'userID': userID, 'UID': UID, 'uid_nick': NickName, 'password': encrypt_password}]
-
-                        # 请求Alexa服务器更新事件网关
-                        data_list = json.dumps(data_list)
-                        data = {'data_list': data_list}
-                        url = 'https://www.zositech.xyz/deviceStatus/addOrUpdateV2'
-                        requests.post(url, data=data, timeout=2)
+                    # if isCheckMainUser == '1':
+                    #     uid_main_dict = {
+                    #         'UID': UID,
+                    #         'user_id': vodPrimaryUserID
+                    #     }
+                    #     UIDMainUser.objects.create(**uid_main_dict)
+                # redisObj = RedisObject(db=8)
+                    # redisObj.del_data(key='uid_qs_' + userID)
                 except Exception as e:
                     return response.json(10, repr(e))
                 else:
@@ -962,11 +939,12 @@ def queryInterface(request):
         data = []
         # 设备拓展信息表
         us_qs = UidSetModel.objects.filter(uid__in=uid_list).\
-            values('uid', 'version', 'nickname', 'detect_interval')
+            values('uid', 'version', 'nickname', 'detect_interval', 'is_ptz')
         uv_dict = {}
         for us in us_qs:
             uv_dict[us['uid']] = {'version': us['version'],
                                   'nickname': us['nickname'],
+                                  'is_ptz': us['is_ptz'],
                                   'detect_interval': us['detect_interval']}
 
         for p in dvls:
@@ -1035,7 +1013,7 @@ def uid_status(request):
     # 判断用户是否绑定设备
     qs = UidSetModel.objects.filter(uid=uid).values('uid', 'detect_status', 'detect_interval', 'version', 'ucode',
                                                     'p2p_region', 'tz', 'video_code', 'channel', 'cloud_vod', 'id',
-                                                    'detect_group', 'is_alexa', 'region_alexa')
+                                                    'detect_group', 'is_alexa', 'region_alexa','is_ptz')
 
     # 调试
     debugOnes = int(time.time())
@@ -1066,6 +1044,7 @@ def uid_status(request):
             'detect_group': qs[0]['detect_group'],  # 推送组
             'is_alexa': qs[0]['is_alexa'],  # 推送组
             'region_alexa': qs[0]['region_alexa'],  # 推送组
+            'is_ptz': qs[0]['is_ptz']
         }
 
         # 调试

+ 3 - 1
Controller/EquipmentManagerV2.py

@@ -173,7 +173,7 @@ class EquipmentManagerV2(View):
             nowTime = int(time.time())
             data = []
             # 设备拓展信息表
-            us_qs = UidSetModel.objects.filter(uid__in=uid_list).values('uid', 'version', 'nickname', 'ucode','detect_interval', 'is_human', 'is_custom_voice')
+            us_qs = UidSetModel.objects.filter(uid__in=uid_list).values('uid', 'version', 'nickname', 'ucode','detect_interval', 'is_human', 'is_custom_voice', 'is_ptz')
             uv_dict = {}
             for us in us_qs:
                 uv_dict[us['uid']] = {
@@ -183,6 +183,7 @@ class EquipmentManagerV2(View):
                     'detect_interval': us['detect_interval'],
                     'is_human': us['is_human'],
                     'is_custom_voice': us['is_custom_voice'],
+                    'is_ptz': us['is_ptz']
                 }
             for p in dvls:
                 # 新增云分配UID
@@ -216,6 +217,7 @@ class EquipmentManagerV2(View):
                     p['detect_interval'] = uv_dict[p_uid]['detect_interval']
                     p['is_human'] = uv_dict[p_uid]['is_human']
                     p['is_custom_voice'] = uv_dict[p_uid]['is_custom_voice']
+                    p['is_ptz'] = uv_dict[p_uid]['is_ptz']
                     # 设备昵称 调用影子信息昵称,先阶段不可
                     if uv_dict[p_uid]['nickname']:
                         p['NickName'] = uv_dict[p_uid]['nickname']

+ 13 - 12
Controller/EquipmentManagerV3.py

@@ -255,7 +255,6 @@ class EquipmentManagerV3(View):
                         'endpoint': iotqs[0].endpoint,
                         'token_iot_number': iotqs[0].endpoint
                 }
-
             return response.json(0, res)
 
 
@@ -274,7 +273,6 @@ class EquipmentManagerV3(View):
             return response.json(309)
 
         try:
-            # deviceData = json.loads(deviceContent)
             deviceData = eval(deviceContent)
             if deviceData.__contains__('userID_id'):
                 asy = threading.Thread(target=ModelService.update_log,
@@ -319,6 +317,7 @@ class EquipmentManagerV3(View):
                     UidSetModel.objects.create(**uid_set_create_dict)
                 di_qs = Device_Info.objects.filter(UID=uid)
                 di_qs.update(NickName=nickname)
+
                 if deviceData is not None and deviceData.__contains__('NickName') and us_qs[0].is_alexa == 1:
                     # 请求Alexa服务器更新事件网关
                     url = 'https://www.zositech.xyz/deviceStatus/addOrUpdateV2'
@@ -327,6 +326,7 @@ class EquipmentManagerV3(View):
                     data_list = json.dumps(data_list)
                     data = {'data_list': data_list}
                     requests.post(url, data=data, timeout=2)
+
             return response.json(0, res)
 
     # 编辑通道名
@@ -395,7 +395,7 @@ class EquipmentManagerV3(View):
                                                                     'TimeZone', 'TimeStatus', 'SpaceUsable',
                                                                     'SpaceSum', 'MirrorType', 'RecordType',
                                                                     'OutdoorModel', 'WIFIName', 'isDetector',
-                                                                    'DetectorRank', 'is_human', 'is_custom_voice')
+                                                                    'DetectorRank', 'is_human', 'is_custom_voice', 'is_ptz')
         uv_dict = {}
         for us in us_qs:
             uv_dict[us['uid']] = {
@@ -419,7 +419,8 @@ class EquipmentManagerV3(View):
                 'isDetector': us['isDetector'],
                 'DetectorRank': us['DetectorRank'],
                 'is_human': us['is_human'],
-                'is_custom_voice': us['is_custom_voice']
+                'is_custom_voice': us['is_custom_voice'],
+                'is_ptz': us['is_ptz']
             }
             # 从uid_channel里面取出通道配置信息
             ucs_qs = UidChannelSetModel.objects.filter(uid__id=us['id']).values('channel', 'channel_name',
@@ -480,12 +481,12 @@ class EquipmentManagerV3(View):
 
             p_uid = p['UID']
 
-            # # 返回设备初始化字符
-            # uid_qs = UIDModel.objects.filter(uid=p_uid).values('platform', 'init_string', 'init_string_app')
-            # if uid_qs.exists():
-            #     p['platform'] = uid_qs[0]['platform']
-            #     p['initString'] = uid_qs[0]['init_string']
-            #     p['initStringApp'] = uid_qs[0]['init_string_app']
+            # 返回设备初始化字符
+            uid_qs = UIDModel.objects.filter(uid=p_uid).values('platform', 'init_string', 'init_string_app')
+            if uid_qs.exists():
+                p['platform'] = uid_qs[0]['platform']
+                p['initString'] = uid_qs[0]['init_string']
+                p['initStringApp'] = uid_qs[0]['init_string_app']
 
             if p_uid in uv_dict:
                 # 设备版本号
@@ -563,12 +564,12 @@ class EquipmentManagerV3(View):
             if device_qs.exists():
                 if fuzzy:
                     device_qs = device_qs.filter(Q(UID__icontains=fuzzy) | Q(NickName__icontains=fuzzy))
-
                 device_qs = device_qs.values('id', 'userID', 'NickName', 'UID', 'View_Account',
                                              'View_Password', 'ChannelIndex', 'Type', 'isShare',
                                              'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID',
                                              'vodPrimaryMaster', 'userID__userEmail',
-                                             'version', 'isVod', 'isExist', 'NotificationMode', 'isCameraOpenCloud', 'serial_number')
+                                             'version', 'isVod', 'isExist', 'NotificationMode', 'isCameraOpenCloud',
+                                             'serial_number')
 
                 dvls = CommonService.qs_to_list(device_qs)
                 uid_list = []

+ 5 - 1
Controller/EquipmentStatus.py

@@ -115,7 +115,6 @@ def getTZ(request):
             print(uid)
             redisObject = RedisObject(db=7)
             data = redisObject.get_data(key=ip)
-
             if data:
                 info = json.loads(data)
                 return JsonResponse(status=200, data={'code': 0, 'msg': 'success', 'data': info})
@@ -131,6 +130,11 @@ def getTZ(request):
                     if ':' not in gmtz:
                         gmtz = gmtz + ':00'
                     info['gmt_offset'] = gmtz
+                if len(tz) == 6:
+                    gmtz = tz.replace('UTC-', 'GMT-').replace('UTC+', 'GMT+')
+                    if ':' not in gmtz:
+                        gmtz = gmtz + ':00'
+                    info['gmt_offset'] = gmtz
                 elif len(tz) == 8:
                     gmtz = tz.replace('UTC-', 'GMT-0').replace('UTC+', 'GMT+0')
                     info['gmt_offset'] = gmtz

+ 0 - 1
Controller/FAQController.py

@@ -14,7 +14,6 @@ from django.views.generic.base import View
 
 import Ansjer
 from Ansjer.config import BASE_DIR, SERVER_TYPE
-from Ansjer.config_formal import SERVER_DOMAIN
 from Model.models import FAQModel
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject

+ 22 - 15
Controller/IotCoreController.py

@@ -38,7 +38,8 @@ class IotCoreView(View):
 
     def validate(self, operation, request_dict, request):
         response = ResponseObject()
-
+        lang = request_dict.get('lang', 'en')
+        response.lang = lang
         if operation == 'createKeysAndCertificate':
             return self.create_keys_and_certificate(request_dict, response, request)
         elif operation == 'requestPublishMessage':
@@ -49,6 +50,8 @@ class IotCoreView(View):
             token = TokenObject(request_dict.get('token', None))
             if token.code != 0:
                 return response.json(token.code)
+            response.lang = token.lang
+
             if operation == 'clearIotCerm':
                 return self.clear_Iot_Cerm(request_dict, response)
             else:
@@ -226,7 +229,7 @@ class IotCoreView(View):
             return response.json(444)
 
     def request_publish_message(self, request_dict, response, request):
-        # Alexa请求IoT Core下发MQTT消息
+        # Alexa请求IoT Core下发MQTT消息通知设备开始或停止推流,或唤醒设备
         UID = request_dict.get('UID', None)
         MSG = request_dict.get('MSG', None)
 
@@ -236,36 +239,40 @@ class IotCoreView(View):
         try:
             # 获取检查uid的序列号,如果没有序列号,不使用MQTT下发消息
             device_info_qs = Device_Info.objects.filter(UID=UID).values('UID', 'serial_number')
+            if not device_info_qs.exists():
+                return response.json(10043)
             uid = device_info_qs[0]['UID']
             serial_number = device_info_qs[0]['serial_number']
             # 如果device_info表的serial_number不为空,物品名为'Ansjer_Device_序列号'
-            ThingNameSuffix = serial_number if serial_number != '' else uid
-
-            thing_name = 'Ansjer_Device_' + ThingNameSuffix
+            thing_name_suffix = serial_number if serial_number != '' else uid
             # 获取数据组织将要请求的url
-            iot = iotdeviceInfoModel.objects.filter(thing_name__contains=thing_name).values('thing_name', 'endpoint',
-                                                                                            'token_iot_number')
+            iot = iotdeviceInfoModel.objects.filter(thing_name__contains=thing_name_suffix).values('thing_name',
+                                                                                                   'endpoint',
+                                                                                                   'token_iot_number')
             if not iot.exists():
                 return response.json(10043)
-            thing_name = iot[0]['thing_name']  # IoT core上的物品名: Ansjer_Device_+序列号+企业编码
+            thing_name = iot[0]['thing_name'][14:]  # IoT core上的物品名: Ansjer_Device_ + 序列号+企业编码/uid
             endpoint = iot[0]['endpoint']
             Token = iot[0]['token_iot_number']
             # Token = '297a601b3925e04daab5a60280650e09'
-            topic_name = thing_name + '_rtsp_topic'     # MQTT主题
+            topic_suffix = '_power_topic' if 'Turn' in MSG else '_rtsp_topic'
+            topic_name = thing_name + topic_suffix     # MQTT主题
 
-            # rtsp://rtsp.zositech.org:8554/ZFdqWldXRFpMTkVaYVZEaEJXRXhUV0RFeE1VRT1B
             # api doc: https://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/http.html
-            # https://IoT_data_endpoint/topics/url_encoded_topic_name?qos=1
-            # POST请求url来发布消息
-            url = 'https://{}/topics/{}?rtsp_command={}'.format(endpoint, topic_name, MSG)
+            # url: https://IoT_data_endpoint/topics/url_encoded_topic_name?qos=1
+            # post请求url来发布MQTT消息
+            url = 'https://{}/topics/{}'.format(endpoint, topic_name)
             authorizer_name = 'Ansjer_Iot_Auth'
             signature = self.rsa_sign(Token)  # Token签名
             headers = {'x-amz-customauthorizer-name': authorizer_name, 'Token': Token,
                        'x-amz-customauthorizer-signature': signature}
-            params = {'rtsp_command': MSG}
+            params = {'command': MSG}
             r = requests.post(url=url, headers=headers, json=params, timeout=2)
             if r.status_code == 200:
-                return response.json(0)
+                res = r.json()
+                if res['message'] == 'OK':
+                    return response.json(0)
+                return response.json(10044)
             else:
                 # print('发布失败')
                 return response.json(10044)

+ 1 - 1
Controller/LogManager.py

@@ -2,7 +2,7 @@ from Controller import OTAEquipment
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
 from django.utils.decorators import method_decorator
-from Ansjer import local_settings as api_settings
+from Ansjer import config as api_settings
 from Service.ModelService import ModelService
 import time,os
 from Object.ResponseObject import ResponseObject

+ 5 - 3
Controller/OrderContrller.py

@@ -19,7 +19,7 @@ from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
 
-from Ansjer.config_test import PAYPAL_CRD
+from Ansjer.us_config.config_test import PAYPAL_CRD
 from Object.AliPayObject import AliPayObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -109,7 +109,7 @@ class OrderView(View):
                                                               "addTime",
                                                               "updTime", "paypal", "rank__day", "payType",
                                                               "rank__price", "status",
-                                                              "rank__content", "rank__title", "rank__currency",
+                                                              "rank__lang__content", "rank__title", "rank__currency",
                                                               "rank_id","rank__expire")
         order_list = list(order_ql)
         data = []
@@ -128,7 +128,9 @@ class OrderView(View):
                     d['did'] = did['id']
                     d['Type'] = did['Type']
                     data.append(d)
-            d['rank__expire_unit'] = '月' if lang == 'cn' else 'month'
+            d['rank__content'] = d['rank__lang__content']
+            del d['rank__lang__content']
+            # d['rank__lang__content'] = '月' if lang == 'cn' else 'month'
         return response.json(0, {'data': data, 'count': count})
 
     # admins ^^^^^^^^^^^^

+ 611 - 0
Controller/PcInfo.py

@@ -0,0 +1,611 @@
+import hashlib
+import logging
+import shutil
+import time
+import traceback
+import os
+from urllib import request, parse
+import requests
+from boto3 import Session
+from django.http import HttpResponse
+
+from django.views.generic.base import View
+
+from Model.models import Pc_Info
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
+from Ansjer.config import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_ARN, BASE_DIR
+import boto3
+import botocore
+from botocore import client
+from wsgiref.util import FileWrapper
+from zlib import crc32
+from typing import Union
+
+
+class PcInfo(View):
+    def dispatch(self, requset, *args, **kwargs):
+        return super(PcInfo, self).dispatch(requset, *args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        operation = kwargs.get('operation')
+        request.encoding = 'utf-8'
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        operation = kwargs.get('operation')
+        request.encoding = 'utf-8'
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        response = ResponseObject()
+        if not operation:
+            return response.json(444, 'operation')
+        else:
+
+            if operation == 'query':     # pc端调用查询
+                return self.query(request_dict, response)
+            elif operation == 's3addandupload':
+                return self.s3addandupload(request_dict, response, request)
+            elif operation == 's3download':
+                return self.s3download(request_dict, response)
+            elif operation == 's3delete':
+                return self.s3delete(request_dict, response)
+            elif operation == 'edit':
+                return self.edit(request_dict, response)
+            elif operation == 'getnewversion':    # 获取当前软件的最新版本
+                return self.getnewversion(request_dict, response)
+            elif operation == 'getnewversionV2':   # 获取当前软件的最新版本
+                return self.getnewversionV2(request_dict, response)
+            elif operation == 'queryall':   # 后台查询
+                return self.queryall(request_dict, response)
+            elif operation == 'addandupload':   # 上传到服务器
+                return self.addandupload(request_dict, response, request)
+            elif operation == 'download':   # 服务器下载
+                return self.download(request_dict, response)
+            elif operation == 'delete':
+                return self.delete(request_dict, response)
+            else:
+                return response.json(414)
+
+    def getnewversion(self, request_dict, response):
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test])
+        if param_flag is not True:
+            return response.json(444)
+        file = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_test=pc_test)
+        if not file:
+            return response.json(173)
+        app_list = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_test=pc_test)
+        all_version = app_list.values('pc_version')
+        v = []
+        for i in all_version:
+            v.append(i['pc_version'])
+        new_version = max(v)
+        if pc_version == new_version:
+            return response.json(10045)
+        else:
+            path = app_list.filter(pc_version=new_version).values('download_link')[0]['download_link']
+            print('path', path)
+            aws_s3_guonei = boto3.client(
+                's3',
+                aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+                aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+                config=botocore.client.Config(signature_version='s3v4'),
+                region_name='cn-northwest-1')
+            response_url = aws_s3_guonei.generate_presigned_url(
+                ClientMethod='get_object',
+                Params={'Bucket': 'pc-package', 'Key': path}, ExpiresIn=3600)
+            res = {'pc_name': pc_name,
+                   'new_version': new_version,
+                   'path': path,
+                   'response_url': response_url}
+            return response.json(0, res)
+
+    def getnewversionV2(self, request_dict, response):
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test])
+        if param_flag is not True:
+            return response.json(444)
+        file = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_test=pc_test)
+        if not file.exists():
+            return response.json(173)
+        aws_s3_guonei = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='cn-northwest-1')
+        version_list = []
+        for i in range(2):
+            app_list = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_test=pc_test, is_update=i)
+            # 当前软件不存在强制更新(is_update=1)的版本返回空
+            if not app_list.exists():
+                res = {'pc_name': '',
+                       'new_version': '',
+                       'is_update': i,
+                       'explain': '',
+                       'path': '',
+                       'response_url': ''}
+                version_list.append(res)
+                continue
+            all_version = app_list.values('pc_version')
+            v = []
+            for i in all_version:
+                v.append(i['pc_version'])
+            new_version = max(v)
+            # 当前软件版本为最新时返回空
+            if pc_version >= new_version:
+                res = {'pc_name': '',
+                       'new_version': '',
+                       'is_update': app_list.filter(pc_version=new_version).values('is_update')[0]['is_update'],
+                       'explain': '',
+                       'path': '',
+                       'response_url': ''}
+                version_list.append(res)
+                continue
+            path = app_list.filter(pc_version=new_version).values('download_link')[0]['download_link']
+            print('path', path)
+            response_url = aws_s3_guonei.generate_presigned_url(
+                ClientMethod='get_object',
+                Params={'Bucket': 'pc-package', 'Key': path}, ExpiresIn=3600)
+            res = {'pc_name': pc_name,
+                   'new_version': new_version,
+                   'is_update': app_list.filter(pc_version=new_version).values('is_update')[0]['is_update'],
+                   'explain': app_list.filter(pc_version=new_version).values('explain')[0]['explain'],
+                   'path': path,
+                   'response_url': response_url}
+            version_list.append(res)
+        return response.json(0, version_list)
+
+    def query(self, request_dict, response):
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        package = request_dict.get('package', None)
+        file_type = request_dict.get('file_type', None)
+        # 根据传的参数筛选,没传时返回全部
+        queryset = Pc_Info.objects.all()
+        if package:
+            queryset = Pc_Info.objects.filter(package=package)
+        if file_type:
+            queryset = Pc_Info.objects.filter(file_type=file_type)
+        if pc_name and file_type:
+            queryset = Pc_Info.objects.filter(pc_name=pc_name, file_type=file_type)
+        if file_type and package:
+            queryset = Pc_Info.objects.filter(file_type=file_type, package=package)
+        if pc_name and bundle_version and pc_version and pc_test:
+            queryset = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_version=pc_version, pc_test=pc_test)
+        count = queryset.count()
+        res = queryset
+        send_json = CommonService.qs_to_dict(res)
+        send_json['count'] = count
+        return response.json(0, send_json)
+
+    def s3addandupload(self, request_dict, response, request):
+        logger = logging.getLogger('info')
+        logger.info('s3方式上传参数:')
+        logger.info(request_dict)
+        token = request_dict.get('token', None)
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if not userID:
+            return response.json(104)
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        lang = request_dict.get('lang', None)
+        file_name = request_dict.get('file_name', None)
+        file_type = request_dict.get('file_type', None)
+        package = request_dict.get('package', None)
+        explain = request_dict.get('explain', '')
+        is_update = request_dict.get('is_update', None)
+        is_open = request_dict.get('is_open', None)
+        # logger.info('文件名字:')
+        # logger.info(file_name)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test, lang, file_name, file_type, package, is_update, is_open])
+        if param_flag is not True:
+            return response.json(444)
+        else:
+            file = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version,
+                                          pc_version=pc_version, pc_test=pc_test)
+            if file:
+                return response.json(174)
+            try:
+                logger.info('开始上传')
+                # 把安装包上传到s3
+                aws_s3_guonei = boto3.client(
+                    's3',
+                    aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+                    aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+                    config=botocore.client.Config(signature_version='s3v4'),
+                    region_name='cn-northwest-1'
+                )
+                download_link = '{pc_name}/{pc_version}_{bundle_version}_{pc_test}_{file_name}'.format(
+                    pc_name=pc_name, pc_version=pc_version, bundle_version=bundle_version,
+                    pc_test=pc_test, file_name=file_name)
+                response_url = aws_s3_guonei.generate_presigned_url(
+                    ClientMethod='put_object',
+                    Params={
+                        'Bucket': 'pc-package',
+                        'Key': download_link
+                    },
+                    ExpiresIn=3600
+                )
+                # 通过上传签名url对文件进行上传
+                # requests.put(response_url, data=file_name)
+                # logger.info('上传完成')
+                add_time = time.time()
+                create_dict = {
+                    'pc_name': pc_name,
+                    'bundle_version': bundle_version,
+                    'pc_version': pc_version,
+                    'pc_test': pc_test,
+                    'lang': lang,
+                    'download_link': download_link,
+                    'add_time': add_time,
+                    'update_time': add_time,
+                    'file_type': file_type,
+                    'package': package,
+                    'explain': explain,
+                    'is_update': is_update,
+                    'is_open': is_open
+                }
+                pc_Info = Pc_Info(**create_dict)
+                pc_Info.save()
+            except Exception:
+                errorInfo = traceback.format_exc()
+                print(errorInfo)
+                return response.json(500, {'details': errorInfo})
+            else:
+                if pc_Info.id:
+                    res = {'id': pc_Info.id,
+                           'pc_name': pc_Info.pc_name,
+                           'bundle_version': pc_Info.bundle_version,
+                           'pc_version': pc_Info.pc_version,
+                           'pc_test': pc_Info.pc_test,
+                           'download_link': pc_Info.download_link,
+                           'lang': pc_Info.lang,
+                           'add_time': pc_Info.add_time,
+                           'update_time': pc_Info.update_time,
+                           'file_type': pc_Info.file_type,
+                           'package': pc_Info.package,
+                           'explain': pc_Info.explain,
+                           'is_update': pc_Info.is_update,
+                           'is_open': pc_Info.is_open,
+                           'upload_url': response_url
+                           }
+                    return response.json(0, res)
+                else:
+                    return response.json(500)
+
+    def s3download(self, request_dict, response):
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test])
+        if param_flag is not True:
+            return response.json(444)
+        path = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_version=pc_version,
+                                      pc_test=pc_test).values('download_link')
+        if not path:
+            return response.json(173)
+        path = path[0]['download_link']
+        aws_s3_guonei = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='cn-northwest-1'
+        )
+        response_url = aws_s3_guonei.generate_presigned_url(
+            ClientMethod='get_object',
+            Params={
+                'Bucket': 'pc-package',
+                'Key': path
+            },
+            ExpiresIn=3600
+        )
+        res = {'path': path,
+               'response_url': response_url
+               }
+        return response.json(0, res)
+
+    def edit(self, request_dict, response):
+        id = request_dict.get('id', None)
+        explain = request_dict.get('explain', None)
+        is_open = request_dict.get('is_open', None)
+        param_flag = CommonService.get_param_flag(
+            data=[id, explain, is_open])
+        if param_flag is not True:
+            return response.json(444)
+        file = Pc_Info.objects.filter(id=id)
+        if not file.exists():
+            return response.json(173)
+        else:
+            file.update(explain=explain, is_open=is_open)
+            return response.json(0)
+
+    def s3delete(self, request_dict, response):
+        global file
+        token = request_dict.get('token', None)
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if not userID:
+            return response.json(104)
+        id = request_dict.get('id', None)
+        package = request_dict.get('package', None)
+        if id and package:
+            return response.json(444)
+        elif id and package is None:
+            file = Pc_Info.objects.filter(id=id)
+        elif package and id is None:
+            try:
+                package = int(package)
+                file = Pc_Info.objects.filter(package=package)
+            except Exception as e:
+                return response.json(176)
+        if not file.exists():
+            return response.json(173)
+        try:
+            # 删除s3和数据库里的相应数据
+            file_path = file[0].download_link
+            aws_s3_guonei = boto3.client(
+                's3',
+                aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+                aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+                config=botocore.client.Config(signature_version='s3v4'),
+                region_name='cn-northwest-1'
+            )
+            try:
+                # 获取存储桶的对象,判断对象是否上传成功
+                obj = aws_s3_guonei.get_object(Bucket='pc-package', Key=file_path)
+            except Exception as e:
+                print(e)
+                file.delete()
+            else:
+                if obj:
+                    aws_s3_guonei.delete_object(Bucket='pc-package', Key=file_path)
+                    file.delete()
+        except Exception as e:
+            return response.json(176, repr(e))
+        else:
+            return response.json(0)
+
+    def queryall(self, request_dict, response):
+        token = request_dict.get('token', None)
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if not userID:
+            return response.json(104)
+        page = int(request_dict.get('page', None))
+        line = int(request_dict.get('line', None))
+        if page is None or line is None:
+            return response.json(444, 'page,line')
+        queryset = Pc_Info.objects.all()
+        if queryset.exists():
+            count = queryset.count()
+            res = queryset[(page - 1) * line:page * line]
+            send_json = CommonService.qs_to_dict(res)
+            send_json['count'] = count
+            return response.json(0, send_json)
+        else:
+            return response.json(173)
+
+    def addandupload(self, request_dict, response, request):
+        token = request_dict.get('token', None)
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if not userID:
+            return response.json(104)
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        lang = request_dict.get('lang', None)
+        file_name = request.FILES.get('file_name', None)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test, lang, file_name])
+        if param_flag is not True:
+            return response.json(444)
+        else:
+            file = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version,
+                                          pc_version=pc_version, pc_test=pc_test)
+            if file:
+                return response.json(174)
+            try:
+                # 安装包上传到服务器本地
+                file_path = 'static/pc/' + pc_name
+                if not os.path.exists(file_path):
+                    os.makedirs(os.path.join(BASE_DIR, file_path))
+                a = os.path.splitext(str(file_name))[-1]
+                if not a:
+                    return response.json(444, "文件无后缀")
+                name = pc_version + '_' + bundle_version + '_' + pc_test + str(a)
+                file_path = file_path + '/' + str(name)
+                upload_path = os.path.join(BASE_DIR, file_path)
+                print('upload_path:', upload_path)
+                with open(upload_path, 'wb+') as destination:
+                    for chunk in file_name.chunks():
+                        destination.write(chunk)
+                add_time = time.time()
+                create_dict = {
+                    'pc_name': pc_name,
+                    'bundle_version': bundle_version,
+                    'pc_version': pc_version,
+                    'pc_test': pc_test,
+                    'lang': lang,
+                    'download_link': file_path,
+                    'add_time': add_time,
+                    'update_time': add_time
+                }
+                pc_Info = Pc_Info(**create_dict)
+                pc_Info.save()
+            except Exception:
+                errorInfo = traceback.format_exc()
+                print(errorInfo)
+                return response.json(700, {'details': errorInfo})
+            else:
+                if pc_Info.id:
+                    res = {'pc_name': pc_Info.pc_name,
+                           'bundle_version': pc_Info.bundle_version,
+                           'pc_version': pc_Info.pc_version,
+                           'pc_test': pc_Info.pc_test,
+                           'download_link': pc_Info.download_link,
+                           'lang': pc_Info.lang,
+                           'add_time': pc_Info.add_time,
+                           'update_time': pc_Info.update_time
+                           }
+                    return response.json(0, res)
+                else:
+                    return response.json(500)
+
+
+    def download(self, request_dict, response):
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test])
+        if param_flag is not True:
+            return response.json(444)
+        path = Pc_Info.objects.filter(pc_name=pc_name, bundle_version=bundle_version, pc_version=pc_version,
+                                      pc_test=pc_test).values('download_link')
+        if not path:
+            return response.json(173)
+        filepath = path[0]['download_link']
+        fullPath = os.path.join(BASE_DIR, filepath)
+        fullPath.replace('\\', '/')
+        res = ResponseObject()
+        print('fullPath:')
+        print(fullPath)
+        print(os.path.basename(fullPath))
+        if fullPath:
+            if os.path.isfile(fullPath):
+                try:
+                    wrapper = FileWrapper(open(fullPath, 'rb'))
+                    response = HttpResponse(wrapper, content_type="application/octet-stream")
+                    response['Content-Length'] = os.path.getsize(fullPath)
+                    response['Content-Disposition'] = 'attachment; filename={}'.format(parse.quote_plus(os.path.basename(fullPath), encoding="utf-8"))
+                    response['Content-MD5'] = getMD5orSHA265(fullPath)
+                    # 校验文件md5值
+                    response['Content-SHA265'] = getMD5orSHA265(fullPath, 'SHA265')
+                    response['Content-CRC32'] = getMD5orSHA265(fullPath, 'CRC32')
+                    response['Content-Error'] = res.formal(0)
+                    return response
+                except Exception as e:
+                    return res.json(906, repr(e))
+            else:
+                return res.json(907)
+        else:
+            return res.json(444, 'fullPath')
+
+    def delete(self, request_dict, response):
+        token = request_dict.get('token', None)
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if not userID:
+            return response.json(104)
+        id = request_dict.get('id', None)
+        param_flag = CommonService.get_param_flag(data=[id])
+        if param_flag is not True:
+            return response.json(444)
+        file = Pc_Info.objects.filter(id=id)
+        if not file.exists():
+            return response.json(173)
+        try:
+            # 删除文件,文件夹和数据库里的相应数据
+            file_path = file[0].download_link
+            file_path = os.path.join(BASE_DIR, file_path).replace('\\', '/')
+            os.remove(file_path)
+            # file_path = file_path.split("/")
+            # file_path = [str(i) for i in file_path][:-1]
+            # file_path = "/".join(file_path)
+            # shutil.rmtree(file_path)
+            file.delete()
+        except Exception as e:
+            return response.json(176, repr(e))
+        else:
+            return response.json(0)
+
+def compareVersion(s1: str, s2: str) -> Union[str, int]:
+    i, j = 0, 0
+    while i < len(s1) or j < len(s2):
+        k1 = i
+        while k1 < len(s1) and s1[k1] != '.':
+            k1 += 1
+        k2 = j
+        while k2 < len(s2) and s2[k2] != '.':
+            k2 += 1
+
+        a = int(s1[i:k1]) if i != k1 else 0
+        b = int(s2[j:k2]) if j != k2 else 0
+        if a > b:
+            return s1
+        if a < b:
+            return s2
+        i = k1 + 1
+        j = k2 + 1
+    return 0
+
+def getMD5orSHA265(fileName, encryptionType='MD5'):
+    """
+
+    :param filePath:
+    :param encryptionType:
+    :return:
+    """
+    if not os.path.isfile(fileName):
+        return ''
+    else:
+        if encryptionType == 'MD5':
+            encryption = hashlib.md5()
+        elif encryptionType == 'SHA265':
+            encryption = hashlib.sha256()
+        elif encryptionType == 'CRC32':
+            f = open(fileName, 'rb')
+            chunk = f.read()
+            return crc32(chunk)
+
+        f = open(fileName, 'rb')
+        block_size = 8192  # why is 8192 | 8192 is fast than 2048
+
+        while True:
+            chunk = f.read(block_size)
+            if not chunk:
+                break
+            encryption.update(chunk)
+
+        f.close()
+        return encryption.hexdigest()
+

+ 360 - 0
Controller/PctestController.py

@@ -0,0 +1,360 @@
+import hashlib
+import logging
+import shutil
+import time
+import traceback
+import os
+from urllib import request, parse
+import requests
+from django.http import HttpResponse
+import jwt
+from django.views.generic.base import View
+
+from Model.models import PctestuserModel, PctestjobModel, PctestdeviceModel,\
+    PctestfunctionModel, PctestjobdeviceModel, PctestModel, PctestlogModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
+from Ansjer.config import OAUTH_ACCESS_TOKEN_SECRET
+
+
+class PcTest(View):
+    def dispatch(self, requset, *args, **kwargs):
+        return super(PcTest, self).dispatch(requset, *args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        operation = kwargs.get('operation')
+        request.encoding = 'utf-8'
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        operation = kwargs.get('operation')
+        request.encoding = 'utf-8'
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        response = ResponseObject()
+        if not operation:
+            return response.json(444, 'operation')
+        else:
+            if operation == 'login':
+                return self.login(request_dict, response)
+            else:
+                print(operation)
+                token = request_dict.get('token', None)
+                print('token:', token)
+                # 解析token,验证是否有id
+                tko = TokenObject1(token)
+                response.lang = tko.lang
+                if tko.code != 0:
+                    return response.json(tko.code)
+                # 获取访问者的id和岗位
+                userID = tko.id
+                jobID = tko.job
+                if jobID == 1:
+                    # 管理员可访问的接口
+                    if operation == 'job/add':
+                        return self.jobadd(request_dict, userID, response)
+                    elif operation == 'job/query':
+                        return self.jobquery(request_dict, userID, response)
+                    elif operation == 'device/add':
+                        return self.deviceadd(request_dict, userID, response)
+                    elif operation == 'device/query':
+                        return self.devicequery(request_dict, userID, response)
+                    elif operation == 'function/add':
+                        return self.functionadd(request_dict, userID, response)
+                    elif operation == 'function/query':
+                        return self.functionquery(request_dict, userID, response)
+                    elif operation == 'job/device/add':
+                        return self.jobdeviceadd(request_dict, userID, response)
+                    elif operation == 'job/device/query':
+                        return self.jobdevicequery(request_dict, jobID, response)
+                    elif operation == 'device/function/add':
+                        return self.devicefunctionadd(request_dict, userID, response)
+                    elif operation == 'device/function/query':
+                        return self.devicefunctionquery(request_dict, jobID, response)
+                    elif operation == 'staff/add':
+                        return self.staffadd(request_dict, userID, response)
+                    elif operation == 'staff/query':
+                        return self.staffquery(request_dict, userID, response)
+                    elif operation == 'staff/delete':
+                        return self.staffdelete(request_dict, userID, response)
+                    elif operation == 'log/query':
+                        return self.logquery(request_dict, userID, response)
+                    else:
+                        return response.json(404)
+                else:
+                    # 普通员工访问的接口
+                    if operation == 'job/device/query':
+                        return self.jobdevicequery(request_dict, jobID, response)
+                    elif operation == 'device/function/query':
+                        return self.devicefunctionquery(request_dict, jobID, response)
+                    elif operation == 'log/add':
+                        return self.logadd(request_dict, userID, response)
+                    elif operation == 'log/query':
+                        return self.logquery(request_dict, userID, response)
+                    else:
+                        return response.json(404)
+
+    def login(self, request_dict, response):
+        username = request_dict.get('username', None)
+        password = request_dict.get('password', None)
+        param_flag = CommonService.get_param_flag(
+            data=[username, password])
+        if param_flag is not True:
+            return response.json(444)
+        user_qs = PctestuserModel.objects.filter(username=username, password=password)
+        if not user_qs.exists():
+            return response.json(104)
+        users = user_qs.values('id', 'username', 'password', 'job')[0]
+        tko = TokenObject()
+        # 加密
+        res = tko.generate(
+            data={'id': users['id'], 'username': users['username'], 'password': users['password'], 'job': users['job']})
+        res_qs = {
+            'res': res,
+            'job': users['job']
+        }
+        return response.json(0, res_qs)
+
+    def jobadd(self, request_dict, userID, response):
+        jobname = request_dict.get('jobname', None)
+        param_flag = CommonService.get_param_flag(
+            data=[jobname])
+        if param_flag is not True:
+            return response.json(444)
+        job_qs = PctestjobModel.objects.filter(jobname=jobname)
+        if job_qs.exists():
+            return response.json(174)
+        else:
+            PctestjobModel.objects.create(jobname=jobname)
+            return response.json(0)
+
+    def jobquery(self, request_dict, userID, response):
+        job_list = PctestjobModel.objects.filter(id__gt=1)
+        count = job_list.count()
+        res = job_list
+        send_json = CommonService.qs_to_dict(res)
+        send_json['count'] = count
+        return response.json(0, send_json)
+
+    def deviceadd(self, request_dict, userID, response):
+        devicename = request_dict.get('devicename', None)
+        param_flag = CommonService.get_param_flag(
+            data=[devicename])
+        if param_flag is not True:
+            return response.json(444)
+        job_qs = PctestdeviceModel.objects.filter(devicename=devicename)
+        if job_qs.exists():
+            return response.json(174)
+        else:
+            PctestdeviceModel.objects.create(devicename=devicename)
+            return response.json(0)
+
+    def devicequery(self, request_dict, userID, response):
+        device_list = PctestdeviceModel.objects.all()
+        count = device_list.count()
+        res = device_list
+        send_json = CommonService.qs_to_dict(res)
+        send_json['count'] = count
+        return response.json(0, send_json)
+
+    def functionadd(self, request_dict, userID, response):
+        functionname = request_dict.get('functionname', None)
+        param_flag = CommonService.get_param_flag(
+            data=[functionname])
+        if param_flag is not True:
+            return response.json(444)
+        job_qs = PctestfunctionModel.objects.filter(functionname=functionname)
+        if job_qs.exists():
+            return response.json(174)
+        else:
+            PctestfunctionModel.objects.create(functionname=functionname)
+            return response.json(0)
+
+    def functionquery(self, request_dict, userID, response):
+        function_list = PctestfunctionModel.objects.all()
+        count = function_list.count()
+        res = function_list
+        send_json = CommonService.qs_to_dict(res)
+        send_json['count'] = count
+        return response.json(0, send_json)
+
+    def jobdeviceadd(self, request_dict, userID, response):
+        job_id = request_dict.get('job_id', None)
+        device_id = request_dict.get('device_id', None)
+        param_flag = CommonService.get_param_flag(
+            data=[job_id, device_id])
+        if param_flag is not True:
+            return response.json(444)
+        # 判断岗位与设备是否存在
+        job_list = PctestjobModel.objects.filter(id=job_id)
+        device_list = PctestdeviceModel.objects.filter(id=device_id)
+        if not job_list.exists() or not device_list.exists():
+            return response.json(173)
+        # 判断岗位与此设备是否有关联,避免重复添加
+        job_device_list = PctestjobdeviceModel.objects.filter(job_id=job_id, device_id=device_id)
+        if job_device_list.exists():
+            return response.json(174)
+        else:
+            PctestjobdeviceModel.objects.create(job_id=job_id, device_id=device_id)
+            return response.json(0)
+
+    def jobdevicequery(self, request_dict, jobID, response):
+        if jobID == 1:
+            job_device_list = PctestjobdeviceModel.objects.values('job__jobname', 'device__devicename')
+        else:
+            job_device_list = PctestjobdeviceModel.objects.filter(job_id=jobID).values('device_id','device__devicename')
+        device_list = []
+        for i in job_device_list:
+            device_list.append(i)
+        return response.json(0, device_list)
+
+    def devicefunctionadd(self, request_dict, userID, response):
+        device_id = request_dict.get('device_id', None)
+        function_id = request_dict.get('function_id', None)
+        param_flag = CommonService.get_param_flag(
+            data=[function_id, device_id])
+        if param_flag is not True:
+            return response.json(444)
+        # 判断设备与职能是否存在
+        device_list = PctestdeviceModel.objects.filter(id=device_id)
+        function_list = PctestfunctionModel.objects.filter(id=function_id)
+        if not function_list.exists() or not device_list.exists():
+            return response.json(173)
+        # 判断设备与此职能是否有关联,避免重复添加
+        device_function_list = PctestModel.objects.filter(device_id=device_id, function_id=function_id)
+        if device_function_list.exists():
+            return response.json(174)
+        else:
+            PctestModel.objects.create(device_id=device_id, function_id=function_id)
+            return response.json(0)
+
+    def devicefunctionquery(self, request_dict, jobID, response):
+        if jobID == 1:
+            device_function_list = PctestModel.objects.values('device__devicename', 'function__functionname')
+        else:
+            device_id = request_dict.get('device_id', None)
+            param_flag = CommonService.get_param_flag(
+                data=[device_id])
+            if param_flag is not True:
+                return response.json(444)
+            # 判断岗位与此设备是否有关联,有关联则通过
+            job_device_list = PctestjobdeviceModel.objects.filter(job_id=jobID, device_id=device_id)
+            if not job_device_list.exists():
+                return response.json(173)
+            device_function_list = PctestModel.objects.filter(device_id=device_id).values('function_id', 'function__functionname')
+        function_list = []
+        for i in device_function_list:
+            function_list.append(i)
+        return response.json(0, function_list)
+
+    def staffadd(self, request_dict, userID, response):
+        username = request_dict.get('username', None)
+        password = request_dict.get('password', None)
+        job_id = request_dict.get('job_id', None)
+        param_flag = CommonService.get_param_flag(
+            data=[username, password, job_id])
+        if param_flag is not True:
+            return response.json(444)
+        # 判断员工与岗位是否存在,员工存在返回174
+        user_list = PctestuserModel.objects.filter(username=username)
+        job_list = PctestjobModel.objects.filter(id=job_id)
+        if not job_list.exists() or user_list.exists():
+            return response.json(174)
+        else:
+            PctestuserModel.objects.create(username=username, password=password, job_id=job_id)
+            return response.json(0)
+
+    def staffquery(self, request_dict, userID, response):
+        user_list = PctestuserModel.objects.filter(id__gt=1).values('id', 'username', 'job__jobname')
+        users_list = []
+        for i in user_list:
+            users_list.append(i)
+        return response.json(0, users_list)
+
+    def staffdelete(self, request_dict, userID, response):
+        id = request_dict.get('id', None)
+        param_flag = CommonService.get_param_flag(data=[id])
+        if param_flag is not True:
+            return response.json(444)
+        staff = PctestuserModel.objects.filter(id=id)
+        if not staff.exists():
+            return response.json(173)
+        else:
+            staff.delete()
+            return response.json(0)
+
+    def logadd(self, request_dict, userID, response):
+        content = request_dict.get('content', None)
+        param_flag = CommonService.get_param_flag(data=[content])
+        if param_flag is not True:
+            return response.json(444)
+        addtime = time.time()
+        PctestlogModel.objects.create(user_id=userID, content=content, addtime=addtime)
+        return response.json(0)
+
+    def logquery(self, request_dict, userID, response):
+        if userID == 1:
+            job_device_list = PctestlogModel.objects.values('user__username', 'content', 'addtime')
+        else:
+            job_device_list = PctestlogModel.objects.filter(user_id=userID).values('content','addtime')
+        device_list = []
+        for i in job_device_list:
+            device_list.append(i)
+        return response.json(0, device_list)
+
+
+class TokenObject1:
+
+    def __init__(self, token=None):
+        if token == 'local':
+            token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySUQiOiIxNTg0MzUxODk2MjgyMTM4MDAxMzgwMDAiLCJsYW5nIjoiZW4iLCJ1c2VyIjoiMTM2ODAzMTc1OTYiLCJtX2NvZGUiOiIxMjM0MTMyNDMyMTQiLCJleHAiOjE1ODcyNzcwNjB9.c0LV_XyxwbzUlYqMJqx7vw9f19Jv-0kGnUHuu_go-mo'
+        if token == 'test':
+            token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiMTM4MDAxMzgwMDEiLCJleHAiOjE1Njk5OTg4OTYsInVzZXJJRCI6IjE1MTU2NDI2MjMzNzkzOTUxMzgwMDEzODAwMSIsImxhbmciOiJlbiIsIm1fY29kZSI6IjEyMzQxMzI0MzIxNCJ9.VAQtT9AbCCfXcrNj9DL5cvVasMDoI7AP8ptgU1GoMu8'
+        self.token = token
+        self.lang = None
+        self.id = None
+        self.job = None
+        self.user = ''
+        self.code = 0
+        # 令牌校验
+        self.valid()
+
+    def valid(self):
+        if self.token is None:
+            self.code = 309
+            return
+        try:
+            res = jwt.decode(self.token, OAUTH_ACCESS_TOKEN_SECRET, algorithms='HS256')
+            print('res:', res)
+            # print(res)
+            self.id = res.get('id', None)
+            self.lang = res.get('lang', None)
+            self.job = res.get('job', None)
+            self.user = res.get('user', '')
+            # 刷新登录时间
+            # if self.userID:
+            #     print(self.user)
+            #     redisObj = RedisObject(db=3)
+            #     redisObj.set_data(key=self.userID, val=self.user, expire=300)
+
+        except jwt.ExpiredSignatureError as e:
+            print('过期')
+            print(repr(e))
+            self.code = 309
+            return
+        except Exception as e:
+            self.code = 309
+            return
+        else:
+            if not self.id:
+                self.code = 309
+                return
+            else:
+                if self.id:
+                    self.code = 0
+                    return res
+                else:
+                    self.code = 309
+                    return

+ 201 - 202
Controller/SerialNumberController.py

@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
+import json
 import logging
 import random
 import time
@@ -7,15 +8,18 @@ import time
 from django.db import transaction
 from django.views import View
 
+from Controller.DetectController import DetectControllerView
 from Controller.DeviceConfirmRegion import Device_Region
 from Model.models import SerialNumberModel, CompanySerialModel, UIDCompanySerialModel, CompanyModel, RegionModel, \
-    CountryModel, UIDModel, Device_Info, iotdeviceInfoModel
+    CountryModel, UIDModel, Device_Info, iotdeviceInfoModel, UidPushModel, LogModel, MacModel
 from Object.RedisObject import RedisObject
 from Object.uidManageResponseObject import uidManageResponseObject
 from Object.TokenObject import TokenObject
 from Service.AlgorithmService import AlgorithmBaseOn35
 from Service.CommonService import CommonService
+from Ansjer.config import CRCKey
 from Service.ModelService import ModelService
+from Object.AWS.S3Email import S3Email
 
 
 class SerialNumberView(View):
@@ -38,12 +42,10 @@ class SerialNumberView(View):
 
         if operation == 'getUID':
             return self.do_get_uid(request_dict, response)
-        elif operation == 'getSerial':
-            return self.do_get_serial_number(request_dict, response)
         elif operation == 'attachUID':
             return self.do_attach_uid(request_dict, response, request)
         elif operation == 'detachUID':
-            return self.do_detach_uid(request_dict, response)
+            return self.do_detach_uid(request, request_dict, response)
         elif operation == 'create':
             return self.do_create(request_dict, response)
         else:
@@ -61,7 +63,6 @@ class SerialNumberView(View):
 
     def do_create(self, request_dict, response):
         quantity = int(request_dict.get('quantity', 0))
-        p2p = int(request_dict.get('p2p', 0))
 
         if not quantity:
             return response.json(444)
@@ -76,10 +77,10 @@ class SerialNumberView(View):
             algorithm = AlgorithmBaseOn35()
             for i in range(quantity):
                 serial_number = algorithm.getLetter(sum)
-                sum += 1    # sum每次递增1
+                sum += 1  # sum每次递增1
                 # 前面补0至六位
-                serial_number = (6-len(serial_number))*'0' + serial_number
-                serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time, p2p=p2p))
+                serial_number = (6 - len(serial_number)) * '0' + serial_number
+                serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time))
             # 开启事务写入
             with transaction.atomic():
                 SerialNumberModel.objects.bulk_create(serial_number_bulk)
@@ -88,59 +89,6 @@ class SerialNumberView(View):
             print(e)
             return response.json(500, repr(e))
 
-    # 提供给pc端获取序列号
-    def do_get_serial_number(self, request_dict, response):
-        quantity = request_dict.get('quantity', None)
-        company_id = request_dict.get('company_id', None)
-        token = request_dict.get('token', None)
-        time_stamp = request_dict.get('time_stamp', None)
-        p2p_type = request_dict.get('p2p_type', None)
-
-        if token and time_stamp and quantity and company_id:
-
-            token = int(CommonService.decode_data(token))
-            time_stamp = int(time_stamp)
-
-            now_time = int(time.time())
-            distance = now_time - time_stamp
-
-            if token != time_stamp or distance > 60000 or distance < -60000: #为了全球化时间控制在一天内
-                return response.json(404)
-
-            redisObject = RedisObject()
-            key = 'serial_lock'
-            value = redisObject.lpop(key)
-            count = 0
-            while value is False and count < 5:
-                time.sleep(1)
-                value = redisObject.lpop(key)
-                count += 1
-
-            if count == 5 and value is False:    #暂时注释
-                return response.json(5)
-
-            quantity = int(quantity)
-
-            company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_id, status=0, p2p=p2p_type)
-            if not company_serial_qs.exists():
-                redisObject.rpush(key, value)
-                return response.json(373)
-
-            # 存在对应的企业
-            company_serial_qs = company_serial_qs[0:quantity]
-
-            #company_serial_qs = company_serial_qs.values('id', 'serial_number__serial_number', 'company__mark')
-            data = []
-            ids = []
-            for serial in company_serial_qs:
-                ids.append(serial.id)
-                data.append(serial.serial_number + serial.company.mark)
-            CompanySerialModel.objects.filter(id__in=ids).update(status=1)
-            redisObject.rpush(key, value)
-            return response.json(0, data)
-        else:
-            return response.json(444)
-
     def do_list(self, userID, request_dict, response):
         # perm = ModelService.check_perm_uid_manage(userID, 0)
         # if not perm:
@@ -178,134 +126,165 @@ class SerialNumberView(View):
         else:
             return response.json(444)
 
-    @transaction.atomic
     def do_attach_uid(self, request_dict, response, request):
         serial_number = request_dict.get('serial_number', None)
         country_id = request_dict.get('country_id', None)
         company_id = request_dict.get('company_id', None)
         token = request_dict.get('token', None)
         time_stamp = request_dict.get('time_stamp', None)
+        DeviceSubType = request_dict.get('DeviceSubType', None)
+        p2ptype = request_dict.get('p2ptype', 1)
+        if not all([serial_number, company_id, token, time_stamp]):
+            return response.json(444)
 
-        if serial_number and len(serial_number) == 9  and company_id:
+        token = int(CommonService.decode_data(token))
+        time_stamp = int(time_stamp)
 
-            token = int(CommonService.decode_data(token))
-            time_stamp = int(time_stamp)
+        now_time = int(time.time())
+        distance = now_time - time_stamp
 
-            now_time = int(time.time())
-            distance = now_time - time_stamp
-
-            if token != time_stamp or distance > 60000 or distance < -60000: #为了全球化时间控制在一天内
-                return response.json(404)
+        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
+            return response.json(404)
 
-            mark = serial_number[6:9]
-            serial = serial_number[0:6]
+        serial = serial_number[0:6]
+        full_serial = serial_number[0:9]
 
-            savePoint = transaction.savepoint()
-            try:
-                try:
-                    if not country_id :
-                        ip = CommonService.get_ip_address(request)
-                        country_id = Device_Region().get_device_region(ip)
+        if serial_number[9:10]:
+            p2ptype = serial_number[9:10]
+        try:
+            if not country_id:
+                ip = CommonService.get_ip_address(request)
+                country_id = Device_Region().get_device_region(ip)
 
-                    # 判断序列号是否已和企业关联
-                    company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_id,
-                                                                          serial_number=serial)
-                    if not company_serial_qs.exists():
-                        return response.json(173)
+            # 判断序列号是否已和企业关联
+            company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_id, serial_number=serial)
+            if not company_serial_qs.exists():
+                return response.json(173)
 
-                    # 当序列号已关联UID
-                    company_serial = company_serial_qs[0]
+            # 当序列号已关联UID
+            company_serial = company_serial_qs[0]
 
-                    if company_serial.status == 0:
-                        # 该序列号未绑定企业
-                        return response.json(173)
-                    elif company_serial.status == 1:
-                        # 确定所在区域
-                        country_qs = CountryModel.objects.filter(number=country_id)
-                        if not country_qs.exists():
-                            return response.json(374)
-
-                        region = country_qs.values('region_id')[0]
-
-                        count = 0
-                        while count < 3:
-                            p2p = SerialNumberModel.objects.filter(serial_number=serial).values('p2p')
-                            print('此序列号的p2p类型:', p2p[0]['p2p'])
-                            uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id, vpg__region_id=region['region_id'],
-                                                             status=0, p2p_type=p2p[0]['p2p']).order_by('id')[0:10]
-                            # uid_qs:未进行绑定的uid列表
-                            if uid_qs.exists():
-                                uid = uid_qs[0]
-                                # uid.status = 2
-                                # uid.update_time = int(time.time())
-                                result = UIDModel.objects.filter(id=uid.id, status=0).update(**{
-                                    'status': 2, 'update_time': int(time.time())
-                                })
-
-                                if int(result) <= 0:
-                                    count += 1
-                                    continue
-
-                                now_time = int(time.time())
-                                uid_serial = UIDCompanySerialModel(uid_id=uid.id, company_serial_id=company_serial.id,
-                                                                   add_time=now_time, update_time=now_time)
-                                uid_serial.save()
-
-                                company_serial.status = 2
-                                company_serial.save()
-
-                                dev = Device_Info.objects.filter(UID=uid.uid)
-                                if dev.exists():
-                                    dev.update(serial_number=serial_number)
-
-                                res = {
-                                    'full_uid_code': CommonService.encode_data(uid.full_uid_code),
-                                    'uid': CommonService.encode_data(uid.uid),
-                                    'mac': CommonService.encode_data(uid.mac),
-                                    'extra': uid.uid_extra
-                                }
-                                return response.json(0, res)
-                            else:
-                                return response.json(375)
-
-                        return response.json(5)
-                    else:
-                        uid_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id)
-                        if uid_qs.exists():
-                            uid = uid_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__full_uid_code')[0]
-                            res = {
-                                'full_uid_code': CommonService.encode_data(uid['uid__full_uid_code']),
-                                'uid': CommonService.encode_data(uid['uid__uid']),
-                                'mac': CommonService.encode_data(uid['uid__mac']),
-                                'extra': uid['uid__uid_extra']
-                            }
-                            return response.json(0, res)
-                        else:
+            if company_serial.status == 0:  # 该序列号未绑定企业
+                return response.json(173)
+            elif company_serial.status == 1:    # 绑定uid
+                with transaction.atomic():
+                    count = 0
+                    while count < 3:
+                        # 查询是否存在未绑定序列号的uid
+                        uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id,
+                                                         vpg__region_id=country_id, status=0, p2p_type=p2ptype). \
+                                                         order_by('id')
+                        if not uid_qs.exists():
                             return response.json(173)
-                except Exception as e:
-                    # print('--------------------------error 5000')
-                    # print(repr(e))
-                    if savePoint:
-                        transaction.rollback(savePoint)
-                    djangoLogger = logging.getLogger('django')
-                    djangoLogger.exception(repr(e))
-                    return response.json(176, str(e))
-            except Exception as e:
-                # print('--------------------------error 5001')
-                # print(repr(e))
-                djangoLogger = logging.getLogger('django')
-                djangoLogger.exception(repr(e))
-                return response.json(176, str(e))
 
-        else:
-            return response.json(444)
+                        uid = uid_qs[0]
+
+                        if DeviceSubType:
+                            # 获取最新的mac,判断分配到哪里,且进行绑定
+                            mac = MacModel.objects.filter().values('id', 'value', 'is_active')[0]
+                            current_mac = mac['value']
+                            username = 'cspublic@ansjer.com'
+                            if current_mac[-8:] == '1F:42:40':  # 一组一共1048576个,此mac是第100w个时
+                                sys_msg_text = "当前国外uid管理系统mac地址已分配到" + current_mac + ",此mac地址是当前组的第100w个,还剩下48576个可分配,mac地址即将用完。"
+                                S3Email().faEmail(sys_msg_text, username)
+                            elif current_mac[-8:] == '1F:90:60':  # 此mac是第102w个时
+                                sys_msg_text = "当前国外uid管理系统mac地址已分配到" + current_mac + ",此mac地址是当前组的第102w个,还剩下28576个可分配,mac地址即将用完。"
+                                S3Email().faEmail(sys_msg_text, username)
+                            elif not mac['is_active']:
+                                return response.json(175)
+                            elif current_mac[-8:] == '1F:FF:FF':
+                                MacModel.objects.filter().update(is_active=False)  # 更改mac可使用的状态,当再此调用接口时使用上面条件进行阻止
+                                sys_msg_text = "当前国外uid管理系统mac地址已分配到" + current_mac + ",mac地址已分配使用完,请更换分组。"
+                                S3Email().faEmail(sys_msg_text, username)
+                                return response.json(175)
+                            UIDModel.objects.filter(id=uid.id).update(mac=current_mac)  # 更新绑定uid的mac值
+                            # 绑定mac地址成功后更新mac表
+                            temp_mac = CommonService.updateMac(current_mac)  # mac地址值+1;后3个字节为FF时返回None
+                            if temp_mac:
+                                current_mac = temp_mac  # 更新赋值写入uid表
+                            else:
+                                temp_mac = current_mac  # 赋值为FF写入mac表
+                            MacModel.objects.filter().update(value=temp_mac, add_time=now_time,
+                                                             update_time=now_time)  # 更新mac表的mac地址值
+
+                        result = UIDModel.objects.filter(id=uid.id, status=0).\
+                            update(status=2, update_time=now_time)
+
+                        if int(result) <= 0:    # 更新失败
+                            count += 1
+                            continue
+
+                        # UID关联【企业关联序列号】表创建数据
+                        UIDCompanySerialModel.objects.create(uid_id=uid.id, company_serial_id=company_serial.id,
+                                                             add_time=now_time, update_time=now_time)
+
+                        company_serial.status = 2
+                        company_serial.save()
+
+                        dev = Device_Info.objects.filter(UID=uid.uid)
+                        if dev.exists():
+                            dev.update(serial_number=full_serial)
+
+                        full_uid_code = uid.full_uid_code
+                        if uid.platform in CRCKey.keys():
+                            full_uid_code += ':'+CRCKey[uid.platform]
+
+                        res = {
+                            'full_uid_code': CommonService.encode_data(full_uid_code),
+                            'uid': CommonService.encode_data(uid.uid),
+                            'mac': CommonService.encode_data(uid.mac),
+                            'extra': uid.uid_extra,
+                            'platform': uid.platform,
+                            'initString': uid.init_string,
+                            'initStringApp': uid.init_string_app,
+                        }
+
+                        # 记录操作日志
+                        ip = CommonService.get_ip_address(request)
+                        content = json.loads(json.dumps(request_dict))
+                        log = {
+                            'ip': ip,
+                            'user_id': 1,
+                            'status': 200,
+                            'time': now_time,
+                            'content': json.dumps(content),
+                            'url': 'serialNumber/attachUID',
+                            'operation': '序列号{}绑定uid: {}'.format(serial, uid.uid),
+                        }
+                        LogModel.objects.create(**log)
+                        return response.json(0, res)
+
+                    return response.json(5)
+            else:   # 返回uid
+                uid_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id)
+                if not uid_qs.exists():
+                    return response.json(173)
+                uid = uid_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__full_uid_code',
+                                    'uid__platform', 'uid__init_string', 'uid__init_string_app')[0]
+                full_uid_code = uid['uid__full_uid_code']
+                if uid['uid__platform'] in CRCKey.keys():
+                    full_uid_code += ':'+CRCKey[uid['uid__platform']]
+                res = {
+                    'full_uid_code': CommonService.encode_data(full_uid_code),
+                    'uid': CommonService.encode_data(uid['uid__uid']),
+                    'mac': CommonService.encode_data(uid['uid__mac']),
+                    'extra': uid['uid__uid_extra'],
+                    'platform': uid['uid__platform'],
+                    'initString': uid['uid__init_string'],
+                    'initStringApp': uid['uid__init_string_app'],
+                }
+                return response.json(0, res)
+        except Exception as e:
+            djangoLogger = logging.getLogger('django')
+            djangoLogger.exception(repr(e))
+            return response.json(176, str(e))
 
     def do_get_uid(self, request_dict, response):
         serial_number = request_dict.get('serial_number', None)
         token = request_dict.get('token', None)
         time_stamp = request_dict.get('time_stamp', None)
 
-        if token and time_stamp and serial_number and len(serial_number) == 9:
+        if token and time_stamp and serial_number :
 
             token = int(CommonService.decode_data(token))
             time_stamp = int(time_stamp)
@@ -313,12 +292,13 @@ class SerialNumberView(View):
             now_time = int(time.time())
             distance = now_time - time_stamp
 
-            if token != time_stamp or distance > 60000 or distance < -60000:  #为了全球化时间控制在一天内
+            if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
                 return response.json(404)
 
             mark = serial_number[6:9]
             serial = serial_number[0:6]
-            uid_company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__company__mark=mark, company_serial__serial_number__serial_number=serial)
+            uid_company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__company__mark=mark,
+                                                                         company_serial__serial_number__serial_number=serial)
 
             if uid_company_serial_qs.exists():
                 uid = uid_company_serial_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra')[0]
@@ -328,60 +308,80 @@ class SerialNumberView(View):
                     'mac': CommonService.encode_data(uid['uid__mac']),
                     'extra': uid['uid__uid_extra']
                 }
-
                 return response.json(0, res)
             else:
                 return response.json(173)
         else:
             return response.json(444)
 
-    def do_detach_uid(self, request_dict, response):
-        serial_number = request_dict.get('serial_number', None)
+    def do_detach_uid(self, request, request_dict, response):
         token = request_dict.get('token', None)
         time_stamp = request_dict.get('time_stamp', None)
+        serial_number = request_dict.get('serial_number', None)
 
-        if token and time_stamp and serial_number:
-            token = int(CommonService.decode_data(token))
-            time_stamp = int(time_stamp)
-
-            now_time = int(time.time())
-            distance = now_time - time_stamp
+        if not all([token, time_stamp, serial_number]):
+            return response.json(444)
+        token = int(CommonService.decode_data(token))
+        time_stamp = int(time_stamp)
 
-            if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-                return response.json(404)
+        now_time = int(time.time())
+        distance = now_time - time_stamp
 
-            serial = serial_number[0:6]
+        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
+            return response.json(404)
 
-            uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial)
-            if uid_serial_qs.exists():
-                uid_serial = uid_serial_qs[0]
+        serial = serial_number[0:6]
+        uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial)
+        if not uid_serial_qs.exists():
+            return response.json(173)
+        uid_serial = uid_serial_qs[0]
 
-                #iot = iotdeviceInfoModel.objects.filter(serial_number__serial_number=serial)
-                iot = iotdeviceInfoModel.objects.filter(thing_name="Ansjer_Device_" + serial_number)
+        try:
+            with transaction.atomic():
+                # 删除iot设备信息表数据
+                iot = iotdeviceInfoModel.objects.filter(serial_number=serial)
                 if iot.exists():
                     iot.delete()
 
+                uid = uid_serial.uid.uid
                 company_serial_qs = CompanySerialModel.objects.filter(id=uid_serial.company_serial.id)
                 if company_serial_qs.exists():
                     company_serial = company_serial_qs[0]
                     company_serial.status = 1
                     company_serial.save()
+                    dv_qs = Device_Info.objects.filter(UID=uid)
+                    if dv_qs.exists():
+                        # 删除设备
+                        dv_qs.delete()
+                        # 删除设备影子信息uid_set   外键关联删除设备推送配置信息 uid_push
+                        up_qs = UidPushModel.objects.filter(uid_set__uid=uid)
+                        DetectControllerView().do_delete_redis(uid)
+                        if up_qs.count() > 1:
+                            UidPushModel.objects.filter(uid_set__uid=uid).delete()
+                        else:
+                            up_qs.delete()
 
-                uid_qs = UIDModel.objects.filter(uid=uid_serial.uid.uid)
-                if uid_qs.exists():
-                    uid = uid_qs[0]
-                    uid.status = 0
-                    uid.save()
+                UIDModel.objects.filter(uid=uid).update(status=0, mac='')    # 重置uid的使用状态为未分配
                 uid_serial.delete()
 
-                dev = Device_Info.objects.filter(serial_number=serial_number)
-                if dev.exists():
-                    dev.update(serial_number='')
-                return response.json(0)
-            else:
-                return response.json(173)
-        else:
-            return response.json(444)
+                # 记录操作日志
+                ip = CommonService.get_ip_address(request)
+                content = json.loads(json.dumps(request_dict))
+                log = {
+                    'ip': ip,
+                    'user_id': 1,
+                    'status': 200,
+                    'time': now_time,
+                    'content': json.dumps(content),
+                    'url': 'serialNumber/detachUID',
+                    'operation': '序列号{}解绑uid: {}'.format(serial, uid),
+                }
+                LogModel.objects.create(**log)
+            return response.json(0)
+        except Exception as e:
+            djangoLogger = logging.getLogger('django')
+            djangoLogger.exception(repr(e))
+            return response.json(176, str(e))
 
     def do_update(self, userID, request_dict, response):
         # perm = ModelService.check_perm_uid_manage(userID, 0)
@@ -390,14 +390,13 @@ class SerialNumberView(View):
 
         id = request_dict.get('id', None)
         status = request_dict.get('status', None)
-        p2p = request_dict.get('p2p', None)
 
         if id and status:
             serial_number_qs = SerialNumberModel.objects.filter(id=id)
             if serial_number_qs.exists():
-                serial_number_qs.update(**{'status': status, 'p2p': p2p})
+                serial_number_qs.update(**{'status': status})
                 return response.json(0)
             else:
                 return response.json(173)
         else:
-            return response.json(444)
+            return response.json(444)

+ 3 - 1
Controller/ShadowController.py

@@ -102,7 +102,7 @@ def update_device_shadow(request):
         is_human = request_dict.get('is_human', None)
         is_custom_voice = request_dict.get('is_custom', None)
         double_wifi = request_dict.get('double_wifi', None)
-
+        is_ptz = request_dict.get('is_ptz', None)
         us_qs = UidSetModel.objects.filter(uid=uid)
         # 更新
         nowTime = int(time.time())
@@ -138,6 +138,8 @@ def update_device_shadow(request):
             qs_dict['is_custom_voice'] = is_custom_voice
         if double_wifi:
             qs_dict['double_wifi'] = double_wifi
+        if double_wifi:
+            qs_dict['is_ptz'] = is_ptz
         if us_qs.exists():
             if is_alexa and us_qs[0].is_alexa == 0:
                 qs_dict['is_alexa'] = is_alexa

+ 62 - 47
Controller/TestApi.py

@@ -11,6 +11,7 @@
 @file: Test.py
 @Contact: chanjunkai@163.com
 """
+import botocore
 from django.views.generic.base import View
 import os
 
@@ -23,7 +24,6 @@ import time
 import urllib
 import datetime
 from Object.AliPayObject import AliPayObject
-import logging
 import boto3
 from boto3.session import Session
 from botocore.exceptions import ClientError
@@ -39,9 +39,10 @@ from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
+from Object.RedisObject import RedisObject
 from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
 from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, SERVER_DOMAIN, PAYPAL_CRD, \
-    SERVER_DOMAIN_SSL
+    SERVER_DOMAIN_SSL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
 from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, CompanySerialModel, SerialNumberModel, CompanyModel, VPGModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -75,6 +76,12 @@ class testView(View):
         operation = kwargs.get('operation')
         return self.validation(request.POST, request, operation)
 
+    def put(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        response = ResponseObject()
+        return response.json(0,request.body)
+
     def validation(self, request_dict, request, operation):
         response = ResponseObject()
         # operation => cloudVod/path
@@ -105,10 +112,10 @@ class testView(View):
             return self.generate_token(request_dict,userID)
         elif operation == 'test_upload_s3':
             userID = '158943604783713800138000'
-            return self.test_upload_s3(request_dict)
-        elif operation == 'test_request':
+            return self.test_upload_s3(request_dict, response)
+        elif operation == 'rekognition':
             userID = '158943604783713800138000'
-            return self.testRequest(request,request_dict)
+            return self.testRekognition(request,request_dict)
         elif operation == 'deleteDevice':
             return self.delete_device(response)
         else:
@@ -700,51 +707,59 @@ class testView(View):
         return JsonResponse(status=200, data=res,safe=False)
 
 
-    def test_upload_s3(self,request_dict):
-        res = CompanyModel.objects.filter(id=3).delete()
-        exit(res)
-
-        testd = hmac.new('AWS4rf/xnQ3jIgY8bj7Sz4An4KbYct2sq2MbrfmP8rVV'.encode("utf-8"), '20210223'.encode("utf-8"), hashlib.sha256).digest()
-        region_sign = hmac.new(testd, 'cn-northwest-1'.encode("utf-8"), hashlib.sha256).hexdigest()
-        exit(region_sign)
-        kService = sign(kRegion, 's3')
-        kSigning = sign(kService, 'aws4_request')
-
-        # exit(CommonService.getIpIpInfo("120.197.196.156",'CN'))
-        aws_key = "ASIA2MMWBR4DUPTFDTOJ" #【你的 aws_access_key】
-        aws_secret = "tTFZ9wpxFadeufhfaJ1erErv4U1bJ+TS/SJwTptx" #【你的 aws_access_key】
-        aws_session_token = "IQoJb3JpZ2luX2VjEJT//////////wEaDmNuLW5vcnRod2VzdC0xIkYwRAIgenLaMN6NdFji0x18OuaUTPvvtRBAWwjdEYdBTCMh0ywCIEzntAbgRPmwS+YFuNg+F31z60I4J1IoqmrQHR7wmPzVKtsCCML//////////wEQABoMNzEzODE2MTE2OTk5IgyJTmdtNJ319TtNORAqrwLPG6Px0z5CsEQpFt/TCbSSMRtYqBU+x5Ll9hZIuTvg8H+56H02/cr0nSCNiy05z7dSrSWMFoMhVKvHq7as5TRvVXkvMbbYPQuQxxPFr7EswaB+XITeDpdGBI6N7mqnt6h4YJbhk2dNRa2/4Ypr1DuyGnhVV6NxNHA5INtY7apLi3UTcNKwKSQRVzUWZBpoj86wG3j77KOZg18I9P8UWBpA9fpz/Wiv4xrzZSexrUnq5svTLEqMfTYCPBXkxrJBjNrwVjvkBkgeIfQZPz+A5X97p7wXbPf0Jo5aHHRDefbAmBuXYoSfpHjiFWindkcvCaMxQzUiHVLvnN/5SvgQEzN3pLUAAioepRZIZQLaky1aRmYYm1wOCjzgsg9V+GV6gKTE+ipFG/6Nv03Vh++Hv+YwyamJgQY6mgEmxhOhncek0PgQeExx2EXk73olY/6L15eDyHbSWoEKBMTmdlmpYD9Cj3qP4aUUW6UT6V5Tql/s5eBEsYwY+hzgtQiTmd7vjytXxae+dpN9VsWGW4AJ9P+/LgBe6zExUx2MOVst0+hb+dd8bg/qkz7UBYNQAmU+BEoL2Cd7lNXdrv56Gboapo+BosQO49GT8u1k5EheQ9JKHCqv"
-        session = Session(aws_access_key_id=aws_key,
-                          aws_secret_access_key=aws_secret,
-                          aws_session_token=aws_session_token,
-                          region_name="cn-northwest-1") # 此处根据自己的 s3 地区位置改变
-        s3 = session.resource("s3")
-        # client = session.client("s3")
-        bucket = "7cdk" # 【你 bucket 的名字】 # 首先需要保.证 s3 上已经存在该存储桶,否则报错
-        upload_data = open("./././static/log/test.log", "rb")
-        upload_key = "XKWZSC5FCJYT19B7111A/test/test6/test.log"
-        file_obj = s3.Bucket(bucket).put_object(Key=upload_key, Body=upload_data)
-        print('---------------------')
-        print(file_obj)
-        print(8/0)
-        exit()
-
-
-    def testRequest(self,request,request_dict):
-        ip = CommonService.get_ip_address(request)
-        ipInfo = CommonService.getIpIpInfo(ip,"CN")
-        # print(type(ipInfo))
-        # exit(ipInfo)
-        addr = CommonService.getAddr(ip)
-        dicts = {
-            'ipInfo':ipInfo,
-            'addr':addr,
-        }
-        return HttpResponse(json.dumps(dicts, ensure_ascii=False),
+    def test_upload_s3(self,request_dict , response):
+        aws_s3_guonei = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='cn-northwest-1'
+        )
+        download_link = 'ipctest'
+        response_url = aws_s3_guonei.generate_presigned_url(
+            ClientMethod='put_object',
+            Params={
+                'Bucket': 'pc-package',
+                'Key': download_link
+            },
+            ExpiresIn=3600
+        )
+        return response.json(0, {'datas': response_url, 'count': 1})
+
+
+    def testRekognition(self,request,request_dict):
+        # ip = CommonService.get_ip_address(request)
+        # ipInfo = CommonService.getIpIpInfo(ip,"CN")
+        # # print(type(ipInfo))
+        # # exit(ipInfo)
+        # addr = CommonService.getAddr(ip)
+        # dicts = {
+        #     'ipInfo':ipInfo,
+        #     'addr':addr,
+        # }
+        # return HttpResponse(json.dumps(dicts, ensure_ascii=False),
+        #                     content_type="application/json,charset=utf-8")
+        # client = boto3.client('s3', aws_access_key_id='AKIA2E67UIMD45Y3HL53',aws_secret_access_key='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',region_name='us-east-1')
+        # exit(request.FILES)
+
+
+        files = request.FILES.get('image')
+        labels = int(request_dict.get('labels',5))
+        minConfidence = int(request_dict.get('minConfidence',99))
+        if not files:
+            return HttpResponse('请上传图片!!!!')
+        client = boto3.client('rekognition', aws_access_key_id='AKIA2E67UIMD6JD6TN3J',aws_secret_access_key='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',region_name='us-east-1')
+        # image = open('E:/photo/a615fa40b8c476bab0f6eeb332e62a5a-1000.jpg', "rb")
+        response = client.detect_labels(Image={'Bytes':files.read()},MaxLabels=labels,MinConfidence=minConfidence)
+        # for obj in response['Labels']:
+        #     exit(obj)
+        #     if obj['Name'] == 'Person':
+        #         jsonstr = json.dumps(obj)
+        return HttpResponse(json.dumps(response, ensure_ascii=False),
                             content_type="application/json,charset=utf-8")
 
     def delete_device(self, response):
-        # 定时删除tech01@ansjer.com~tech10@ansjer.com账号下的设备
+        # 每两周删除一次tech01@ansjer.com~tech10@ansjer.com账号下的设备
         try:
             userID_list = ['tech01@ansjer.com', 'tech02@ansjer.com', 'tech03@ansjer.com',
                            'tech04@ansjer.com', 'tech05@ansjer.com', 'tech06@ansjer.com',

+ 16 - 0
Controller/UIDController.py

@@ -66,6 +66,8 @@ class UIDView(View):
             return self.do_history(token.userID, request_dict, response)
         elif operation == 'statistics':
             return self.do_admin_statistics(token.userID, request_dict, response)
+        elif operation == 'queryInitString':
+            return self.query_init_string(token.userID, request_dict, response)
         else:
             return response.json(309)
 
@@ -487,3 +489,17 @@ class UIDView(View):
 
         return response.json(0, res)
 
+    def query_init_string(self, userID, request_dict, response):
+        uid = request_dict.get('uid', None)
+        if not uid:
+            return response.json(444)
+        uid_qs = UIDModel.objects.filter(uid=uid).values('platform', 'init_string', 'init_string_app')
+        if not uid_qs.exists():
+            return response.json(173)
+        res = {
+            'platform': uid_qs[0]['platform'],
+            'initString': uid_qs[0]['init_string'],
+            'initStringApp': uid_qs[0]['init_string_app'],
+        }
+        return response.json(0, res)
+

+ 2 - 0
Controller/UidSetController.py

@@ -11,9 +11,11 @@
 @file: AliPayObject.py
 @Contact: pzb3076@163.com
 """
+import threading
 import time
 import traceback
 
+import requests
 from django.db.models import Count
 
 from Object.RedisObject import RedisObject

+ 3 - 1
Controller/UidUser.py

@@ -61,7 +61,9 @@ def addInterface(request):
         if tko.code == 0:
             userID = tko.userID
             re_uid = re.compile(r'^[A-Za-z0-9]{20}$')
-            if re_uid.match(UID):
+            sy_uid = re.compile(r'^[A-Za-z0-9]{14}$')
+            sy_uid23 = re.compile(r'^[A-Za-z0-9]{23}$')
+            if re_uid.match(UID) or sy_uid.match(UID) or sy_uid23.match(UID):
                 is_ap = int(is_ap)
                 is_exist = UidUserModel.objects.filter(UID=UID, userID_id=userID, is_ap=is_ap)
                 if is_exist:

+ 42 - 28
Controller/UserController.py

@@ -32,7 +32,7 @@ from ratelimit.decorators import ratelimit
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
-    UserAppFrequencyModel, CountryIPModel, CountryModel
+    UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
@@ -789,8 +789,8 @@ class v2authCodeView(TemplateView):
             msg = res["Message"]
             if code == "isv.MOBILE_NUMBER_ILLEGAL":
                 if response.lang == "cn":
-                    msg = phone + "非法手机"
-            return response.json(10, msg)
+                    msg = phone+"非法手机"
+            return response.json(10,msg)
 
     def phoneCodeV2(self, country_code, phone, response, sign_name):
         dataValid = DataValid()
@@ -2744,32 +2744,46 @@ class alexaUidView(TemplateView):
         if not uid_qs.exists():
             return response.json(107)
 
-        uid_dict = {}
-        uid_list = []
-        for uid_q in uid_qs:
-            # 追加
-            uid_list.append(uid_q['UID'])
-            # 给uid_q['UID']赋值
-            uid_dict[uid_q['UID']] = {'nick': uid_q['NickName'], 'password': uid_q['View_Password']}
-
-        us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=1).values('uid', 'region_alexa')
-        if not us_qs.exists():
-            return response.json(173)
-        # uid,password,region的列表
-        uid_arr = []
-        for us in us_qs:
-            uid = us['uid']
-            # 设备alexa区域
-            region_alexa = us['region_alexa']
-            if region_alexa == '':
-                region_alexa = 'EN'
-            uid_arr.append({'uid': uid, 'nick': uid_dict[uid]['nick'], 'password': uid_dict[uid]['password'],
-                            'region': region_alexa})
-        res = {
-            'uid_arr': uid_arr
-        }
-        return response.json(0, res)
+        try:
+            uid_dict = {}
+            uid_list = []
+            for uid_q in uid_qs:
+                # 追加
+                uid_list.append(uid_q['UID'])
+                # 给uid_q['UID']赋值
+                uid_dict[uid_q['UID']] = {'nick': uid_q['NickName'], 'password': uid_q['View_Password']}
 
+            us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=1).values('id', 'uid', 'region_alexa', 'channel')
+            if not us_qs.exists():
+                return response.json(173)
+            # uid,password,region的列表
+            uid_arr = []
+            for us in us_qs:
+                uid = us['uid']
+                channel = us['channel']
+                # 设备alexa区域
+                region_alexa = us['region_alexa']
+                if region_alexa == '':
+                    region_alexa = 'EN'
+
+                # 多通道设备获取通道名
+                if channel > 1:
+                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us['id']).values('channel', 'channel_name')
+                    if uid_channel_set_qs.exists():
+                        # DVR设备名为 UidChannelSetModel 的 channel_name
+                        for uid_channel_set in uid_channel_set_qs:
+                            uid_arr.append({'uid': uid, 'nick': uid_channel_set['channel_name'], 'region': region_alexa,
+                                            'password': uid_dict[uid]['password'], 'multi_channel': 1,
+                                            'channel': uid_channel_set['channel']})
+                else:
+                    uid_arr.append({'uid': uid, 'nick': uid_dict[uid]['nick'], 'region': region_alexa,
+                                    'password': uid_dict[uid]['password'], 'multi_channel': 0})
+            res = {
+                'uid_arr': uid_arr
+            }
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
 
 # 登出
 class V2LogoutView(TemplateView):

+ 40 - 15
Controller/VPGController.py

@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
+import json
 import os
 import re
 import time
@@ -9,7 +10,7 @@ from django.views import View
 from django.views.decorators.csrf import csrf_exempt
 
 from Ansjer.config import BASE_DIR
-from Model.models import RegionModel, CompanyModel, VPGModel, UIDModel, MacModel, UIDCompanySerialModel
+from Model.models import RegionModel, CompanyModel, VPGModel, UIDModel, MacModel, UIDCompanySerialModel, LogModel
 from Object.uidManageResponseObject import uidManageResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -181,7 +182,7 @@ class VPGView(View):
 
         start = (page - 1) * line
         end = start + line
-        uid_qs = UIDModel.objects.filter(vpg_id=vpg_id).values('uid')
+        uid_qs = UIDModel.objects.filter(vpg_id=vpg_id).values('uid', 'platform', 'init_string', 'init_string_app')
 
         count = VPGModel.objects.get(id=vpg_id).uid_count   # 从vpg表获取uid总数
         uid_qs = uid_qs[start:end]  # 显示条数
@@ -209,14 +210,21 @@ def do_upload_uid(request):
         return response.json(444)
     file = request.FILES.get('file', None)
     vpg_id = request_dict.get('vpg_id', None)
+    platform = request_dict.get('platform', None)
+    init_string = request_dict.get('init_string', None)
+    init_string_app = request_dict.get('init_string_app', None)
+
+    if not all([vpg_id, platform, init_string, init_string_app]):
+        return response.json(444)
 
     bulk = []
     add_time = update_time = int(time.time())
-    MAC = MacModel.objects.filter().values('id', 'value', 'is_active')[0]   # 获取最新可用的mac
-    current_mac = MAC['value']
-    if (not MAC['is_active']) or (current_mac[-8:] == 'FF.FF.FF'):
-        return response.json(175)
+    # MAC = MacModel.objects.filter().values('id', 'value', 'is_active')[0]   # 获取最新可用的mac
+    # current_mac = MAC['value']
+    # if (not MAC['is_active']) or (current_mac[-8:] == 'FF.FF.FF'):
+    #     return response.json(175)
 
+    area = 1 if vpg_id != '1' else 0
     # path = '/'.join((BASE_DIR, 'static/uid')).replace('\\', '/') + '/'
     # if not os.path.exists(path):
     #     os.makedirs(path)
@@ -232,13 +240,16 @@ def do_upload_uid(request):
             uid_list = re.findall("b\'(.*)\'", str(chunk))[0].split('\\r\\n')
             for uid in uid_list:
                 UID = UIDModel(
-                    mac=current_mac,
+                    mac='',
                     uid_extra='',
                     status=0,
                     add_time=add_time,
                     update_time=update_time,
-                    area=0,  # 关联vgp表已有区域信息,可以考虑去掉
+                    area=area,  # 关联vgp表已有区域信息,可以考虑去掉
                     vpg_id=vpg_id,
+                    platform=platform,
+                    init_string=init_string,
+                    init_string_app=init_string_app
                 )
                 if len(uid) == 14:  # 宸云
                     UID.p2p_type = 1
@@ -253,17 +264,31 @@ def do_upload_uid(request):
                     UID.uid = new_uid
                     UID.full_uid_code = uid
                 bulk.append(UID)
-                temp_mac = CommonService.updateMac(current_mac)    # mac地址值+1;后3个字节为FF时返回None
-                if temp_mac:
-                    current_mac = temp_mac  # 更新赋值写入uid表
-                else:
-                    temp_mac = current_mac  # 赋值为FF写入mac表
-                    break
+                # temp_mac = CommonService.updateMac(current_mac)    # mac地址值+1;后3个字节为FF时返回None
+                # if temp_mac:
+                #     current_mac = temp_mac  # 更新赋值写入uid表
+                # else:
+                #     temp_mac = current_mac  # 赋值为FF写入mac表
+                #     break
+
+        ip = CommonService.get_ip_address(request)
+        content = json.loads(json.dumps(request_dict))
+        log = {
+            'ip': ip,
+            'user_id': 1,
+            'status': 200,
+            'time': add_time,
+            'url': 'vpgUid/uid',
+            'content': json.dumps(content),
+            'operation': '上传{}个uid到VPG ID {}'.format(len(uid_list), vpg_id),
+        }
+        
         with transaction.atomic():
+            LogModel.objects.create(**log)  # 记录操作日志
             UIDModel.objects.bulk_create(bulk)  # 批量写入uid数据
             uid_count = UIDModel.objects.filter(vpg_id=vpg_id).count()  # 获取族群下uid的数量
             VPGModel.objects.filter(id=vpg_id).update(uid_count=uid_count)   # 更新vgp表的uid_count
-            MacModel.objects.filter().update(value=temp_mac)  # 更新mac表的mac地址值
+            # MacModel.objects.filter().update(value=temp_mac)  # 更新mac表的mac地址值
         return response.json(0)
     except Exception as e:
         print(e)

+ 22 - 15
Controller/VoicePromptController.py

@@ -139,24 +139,31 @@ class VoicePromptView(View):
 
     def do_delete(self, userID, request_dict, response):
         id = request_dict.get('id', None)
+        ids = request_dict.get('ids', None)
         if id:
             voice_qs = VoicePromptModel.objects.filter(id=id)
-            if voice_qs.exists():
-                uid = voice_qs[0].uid
-                device_qs = Device_Info.objects.filter(UID=uid, userID=userID)
-                if device_qs.exists():
-                    channel = voice_qs[0].channel
-                    filename = voice_qs[0].filename
-                    voice_qs.delete()
-                    auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
-                    bucket = oss2.Bucket(auth, 'http://oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
-                    obj = 'voice_prompt/{uid}/{channel}/'.format(uid=uid, channel=channel) + filename
-                    bucket.delete_object(obj)
-                    return response.json(0)
-                else:
-                    return response.json(404)
+        elif ids:
+            voice_qs = VoicePromptModel.objects.filter(id__in=ids.split(','))
+
+
+        if not voice_qs.exists():
+            return response.json(14)
+
+        for voice in voice_qs:
+            uid = voice.uid
+            device_qs = Device_Info.objects.filter(UID=uid, userID=userID)
+            if device_qs.exists():
+                channel = voice.channel
+                filename = voice.filename
+                voice_qs.delete()
+                auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+                bucket = oss2.Bucket(auth, 'http://oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
+                obj = 'voice_prompt/{uid}/{channel}/'.format(uid=uid, channel=channel) + filename
+                bucket.delete_object(obj)
+                return response.json(0)
             else:
-                return response.json(173)
+                return response.json(404)
+
         else:
             return response.json(444)
 

+ 27 - 0
CrontabTask/formal_statistics_push_day_task.py

@@ -0,0 +1,27 @@
+import json
+
+import requests
+
+
+base_url = 'http://dvema.com'
+username='13800138001'
+password='ansjer123456'
+
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushDay'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 27 - 0
CrontabTask/formal_statistics_push_month_task.py

@@ -0,0 +1,27 @@
+import json
+
+import requests
+
+
+# url = 'http://test.dvema.com'
+base_url = 'http://dvema.com/'
+username='13800138001'
+password='ansjer123456'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushMonth'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 49 - 0
CrontabTask/formal_zositech_help_weekly_task.py

@@ -0,0 +1,49 @@
+import json
+
+import requests
+import time
+
+
+# url = 'http://test.dvema.com'
+# base_url = 'http://127.0.0.1:8000/'
+base_url = 'http://dvema.com/'
+username='13800138001'
+password='ansjer.x123789'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+
+if res['result_code'] == 0:
+    request_times = 0
+    while request_times < 5:
+        try:
+            statistics_url = base_url + 'faq/synZositechHelp'
+            # zh_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/articles/embeddable_search.json?locale=zh-cn&section=null&origin=web_widget'
+            zh_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/zh-cn/articles.json?page%5Bsize%5D=100'
+            zhcnDatares = requests.get(url=zh_url, timeout=10).text
+
+            en_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/en-us/articles.json?page%5Bsize%5D=100'
+            # en_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/articles/embeddable_search.json?locale=en-us&section=null&origin=web_widget'
+            enusDatares = requests.get(url=en_url, timeout=10).text
+            data = {
+                'token': res['result']['access_token'],
+                'zhresults': zhcnDatares,
+                'enresults': enusDatares
+            }
+            res = requests.post(url=statistics_url, data=data)
+
+        except Exception as e:
+            print(e)
+            request_times += 1
+            print(request_times)
+            time.sleep(3)
+
+print('success')
+
+
+

+ 31 - 0
CrontabTask/test_statistics_push_day_task.py

@@ -0,0 +1,31 @@
+import json
+
+import requests
+from Ansjer.config import SERVER_TYPE
+
+base_url = ''
+if SERVER_TYPE == "Ansjer.us_config.test_settings":
+    base_url = 'http://test.dvema.com/'
+elif SERVER_TYPE == "Ansjer.cn_config.test_settings":
+    base_url = 'http://http://test.zositechc.cn/'
+
+username='13800138001'
+password='ansjer999999'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushDay'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 31 - 0
CrontabTask/test_statistics_push_month_task.py

@@ -0,0 +1,31 @@
+import json
+
+import requests
+from Ansjer.config import SERVER_TYPE
+
+base_url = ''
+if SERVER_TYPE == "Ansjer.us_config.test_settings":
+    base_url = 'http://test.dvema.com/'
+elif SERVER_TYPE == "Ansjer.cn_config.test_settings":
+    base_url = 'http://http://test.zositechc.cn/'
+
+username='13800138001'
+password='ansjer999999'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushMonth'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 52 - 0
CrontabTask/test_zositech_help_weekly_task.py

@@ -0,0 +1,52 @@
+import json
+
+import requests
+import time
+from Ansjer.config import SERVER_TYPE
+
+base_url = ''
+if SERVER_TYPE == "Ansjer.us_config.test_settings":
+    base_url = 'http://test.dvema.com/'
+elif SERVER_TYPE == "Ansjer.cn_config.test_settings":
+    base_url = 'http://http://test.zositechc.cn/'
+
+# base_url = 'http://127.0.0.1:8000/'
+username='13800138001'
+password='ansjer999999'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data, timeout=10)
+res = res.json()
+
+if res['result_code'] == 0:
+    request_times = 0
+    while request_times < 5:
+        try:
+            statistics_url = base_url + 'faq/synZositechHelp'
+            # zh_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/articles/embeddable_search.json?locale=zh-cn&section=null&origin=web_widget'
+            zh_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/zh-cn/articles.json?page%5Bsize%5D=100'
+            zhcnDatares = requests.get(url=zh_url, timeout=10).text
+
+            en_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/en-us/articles.json?page%5Bsize%5D=100'
+            # en_url = 'https://mobileapphelp.zendesk.com/api/v2/help_center/articles/embeddable_search.json?locale=en-us&section=null&origin=web_widget'
+            enusDatares = requests.get(url=en_url, timeout=10).text
+            data = {
+                'token': res['result']['access_token'],
+                'zhresults': zhcnDatares,
+                'enresults': enusDatares
+            }
+            res = requests.post(url=statistics_url, data=data)
+
+        except Exception as e:
+            print(e)
+            request_times += 1
+            print(request_times)
+            time.sleep(3)
+
+print('success')
+
+

+ 128 - 5
Model/models.py

@@ -776,7 +776,7 @@ class UidSetModel(models.Model):
     is_human = models.IntegerField(default=0, verbose_name='是否支持人形追踪。0:不支持,1:支持')
     is_custom_voice = models.IntegerField(default=0, verbose_name='是否支持自定义语音。0:不支持,1:支持')
     double_wifi = models.IntegerField(default=0, verbose_name='是否支持双频wifi。0:不支持,1:支持')
-
+    is_ptz = models.IntegerField(default=0, verbose_name='是否支持云台。0:不支持,1:支持')
     class Meta:
         db_table = 'uid_set'
         verbose_name = u'设备配置表'
@@ -1341,7 +1341,7 @@ class VPGModel(models.Model):
 class UIDModel(models.Model):
     id = models.AutoField(primary_key=True)
     uid = models.CharField(max_length=20, null=False, db_index=True, unique=True, verbose_name='设备id')
-    mac = models.CharField(max_length=17, null=False, default='', unique=True, verbose_name='设备id对应的mac地址')
+    mac = models.CharField(max_length=17, null=True, default='', verbose_name='设备id对应的mac地址')
     uid_extra = models.TextField(default='', verbose_name='uid的额外描述')
     status = models.SmallIntegerField(default=0, verbose_name='使用状态')   # 0:未分配,1:已分配,2:已使用
     add_time = models.IntegerField(default=0, verbose_name='添加时间')
@@ -1350,6 +1350,9 @@ class UIDModel(models.Model):
     vpg = models.ForeignKey(VPGModel, to_field='id', default=1, on_delete=models.DO_NOTHING, verbose_name='关联VPG表的id')
     p2p_type = models.IntegerField(default=1, verbose_name='p2p类型。1:宸云,2:tutk')
     full_uid_code = models.CharField(max_length=256, default='', verbose_name='宸云完整uid')
+    platform = models.CharField(max_length=10, default='', verbose_name='平台')
+    init_string = models.CharField(max_length=256, default='', verbose_name='尚云设备初始化字符')
+    init_string_app = models.CharField(max_length=256, default='', verbose_name='尚云设备app初始化字符')
 
     class Meta:
         ordering = ('-add_time',)
@@ -1503,7 +1506,6 @@ class SerialNumberModel(models.Model):
     serial_number = models.CharField(max_length=9, db_index=True, unique=True, verbose_name='序列号')
     status = models.SmallIntegerField(default=1, verbose_name='可用状态。0:不可用,1:可用')
     use_status = models.SmallIntegerField(default=0, db_index=True, verbose_name='使用状态, 0: 未使用, 1: 已分配')
-    p2p = models.SmallIntegerField(default=0, db_index=True, verbose_name='p2p类型。0:无,1:宸云,2:tutk')
     add_time = models.IntegerField(default=0, verbose_name='添加时间')
 
     class Meta:
@@ -1517,7 +1519,6 @@ class CompanySerialModel(models.Model):
     company = models.ForeignKey(CompanyModel, to_field='id', on_delete=models.CASCADE, verbose_name='关联企业表的id')
     serial_number = models.CharField(max_length=11, db_index=True, blank=True, default='', verbose_name=u'6位数序列号')
     status = models.SmallIntegerField(default=0, verbose_name='序列号的状态。0:未使用,1:已使用,2:已和UID关联')
-    p2p = models.SmallIntegerField(default=0, verbose_name='p2p类型。0:无,1:宸云,2:tutk')
     add_time = models.IntegerField(default=0, verbose_name='添加时间')
     update_time = models.IntegerField(default=0, verbose_name='更新时间')
 
@@ -1568,6 +1569,29 @@ class UIDMainUser(models.Model):
         verbose_name_plural = verbose_name
 
 
+class Pc_Info(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    pc_name = models.CharField(blank=True, max_length=32, verbose_name=u'软件名称')
+    bundle_version = models.IntegerField(default=0, verbose_name=u'项目类型。0:Zosi;149:COCOON HD; 150:Loocam; 151:中性')
+    pc_version = models.CharField(blank=True, max_length=12, verbose_name=u'版本号')
+    pc_test = models.SmallIntegerField(default=0, verbose_name='测试版。0:否,1:是')
+    lang = models.CharField(blank=True, max_length=32, verbose_name=u'语言类型')
+    download_link = models.CharField(max_length=300, blank=True, default='', verbose_name='下载链接')
+    add_time = models.IntegerField(verbose_name='添加时间', default=0)
+    update_time = models.IntegerField(verbose_name='更新时间', default=0)
+    file_type = models.CharField(blank=True, max_length=32, verbose_name=u'文件类型')
+    package = models.CharField(blank=True, max_length=32, verbose_name=u'整合包id')
+    explain = models.TextField(blank=True, default='', verbose_name=u'更新内容')
+    is_update = models.SmallIntegerField(blank=True, default=0, verbose_name='强制更新。0:否,1:是')
+    is_open = models.SmallIntegerField(blank=True, default=0, verbose_name='是否开启版本。0:否,1:是')
+
+    class Meta:
+        db_table = 'pc_info'
+        verbose_name = u'pc信息表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
 class CloudLogModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
     user = models.CharField(max_length=100, default='', db_index=True, blank=True, verbose_name=u'用户')
@@ -1580,4 +1604,103 @@ class CloudLogModel(models.Model):
     class Meta:
         db_table = 'cloud_log'
         verbose_name = '云存api记录表'
-        verbose_name_plural = verbose_name
+        verbose_name_plural = verbose_name
+
+
+class PctestjobModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    jobname = models.CharField(blank=True, max_length=32, verbose_name=u'岗位名字')
+
+    class Meta:
+        db_table = 'pctest_job'
+        verbose_name = u'pc岗位表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class PctestdeviceModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    devicename = models.CharField(blank=True, max_length=32, verbose_name=u'设备名字')
+
+    class Meta:
+        db_table = 'pctest_device'
+        verbose_name = u'pc测试设备表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class PctestfunctionModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    functionname = models.CharField(blank=True, max_length=32, verbose_name=u'职能名字')
+
+    class Meta:
+        db_table = 'pctest_function'
+        verbose_name = u'pc设备职能表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class PctestuserModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    username = models.CharField(blank=True, max_length=32, verbose_name=u'用户名字')
+    password = models.CharField(blank=True, max_length=32, verbose_name=u'用户名字')
+    job = models.ForeignKey(PctestjobModel, to_field='id', on_delete=models.DO_NOTHING, verbose_name='关联pc岗位表')
+
+    class Meta:
+        db_table = 'pctest_user'
+        verbose_name = u'pc角色岗位表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class PctestlogModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    user = models.ForeignKey(PctestuserModel, to_field='id', on_delete=models.DO_NOTHING, verbose_name='关联pc岗位表')
+    content = models.TextField(blank=True, default='', verbose_name=u'测试日志')
+    addtime = models.IntegerField(verbose_name='添加时间', default=0)
+
+    class Meta:
+        db_table = 'pctest_log'
+        verbose_name = u'pc测试日志表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class PctestjobdeviceModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    job = models.ForeignKey(PctestjobModel, to_field='id', on_delete=models.DO_NOTHING, verbose_name='关联pc岗位表')
+    device = models.ForeignKey(PctestdeviceModel, to_field='id', on_delete=models.DO_NOTHING, verbose_name='关联pc测试设备表')
+
+    class Meta:
+        db_table = 'pctest_job_device'
+        verbose_name = u'pc岗位设备关联表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class PctestModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    device = models.ForeignKey(PctestdeviceModel, to_field='id', on_delete=models.DO_NOTHING, verbose_name='关联pc测试设备表')
+    function = models.ForeignKey(PctestfunctionModel, to_field='id', on_delete=models.DO_NOTHING, verbose_name='关联pc设备职能表')
+
+    class Meta:
+        db_table = 'pctest_device_function'
+        verbose_name = u'pc岗位设备关联表'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+class P2PIpModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    uid = models.CharField(max_length=20, default='', unique=True, verbose_name='设备uid')
+    ip = models.CharField(default='', max_length=32, verbose_name='ip')
+    country_name = models.CharField(default='', max_length=100, verbose_name='国家')
+    region_name = models.CharField(default='', max_length=100, verbose_name='地区')
+    city_name = models.CharField(default='', max_length=100, verbose_name='城市')
+    add_time = models.IntegerField(default=0, verbose_name='添加时间')
+
+    class Meta:
+        db_table = 'p2p_ip'
+        verbose_name = u'设备p2p_ip地区表'
+        verbose_name_plural = verbose_name
+

+ 15 - 20
Object/AWS/S3Email.py

@@ -5,21 +5,16 @@ from email.mime.text import MIMEText
 
 class S3Email:
 
-   def __init__(self, *args, **kwargs):
-       SENDER = 'rdpublic@ansjer.com'  # 邮箱名
-       SENDERNAME = 'rdpublic@ansjer.com'
-       USERNAME_SMTP = "AKIA2E67UIMD6MOSFKXW"  # 带有邮件权限的 IAM 帐号
-       PASSWORD_SMTP = "BHuQ6EQTtFK4qh46o9omO9ZzO3NXzjk/JCWLXnVFmqzM"  # 带有邮件权限的 IAM 密码
-       PORT = 587
-       HOST = "email-smtp.us-east-1.amazonaws.com"
 
-
-   def faEmail(self, content ,RECIPIENT):
-
-        SUBJECT = 'Amazon SES Error (Python smtplib)'
-        BODY_TEXT = ("Amazon SES Test\r\n"
-                     "This email was sent through the Amazon SES SMTP "
-                     "Interface using the Python smtplib package."
+   def faEmail(self, sys_msg_text ,username):
+        SENDER = 'rdpublic@ansjer.com'  # 邮箱名
+        SENDERNAME = 'rdpublic@ansjer.com'
+        USERNAME_SMTP = 'AKIA2E67UIMD6MOSFKXW'  # 带有邮件权限的 IAM 帐号
+        PASSWORD_SMTP = 'BHuQ6EQTtFK4qh46o9omO9ZzO3NXzjk/JCWLXnVFmqzM'  # 带有邮件权限的 IAM 密码
+        PORT = '587'
+        HOST = 'email-smtp.us-east-1.amazonaws.com'
+        SUBJECT = sys_msg_text
+        BODY_TEXT = (sys_msg_text
                      )
         BODY_HTML = """<html>
         <head></head>
@@ -27,24 +22,24 @@ class S3Email:
           <h1>{}<h1>
         </body>
         </html>
-                    """.format(content)
+                    """.format(sys_msg_text)
 
         msg = MIMEMultipart('alternative')
         msg['Subject'] = SUBJECT
-        msg['From'] = email.utils.formataddr((self.SENDERNAME, self.SENDER))
-        msg['To'] = RECIPIENT
+        msg['From'] = email.utils.formataddr((SENDERNAME, SENDER))
+        msg['To'] = username
         part1 = MIMEText(BODY_TEXT, 'plain')
         part2 = MIMEText(BODY_HTML, 'html')
         msg.attach(part1)
         msg.attach(part2)
 
         try:
-            server = smtplib.SMTP(self.HOST, self.PORT)
+            server = smtplib.SMTP(HOST, PORT)
             server.ehlo()
             server.starttls()
             server.ehlo()
-            server.login(self.USERNAME_SMTP, self.PASSWORD_SMTP)
-            server.sendmail(self.SENDER, RECIPIENT, msg.as_string())
+            server.login(USERNAME_SMTP, PASSWORD_SMTP)
+            server.sendmail(SENDER, username, msg.as_string())
             server.close()
         except Exception as e:
             print("Error: ", e)

+ 4 - 2
Object/ResponseObject.py

@@ -96,8 +96,9 @@ class ResponseObject(object):
             10040: 'Invalid activation code',
             10041: 'This device has purchased a domestic cloud storage package, and cannot purchase a foreign cloud storage package',
             10042: 'The device has registered a certificate',
-            10043: 'The device does not have a serial number',
+            10043: 'The device does not registered a certificate',
             10044: 'Request to publish MQTT topic message failed',
+            10045: 'Already the latest version',
         }
         data_cn = {
             0: '成功',
@@ -188,8 +189,9 @@ class ResponseObject(object):
             10040: '无效激活码',
             10041: '此设备已购买过国内云存套餐,无法购买国外云存套餐',
             10042: '此设备已注册证书',
-            10043: '此设备没有序列号',
+            10043: '此设备没有注册证书',
             10044: '请求发布MQTT主题消息失败',
+            10045: '当前为最新版本',
         }
         if self.lang == 'cn':
             msg = data_cn

+ 3 - 3
Service/CloudLogs.py

@@ -32,7 +32,7 @@ def batch_add_log_ctr(request, status_code):
         'cloudstorage/queryvodlist',
     ]
     request_path = request.path.strip().strip('/')
-    if 'cloudstorage' in request_path:
+    if request_path in api_list:
         user = MiscellService.get_access_name(request_dict)
         uidToken = request_dict.get('uidToken', None)
         utko = UidTokenObject(uidToken)
@@ -69,7 +69,7 @@ def batch_add_log_ctr(request, status_code):
             logKey = 'test_logger'
         redisObj.rpush(name=logKey, val=loggerData)
         # 判断redis列表长度
-        if redisObj.llen(name=logKey) > 0:
+        if redisObj.llen(name=logKey) > 100:
             data_list = redisObj.lrange(logKey, 0, -1)
             redisObj.del_data(key=logKey)
             add_batch_log(data_list)
@@ -97,4 +97,4 @@ def add_batch_log(data_list):
         print(repr(e))
         return False
     else:
-        return True
+        return True

+ 1 - 1
Service/MiscellService.py

@@ -5,7 +5,7 @@ import time
 import requests
 import simplejson as json
 from django.utils.timezone import utc
-from Ansjer import local_settings as api_settings
+from Ansjer import config as api_settings
 
 from Object.TokenObject import TokenObject
 from Object.mongodb import mongodb

+ 0 - 40
Service/ModelService.py

@@ -1,11 +1,9 @@
-import base64
 import logging
 import time
 
 import requests
 
 from Ansjer.config import BASE_DIR
-from Controller.CheckUserData import RandomStr
 from Model.models import *
 import json
 from django.db.models import Q
@@ -250,44 +248,6 @@ class ModelService:
         file.flush()
         file.close()
 
-    @staticmethod
-    # 加密
-    def encrypt_pwd(userPwd):
-        for i in range(1, 4):
-            if i == 1:
-                userPwd = RandomStr(3, False) + userPwd + RandomStr(3, False)
-                userPwd = base64.b64encode(str(userPwd).encode("utf-8")).decode('utf8')
-            if i == 2:
-                userPwd = RandomStr(2, False) + str(userPwd) + RandomStr(2, False)
-                userPwd = base64.b64encode(str(userPwd).encode("utf-8")).decode('utf8')
-            if i == 3:
-                userPwd = RandomStr(1, False) + str(userPwd) + RandomStr(1, False)
-                userPwd = base64.b64encode(str(userPwd).encode("utf-8")).decode('utf8')
-        return userPwd
-
-    @staticmethod
-    # 解密
-    def decode_pwd(password):
-        for i in range(1, 4):
-            if i == 1:
-                # 第一次先解密
-                password = base64.b64decode(password)
-                password = password.decode('utf-8')
-                # 截去第一位,最后一位
-                password = password[1:-1]
-            if i == 2:
-                # 第2次先解密
-                password = base64.b64decode(password)
-                password = password.decode('utf-8')
-                # 去前2位,后2位
-                password = password[2:-2]
-            if i == 3:
-                # 第3次先解密
-                password = base64.b64decode(password)
-                password = password.decode('utf-8')
-                # 去前3位,后3位
-                password = password[3:-3]
-        return password
 
 def notify_alexa_delete(userID, UID):
     url = 'https://www.zositech.xyz/deviceStatus/delete'

+ 8 - 5
Service/middleware.py

@@ -2,12 +2,13 @@
 # -*- coding: utf-8 -*-
 from django.utils.deprecation import MiddlewareMixin
 
-from Ansjer import local_settings as api_settings
+from Ansjer import config as api_settings
 from Ansjer.config import SERVER_TYPE
 
 from Object.ResponseObject import ResponseObject
 from Service.MiscellService import MiscellService
-from Service import OperatingLogs, CloudLogs
+from Service import OperatingLogs
+from Service import CloudLogs
 import django.db
 
 
@@ -56,7 +57,7 @@ class StatisticsUrlMiddleware(MiddlewareMixin):
         (无视其种类)以及相应的view。 Django将立即返回该 HttpResponse。
         '''
         if request.path != '/favicon.ico':
-            print('process_request', request)
+            print('process_request:', request)
         result = self._https_statistics_to_reverse(request)
         if result == -1:
             response = ResponseObject()
@@ -65,7 +66,7 @@ class StatisticsUrlMiddleware(MiddlewareMixin):
 
     def process_view(self, request, callback, callback_args, callback_kwargs):
         if request.path != '/favicon.ico':
-            print('process_view', request)
+            print('process_view:', request)
         return None
 
     def process_response(self, request, response):
@@ -82,13 +83,15 @@ class StatisticsUrlMiddleware(MiddlewareMixin):
         ########记录访问日志
         # MiscellService.DynamoDB_add_access_log(request=request, status_code=response.status_code)
         if request.path !='/favicon.ico':
-            print('process_response', request, response)
+            print('process_response:', request, response)
+            print('SERVER_TYPE:', SERVER_TYPE)
             CloudLogs.batch_add_access_log(request=request, status_code=response.status_code)
             try:
                 pass
                 # mysql
                 if SERVER_TYPE!="Ansjer.formal_settings":
                     # print('添加日志')
+                    # CloudLogs.batch_add_access_log(request=request, status_code=response.status_code)
                     OperatingLogs.add_access_log(request=request, status_code=response.status_code)
                     MiscellService.add_access_log(request=request, status_code=response.status_code)
                 # else:

+ 15 - 0
cn_formal_manage.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.cn_config.formal_settings")
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)

+ 15 - 0
cn_test_manage.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.cn_config.test_settings")
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)

+ 1 - 1
local_manage.py

@@ -11,7 +11,7 @@ if __name__ == "__main__":
     #         ip = item[4][0]
     #
     #         print('当前局域网ip地址为:' + ip)
-    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.local_settings")
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.us_config.local_settings")
     try:
         from django.core.management import execute_from_command_line
     except ImportError as exc:

+ 15 - 0
us_formal_manage.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.us_config.formal_settings")
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)

+ 15 - 0
us_test_manage.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ansjer.us_config.test_settings")
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)