Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

locky 2 gadi atpakaļ
vecāks
revīzija
6bb9f6f6cd

+ 3 - 1
AdminController/DeviceManagementController.py

@@ -15,7 +15,7 @@ from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_
 from Model.models import Device_Info, UidSetModel, LogModel, UID_Bucket, Unused_Uid_Meal, Order_Model, StsCrdModel, \
     VodHlsModel, ExperienceContextModel, DeviceTypeModel, Equipment_Info, UidUserModel, ExperienceAiModel, AiService, \
     AppBundle, App_Info, AppDeviceType, DeviceNameLanguage, AppVersionNumber, UIDCompanySerialModel, UIDModel, \
-    CompanySerialModel
+    CompanySerialModel, UidPushModel
 from Object.AWS.AmazonS3Util import AmazonS3Util
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
@@ -285,6 +285,7 @@ class DeviceManagement(View):
         try:
             with transaction.atomic():
                 Device_Info.objects.filter(id=deviceID).delete()
+                UidPushModel.objects.filter(uid_set__uid=uid).delete()
                 # 删除推送消息
                 for val in range(1, 8):
                     EquipmentInfoService.get_equipment_info_model('', val). \
@@ -508,6 +509,7 @@ class DeviceManagement(View):
                     UIDModel.objects.filter(uid__in=uidList).update(status=0)
                     UIDCompanySerialModel.objects.filter(uid__uid__in=uidList).delete()
                     CompanySerialModel.objects.filter(serial_number__in=serial_number_list).update(status=1)
+                    UidPushModel.objects.filter(uid_set__uid__in=uidList).delete()
                     # 序列号加入重置状态redis列表
                     redis_obj = RedisObject()
                     for serial in serial_number_list:

+ 164 - 0
AdminController/dataSystemManagement/UnicomDataController.py

@@ -0,0 +1,164 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : UserDataController.py
+@Time    : 2023/6/29 14:56
+@Author  : peng
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+
+from django.db.models import Q, Sum
+from django.views.generic.base import View
+
+from Model.models import UnicomDeviceInfo, UnicomComboOrderInfo
+from Service.CommonService import CommonService
+from Object.RedisObject import RedisObject
+
+
+class UnicomDataView(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):
+        token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
+        if token_code != 0:
+            return response.json(token_code)
+        if operation == 'getFlowInfo':  # 查询流量使用情况
+            return self.get_flow_info(request_dict, response)
+        elif operation == 'getMonthlyFlowInfo':  # 查询流量使用情况
+            return self.get_monthly_flow_info(request_dict, response)
+        else:
+            return response.json(414)
+
+    @classmethod
+    def get_flow_info(cls, request_dict, response):
+        """
+        查询流量使用情况
+        @param request_dict: 请求数据
+        @request_dict year: 年
+        @request_dict month: 月
+        @request_dict query_type: 查询流量类型
+        @request_dict iccid: 卡号
+        @request_dict user_id: 用户id
+        @request_dict page: 查询分页数
+        @request_dict line: 查询条数
+        @param response:响应对象
+        @return:
+        """
+        query_type = request_dict.get('query_type', None)
+        iccid = request_dict.get('iccid', None)
+        user_id = request_dict.get('user_id', None)
+        year = request_dict.get('year', None)
+        month = request_dict.get('month', None)
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+        if not all([query_type, page, line]):
+            return response.json(444)
+        page = int(page)
+        line = int(line)
+        redis_obj = RedisObject()
+        iccid_list = []
+        try:
+            if query_type == '1':  # 查询联通测试流量信息
+                iccid_qs = UnicomComboOrderInfo.objects.all()
+                iccid_qs = iccid_qs.filter(combo__combo_type=1)
+                if user_id:
+                    user_qs = UnicomDeviceInfo.objects.filter(user_id=user_id).values('iccid')
+                    if not user_qs.exists():
+                        return response.json(173)
+                    iccid_qs = iccid_qs.filter(iccid=user_qs[0]['iccid'])
+                if iccid:
+                    iccid_qs = iccid_qs.filter(iccid=iccid)
+                iccid_qs = iccid_qs.values('iccid', 'flow_total_usage')
+                total_flow = iccid_qs.aggregate(total=Sum('flow_total_usage'))['total']
+                count = iccid_qs.count()
+                iccid_qs = iccid_qs[(page - 1) * line:page * line]
+                for item in iccid_qs:
+                    user_qs = UnicomDeviceInfo.objects.filter(iccid=item['iccid']).values('user_id')
+                    item['user_id'] = user_qs[0]['user_id'] if user_qs.exists() else ''
+                    iccid_list.append(item)
+            elif query_type == '2':  # 查询联通月度流量信息
+                iccid_qs = UnicomDeviceInfo.objects.filter(card_type=0)
+                if iccid:
+                    iccid_qs = iccid_qs.filter(iccid=iccid)
+                if user_id:
+                    iccid_qs = iccid_qs.filter(user_id=user_id)
+                iccid_qs = iccid_qs.values('iccid').distinct().order_by('iccid')
+                count = iccid_qs.count()
+                iccid_qs = iccid_qs[(page - 1) * line:page * line]
+                total_flow = 0
+                for item in iccid_qs:
+                    item['flow_total_usage'] = 0
+                    key = 'monthly_flow_' + item['iccid']
+                    user_qs = UnicomDeviceInfo.objects.filter(iccid=item['iccid']).values('user_id')
+                    item['user_id'] = user_qs[0]['user_id'] if user_qs.exists() else ''
+                    if year and month:
+                        file = year + '-' + month
+                        flow = redis_obj.get_hash_data(key, file)[0]
+                        flow = float(flow.decode()) if flow else 0
+                        item['flow_total_usage'] = flow
+                    else:
+                        flow_dict = redis_obj.get_all_hash_data(key)
+                        for k, v in flow_dict.items():
+                            item['flow_total_usage'] += float(v)
+                    iccid_list.append(item)
+                    item['flow_total_usage'] = round(item['flow_total_usage'], 2)
+                    total_flow += float(item['flow_total_usage'])
+            else:
+                return response.json(444)
+            res = {
+                'iccidInfo': iccid_list,
+                'totalFlow': round(total_flow, 2),
+                'count': count
+            }
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @classmethod
+    def get_monthly_flow_info(cls, request_dict, response):
+        """
+        查询月度流量使用情况
+        @param request_dict: 请求数据
+        @request_dict year: 年
+        @request_dict month: 月
+        @request_dict iccid: 卡号
+        @param response:响应对象
+        @return:
+        """
+        iccid = request_dict.get('iccid', None)
+        year = request_dict.get('year', None)
+        month = request_dict.get('month', None)
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+        redis_obj = RedisObject()
+        data_list = []
+        if not all([iccid, page, line]):
+            return response.json(444)
+        page = int(page)
+        line = int(line)
+        try:
+            key = 'monthly_flow_' + iccid
+            if year and month:
+                file = year + '-' + month
+                flow = redis_obj.get_hash_data(key, file)[0]
+                flow = flow.decode() if flow else 0
+                data_list.append({file: flow})
+            else:
+                flow_dict = redis_obj.get_all_hash_data(key)
+                for k, v in flow_dict.items():
+                    data_list.append({k.decode(): float(v)})
+            res = {
+                'list': data_list[(page - 1) * line:page * line],
+                'count': len(data_list)
+            }
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

+ 8 - 6
Ansjer/config.py

@@ -455,11 +455,11 @@ APP_TYPE = {
 
 # 联通Unicom config
 # 应用地址,请向开发人员索取
-unicomAppUrl = 'https://chinaunicom-iot.unimip.cn'
+unicomAppUrl = 'https://iot-cop.unimip.cn'
 # 应用id,请向开发人员创建应用,分配appId
-unicomAppId = 'LNO7ojB7mZU5ep9IuiHvygVWbwaO9vt0'
+unicomAppId = 'gyAkIBgnqlUrTNJfvcj7vA0XRIOFyh3U'
 # 应用密匙,请向开发人员创建应用,分配appSecret
-unicomAppSecret = 'p8MT1CS4QAVl0xb4cp7VOCgMvtQp2O43'
+unicomAppSecret = 'D6u6ROqceuCaYujMjBSIXDHXRZQGtaS3'
 # 租户/产品ID,请向开发人员索取
 unicomTenantId = '1469181295663300608'
 # 密码加密密匙,请向开发人员索取
@@ -467,11 +467,13 @@ unicomEncodeKey = 'uBdUx82vPHkDKb284d7NkjFoNcKWBuka'
 # 密码加密参数,请向开发人员索取
 unicomIvKey = 'oCRU0D1wKfBlNeTz'
 # 用户名,如无请联系客户经理开通
-unicomUserName = 'zh-zhasjdz'
+unicomUserName = 'zhasj_admin'
 # 登录密码,如无请联系客户经理
-unicomPassword = 'XoROL1vCl5@_'
+unicomPassword = 'Ansjer2023..'
 # 回调签名验证加密密匙,请向开发人员索取
-unicomPushKey = 'NVVDQMBSOJTXA'
+unicomPushKey = 'N5SGE4LVOR2GG'
+# token key
+UNICOM_KEY = 'ASJ:UNICOM:API:TOKEN'
 
 # 五兴域名
 WX_TECH_URL = 'http://www.wxkjwlw.com'

+ 2 - 1
Ansjer/server_urls/datasystem_url.py

@@ -9,7 +9,7 @@
 from django.urls import re_path
 
 from AdminController.dataSystemManagement import UserDataController, DeviceDataController, ServiceDataController, \
-    BusinessDataController, HomeDataController
+    BusinessDataController, HomeDataController, UnicomDataController
 
 urlpatterns = [
     re_path(r'^userData/(?P<operation>.*)$', UserDataController.UserDataView.as_view()),
@@ -17,4 +17,5 @@ urlpatterns = [
     re_path(r'^serviceData/(?P<operation>.*)$', ServiceDataController.ServiceDataView.as_view()),
     re_path(r'^businessData/(?P<operation>.*)$', BusinessDataController.BusinessDataView.as_view()),
     re_path(r'^homeData/(?P<operation>.*)$', HomeDataController.HomeDataView.as_view()),
+    re_path(r'^unicomData/(?P<operation>.*)$', UnicomDataController.UnicomDataView.as_view()),
 ]

+ 3 - 2
Controller/AiController.py

@@ -8,7 +8,7 @@ from django.db.models import Q, F, Sum
 from django.http import HttpResponseRedirect, HttpResponse
 from django.views.generic.base import View
 
-from Ansjer.config import PAYPAL_CRD, SERVER_DOMAIN_SSL, DETECT_PUSH_DOMAINS
+from Ansjer.config import PAYPAL_CRD, SERVER_DOMAIN_SSL, DETECT_PUSH_DOMAINS, LOGGER
 from Model.models import Device_Info, Order_Model, ExperienceAiModel, Pay_Type, CDKcontextModel, UidPushModel, \
     AiStoreMeal, AiService, UidSetModel
 from Object.AliPayObject import AliPayObject
@@ -565,7 +565,8 @@ class AiView(View):
                     uid_push_data['m_code'] = m_code
                     uid_push_data['addTime'] = nowTime
                     UidPushModel.objects.create(**uid_push_data)
-
+                if appBundleId == 0 or appBundleId == '0':
+                    LOGGER.info('AiService/changeaistatus接口推送数据:{}'.format(request_dict))
                 etkObj = ETkObject(etk='')
                 etk = etkObj.encrypt(uid)
 

+ 3 - 1
Controller/CloudStorage.py

@@ -1394,7 +1394,9 @@ class CloudStorageView(View):
         device_info_qs = Device_Info.objects.filter(userID_id=user_id, UID=uid, isShare=False, isExist=1)
         if not device_info_qs.exists():
             return response.json(12)
-
+        device_vo = device_info_qs.first()
+        if device_vo.Type == 103 or device_vo.Type == 26:
+            return response.json(10064)
         order_id = CommonService.createOrderID()
         now_time = int(time.time())
         store_qs = Store_Meal.objects.filter(id=rank, lang__lang=lang, is_show=0).values("day", "bucket_id",

+ 41 - 4
Controller/Cron/CronTaskController.py

@@ -8,9 +8,9 @@
 # @File    : CronTaskController.py
 # @Software: PyCharm
 import datetime
-import logging
+import threading
 import time
-
+import logging
 import requests
 from django.db import connection, connections, transaction
 from django.db.models import Q, Sum, Count
@@ -22,16 +22,16 @@ from Model.models import Device_User, Device_Info, UidSetModel, UID_Bucket, Unus
     VodHlsModel, ExperienceContextModel, AiService, VodHlsSummary, VideoPlaybackTimeModel, DeviceUserSummary, \
     CountryModel, DeviceTypeModel, OrdersSummary, DeviceInfoSummary, CompanySerialModel, \
     CloudLogModel, UidCloudStorageCount, UserExModel, DeviceDomainRegionModel, VodHlsTag, VodHlsTagType, \
-    Store_Meal, Lang, VodBucketModel
+    Store_Meal, Lang, VodBucketModel, UnicomComboOrderInfo, UnicomDeviceInfo
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.utils import LocalDateTimeUtil
 from Service.CommonService import CommonService
 from Service.VodHlsService import SplitVodHlsObject
+from Object.UnicomObject import UnicomObjeect
 
 LOGGER = logging.getLogger('info')
 
-
 class CronDelDataView(View):
     def get(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
@@ -603,6 +603,8 @@ class CronCollectDataView(View):
             return self.collect_order(response)
         elif operation == 'collectDeviceInfo':  # 定时保存设备数据
             return self.collect_device_info(response)
+        elif operation == 'collectFlowInfo':  # 定时保存设备数据
+            return self.collect_flow_info(response)
         else:
             return response.json(404)
 
@@ -1069,6 +1071,41 @@ class CronCollectDataView(View):
                                                      unicom_service=active_device_unicom_dict,
                                                      device_type=active_device_type_dict)
 
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def collect_flow_info(response):
+        try:
+            unicom_qs = UnicomDeviceInfo.objects.filter(card_type=0).values('iccid').distinct().order_by('iccid')
+            asy = threading.Thread(target=CronCollectDataView.thread_collect_flow, args=(unicom_qs,))
+            asy.start()
             return response.json(0)
         except Exception as e:
             return response.json(500, repr(e))
+
+    @staticmethod
+    def thread_collect_flow(qs):
+        try:
+            unicom_api = UnicomObjeect()
+            redis_obj = RedisObject()
+            for item in qs:
+                res = unicom_api.query_device_usage_history(**item)
+                if res.status_code == 200:
+                    res_json = res.json()
+                    if res_json['code'] == 0:
+                        redis_dict = {}
+                        for data in res_json['data']['deviceUsageHistory']:
+                            year = data.get('year', None)
+                            month = data.get('month', None)
+                            flow = data.get('flowTotalUsage', None)
+                            if not all([year, month, flow]):
+                                continue
+                            file = str(year) + '-' + str(month)
+                            redis_dict[file] = flow
+                        key = 'monthly_flow_' + item['iccid']
+                        if redis_dict:
+                            redis_obj.set_hash_data(key, redis_dict)
+        except Exception as e:
+            LOGGER.info('统计联通流量失败,时间为:{}'.format(int(time.time())))

+ 3 - 2
Controller/DetectController.py

@@ -24,7 +24,7 @@ from pyfcm import FCMNotification
 
 from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, DETECT_PUSH_DOMAIN, \
     JPUSH_CONFIG, FCM_CONFIG, APNS_CONFIG, \
-    BASE_DIR, APNS_MODE, SERVER_TYPE
+    BASE_DIR, APNS_MODE, SERVER_TYPE, LOGGER
 from Ansjer.config import PUSH_REDIS_ADDRESS
 from Model.models import Device_Info, VodHlsModel, Equipment_Info, UidSetModel, UidPushModel, SysMsgModel, \
     VodBucketModel
@@ -293,7 +293,8 @@ class DetectControllerView(View):
                     }
                     # 绑定设备推送
                     UidPushModel.objects.create(**uid_push_create_dict)
-
+                if appBundleId == 0 or appBundleId == '0':
+                    LOGGER.info('detect/changeStatus接口推送数据:{}'.format(request_dict))
                 if interval:
                     self.do_delete_redis(uid, int(interval))
                 else:

+ 63 - 59
Controller/DetectControllerV2.py

@@ -9,7 +9,7 @@ from django.http import JsonResponse
 from django.views.generic.base import View
 
 from Ansjer.config import DETECT_PUSH_DOMAIN, DETECT_PUSH_DOMAINS, DETECT_PUSH_DOMAIN_JIUAN, DETECT_PUSH_DOMAINS_JIUAN, \
-    OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
+    OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, LOGGER
 from Ansjer.config import PUSH_REDIS_ADDRESS
 from Model.models import Device_Info, Equipment_Info, UidSetModel, UidPushModel, CompanyModel, SysMsgModel, \
     AiService, VodBucketModel
@@ -159,34 +159,37 @@ class DetectControllerViewV2(View):
 
             # 初始化UidPushModel推送表
             if electricity_status:
-                uid_push_qs = UidPushModel.objects.filter(userID_id=userID, m_code=m_code, uid_set__uid=uid)
-                if uid_push_qs.exists():
-                    uid_push_update_dict = {
-                        'appBundleId': appBundleId,
-                        'app_type': app_type,
-                        'push_type': push_type,
-                        'token_val': token_val,
-                        'updTime': nowTime,
-                        'lang': lang,
-                        'tz': tz
-                    }
-                    uid_push_qs.update(**uid_push_update_dict)
-                else:
-                    uid_push_create_dict = {
-                        'uid_set_id': uid_set_id,
-                        'userID_id': userID,
-                        'appBundleId': appBundleId,
-                        'app_type': app_type,
-                        'push_type': push_type,
-                        'token_val': token_val,
-                        'm_code': m_code,
-                        'addTime': nowTime,
-                        'updTime': nowTime,
-                        'lang': lang,
-                        'tz': tz
-                    }
-                    # 绑定设备推送
-                    UidPushModel.objects.create(**uid_push_create_dict)
+                if m_code != 0 and m_code != '0':
+                    uid_push_qs = UidPushModel.objects.filter(userID_id=userID, m_code=m_code, uid_set__uid=uid)
+                    if uid_push_qs.exists():
+                        uid_push_update_dict = {
+                            'appBundleId': appBundleId,
+                            'app_type': app_type,
+                            'push_type': push_type,
+                            'token_val': token_val,
+                            'updTime': nowTime,
+                            'lang': lang,
+                            'tz': tz
+                        }
+                        uid_push_qs.update(**uid_push_update_dict)
+                    else:
+                        uid_push_create_dict = {
+                            'uid_set_id': uid_set_id,
+                            'userID_id': userID,
+                            'appBundleId': appBundleId,
+                            'app_type': app_type,
+                            'push_type': push_type,
+                            'token_val': token_val,
+                            'm_code': m_code,
+                            'addTime': nowTime,
+                            'updTime': nowTime,
+                            'lang': lang,
+                            'tz': tz
+                        }
+                        # 绑定设备推送
+                        UidPushModel.objects.create(**uid_push_create_dict)
+                if appBundleId == 0 or appBundleId == '0':
+                    LOGGER.info('detectV2/changeStatus接口推送数据:{}'.format(request_dict))
                 return response.json(0)
 
             if status == 0:
@@ -194,36 +197,37 @@ class DetectControllerViewV2(View):
                 self.do_delete_redis(uid)
                 return response.json(0)
             elif status == 1:
-                uid_push_qs = UidPushModel.objects.filter(userID_id=userID, m_code=m_code, uid_set__uid=uid)
-
-                if uid_push_qs.exists():
-                    uid_push_update_dict = {
-                        'appBundleId': appBundleId,
-                        'app_type': app_type,
-                        'push_type': push_type,
-                        'token_val': token_val,
-                        'updTime': nowTime,
-                        'lang': lang,
-                        'tz': tz
-                    }
-                    uid_push_qs.update(**uid_push_update_dict)
-                else:
-                    uid_push_create_dict = {
-                        'uid_set_id': uid_set_id,
-                        'userID_id': userID,
-                        'appBundleId': appBundleId,
-                        'app_type': app_type,
-                        'push_type': push_type,
-                        'token_val': token_val,
-                        'm_code': m_code,
-                        'addTime': nowTime,
-                        'updTime': nowTime,
-                        'lang': lang,
-                        'tz': tz
-                    }
-                    # 绑定设备推送
-                    UidPushModel.objects.create(**uid_push_create_dict)
-
+                if m_code != 0 and m_code != '0':
+                    uid_push_qs = UidPushModel.objects.filter(userID_id=userID, m_code=m_code, uid_set__uid=uid)
+                    if uid_push_qs.exists():
+                        uid_push_update_dict = {
+                            'appBundleId': appBundleId,
+                            'app_type': app_type,
+                            'push_type': push_type,
+                            'token_val': token_val,
+                            'updTime': nowTime,
+                            'lang': lang,
+                            'tz': tz
+                        }
+                        uid_push_qs.update(**uid_push_update_dict)
+                    else:
+                        uid_push_create_dict = {
+                            'uid_set_id': uid_set_id,
+                            'userID_id': userID,
+                            'appBundleId': appBundleId,
+                            'app_type': app_type,
+                            'push_type': push_type,
+                            'token_val': token_val,
+                            'm_code': m_code,
+                            'addTime': nowTime,
+                            'updTime': nowTime,
+                            'lang': lang,
+                            'tz': tz
+                        }
+                        # 绑定设备推送
+                        UidPushModel.objects.create(**uid_push_create_dict)
+                if appBundleId == 0 or appBundleId == '0':
+                    LOGGER.info('detectV2/changeStatus接口推送数据:{}'.format(request_dict))
                 if interval:
                     self.do_delete_redis(uid, interval)
                 else:

+ 3 - 7
Controller/EquipmentManager.py

@@ -813,27 +813,23 @@ def deleteInterface(request):
             if userID == dv_qs[0].vodPrimaryUserID:
                 Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
 
+            up_qs = UidPushModel.objects.filter(uid_set__uid=uid)
             if dv_qs[0].isShare:
-                dv_qs.delete()
                 DeviceShareView.del_device_channel_permission(userID, uid)
             else:
                 # a.主用户删除设备
-                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, userID_id=userID).delete()
                     redisObj = RedisObject()
                     ykey = '{uid}_redis_qs'.format(uid=uid)
                     if ykey:
                         redisObj.del_data(key=ykey)
-                else:
-                    up_qs.delete()
                 # b.删除次用户设备
                 Device_Info.objects.filter(UID=uid, isShare=True, primaryUserID=userID).delete()
                 DeviceShareView.del_device_channel_permission('', uid)
-
+            up_qs.delete()
+            dv_qs.delete()
             if not serial_number:
                 serial_number = CommonService.query_serial_with_uid(uid)
             del_unicom_info(userID, serial_number)

+ 32 - 5
Controller/EquipmentManagerV3.py

@@ -74,9 +74,32 @@ class EquipmentManagerV3(View):
             return self.do_mainUserDevice(request_dict, response)
         elif operation == 'getDeviceFeatures':
             return self.do_get_device_features(request_dict, response)
+        elif operation == 'deviceRouse':
+            return self.device_rouse(request_dict, response)
         else:
             return response.json(414)
 
+    @classmethod
+    def device_rouse(cls, request_dict, response):
+        """
+        设备唤醒
+        """
+        serial_number = request_dict.get('serialNumber', None)
+        if not serial_number:
+            return response.json(444)
+        try:
+            # 主题名称
+            topic_name = f'/wakeup/{serial_number}_0'
+            # 发布消息内容
+            msg = {'payload': 'A'}
+            result = CommonService.req_publish_mqtt_msg(serial_number, topic_name, msg)
+            if not result:
+                return response.json(10044)
+            return response.json(0)
+        except Exception as e:
+            LOGGER.info('****设备唤醒发布消息异常:{},{}'.format(serial_number, repr(e)))
+            return response.json(500, repr(e))
+
     def do_add(self, userID, request_dict, response, request):
         UID = request_dict.get('UID', None)
         NickName = request_dict.get('NickName', None)
@@ -250,7 +273,8 @@ class EquipmentManagerV3(View):
                     }
                     # 绑定设备推送
                     UidPushModel.objects.create(**uid_push_create_dict)
-
+                if appBundleId == 0 or appBundleId == '0':
+                    LOGGER.info('v3/equipment/add接口推送数据:{}'.format(request_dict))
             # 查询uid_channel表有无该uid的数据
             uid_channel_set = UidChannelSetModel.objects.filter(uid_id=UidSet_id)
             if not uid_channel_set.exists():
@@ -345,15 +369,18 @@ class EquipmentManagerV3(View):
         @return: True | False
         """
         try:
-            unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number)
+            # 根据序列号查询联通iccid
+            unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number, card_type=0)
             if not unicom_device_info_qs.exists():
                 return False
+            if unicom_device_info_qs.first().status == 1:  # 已测试
+                # 领取4G体验套餐
+                res = UnicomComboView.user_activate_flow(unicom_device_info_qs[0].iccid)
+                logging.info('{}联通领取体验流量:{}'.format(unicom_device_info_qs[0].iccid, res))
             if not unicom_device_info_qs[0].user_id:
-                n_time = int(time.time())
                 # 生成4G免费订单
                 UnicomComboView.experience_order_4G(unicom_device_info_qs[0].iccid,
-                                                    serial_number, user_id, False)
-                unicom_device_info_qs.update(user_id=user_id, updated_time=n_time)
+                                                    serial_number, user_id, True)
             return True
         except Exception as e:
             logging.info('创建体验4G订单异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

+ 53 - 43
Controller/TestApi.py

@@ -896,74 +896,84 @@ class testView(View):
             print(e)
             return response.json(500, repr(e))
 
-    @staticmethod
-    def getSerialNumberInfo(request_dict, response):
+    @classmethod
+    def getSerialNumberInfo(cls, request_dict, response):
         logger = logging.getLogger('info')
         serial_number = request_dict.get('serialNumber', None)
         if not serial_number:
             return response.json(444)
-        serialNumber = serial_number[:9]
-        serial_number = serial_number[:6]
         try:
             uid_user_message = {
                 "uid": "",
                 "serialNumber": "",
                 "userID": "",
                 "username": "",
-                "primaryUserID": ""
+                "primaryUserID": "",
             }
             data = {
                 "uid": "",
-                "serialNumber": serialNumber,
+                "serialNumber": serial_number[:9],
                 "status": "",
+                "add_time": "",
                 "uid_user_message": uid_user_message
             }
-            company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial_number).values('status')
+            # 获取序列哈状态
+            company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial_number[:6]).values('status')
             if not company_serial_qs.exists():
                 return response.json(173)
-            if company_serial_qs[0]['status'] == 0:
+            company_serial_qs = company_serial_qs.first()
+            if company_serial_qs['status'] == 0:
                 return response.json(0, {'contents': '序列号未分配'})
             uid_company_serial_qs = UIDCompanySerialModel.objects.filter(
-                company_serial__serial_number=serial_number).values('uid__uid', 'uid__status',
-                                                                    'company_serial__serial_number')
-            if not uid_company_serial_qs.exists() and company_serial_qs[0]['status'] != 0:
-                if company_serial_qs[0]['status'] == 1:
-                    data['status'] = '已分配'
-                if company_serial_qs[0]['status'] == 2:
-                    data['status'] = '绑定uid'
-                if company_serial_qs[0]['status'] == 3:
-                    data['status'] = '已占用'
+                company_serial__serial_number=serial_number[:6]).values('uid__uid', 'uid__status',
+                                                                        'company_serial__serial_number', 'add_time')
+            if not uid_company_serial_qs.exists():
+                data['status'] = cls.serial_number_status(company_serial_qs['status'])
                 return response.json(0, data)
-            for uid_company_serial in uid_company_serial_qs:
-                data['uid'] = uid_company_serial['uid__uid']
-                data['serialNumber'] = serialNumber
-                data['status'] = uid_company_serial['uid__status']
-                if company_serial_qs[0]['status'] == 1:
-                    data['status'] = '已分配'
-                if company_serial_qs[0]['status'] == 2:
-                    data['status'] = '绑定uid'
-                if company_serial_qs[0]['status'] == 3:
-                    data['status'] = '已占用'
-                uid = uid_company_serial['uid__uid'] if uid_company_serial['uid__uid'] else ''
-                device_info_qs = Device_Info.objects.filter(UID=uid).values(
-                    'UID',
-                    'serial_number',
-                    'userID_id',
-                    'primaryUserID',
-                    'userID__username')
-                uid_user_message = {
-                    'uid': device_info_qs[0]['UID'] if device_info_qs.exists() else '',
-                    'serialNumber': device_info_qs[0]['serial_number'] if device_info_qs.exists() else '',
-                    'userID': device_info_qs[0]['userID_id'] if device_info_qs.exists() else '',
-                    'username': device_info_qs[0]['userID__username'] if device_info_qs.exists() else '',
-                    'primaryUserID': device_info_qs[0]['primaryUserID'] if device_info_qs.exists() else ''
-                }
-                data['uid_user_message'] = uid_user_message
+            uid_company_serial = uid_company_serial_qs.first()
+            data['uid'] = uid_company_serial['uid__uid']
+            data['status'] = uid_company_serial['uid__status']
+            data['add_time'] = CommonService.timestamp_to_str(uid_company_serial['add_time'])
+            data['status'] = cls.serial_number_status(company_serial_qs['status'])
+            device_info_qs = Device_Info.objects.filter(UID=data['uid']).values(
+                'UID',
+                'serial_number',
+                'userID_id',
+                'primaryUserID',
+                'userID__username',
+                'data_joined').order_by('-data_joined')
+            if device_info_qs.exists():
+                # 判断主用户是否存在
+                primary_qs = device_info_qs.exclude(primaryUserID='')
+                if primary_qs.exists():
+                    uid_user_message['uid'] = primary_qs[0]['UID'],
+                    uid_user_message['serialNumber'] = primary_qs[0]['serial_number']
+                    uid_user_message['userID'] = primary_qs[0]['userID_id']
+                    uid_user_message['username'] = primary_qs[0]['userID__username']
+                    uid_user_message['primaryUserID'] = primary_qs[0]['primaryUserID']
+                else:
+                    device_info = device_info_qs.first()
+                    uid_user_message['uid'] = device_info['UID']
+                    uid_user_message['serialNumber'] = device_info['serial_number']
+                    uid_user_message['userID'] = device_info['userID_id']
+                    uid_user_message['username'] = device_info['userID__username']
+                    uid_user_message['primaryUserID'] = device_info['primaryUserID']
             return response.json(0, data)
         except Exception as e:
-            logger.info('查询异常:{}'.format(e))
+            logger.error('序列号:{}, 查询异常:{}'.format(serial_number, e))
             return response.json(500)
 
+    @staticmethod
+    def serial_number_status(status):
+        # 判断序号状态
+        if status == 1:
+            status = '已分配'
+        elif status == 2:
+            status = '绑定uid'
+        elif status == 3:
+            status = '已占用'
+        return status
+
     @classmethod
     def get_serial_details(cls, request_dict, response, request):
         """

+ 41 - 41
Controller/UnicomCombo/UnicomComboController.py

@@ -130,7 +130,7 @@ class UnicomComboView(View):
                     'month': combo_order['month'],
                 }
                 activate_flow = float(flow_details['flowTotalUsage'])
-                flow_total_usage = unicom_api.get_flow_usage_total(iccid)
+                flow_total_usage = float(unicom_api.get_flow_usage_total(iccid))
                 flow = 0 if flow_total_usage <= 0 else flow_total_usage - activate_flow
                 # 因APP问题,usableFlow可用流量替换为,已用流量值
                 flow_details['usableFlow'] = 0 if flow == 0 else flow
@@ -264,36 +264,37 @@ class UnicomComboView(View):
             redis = RedisObject()
             with transaction.atomic():
                 device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no)
-                if device_info_qs.exists():  # 首先查询SIM卡绑定信息是否存在
-                    iccid = device_info_qs.first().iccid
-                    if device_info_qs.first().card_type == 1:
-                        cls.reset_telecom_user(serial_no)
-                        device_info_qs.update(updated_time=now_time, user_id='')
-                        return response.json(0)
-                    key = 'ASJ:UNICOM:RESET:{}'.format(serial_no)
-                    flow_push_qs = UnicomFlowPush.objects.filter(serial_no=serial_no)
-                    if flow_push_qs.exists():  # 删除流量预警推送
-                        flow_push_qs.delete()
-                    sys_msg_qs = SysMsgModel.objects.filter(uid=serial_no)
-                    if sys_msg_qs.exists():  # 删除有关系统消息数据
-                        sys_msg_qs.delete()
-                    device_info_qs.update(status=1, updated_time=now_time, user_id='')
-                    combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid)
-                    order_list = []
-                    if combo_order_qs.exists():
-                        for item in combo_order_qs:
-                            if item.order_id:
-                                order_list.append(item.order_id)
-                        combo_order_qs.delete()
-                    combo_experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid)
-                    if combo_experience_history_qs.exists():
-                        combo_experience_history_qs.delete()
-                    redis.set_data(key, iccid, 60 * 30)  # 缓存当前SIM卡,记录为半个小时内无法赠送免费流量套餐。
-                    UnicomObjeect().change_device_to_activate(iccid)
-                    logger.info('4GResetFlow相关订单号:{}'.format(order_list))
-                    describe = '重置4G流量序列号{},iccid:{}'.format(serial_no, iccid)
-                    ip = CommonService.get_ip_address(request)
-                    cls.create_operation_log('unicom/api/device-status', ip, request_dict, describe)
+                if not device_info_qs.exists():  # 首先查询SIM卡绑定信息是否存在
+                    return response.json(173)
+                iccid = device_info_qs.first().iccid
+                if device_info_qs.first().card_type == 1:
+                    cls.reset_telecom_user(serial_no)
+                    device_info_qs.update(updated_time=now_time, user_id='')
+                    return response.json(0)
+                key = 'ASJ:UNICOM:RESET:{}'.format(serial_no)
+                flow_push_qs = UnicomFlowPush.objects.filter(serial_no=serial_no)
+                if flow_push_qs.exists():  # 删除流量预警推送
+                    flow_push_qs.delete()
+                sys_msg_qs = SysMsgModel.objects.filter(uid=serial_no)
+                if sys_msg_qs.exists():  # 删除有关系统消息数据
+                    sys_msg_qs.delete()
+                device_info_qs.update(status=1, updated_time=now_time, user_id='')
+                combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid)
+                order_list = []
+                if combo_order_qs.exists():
+                    for item in combo_order_qs:
+                        if item.order_id:
+                            order_list.append(item.order_id)
+                    combo_order_qs.delete()
+                combo_experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid)
+                if combo_experience_history_qs.exists():
+                    combo_experience_history_qs.delete()
+                redis.set_data(key, iccid, 60 * 30)  # 缓存当前SIM卡,记录为半个小时内无法赠送免费流量套餐。
+                UnicomObjeect().change_device_to_disable(iccid)
+                logger.info('4GResetFlow相关订单号:{}'.format(order_list))
+                describe = '重置4G流量序列号{},iccid:{}'.format(serial_no, iccid)
+                ip = CommonService.get_ip_address(request)
+                cls.create_operation_log('unicom/api/device-status', ip, request_dict, describe)
                 return response.json(0)
         except Exception as e:
             print(e.args)
@@ -378,19 +379,18 @@ class UnicomComboView(View):
         n_time = int(time.time())
         try:
             logger.info('--->参数验证通过,sign验证通过')
-            redis = RedisObject()
             with transaction.atomic():
                 ip = CommonService.get_ip_address(request)
                 # 待完善代码 根据uid与用户id验证系统设备mdcmd
                 unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
                 if unicom_device_qs.exists():
-                    if unicom_device_qs.first().status == 1:
-                        key = 'ASJ:UNICOM:RESET:{}'.format(serial_no)
-                        reset_cache = redis.get_data(key)
-                        if reset_cache:
-                            logger.info('--->三十分后再次访问接口生效赠送流量套餐')
-                            return response.json(0, 'Thirty minutes later to visit again take effect')
-                        cls.user_activate_flow(iccid)
+                    # if unicom_device_qs.first().status == 1:
+                    #     key = 'ASJ:UNICOM:RESET:{}'.format(serial_no)
+                    #     reset_cache = redis.get_data(key)
+                    #     if reset_cache:
+                    #         logger.info('--->三十分后再次访问接口生效赠送流量套餐')
+                    #         return response.json(0, 'Thirty minutes later to visit again take effect')
+                    #     cls.user_activate_flow(iccid)
                     if unicom_device_qs.first().serial_no != serial_no:
                         unicom_device_qs.update(main_card=sim, updated_time=n_time, serial_no=serial_no)
                         cls.create_operation_log('unicom/api/device-bind',
@@ -415,7 +415,7 @@ class UnicomComboView(View):
                         if res_dict['data']['status'] == 0:
                             logger.info('--->设备请求绑定{}验证不存在{}'.format(iccid, res_dict))
                             return response.json(173)
-                        unicom_obj.change_device_to_activate(iccid)
+                        # unicom_obj.change_device_to_activate(iccid)
                         UnicomDeviceInfo.objects.create(**params)
                         cls.create_operation_log('unicom/api/device-bind',
                                                  ip, request_dict, '4G序列号{}绑定{}'.format(serial_no, iccid))
@@ -639,7 +639,7 @@ class UnicomComboView(View):
                 return response.json(0, res_data)
         except Exception as e:
             print(e)
-            return response.json(500, repr(e))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def get_cloud_or_ai_combo():

+ 122 - 6
Controller/UnicomCombo/UnicomComboTaskController.py

@@ -16,7 +16,9 @@ from django.db import transaction
 from django.db.models import Q
 from django.views import View
 
-from Model.models import UnicomComboOrderInfo, UnicomCombo, Order_Model, UnicomDeviceInfo, UnicomFlowPush
+from Model.models import UnicomComboOrderInfo, UnicomCombo, Order_Model, UnicomDeviceInfo, UnicomFlowPush, \
+    IotCardUsageHistory
+from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.UnicomObject import UnicomObjeect
 
@@ -50,6 +52,13 @@ class UnicomComboTaskView(View):
             month = today.month
             self.query_unused_combo_and_activate(request_dict.get('iccid'), year, month, '666')
             return response.json(0)
+        elif operation == 'updateFlowUsed':  # 更新流量使用
+            self.unicom_flow_used(request_dict, response)
+            return response.json(0)
+        elif operation == 'queryFlowUsedHistory':
+            return self.query_flow_used_history(response)
+        elif operation == 'queryFlowCache':
+            return self.query_flow_cache(response)
 
     @classmethod
     def check_activate_combo(cls, request_dict, response):
@@ -110,10 +119,23 @@ class UnicomComboTaskView(View):
         """
         logger.info('--->进入监控流量使用情况')
         try:
-            unicom_api = UnicomObjeect()
             combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, is_del=False, combo__is_unlimited=0).values()
             if not combo_order_qs.exists():
                 return response.json(0)
+            asy = threading.Thread(target=UnicomComboTaskView.async_monitoring_flow, args=(combo_order_qs,))
+            asy.start()
+            return response.json(0)
+        except Exception as e:
+            logger.info('出错了~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))
+
+    @classmethod
+    def async_monitoring_flow(cls, combo_order_qs):
+        """
+        异步检测流量使用详情
+        """
+        try:
+            unicom_api = UnicomObjeect()
             today = datetime.datetime.today()
             year = today.year
             month = today.month
@@ -133,6 +155,7 @@ class UnicomComboTaskView(View):
                 flow_total = combo_qs['flow_total']
                 # 队列已使用总流量总量
                 flow_total_usage = unicom_api.get_flow_usage_total(iccid)
+                flow_total_usage = float(flow_total_usage)
                 is_expire = False
                 flow = activate_usage_flow + flow_total
                 if flow_total_usage > 0:
@@ -154,11 +177,8 @@ class UnicomComboTaskView(View):
                     if not activate_status:
                         # 停用
                         unicom_api.change_device_to_disable(iccid)
-
-            return response.json(0)
         except Exception as e:
-            logger.info('出错了~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
-            return response.json(177, repr(e))
+            logger.info('异步~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
     @staticmethod
     def flow_warning_push(app_user_id, serial_no, combo_order_id, flow_total, flow_usage):
@@ -306,3 +326,99 @@ class UnicomComboTaskView(View):
             UnicomFlowPush.objects.create(**push_data)
         except Exception as e:
             logger.info('-->出错了~,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def unicom_flow_used(request_dict, response):
+        """
+        查询设备每张卡流量使用情况
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        page_size = int(request_dict.get('pageSize', 1))
+        device_count = UnicomDeviceInfo.objects.filter(card_type=0).count()
+        total_pages = device_count // page_size + (device_count % page_size > 0)  # 计算总页数
+        for page_number in range(1, total_pages + 1):
+            u_device_qs = UnicomDeviceInfo.objects.filter(card_type=0).values('id', 'iccid', 'sim_used_flow').order_by(
+                '-created_time')[(page_number - 1) * page_size:page_number * page_size]
+            asy = threading.Thread(target=UnicomComboTaskView.thread_collect_flow_used, args=(u_device_qs,))
+            asy.start()
+        return response.json(0)
+
+    @staticmethod
+    def thread_collect_flow_used(u_device_qs):
+        for item in u_device_qs:
+            try:
+                unicom_api = UnicomObjeect()
+                n_time = int(time.time())
+                # 队列已使用总流量总量
+                flow_total_usage = unicom_api.get_flow_usage_total(item['iccid'])
+                UnicomDeviceInfo.objects.filter(id=item['id']).update(updated_time=n_time,
+                                                                      sim_used_flow=flow_total_usage)
+            except Exception as e:
+                print(repr(e))
+                continue
+
+    @classmethod
+    def query_flow_used_history(cls, response):
+        # 获取符合条件的卡片对象查询集,并按创建时间升序排序
+        card_qs = UnicomDeviceInfo.objects.filter(card_type=0).values('iccid').order_by('created_time')
+        if not card_qs.exists():
+            return response.json(0)
+        asy = threading.Thread(target=UnicomComboTaskView.async_bulk_create_usage_history, args=(card_qs,))
+        asy.start()
+        return response.json(0)
+
+    @staticmethod
+    def async_bulk_create_usage_history(qs):
+        """
+        异步批量创建流量用量历史记录
+        """
+        redis_obj = RedisObject()
+        current_time = int(time.time())  # 获取当前时间戳
+
+        for item in qs:
+            iccid = item['iccid']
+            key = 'monthly_flow_' + iccid
+
+            flow_dict = redis_obj.get_all_hash_data(key)  # 获取Redis中指定键的哈希表数据
+            iot_card_list = []  # 创建一个空的列表,用于批量创建IotCardUsageHistory对象
+            for k, v in flow_dict.items():
+                try:
+                    cycle = datetime.datetime.strptime(str(k.decode()), '%Y-%m')  # 将字符串日期解析为datetime类型
+                    flow = float(v)
+
+                    iot_card_list.append(IotCardUsageHistory(
+                        iccid=iccid,
+                        card_type=1,
+                        cycle=int(cycle.strftime('%Y%m')),  # 将日期转换为整数形式,如202201
+                        flow_total_usage=flow,
+                        created_time=current_time,
+                        updated_time=current_time
+                    ))
+                except Exception as e:
+                    print(repr(e))
+                    continue
+            # 批量创建IotCardUsageHistory对象
+            if iot_card_list:
+                IotCardUsageHistory.objects.bulk_create(iot_card_list)
+
+    @classmethod
+    def query_flow_cache(cls, response):
+        """
+        查询流量缓存永久的将设置过期时间为10分钟
+        """
+        redis = RedisObject()
+        try:
+            res = redis.get_keys('ASJ:UNICOM:FLOW:*')
+            keys = [key.decode() for key in res]
+            # 进行进一步的处理或打印
+            for key in keys:
+                ttl = redis.get_ttl(key)
+                if ttl == -1:
+                    logger.info('iccidFlow:{}'.format(key))
+                    redis.CONN.expire(key, 60 * 10)
+            return response.json(0)
+        except Exception as e:
+            logger.info('出错了~次月激活套餐异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))

+ 44 - 14
Controller/UserController.py

@@ -37,12 +37,13 @@ from django.views.generic import View
 from jwt.algorithms import RSAAlgorithm
 from ratelimit import limits
 
-from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
-from Ansjer.config import BASE_DIR, CONFIG_EUR, CONFIG_INFO, SERVER_DOMAIN_EUR
+from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN, LOGGER
+from Ansjer.config import BASE_DIR, CONFIG_EUR, CONFIG_INFO, SERVER_DOMAIN_EUR, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
     UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal, \
-    GatewayPush, CountryLanguageModel, LanguageModel
+    GatewayPush, CountryLanguageModel, LanguageModel, VodBucketModel
+from Object.AWS.AmazonS3Util import AmazonS3Util
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
@@ -2148,7 +2149,8 @@ class v3LoginView(TemplateView):
                 GatewayPush.objects.create(user_id=userID, app_bundle_id=app_bundle_id, app_type=app_type,
                                            push_type=push_type, token_val=token_val, m_code=m_code, lang=lang, tz=tz)
             UidPushModel.objects.filter(userID=userID, m_code=m_code).update(token_val=token_val, push_type=push_type)
-
+            if app_bundle_id == 0 or app_bundle_id == '0':
+                LOGGER.info('v3/account/login接口推送数据:{}'.format(request_dict))
         now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
         region_country = users['region_country']
         # 语言不存在返回英文
@@ -2325,18 +2327,11 @@ class InitInfoView(View):
         tz = request_dict.get('tz', '0')
         lang = request_dict.get('lang', '')  # 语言区域
         now_time = int(time.time())
+        if m_code[:4] == 'iOS_':
+            m_code = m_code[4:]
         if all([token_val, push_type, appBundleId, userID]):
             self.save_push_config(userID, appBundleId, push_type, token_val, m_code, lang, tz)
-            if m_code:
-                # 获取设备推送状态
-                update_dict = {
-                    'token_val': token_val,
-                    'push_type': push_type,
-                    'tz': tz,
-                }
-                # 更新当前用户推送设备状态
-                UidPushModel.objects.filter(userID_id=userID, m_code=m_code). \
-                    update(**update_dict)
+            self.save_or_creat_uid_push(userID, appBundleId, push_type, token_val, m_code, lang, tz, now_time)
             if appBundleId:
                 user_ex_qs = UserExModel.objects.filter(userID_id=userID)
                 user_ex = None
@@ -2398,6 +2393,41 @@ class InitInfoView(View):
         except Exception as e:
             print('出错了~异步保存配置信息错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
+    @staticmethod
+    def save_or_creat_uid_push(user_id, app_bundle_id, push_type, token_val, m_code, lang, tz, now_time):
+        """
+        异步保存推送配置
+        @param user_id: 用户id
+        @param app_bundle_id: app版本包id
+        @param push_type: 推送类型 0:Ios,1:Google,2:国内极光
+        @param token_val: 推送token
+        @param m_code: 手机唯一标识
+        @param lang: 语言
+        @param tz: 时区
+        @param now_time: 时间戳
+        @return: None
+        """
+        try:
+            app_type = 1 if push_type == 0 else 2
+            device_info = Device_Info.objects.filter(userID=user_id).values('UID')
+            if device_info.exists():
+                uid_set = UidSetModel.objects.filter(uid__in=device_info).values('id')
+                for item in uid_set:
+                    uid_push_qs = UidPushModel.objects.filter(userID=user_id, m_code=m_code, uid_set_id=item['id'])
+                    if uid_push_qs.exists():
+                        if uid_push_qs.first().token_val != token_val:
+                            uid_push_qs.update(token_val=token_val, push_type=push_type)
+                    else:
+                        UidPushModel.objects.create(userID_id=user_id, appBundleId=app_bundle_id, app_type=app_type,
+                                                    push_type=push_type, token_val=token_val, m_code=m_code, lang=lang,
+                                                    tz=tz, addTime=now_time, updTime=now_time, uid_set_id=item['id'])
+                    if app_bundle_id == 0 or app_bundle_id == '0':
+                        LOGGER.info(
+                            'user/initInfo接口推送数据:appBundleId:{},app_type:{},push_type:{},token_val:{},m_code:{}'.format(
+                                app_bundle_id, app_type, push_type, token_val, m_code))
+        except Exception as e:
+            LOGGER.info('出错了~保存推送配置信息错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
     def update_country(self, request_dict, response, request):
         username = request_dict.get('unique', None)
         appBundleId = request_dict.get('appBundleId', None)

+ 22 - 0
Model/models.py

@@ -2943,6 +2943,9 @@ class UnicomDeviceInfo(models.Model):
     user_id = models.CharField(blank=True, max_length=32, verbose_name=u'用户id')
     card_type = models.SmallIntegerField(default=0, verbose_name=u'状态{0:联通,1:电信,2:移动}')
     main_card = models.SmallIntegerField(default=0, verbose_name=u'SIM卡类型{0:拔插卡,1:贴片卡}')
+    sim_used_flow = models.DecimalField(default=0, max_digits=10, decimal_places=2, verbose_name=u'sim卡已用总流量(MB)')
+    sim_cycle_used_flow = models.DecimalField(default=0, max_digits=10, decimal_places=2,
+                                              verbose_name=u'设备账期已用流量(MB)')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     created_time = models.IntegerField(default=0, verbose_name='创建时间')
 
@@ -3548,3 +3551,22 @@ class ExchangeCode(models.Model):
         db_table = 'exchange_code'
         verbose_name = '套餐包兑换码'
         verbose_name_plural = verbose_name
+
+
+class IotCardUsageHistory(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='列表主键')
+    iccid = models.CharField(default='', max_length=32, verbose_name=u'ICCID号')
+    card_type = models.SmallIntegerField(default=0, verbose_name='卡类型,1:联通,2:电信,3:移动,4:其它,5:国际')
+    cycle = models.IntegerField(default=0, verbose_name='帐期 如 202307')
+    flow_total_usage = models.DecimalField(default=0, max_digits=10, decimal_places=2, verbose_name=u'月流量用量(MB)')
+    voice_total_usage = models.IntegerField(default=0, verbose_name='帐期已用语音总量(Min)')
+    sms_total_usage = models.IntegerField(default=0, verbose_name='帐期已用短信总量(条)')
+    cycle_start_time = models.DateTimeField(null=True, blank=True, verbose_name='帐期开始时间')
+    cycle_end_time = models.DateTimeField(null=True, blank=True, verbose_name='帐期结束时间')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+    updated_time = models.IntegerField(default=0, verbose_name='修改时间')
+
+    class Meta:
+        db_table = 'iot_card_usage_history'
+        verbose_name = '物联网卡用量历史'
+        verbose_name_plural = verbose_name

+ 9 - 0
Object/RedisObject.py

@@ -92,3 +92,12 @@ class RedisObject:
             return False
         else:
             return True
+
+    def set_hash_data(self, key, kwargs):
+        self.CONN.hmset(key, kwargs)
+
+    def get_hash_data(self, key, file):
+        return self.CONN.hmget(key, file)
+
+    def get_all_hash_data(self, key):
+        return self.CONN.hgetall(key)

+ 2 - 0
Object/ResponseObject.py

@@ -127,6 +127,7 @@ class ResponseObject(object):
             10061: 'Add the limit reached',
             10062: 'This device has experienced the package',
             10063: 'Failed to claim',
+            10064: 'If the claim fails, please contact customer service',
         }
         data_cn = {
             0: '成功',
@@ -243,6 +244,7 @@ class ResponseObject(object):
             10061: '添加已达到上限',
             10062: '此设备已体验过套餐',
             10063: '领取失败',
+            10064: '领取失败,请联系客服',
         }
 
         msg = data_cn if self.lang == 'cn' or self.lang == 'zh-Hans' or self.lang == 'zh-Hant' else data_en

+ 71 - 29
Object/UnicomObject.py

@@ -9,12 +9,15 @@
 import base64
 import json
 import logging
+import time
+from decimal import Decimal
 
 import requests
 from Crypto.Cipher import AES
 
 from Ansjer.config import unicomAppUrl, unicomAppId, unicomAppSecret, unicomTenantId, \
-    unicomEncodeKey, unicomIvKey, unicomUserName, unicomPassword, unicomPushKey, SERVER_DOMAIN_SSL
+    unicomEncodeKey, unicomIvKey, unicomUserName, unicomPassword, unicomPushKey, SERVER_DOMAIN_SSL, UNICOM_KEY
+from Model.models import UnicomDeviceInfo
 from Object.RedisObject import RedisObject
 from Object.utils import SM3Util
 from Object.utils.SymmetricCryptoUtil import AESencrypt
@@ -87,7 +90,7 @@ class UnicomObjeect:
 
     def get_encode_password(self):
         """
-        获取对称加密
+        获取对称加密AES
         @return: encrypt_pwd
         """
         aes = AESencrypt(self.encodeKey.encode('utf-8'), AES.MODE_CBC, self.ivKey.encode('utf-8'),
@@ -101,6 +104,10 @@ class UnicomObjeect:
         生成令牌
         @return: token
         """
+        redis = RedisObject()
+        token = redis.get_data(UNICOM_KEY)
+        if token:
+            return token
         url = self.appUrl + '/auc/oauth/token'
         pwd = self.get_encode_password()
         body = {'username': self.username, 'password': pwd, 'grant_type': 'password', 'scope': 'server'}
@@ -108,7 +115,11 @@ class UnicomObjeect:
         headers['Authorization'] = self.get_login_authorization()
         response_data = requests.post(url, data=body, headers=headers)
         response_data = json.loads(response_data.text)
-        return response_data['access_token']
+        token = response_data['access_token']
+        expires_in = response_data['expires_in']
+        redis.CONN.setnx(UNICOM_KEY, token)
+        redis.CONN.expire(UNICOM_KEY, int(expires_in))
+        return token
 
     def refresh_token(self, refresh_token):
         """
@@ -141,7 +152,8 @@ class UnicomObjeect:
         @param re_params:
         @return:
         """
-        url = self.appUrl + '/platform/api/device/verify-device'
+        re_params['appId'] = self.appId
+        url = self.appUrl + '/cop-platform/api/device/verify-device'
         return requests.get(url, params=re_params, headers=self.business_unify_headers())
 
     def query_device_status(self, **re_params):
@@ -150,8 +162,11 @@ class UnicomObjeect:
         @param re_params:
         @return:
         """
-        url = self.appUrl + '/platform/api/device/device-status'
-        return requests.get(url, params=re_params, headers=self.business_unify_headers())
+        url = self.appUrl + '/cop-platform/api/device/detail'
+        re_params['appId'] = self.appId
+        headers = self.business_unify_headers()
+        headers['content-type'] = 'application/json'
+        return requests.get(url, params=re_params, headers=headers)
 
     def update_device_state(self, **re_data):
         """
@@ -159,9 +174,10 @@ class UnicomObjeect:
         @param re_data:
         @return:
         """
-        url = self.appUrl + '/platform/api/device/async-device-state'
+        url = self.appUrl + '/cop-platform/api/device/async-device-state'
         headers = self.business_unify_headers()
         headers['content-type'] = 'application/json'
+        re_data['appId'] = self.appId
         re_data['callbackUrl'] = SERVER_DOMAIN_SSL + 'unicom/api/device-status-change'
         return requests.post(url, data=json.dumps(re_data), headers=headers)
 
@@ -171,8 +187,10 @@ class UnicomObjeect:
         @param re_params:
         @return:
         """
-        url = self.appUrl + '/platform/api/usage/device-usage-history'
-        return requests.get(url, params=re_params, headers=self.business_unify_headers())
+        headers = self.business_unify_headers()
+        re_params['appId'] = self.appId
+        url = self.appUrl + '/cop-platform/api/usage/device-usage-history'
+        return requests.get(url, params=re_params, headers=headers)
 
     def query_current_renew_list_usage_details(self, **re_params):
         """
@@ -180,7 +198,8 @@ class UnicomObjeect:
         @param re_params:
         @return:
         """
-        url = self.appUrl + '/platform/api/usage/current-renewlist-usage-details'
+        url = self.appUrl + '/cop-platform/api/device/current-package-usage-details'
+        re_params['appId'] = self.appId
         return requests.get(url, params=re_params, headers=self.business_unify_headers())
 
     def get_device_batch_detail(self, **re_data):
@@ -232,7 +251,7 @@ class UnicomObjeect:
         return None
 
     @staticmethod
-    def get_flow_total_usage(key, expire=0, **usage_data):
+    def get_flow_total_usage(key, expire=600, **usage_data):
         """
         设备当前队列用量详情(实现缓存)
         @param key: 缓存key
@@ -241,14 +260,44 @@ class UnicomObjeect:
         @return: 返回结果dict
         """
         redis = RedisObject()
-        flow_usage_details = redis.get_data(key)
-        if flow_usage_details:
-            flow_usage_details = json.loads(flow_usage_details)
+        sim_flow_used_total = redis.get_data(key)
+        if sim_flow_used_total:
+            return Decimal(sim_flow_used_total).quantize(Decimal('0.00'))
         else:
-            flow_usage_details = UnicomObjeect().query_current_renew_list_usage_details(**usage_data)
+            # API查询设备信息其中包含周期流量使用
+            flow_usage_details = UnicomObjeect().query_device_status(**usage_data)
             flow_usage_details = UnicomObjeect().get_text_dict(flow_usage_details)
-            redis.set_data(key=key, val=json.dumps(flow_usage_details), expire=expire)
-        return flow_usage_details
+            if flow_usage_details and flow_usage_details.get('success'):
+                cycle_total = flow_usage_details['data'].get('simCycleUsedFlow', 0)
+            else:
+                cycle_total = 0
+            # 查询SIM卡信息
+            sim_qs = UnicomDeviceInfo.objects.filter(iccid=usage_data['iccid'])
+            if not sim_qs:
+                return cycle_total
+            cycle_total = Decimal(cycle_total).quantize(Decimal('0.00'))
+            sim_vo = sim_qs.first()
+            n_time = int(time.time())
+
+            # 判断数据库周期流量用量 是否大于API查询出来的周期用量 如果是则判定进入了下一个周期
+            if sim_vo.sim_cycle_used_flow != 0 and sim_vo.sim_cycle_used_flow > cycle_total:
+                sim_used_flow = sim_vo.sim_used_flow + sim_vo.sim_cycle_used_flow
+                sim_qs.update(
+                    sim_used_flow=sim_used_flow,
+                    sim_cycle_used_flow=cycle_total,
+                    updated_time=n_time
+                )
+                # 队列用量历史总量 + 上一个周期流量 + 当前周期流量 = 总消耗流量
+                sim_flow_used_total = sim_used_flow + cycle_total
+            elif cycle_total > sim_vo.sim_cycle_used_flow:  # API周期用量大于当前数据库用量则更新记录
+                sim_qs.update(sim_cycle_used_flow=cycle_total, updated_time=n_time)
+                # 队列用量历史总量 + 当前周期流量 = 总消耗流量
+                sim_flow_used_total = sim_vo.sim_used_flow + cycle_total
+            else:
+                sim_flow_used_total = sim_vo.sim_used_flow + sim_vo.sim_cycle_used_flow
+            redis.CONN.setnx(key, str(sim_flow_used_total))
+            redis.CONN.expire(key, expire)
+        return sim_flow_used_total
 
     @staticmethod
     def get_flow_usage_total(iccid):
@@ -258,14 +307,9 @@ class UnicomObjeect:
         @return: flow_total_usage 当前套餐总已使用流量
         """
         flow_key = 'ASJ:UNICOM:FLOW:{}'
-        usage_data = {'iccid': iccid, 'realTime': True}
+        usage_data = {'iccid': iccid}
         expire_time = 60 * 10 + 60
-        flow_usage_details = UnicomObjeect().get_flow_total_usage(flow_key.format(iccid), expire_time, **usage_data)
-        # 当月实际总使用流量
-        flow_total_usage = 0
-        if flow_usage_details and flow_usage_details['success']:
-            flow_total_usage = flow_usage_details['data']['flowTotalUsage']
-        return flow_total_usage
+        return UnicomObjeect().get_flow_total_usage(flow_key.format(iccid), expire_time, **usage_data)
 
     @staticmethod
     def change_device_to_activate(iccid):
@@ -278,7 +322,7 @@ class UnicomObjeect:
             re_data = {'iccid': iccid}
             result = UnicomObjeect().query_device_status(**re_data)
             res_dict = UnicomObjeect().get_text_dict(result)
-            # 状态不等于1(激活)时进行激活 1:激活;2:停用
+            # 状态不等于1(激活)时进行激活 1:激活;3:停用
             if res_dict['data']['status'] != 1:
                 re_data = {"iccid": iccid, "status": 1}
                 UnicomObjeect().update_device_state(**re_data)
@@ -293,7 +337,7 @@ class UnicomObjeect:
         @return:
         """
         if iccid:
-            re_data = {"iccid": iccid, "status": 2}
+            re_data = {"iccid": iccid, "status": 3}
             response = UnicomObjeect().update_device_state(**re_data)
             logger.info('停用iccid响应结果:{}'.format(response.text))
             # 查询是否停用成功
@@ -302,7 +346,7 @@ class UnicomObjeect:
             res_dict = UnicomObjeect().get_text_dict(result)
             logger.info('查询iccid状态:{}'.format(res_dict))
             if res_dict['data']['status'] != 3:
-                re_data['status'] = 2
+                re_data['status'] = 3
                 response = UnicomObjeect().update_device_state(**re_data)
                 logger.info('再次停卡:{}'.format(response.text))
             return True
@@ -328,5 +372,3 @@ class UnicomObjeect:
                 return 0
             traffic_dict = json.loads(traffic_val)
         return traffic_dict['data']['flowTotalUsage']
-
-