Browse Source

Merge branch 'test' of http://192.168.136.99:3000/servers/ASJServer into peng

 Conflicts:
	Controller/AiController.py
	Controller/CloudStorage.py
	Controller/EquipmentManagerV2.py
	Controller/EquipmentManagerV3.py
	Controller/OrderContrller.py
peng 3 years ago
parent
commit
13a2bc65bd

+ 23 - 25
AdminController/ServeManagementController.py

@@ -538,31 +538,29 @@ class serveManagement(View):
         cdk_list = []
         cdk_list = []
         sm_qs = Store_Meal.objects.filter(
         sm_qs = Store_Meal.objects.filter(
             pay_type__payment='cdk_pay', bucket__mold=mold, is_show=0)
             pay_type__payment='cdk_pay', bucket__mold=mold, is_show=0)
-        if sm_qs.exists:
-            rank = sm_qs[0].id
-            for i in range(int(cdk_num)):
-                nowTime = int(time.time())
-                cdk = hashlib.md5((str(uuid.uuid1()) +
-                                   str(nowTime)).encode('utf-8')).hexdigest()
-                cdk_model = CDKcontextModel(
-                    cdk=cdk,
-                    create_time=nowTime,
-                    valid_time=0,
-                    is_activate=0,
-                    is_down=0,
-                    rank_id=rank,
-                    order=order,
-                )
-                cdk_list.append(cdk_model)
-            try:
-                CDKcontextModel.objects.bulk_create(cdk_list)
-            except Exception as e:
-                print(repr(e))
-                return response.json(404, repr(e))
-            else:
-                return response.json(0)
-
-        return response.json(0)
+        if not sm_qs.exists():
+            return response.json(173)
+        rank = sm_qs[0].id
+        for i in range(int(cdk_num)):
+            nowTime = int(time.time())
+            cdk = hashlib.md5((str(uuid.uuid1()) +
+                               str(nowTime)).encode('utf-8')).hexdigest()
+            cdk_model = CDKcontextModel(
+                cdk=cdk,
+                create_time=nowTime,
+                valid_time=0,
+                is_activate=0,
+                is_down=0,
+                rank_id=rank,
+                order=order,
+            )
+            cdk_list.append(cdk_model)
+        try:
+            CDKcontextModel.objects.bulk_create(cdk_list)
+        except Exception as e:
+            return response.json(404, repr(e))
+        else:
+            return response.json(0)
 
 
     def deleteCdk(self, request_dict, response):
     def deleteCdk(self, request_dict, response):
         cdk_id = request_dict.get("id", None)
         cdk_id = request_dict.get("id", None)

+ 235 - 0
AdminController/UnicomManageController.py

@@ -0,0 +1,235 @@
+# Copyright (C) 2022 #
+# @Time    : 2022/7/18 16:16
+# @Author  : ghl
+# @Email   : Guanhailogn@asj6.wecom.work
+# @File    : UnicomManageController.py
+# @Software: PyCharm
+
+from django.db import transaction
+from django.views import View
+
+from Model.models import UnicomComboOrderInfo, UnicomCombo, UnicomDeviceInfo, Pay_Type
+from Object.ResponseObject import ResponseObject
+
+
+class UnicomComboView(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()
+        print(request)
+        # 编辑套餐信息
+        if operation == 'get/info':
+            return self.get_unicom_info(request_dict, response)
+        # 获取套餐表
+        elif operation == 'get/pay':
+            return self.get_pay_type(request_dict, response)
+        # 编辑卡套餐
+        elif operation == 'edit/combo':
+            return self.edit_combo(request_dict, response)
+        # 新增套餐
+        elif operation == 'add/combo':
+            return self.add_combo(response, request_dict)
+        # 获取设备套餐信息
+        elif operation == 'order/info':
+            return self.get_order_info(response, request_dict)
+        # 获取用户信息
+        elif operation == 'user/info':
+            return self.get_user_info(response, request_dict)
+
+    @staticmethod
+    def get_user_info(response, request_dict):
+        pass
+
+    @staticmethod
+    def get_order_info(response, request_dict):
+        serial_no = request_dict.get('serialNo', None)
+        if not all([serial_no]):
+            return response.json(444)
+        get_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no).values('iccid')
+        iccid = get_info_qs[0]['iccid']
+        combo_info_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid).values()
+        if not combo_info_qs.exists():
+            return response.json(173)
+        try:
+            combo_list = []
+            for combo_info in combo_info_qs:
+                combo_list.append(combo_info)
+            return response.json(0, combo_list)
+        except Exception as e:
+            return response.json(500, e)
+
+    @classmethod
+    def edit_combo(cls, request_dict, response):
+        """
+
+        """
+        combo_id = request_dict.get('comboID', None)
+        package_id = request_dict.get('packageId', None)
+        combo_name = request_dict.get('comboName', None)
+        status = request_dict.get('status', None)
+        combo_type = request_dict.get('comboType', None)
+        flow_total = request_dict.get('flowTotal', None)
+        expiration_days = request_dict.get('expirationDays', None)
+        expiration_type = request_dict.get('expirationType', None)
+        pay_type = request_dict.get('payType', None)
+        price = request_dict.get('price', None)
+        remark = request_dict.get('remark', None)
+        updated_time = request_dict.get('updatedTime', None)
+        created_time = request_dict.get('createdTime', None)
+        is_show = request_dict.get('show', None)
+
+        if not all([combo_id]):
+            return response.json(444)
+        UnicomCombo.objects.filter(id=combo_id).values()
+
+        try:
+            with transaction.atomic():
+                re_data = {
+                    'package_id': package_id,
+                    'combo_name': combo_name,
+                    'status': status,
+                    'combo_type': combo_type,
+                    'flow_total': flow_total,
+                    'expiration_days': expiration_days,
+                    'expiration_type': expiration_type,
+                    'price': price,
+                    'remark': remark,
+                    'updated_time': updated_time,
+                    'created_time': created_time,
+                    'is_show': is_show
+                }
+                UnicomCombo.objects.filter(id=combo_id).update(**re_data)
+                UnicomCombo.objects.get(id=combo_id).pay_type.set(pay_type)
+                # UnicomCombo.objects.create(**re_data).pay_type.set(pay_type)
+                return response.json(0)
+
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def add_combo(response, request_dict):
+        """
+        新增卡套餐
+        """
+        combo_id = request_dict.get('ID', None)
+        package_id = request_dict.get('packageId', None)
+        combo_name = request_dict.get('comboName', None)
+        status = request_dict.get('status', None)
+        combo_type = request_dict.get('comboType', None)
+        flow_total = request_dict.get('flowTotal', None)
+        expiration_days = request_dict.get('expirationDays', None)
+        expiration_type = request_dict.get('expirationDays', None)
+        pay_type = request_dict.get('payType', None)
+        price = request_dict.get('price', None)
+        remark = request_dict.get('remark', None)
+        updated_time = request_dict.get('updatedTime', None)
+        created_time = request_dict.get('createdTime', None)
+        is_show = request_dict.get('show', None)
+        pageNo = request_dict.get('pageNO', None)
+        pageSize = request_dict.get('pageSize', None)
+
+        if not all([pageNo, pageSize]):
+            return response.json(444)
+        try:
+            with transaction.atomic():
+                re_data = {
+                    'package_id': package_id,
+                    'combo_name': combo_name,
+                    'status': status,
+                    'combo_type': combo_type,
+                    'flow_total': flow_total,
+                    'expiration_days': expiration_days,
+                    'expiration_type': expiration_type,
+                    'price': price,
+                    'remark': remark,
+                    'updated_time': updated_time,
+                    'created_time': created_time,
+                    'is_show': is_show
+                }
+                UnicomCombo.objects.filter(id=combo_id).update(**re_data)
+                UnicomCombo.objects.get(id=combo_id).pay_type.set(pay_type)
+                UnicomCombo.objects.create(**re_data).pay_type.set(pay_type)
+                return response.json(0)
+
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_unicom_info(request_dict, response):
+        """
+        获取套餐详细表
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        pageNo = request_dict.get('pageNo', None)
+        pageSize = request_dict.get('pageSize', None)
+        if not all([pageNo, pageSize]):
+            return response.json(444)
+        page = int(pageNo)
+        line = int(pageSize)
+        try:
+            combo_qs = UnicomCombo.objects.filter(is_del=False) \
+                           .order_by('sort').values('id', 'combo_name',
+                                                    'flow_total',
+                                                    'expiration_days',
+                                                    'expiration_type', 'price',
+                                                    'remark')[(page - 1) * line:page * line]
+            if not combo_qs.exists():
+                return response.json(0, [])
+            total = combo_qs.count()
+            combo_list = []
+            for item in combo_qs:
+                # 获取支付方式列表
+                pay_type_qs = Pay_Type.objects.filter(unicomcombo=item['id']).values('id', 'payment')
+                combo_list.append({
+                    'id': item['id'],
+                    'comboName': item['combo_name'],
+                    'flowTotal': item['flow_total'],
+                    'expirationDays': item['expiration_days'],
+                    'expirationType': item['expiration_type'],
+                    'price': item['price'],
+                    'remark': item['remark'],
+                    'payTypes': list(pay_type_qs),
+                })
+            return response.json(0, {'list': combo_list, 'total': total})
+        except Exception as e:
+            return response.json(177, repr(e))
+
+    @classmethod
+    def get_pay_type(cls, request_dict, response):
+        """
+        获取套餐表
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        combo_id = request_dict.get('comboID', None)
+
+        if not all([combo_id]):
+            return response.json(444)
+
+        combo_id_qs = UnicomCombo.objects.filter(id=combo_id).values('pay_type')
+        if combo_id_qs.exists():
+            pass
+        pay_type_qs = Pay_Type.objects.all().values('id', 'payment')
+        if not pay_type_qs.exists():
+            return response.json(444)
+        try:
+            pay_type_list = []
+            for pay_type in pay_type_qs:
+                pay_type_qs.exists()
+                pay_type_list.append(pay_type)
+            return response.json(0, pay_type_list)
+        except Exception as e:
+            return response.json(500, e)

+ 2 - 1
Ansjer/server_urls/loocam_url.py

@@ -9,7 +9,7 @@
 from django.urls import re_path
 from django.urls import re_path
 
 
 from Controller.SensorGateway import GatewayFamilyRoomController, SubDeviceController, GatewayFamilyMemberController, \
 from Controller.SensorGateway import GatewayFamilyRoomController, SubDeviceController, GatewayFamilyMemberController, \
-    EquipmentFamilyController, GatewayDeviceController
+    EquipmentFamilyController, GatewayDeviceController, SmartSceneController
 
 
 urlpatterns = [
 urlpatterns = [
     re_path(r'^sensor/gateway/(?P<operation>.*)$', EquipmentFamilyController.EquipmentFamilyView.as_view()),
     re_path(r'^sensor/gateway/(?P<operation>.*)$', EquipmentFamilyController.EquipmentFamilyView.as_view()),
@@ -18,4 +18,5 @@ urlpatterns = [
             GatewayFamilyMemberController.GatewayFamilyMemberView.as_view()),
             GatewayFamilyMemberController.GatewayFamilyMemberView.as_view()),
     re_path(r'^gateway/subdevice/(?P<operation>.*)$', SubDeviceController.GatewaySubDeviceView.as_view()),
     re_path(r'^gateway/subdevice/(?P<operation>.*)$', SubDeviceController.GatewaySubDeviceView.as_view()),
     re_path(r'^gateway/device/info/(?P<operation>.*)$', GatewayDeviceController.GatewayDeviceView.as_view()),
     re_path(r'^gateway/device/info/(?P<operation>.*)$', GatewayDeviceController.GatewayDeviceView.as_view()),
+    re_path(r'^smartscene/(?P<operation>.*)$', SmartSceneController.SmartSceneView.as_view()),
 ]
 ]

+ 5 - 1
Ansjer/server_urls/unicom_url.py

@@ -8,8 +8,12 @@
 """
 """
 from django.urls import re_path
 from django.urls import re_path
 
 
-from Controller.UnicomCombo import UnicomComboController
+from Controller.UnicomCombo import UnicomComboController, UnicomComboPayNotifyController, UnicomComboTaskController
+from AdminController import UnicomManageController
 
 
 urlpatterns = [
 urlpatterns = [
     re_path(r'^api/(?P<operation>.*)$', UnicomComboController.UnicomComboView.as_view()),
     re_path(r'^api/(?P<operation>.*)$', UnicomComboController.UnicomComboView.as_view()),
+    re_path(r'^wap/pay/(?P<operation>.*)$', UnicomComboPayNotifyController.UnicomComboPayNotifyView.as_view()),
+    re_path(r'^combo/cron/(?P<operation>.*)$', UnicomComboTaskController.UnicomComboTaskView.as_view()),
+    re_path(r'^manage/(?P<operation>.*)$',UnicomManageController.UnicomComboView.as_view()),
 ]
 ]

+ 1 - 0
Ansjer/urls.py

@@ -410,3 +410,4 @@ urlpatterns = [
     re_path('(?P<path>.*)', LogManager.errorPath),
     re_path('(?P<path>.*)', LogManager.errorPath),
 
 
 ]
 ]
+# 鹏提交测试代码

+ 2 - 2
Controller/AiController.py

@@ -369,8 +369,8 @@ class AiView(View):
             device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
             device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
             serial_number = device_info_qs[0]['serial_number']
             serial_number = device_info_qs[0]['serial_number']
             device_type = device_info_qs[0]['Type']
             device_type = device_info_qs[0]['Type']
-            if serial_number and device_type == 101:
-                ai_service_data['uid'] = CommonService.get_full_serial_number(uid, serial_number, device_type)
+            if serial_number:
+                ai_service_data['serial_number'] = CommonService.get_full_serial_number(uid, serial_number, device_type)
 
 
             ai_service_data['endTime'] = sum_end_time
             ai_service_data['endTime'] = sum_end_time
             return response.json(0, [ai_service_data])
             return response.json(0, [ai_service_data])

+ 6 - 6
Controller/CloudStorage.py

@@ -743,7 +743,7 @@ class CloudStorageView(View):
                     device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                     device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                     serial_number = device_info_qs[0]['serial_number']
                     serial_number = device_info_qs[0]['serial_number']
                     device_type = device_info_qs[0]['Type']
                     device_type = device_info_qs[0]['Type']
-                    if serial_number and device_type == 101:
+                    if serial_number:
                         device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                         device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                     else:
                     else:
                         device_name = UID
                         device_name = UID
@@ -898,7 +898,7 @@ class CloudStorageView(View):
                 device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                 device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                 serial_number = device_info_qs[0]['serial_number']
                 serial_number = device_info_qs[0]['serial_number']
                 device_type = device_info_qs[0]['Type']
                 device_type = device_info_qs[0]['Type']
-                if serial_number and device_type == 101:
+                if serial_number:
                     device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                     device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                 else:
                 else:
                     device_name = UID
                     device_name = UID
@@ -1033,7 +1033,7 @@ class CloudStorageView(View):
                     device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                     device_info_qs = Device_Info.objects.filter(UID=UID).values('serial_number', 'Type')
                     serial_number = device_info_qs[0]['serial_number']
                     serial_number = device_info_qs[0]['serial_number']
                     device_type = device_info_qs[0]['Type']
                     device_type = device_info_qs[0]['Type']
-                    if serial_number and device_type == 101:
+                    if serial_number:
                         device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                         device_name = CommonService.get_full_serial_number(UID, serial_number, device_type)
                     else:
                     else:
                         device_name = UID
                         device_name = UID
@@ -1387,7 +1387,7 @@ class CloudStorageView(View):
                 device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
                 device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
                 serial_number = device_info_qs[0]['serial_number']
                 serial_number = device_info_qs[0]['serial_number']
                 device_type = device_info_qs[0]['Type']
                 device_type = device_info_qs[0]['Type']
-                if serial_number and device_type == 101:
+                if serial_number:
                     device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
                     device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
                 else:
                 else:
                     device_name = uid
                     device_name = uid
@@ -1489,7 +1489,7 @@ class CloudStorageView(View):
         device_id = uid
         device_id = uid
         serial_number = dv_qs[0]['serial_number']
         serial_number = dv_qs[0]['serial_number']
         device_type = dv_qs[0]['Type']
         device_type = dv_qs[0]['Type']
-        if serial_number and device_type == 101:
+        if serial_number:
             device_id = CommonService.get_full_serial_number(uid, serial_number, device_type)
             device_id = CommonService.get_full_serial_number(uid, serial_number, device_type)
 
 
         uid_bucket[0]['uid'] = device_id
         uid_bucket[0]['uid'] = device_id
@@ -1638,7 +1638,7 @@ class CloudStorageView(View):
                     device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
                     device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
                     serial_number = device_info_qs[0]['serial_number']
                     serial_number = device_info_qs[0]['serial_number']
                     device_type = device_info_qs[0]['Type']
                     device_type = device_info_qs[0]['Type']
-                    if serial_number and device_type == 101:
+                    if serial_number:
                         device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
                         device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
                     else:
                     else:
                         device_name = uid
                         device_name = uid

+ 78 - 75
Controller/DetectController.py

@@ -88,83 +88,86 @@ class DetectControllerView(View):
         #     qs = qs.filter(eventTime__range=(startTime, endTime))
         #     qs = qs.filter(eventTime__range=(startTime, endTime))
         # if eventType:
         # if eventType:
         #     qs = qs.filter(eventType=eventType)
         #     qs = qs.filter(eventType=eventType)
-        if startTime and endTime:
-            qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
-                                                                               endTime, eventType,
-                                                                               request_dict.get('uids', None))
+        try:
+            if startTime and endTime:
+                qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
+                                                                                   endTime, eventType,
+                                                                                   request_dict.get('uids', None))
 
 
-        else:
-            # 默认查询近七天消息推送
-            qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
-                                                                         eventType,
-                                                                         request_dict.get('uids', None))
-        logger.info('<<<|||分表查询结果count:{}'.format(count))
-        uids = request_dict.get('uids', None)
-        if uids:
-            uid_list = uids.split(',')
-            # qs = qs.filter(devUid__in=uid_list)
-            dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        else:
-            dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        # print(uid_type_dict)
-        if not qs or count == 0 or not qs.exists():
-            return response.json(0, {'datas': [], 'count': 0})
-        # if not qs.exists():
-        #     return response.json(0, {'datas': [], 'count': 0})
-        # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
-        #                'receiveTime', 'is_st', 'addTime')
-
-        # count = qs.count()
-        # qr = qs[(page - 1) * line:page * line]
-        qr = qs
-        res = []
-        auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
-        img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
-        # vod_time_list = []
-        for p in qr:
-            devUid = p['devUid']
-            eventTime = p['eventTime']
-            channel = p['Channel']
-            if p['is_st'] == 1:
-                p['img'] = img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
-                                               format(uid=devUid, channel=p['Channel'], time=eventTime), 300)
-                p['img_list'] = [img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
-                                                     format(uid=devUid, channel=channel, time=eventTime), 300)]
-            elif p['is_st'] == 2:
-                # 列表装载回放时间戳标记
-                vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
-                    .values("bucket__bucket", "bucket__endpoint")
-                # print(vodqs)
-                if vodqs.exists():
-                    bucket_name = vodqs[0]['bucket__bucket']
-                    endpoint = vodqs[0]['bucket__endpoint']
-                    bucket = oss2.Bucket(auth, endpoint, bucket_name)
-                    ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
-                    thumb0 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
-                    thumb1 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
-                    thumb2 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
-                    # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
-                    p['img_list'] = [thumb0, thumb1, thumb2]
-            elif p['is_st'] == 3:
-                # 列表装载回放时间戳标记
-                p['img_list'] = []
-                for i in range(p['is_st']):
-                    img = img_bucket.sign_url('GET', '{uid}/{channel}/{time}_{st}.jpeg'.
-                                              format(uid=devUid, channel=p['Channel'], time=eventTime, st=i), 300)
-                    p['img_list'].append(img)
-            if devUid in uid_type_dict.keys():
-                p['uid_type'] = uid_type_dict[devUid]['type']
-                p['devNickName'] = uid_type_dict[devUid]['NickName']
             else:
             else:
-                p['uid_type'] = ''
-            res.append(p)
-        return response.json(0, {'datas': res, 'count': count})
+                # 默认查询近七天消息推送
+                qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
+                                                                             eventType,
+                                                                             request_dict.get('uids', None))
+            logger.info('<<<|||分表查询结果count:{}'.format(count))
+            uids = request_dict.get('uids', None)
+            if uids:
+                uid_list = uids.split(',')
+                # qs = qs.filter(devUid__in=uid_list)
+                dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            else:
+                dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            # print(uid_type_dict)
+            if not qs or count == 0 or not qs.exists():
+                return response.json(0, {'datas': [], 'count': 0})
+            # if not qs.exists():
+            #     return response.json(0, {'datas': [], 'count': 0})
+            # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
+            #                'receiveTime', 'is_st', 'addTime')
+
+            # count = qs.count()
+            # qr = qs[(page - 1) * line:page * line]
+            qr = qs
+            res = []
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+            # vod_time_list = []
+            for p in qr:
+                devUid = p['devUid']
+                eventTime = p['eventTime']
+                channel = p['Channel']
+                if p['is_st'] == 1:
+                    p['img'] = img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
+                                                   format(uid=devUid, channel=p['Channel'], time=eventTime), 300)
+                    p['img_list'] = [img_bucket.sign_url('GET', '{uid}/{channel}/{time}.jpeg'.
+                                                         format(uid=devUid, channel=channel, time=eventTime), 300)]
+                elif p['is_st'] == 2:
+                    # 列表装载回放时间戳标记
+                    vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
+                        .values("bucket__bucket", "bucket__endpoint")
+                    # print(vodqs)
+                    if vodqs.exists():
+                        bucket_name = vodqs[0]['bucket__bucket']
+                        endpoint = vodqs[0]['bucket__endpoint']
+                        bucket = oss2.Bucket(auth, endpoint, bucket_name)
+                        ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
+                        thumb0 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
+                        thumb1 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
+                        thumb2 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
+                        # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
+                        p['img_list'] = [thumb0, thumb1, thumb2]
+                elif p['is_st'] == 3:
+                    # 列表装载回放时间戳标记
+                    p['img_list'] = []
+                    for i in range(p['is_st']):
+                        img = img_bucket.sign_url('GET', '{uid}/{channel}/{time}_{st}.jpeg'.
+                                                  format(uid=devUid, channel=p['Channel'], time=eventTime, st=i), 300)
+                        p['img_list'].append(img)
+                if devUid in uid_type_dict.keys():
+                    p['uid_type'] = uid_type_dict[devUid]['type']
+                    p['devNickName'] = uid_type_dict[devUid]['NickName']
+                else:
+                    p['uid_type'] = ''
+                res.append(p)
+            return response.json(0, {'datas': res, 'count': count})
+        except Exception as e:
+            return response.json(474)
 
 
     def do_change_status(self, userID, request_dict, response):
     def do_change_status(self, userID, request_dict, response):
         token_val = request_dict.get('token_val', None)
         token_val = request_dict.get('token_val', None)

+ 144 - 141
Controller/DetectControllerV2.py

@@ -300,156 +300,159 @@ class DetectControllerViewV2(View):
 
 
         # qs = Equipment_Info.objects.filter(userID_id=userID).order_by('-eventTime')
         # qs = Equipment_Info.objects.filter(userID_id=userID).order_by('-eventTime')
         # qs = qs.filter(eventTime__gt=now_time - 3600 * 168)
         # qs = qs.filter(eventTime__gt=now_time - 3600 * 168)
-        # 根据时间筛选消息推送
-        if startTime and endTime:
-            qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
-                                                                               endTime, eventType,
-                                                                               request_dict.get('uids', None))
+        try:
+            # 根据时间筛选消息推送
+            if startTime and endTime:
+                qs, count = EquipmentInfoService.find_by_start_time_equipment_info(page, line, userID, startTime,
+                                                                                   endTime, eventType,
+                                                                                   request_dict.get('uids', None))
 
 
-        else:
-            # 默认查询近七天消息推送
-            qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
-                                                                         eventType,
-                                                                         request_dict.get('uids', None))
-        # if startTime and endTime:
-        #     qs = qs.filter(eventTime__range=(startTime, endTime))
-        # if eventType:
-        #     if ',' in eventType:  # 兼容AI查询
-        #         eventTypeList = eventType.split(',')
-        #         eventTypeList = [int(i.strip()) for i in eventTypeList]
-        #         qs = qs.filter(eventType__in=eventTypeList)
-        #     else:
-        #         qs = qs.filter(eventType=eventType)
-        uids = request_dict.get('uids', None)
-        if uids:
-            uid_list = uids.split(',')
-            # qs = qs.filter(devUid__in=uid_list)
-            dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        else:
-            dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
-            uid_type_dict = {}
-            for dv in dvqs:
-                uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
-        # print(uid_type_dict)
-        if not qs or count == 0 or not qs.exists():
-            return response.json(0, {'datas': [], 'count': 0})
-        # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
-        #                'receiveTime', 'is_st', 'addTime', 'storage_location', 'borderCoords')
-
-        # count = qs.count()
-        # qr = qs[(page - 1) * line:page * line]
-        qr = qs
-        res = []
-        auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
-        oss_img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
-        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'
-        )
-        aws_s3_guowai = boto3.client(
-            's3',
-            aws_access_key_id=AWS_ACCESS_KEY_ID[1],
-            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
-            config=botocore.client.Config(signature_version='s3v4'),
-            region_name='us-east-1'
-        )
-        # vod_time_list = []
-        # ai消息标识所有组合标签
-        ai_all_event_type = EquipmentInfoService.get_all_comb_event_type()
-        for p in qr:
-            devUid = p['devUid']
-            eventTime = p['eventTime']
-            channel = p['Channel']
-            storage_location = p['storage_location']
-            if p['is_st'] == 1:
-                thumbspng = '{uid}/{channel}/{time}.jpeg'.format(uid=devUid, channel=p['Channel'], time=eventTime)
-                if storage_location == 1:  # oss
-                    response_url = oss_img_bucket.sign_url('GET', thumbspng, 300)
-                    p['img'] = response_url
-                    p['img_list'] = [response_url]
-                elif region == 2 and storage_location == 2:  # 2:国内,aws
-                    response_url = aws_s3_guonei.generate_presigned_url('get_object',
-                                                                        Params={'Bucket': 'push', 'Key': thumbspng},
-                                                                        ExpiresIn=300)
-                    p['img'] = response_url
-                    p['img_list'] = [response_url]
-                elif region == 1 and storage_location == 2:  # 1:国外,aws
-                    response_url = aws_s3_guowai.generate_presigned_url('get_object',
-                                                                        Params={'Bucket': 'foreignpush',
-                                                                                'Key': thumbspng},
-                                                                        ExpiresIn=300)
-                    p['img'] = response_url
-                    p['img_list'] = [response_url]
-
-            elif p['is_st'] == 2:
-                # 列表装载回放时间戳标记
-                vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
-                    .values("bucket__bucket", "bucket__endpoint")
-                # print(vodqs)
-                if vodqs.exists():
-                    bucket_name = vodqs[0]['bucket__bucket']
-                    endpoint = vodqs[0]['bucket__endpoint']
-                    bucket = oss2.Bucket(auth, endpoint, bucket_name)
-                    ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
-                    if storage_location == 1:  # oss
-                        thumb0 = bucket.sign_url('GET', ts, 3600,
-                                                 params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
-                        thumb1 = bucket.sign_url('GET', ts, 3600,
-                                                 params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
-                        thumb2 = bucket.sign_url('GET', ts, 3600,
-                                                 params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
-                        # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
-                        p['img_list'] = [thumb0, thumb1, thumb2]
-                    elif region == 2 and storage_location == 2:  # 2:国内,aws
-                        thumb = aws_s3_guonei.generate_presigned_url('get_object',
-                                                                     Params={'Bucket': 'push', 'Key': ts},
-                                                                     ExpiresIn=3600)
-                        p['img_list'] = [thumb]
-                    elif region == 1 and storage_location == 2:  # 1:国外,aws
-                        thumb = aws_s3_guowai.generate_presigned_url('get_object',
-                                                                     Params={'Bucket': 'foreignpush', 'Key': ts},
-                                                                     ExpiresIn=3600)
-                        p['img_list'] = [thumb]
-            elif p['is_st'] == 3 or p['is_st'] == 4:
-                # 列表装载回放时间戳标记
-                p['img_list'] = []
-                for i in range(p['is_st']):
-                    thumbspng = '{uid}/{channel}/{time}_{st}.jpeg'.format(uid=devUid, channel=p['Channel'],
-                                                                          time=eventTime, st=i)
+            else:
+                # 默认查询近七天消息推送
+                qs, count = EquipmentInfoService.get_equipment_info_week_all(page, line, userID, startTime, endTime,
+                                                                             eventType,
+                                                                             request_dict.get('uids', None))
+            # if startTime and endTime:
+            #     qs = qs.filter(eventTime__range=(startTime, endTime))
+            # if eventType:
+            #     if ',' in eventType:  # 兼容AI查询
+            #         eventTypeList = eventType.split(',')
+            #         eventTypeList = [int(i.strip()) for i in eventTypeList]
+            #         qs = qs.filter(eventType__in=eventTypeList)
+            #     else:
+            #         qs = qs.filter(eventType=eventType)
+            uids = request_dict.get('uids', None)
+            if uids:
+                uid_list = uids.split(',')
+                # qs = qs.filter(devUid__in=uid_list)
+                dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            else:
+                dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
+                uid_type_dict = {}
+                for dv in dvqs:
+                    uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
+            # print(uid_type_dict)
+            if not qs or count == 0 or not qs.exists():
+                return response.json(0, {'datas': [], 'count': 0})
+            # qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
+            #                'receiveTime', 'is_st', 'addTime', 'storage_location', 'borderCoords')
+
+            # count = qs.count()
+            # qr = qs[(page - 1) * line:page * line]
+            qr = qs
+            res = []
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            oss_img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+            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'
+            )
+            aws_s3_guowai = boto3.client(
+                's3',
+                aws_access_key_id=AWS_ACCESS_KEY_ID[1],
+                aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
+                config=botocore.client.Config(signature_version='s3v4'),
+                region_name='us-east-1'
+            )
+            # vod_time_list = []
+            # ai消息标识所有组合标签
+            ai_all_event_type = EquipmentInfoService.get_all_comb_event_type()
+            for p in qr:
+                devUid = p['devUid']
+                eventTime = p['eventTime']
+                channel = p['Channel']
+                storage_location = p['storage_location']
+                if p['is_st'] == 1:
+                    thumbspng = '{uid}/{channel}/{time}.jpeg'.format(uid=devUid, channel=p['Channel'], time=eventTime)
                     if storage_location == 1:  # oss
                     if storage_location == 1:  # oss
-                        img = oss_img_bucket.sign_url('GET', thumbspng, 300)
-                        p['img_list'].append(img)
-                    elif region == 2 and storage_location == 2:  # 2:国内,aws
+                        response_url = oss_img_bucket.sign_url('GET', thumbspng, 300)
+                        p['img'] = response_url
+                        p['img_list'] = [response_url]
+                    elif region == 2 and storage_location == 2:  # 2:国内,aws
                         response_url = aws_s3_guonei.generate_presigned_url('get_object',
                         response_url = aws_s3_guonei.generate_presigned_url('get_object',
                                                                             Params={'Bucket': 'push', 'Key': thumbspng},
                                                                             Params={'Bucket': 'push', 'Key': thumbspng},
                                                                             ExpiresIn=300)
                                                                             ExpiresIn=300)
-                        img = response_url
-                        p['img_list'].append(img)
-                    elif region == 1 and storage_location == 2:  # 1:国外,aws
+                        p['img'] = response_url
+                        p['img_list'] = [response_url]
+                    elif region == 1 and storage_location == 2:  # 1:国外,aws
                         response_url = aws_s3_guowai.generate_presigned_url('get_object',
                         response_url = aws_s3_guowai.generate_presigned_url('get_object',
                                                                             Params={'Bucket': 'foreignpush',
                                                                             Params={'Bucket': 'foreignpush',
                                                                                     'Key': thumbspng},
                                                                                     'Key': thumbspng},
                                                                             ExpiresIn=300)
                                                                             ExpiresIn=300)
-                        img = response_url
-                        p['img_list'].append(img)
-            if devUid in uid_type_dict.keys():
-                p['uid_type'] = uid_type_dict[devUid]['type']
-                p['devNickName'] = uid_type_dict[devUid]['NickName']
-            else:
-                p['uid_type'] = ''
-
-            p['borderCoords'] = '' if p['borderCoords'] == '' else json.loads(p['borderCoords'])  # ai消息坐标信息
-            p['ai_event_type_list'] = []
-            if p['eventType'] in ai_all_event_type:  # 如果是ai消息类型,则分解eventType, 如:123 -> [1,2,3]
-                p['ai_event_type_list'] = list(map(int, str(p['eventType'])))
-            res.append(p)
-        return response.json(0, {'datas': res, 'count': count})
+                        p['img'] = response_url
+                        p['img_list'] = [response_url]
+
+                elif p['is_st'] == 2:
+                    # 列表装载回放时间戳标记
+                    vodqs = VodHlsModel.objects.filter(uid=devUid, channel=channel, time=int(eventTime)) \
+                        .values("bucket__bucket", "bucket__endpoint")
+                    # print(vodqs)
+                    if vodqs.exists():
+                        bucket_name = vodqs[0]['bucket__bucket']
+                        endpoint = vodqs[0]['bucket__endpoint']
+                        bucket = oss2.Bucket(auth, endpoint, bucket_name)
+                        ts = '{uid}/vod{channel}/{etime}/ts0.ts'.format(uid=devUid, channel=p['Channel'], etime=eventTime)
+                        if storage_location == 1:  # oss
+                            thumb0 = bucket.sign_url('GET', ts, 3600,
+                                                     params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
+                            thumb1 = bucket.sign_url('GET', ts, 3600,
+                                                     params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
+                            thumb2 = bucket.sign_url('GET', ts, 3600,
+                                                     params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
+                            # thumb3 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_3000,w_700'})
+                            p['img_list'] = [thumb0, thumb1, thumb2]
+                        elif region == 2 and storage_location == 2:  # 2:国内,aws
+                            thumb = aws_s3_guonei.generate_presigned_url('get_object',
+                                                                         Params={'Bucket': 'push', 'Key': ts},
+                                                                         ExpiresIn=3600)
+                            p['img_list'] = [thumb]
+                        elif region == 1 and storage_location == 2:  # 1:国外,aws
+                            thumb = aws_s3_guowai.generate_presigned_url('get_object',
+                                                                         Params={'Bucket': 'foreignpush', 'Key': ts},
+                                                                         ExpiresIn=3600)
+                            p['img_list'] = [thumb]
+                elif p['is_st'] == 3 or p['is_st'] == 4:
+                    # 列表装载回放时间戳标记
+                    p['img_list'] = []
+                    for i in range(p['is_st']):
+                        thumbspng = '{uid}/{channel}/{time}_{st}.jpeg'.format(uid=devUid, channel=p['Channel'],
+                                                                              time=eventTime, st=i)
+                        if storage_location == 1:  # oss
+                            img = oss_img_bucket.sign_url('GET', thumbspng, 300)
+                            p['img_list'].append(img)
+                        elif region == 2 and storage_location == 2:  # 2:国内,aws
+                            response_url = aws_s3_guonei.generate_presigned_url('get_object',
+                                                                                Params={'Bucket': 'push', 'Key': thumbspng},
+                                                                                ExpiresIn=300)
+                            img = response_url
+                            p['img_list'].append(img)
+                        elif region == 1 and storage_location == 2:  # 1:国外,aws
+                            response_url = aws_s3_guowai.generate_presigned_url('get_object',
+                                                                                Params={'Bucket': 'foreignpush',
+                                                                                        'Key': thumbspng},
+                                                                                ExpiresIn=300)
+                            img = response_url
+                            p['img_list'].append(img)
+                if devUid in uid_type_dict.keys():
+                    p['uid_type'] = uid_type_dict[devUid]['type']
+                    p['devNickName'] = uid_type_dict[devUid]['NickName']
+                else:
+                    p['uid_type'] = ''
+
+                p['borderCoords'] = '' if p['borderCoords'] == '' else json.loads(p['borderCoords'])  # ai消息坐标信息
+                p['ai_event_type_list'] = []
+                if p['eventType'] in ai_all_event_type:  # 如果是ai消息类型,则分解eventType, 如:123 -> [1,2,3]
+                    p['ai_event_type_list'] = list(map(int, str(p['eventType'])))
+                res.append(p)
+            return response.json(0, {'datas': res, 'count': count})
+        except Exception as e:
+            return response.json(474)
 
 
     def do_update_interval(self, userID, request_dict, response):
     def do_update_interval(self, userID, request_dict, response):
         uid = request_dict.get('uid', None)
         uid = request_dict.get('uid', None)

+ 2 - 2
Controller/EquipmentManagerV2.py

@@ -326,8 +326,8 @@ class EquipmentManagerV2(View):
 
 
         for p in dvls:
         for p in dvls:
             # 如果存在序列号返回完整序列号
             # 如果存在序列号返回完整序列号
-            if p['serial_number'] and p['Type'] == 101:
-                p['UID'] = CommonService.get_full_serial_number(p['UID'], p['serial_number'], p['Type'])
+            if p['serial_number']:
+                p['serial_number'] = CommonService.get_full_serial_number(p['UID'], p['serial_number'], p['Type'])
             # 新增IOT
             # 新增IOT
             p['iot'] = []
             p['iot'] = []
             for iot in iotqs:
             for iot in iotqs:

+ 57 - 52
Controller/EquipmentManagerV3.py

@@ -1,24 +1,23 @@
+import json
 import re
 import re
 import threading
 import threading
 import time
 import time
-import traceback
 
 
+import base64
+import oss2
 import requests
 import requests
-
-from Controller.CheckUserData import RandomStr
-import oss2, base64
 from django.db.models import Q
 from django.db.models import Q
 from django.views.generic.base import View
 from django.views.generic.base import View
+
+from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY
+from Controller.CheckUserData import RandomStr
 from Controller.DeviceConfirmRegion import Device_Region
 from Controller.DeviceConfirmRegion import Device_Region
-from Object.RedisObject import RedisObject
-from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY, BASE_DIR
-from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel, UidChannelSetModel, \
-    Device_User, iotdeviceInfoModel, UIDCompanySerialModel, UIDMainUser, UIDModel
+from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidChannelSetModel, \
+    Device_User, iotdeviceInfoModel, UIDCompanySerialModel, UIDModel, UnicomDeviceInfo
 from Object.ResponseObject import ResponseObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
 from Service.CommonService import CommonService
 from Service.ModelService import ModelService
 from Service.ModelService import ModelService
-import time, json
 
 
 
 
 class EquipmentManagerV3(View):
 class EquipmentManagerV3(View):
@@ -61,7 +60,7 @@ class EquipmentManagerV3(View):
         elif operation == 'fuzzyQuery':
         elif operation == 'fuzzyQuery':
             return self.do_fuzzy_query(userID, request_dict, response)
             return self.do_fuzzy_query(userID, request_dict, response)
         elif operation == 'mainUserDevice':
         elif operation == 'mainUserDevice':
-            return self.do_mainUserDevice( request_dict, response)
+            return self.do_mainUserDevice(request_dict, response)
         elif operation == 'getDeviceFeatures':
         elif operation == 'getDeviceFeatures':
             return self.do_get_device_features(request_dict, response)
             return self.do_get_device_features(request_dict, response)
         else:
         else:
@@ -111,19 +110,18 @@ class EquipmentManagerV3(View):
         primaryMaster = ''
         primaryMaster = ''
         isShare = False
         isShare = False
 
 
-        is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID', 'primaryMaster')
+        is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID',
+                                                                            'primaryMaster')
 
 
         if main_exist.exists():
         if main_exist.exists():
             vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
             vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
             vodPrimaryMaster = main_exist[0]['vodPrimaryMaster']
             vodPrimaryMaster = main_exist[0]['vodPrimaryMaster']
 
 
-
         if is_bind.exists():
         if is_bind.exists():
             primaryUserID = is_bind[0]['primaryUserID']
             primaryUserID = is_bind[0]['primaryUserID']
             primaryMaster = is_bind[0]['primaryMaster']
             primaryMaster = is_bind[0]['primaryMaster']
             isShare = True
             isShare = True
 
 
-
         isusermain = False
         isusermain = False
         if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (primaryUserID != userID and primaryUserID != ''):
         if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (primaryUserID != userID and primaryUserID != ''):
             isusermain = True
             isusermain = True
@@ -192,8 +190,8 @@ class EquipmentManagerV3(View):
                 # 多通道设备设置通道名
                 # 多通道设备设置通道名
                 if Type in dvr_type_list:
                 if Type in dvr_type_list:
                     UidChannelSet_bulk = []
                     UidChannelSet_bulk = []
-                    for i in range(1, ChannelIndex+1):
-                        channel_name = 'channel'+str(i)  # channel1,channel2...
+                    for i in range(1, ChannelIndex + 1):
+                        channel_name = 'channel' + str(i)  # channel1,channel2...
                         UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
                         UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
                         UidChannelSet_bulk.append(UidChannelSet)
                         UidChannelSet_bulk.append(UidChannelSet)
                     UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
                     UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
@@ -218,7 +216,7 @@ class EquipmentManagerV3(View):
             if us_qs.exists() and us_qs[0].is_alexa == 1:
             if us_qs.exists() and us_qs[0].is_alexa == 1:
                 if us_qs[0].channel > 1:
                 if us_qs[0].channel > 1:
                     data_list = []
                     data_list = []
-                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id).\
+                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id). \
                         values('channel', 'channel_name')
                         values('channel', 'channel_name')
                     if uid_channel_set_qs.exists():
                     if uid_channel_set_qs.exists():
                         # 多通道设备名为 UidChannelSetModel 的 channel_name
                         # 多通道设备名为 UidChannelSetModel 的 channel_name
@@ -255,15 +253,13 @@ class EquipmentManagerV3(View):
             iotqs = iotdeviceInfoModel.objects.filter(serial_number=dvql[0]['serial_number'])
             iotqs = iotdeviceInfoModel.objects.filter(serial_number=dvql[0]['serial_number'])
             if iotqs.exists():
             if iotqs.exists():
                 res['iot'] = {
                 res['iot'] = {
-                        'endpoint': iotqs[0].endpoint,
-                        'token_iot_number': iotqs[0].endpoint
+                    'endpoint': iotqs[0].endpoint,
+                    'token_iot_number': iotqs[0].endpoint
                 }
                 }
 
 
-            # 除C1的序列号暂时返回''
-            if res['serial_number'] and Type == 101:
+            # 存在序列号返回完整序列号
+            if res['serial_number']:
                 res['serial_number'] = CommonService.get_full_serial_number(UID, res['serial_number'], Type)
                 res['serial_number'] = CommonService.get_full_serial_number(UID, res['serial_number'], Type)
-            else:
-                res['serial_number'] = ''
 
 
             return response.json(0, res)
             return response.json(0, res)
 
 
@@ -275,16 +271,16 @@ class EquipmentManagerV3(View):
             return response.json(444, {'param': 'uidContent'})
             return response.json(444, {'param': 'uidContent'})
 
 
         try:
         try:
-            deviceNumber = 0            # 添加成功数量
-            add_success_flag = False    # 添加成功标识
-            exception_flag = False      # 异常标识
-            exists_flag = False         # 已存在标识
+            deviceNumber = 0  # 添加成功数量
+            add_success_flag = False  # 添加成功标识
+            exception_flag = False  # 异常标识
+            exists_flag = False  # 已存在标识
             uid_content_list = eval(uidContent)
             uid_content_list = eval(uidContent)
             print('uidContent: ', uid_content_list)
             print('uidContent: ', uid_content_list)
             re_uid = re.compile(r'^[A-Za-z0-9]{14,20}$')
             re_uid = re.compile(r'^[A-Za-z0-9]{14,20}$')
             for uid_content in uid_content_list:
             for uid_content in uid_content_list:
                 exception_flag = False  # 重置异常标识
                 exception_flag = False  # 重置异常标识
-                exists_flag = False     # 已存在标识
+                exists_flag = False  # 已存在标识
                 UID = uid_content['uid']
                 UID = uid_content['uid']
                 NickName = uid_content['nickName']
                 NickName = uid_content['nickName']
                 Type = uid_content['type']
                 Type = uid_content['type']
@@ -297,7 +293,7 @@ class EquipmentManagerV3(View):
                 if not all([UID, NickName, View_Account]):  # Type和ChannelIndex可能为0
                 if not all([UID, NickName, View_Account]):  # Type和ChannelIndex可能为0
                     return response.json(444, {'param': 'UID, NickName, View_Account'})
                     return response.json(444, {'param': 'UID, NickName, View_Account'})
 
 
-                if not re_uid.match(UID):   # 检查uid长度
+                if not re_uid.match(UID):  # 检查uid长度
                     return response.json(444, {'error uid length': UID})
                     return response.json(444, {'error uid length': UID})
 
 
                 device_info_qs = Device_Info.objects.filter(UID=UID, userID_id=userID)
                 device_info_qs = Device_Info.objects.filter(UID=UID, userID_id=userID)
@@ -321,7 +317,8 @@ class EquipmentManagerV3(View):
                 primaryMaster = ''
                 primaryMaster = ''
                 isShare = False
                 isShare = False
 
 
-                is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID', 'primaryMaster')
+                is_bind = Device_Info.objects.filter(UID=UID, isShare=False).values('userID__userID', 'primaryUserID',
+                                                                                    'primaryMaster')
 
 
                 if main_exist.exists():
                 if main_exist.exists():
                     vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
                     vodPrimaryUserID = main_exist[0]['vodPrimaryUserID']
@@ -333,7 +330,8 @@ class EquipmentManagerV3(View):
                     isShare = True
                     isShare = True
 
 
                 isusermain = False
                 isusermain = False
-                if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (primaryUserID != userID and primaryUserID != ''):
+                if (vodPrimaryUserID != userID and vodPrimaryUserID != '') or (
+                        primaryUserID != userID and primaryUserID != ''):
                     isusermain = True
                     isusermain = True
 
 
                 # 判断是否有已绑定用户
                 # 判断是否有已绑定用户
@@ -400,14 +398,15 @@ class EquipmentManagerV3(View):
                     multi_channel_list = [1, 2, 3, 4, 10001]
                     multi_channel_list = [1, 2, 3, 4, 10001]
                     if Type in multi_channel_list:
                     if Type in multi_channel_list:
                         UidChannelSet_bulk = []
                         UidChannelSet_bulk = []
-                        for i in range(1, ChannelIndex+1):
-                            channel_name = 'channel'+str(i)  # channel1,channel2...
+                        for i in range(1, ChannelIndex + 1):
+                            channel_name = 'channel' + str(i)  # channel1,channel2...
                             UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
                             UidChannelSet = UidChannelSetModel(uid_id=UidSet_id, channel=i, channel_name=channel_name)
                             UidChannelSet_bulk.append(UidChannelSet)
                             UidChannelSet_bulk.append(UidChannelSet)
                         UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
                         UidChannelSetModel.objects.bulk_create(UidChannelSet_bulk)
 
 
                 userDevice = Device_Info(id=id, userID_id=userID, UID=UID, NickName=NickName, View_Account=View_Account,
                 userDevice = Device_Info(id=id, userID_id=userID, UID=UID, NickName=NickName, View_Account=View_Account,
-                                         View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex, version=version,
+                                         View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex,
+                                         version=version,
                                          vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
                                          vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
                 userDevice.save()
                 userDevice.save()
                 uid_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=UID)
                 uid_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=UID)
@@ -426,13 +425,14 @@ class EquipmentManagerV3(View):
                 if us_qs.exists() and us_qs[0].is_alexa == 1:
                 if us_qs.exists() and us_qs[0].is_alexa == 1:
                     if us_qs[0].channel > 1:
                     if us_qs[0].channel > 1:
                         data_list = []
                         data_list = []
-                        uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id).\
+                        uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us_qs[0].id). \
                             values('channel', 'channel_name')
                             values('channel', 'channel_name')
                         if uid_channel_set_qs.exists():
                         if uid_channel_set_qs.exists():
                             # 多通道设备名为 UidChannelSetModel 的 channel_name
                             # 多通道设备名为 UidChannelSetModel 的 channel_name
                             for uid_channel_set in uid_channel_set_qs:
                             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': encryptPassword})
+                                data_list.append(
+                                    {'userID': userID, 'UID': UID, 'uid_nick': uid_channel_set['channel_name'],
+                                     'channel': uid_channel_set['channel'], 'password': encryptPassword})
                     else:
                     else:
                         data_list = [{'userID': userID, 'UID': UID, 'uid_nick': NickName, 'password': encryptPassword}]
                         data_list = [{'userID': userID, 'UID': UID, 'uid_nick': NickName, 'password': encryptPassword}]
 
 
@@ -449,7 +449,8 @@ class EquipmentManagerV3(View):
                                                                 'vodPrimaryUserID', 'vodPrimaryMaster',
                                                                 'vodPrimaryUserID', 'vodPrimaryMaster',
                                                                 'userID__userEmail',
                                                                 'userID__userEmail',
                                                                 'data_joined', 'version',
                                                                 'data_joined', 'version',
-                                                                'isVod', 'isExist', 'isCameraOpenCloud', 'serial_number')
+                                                                'isVod', 'isExist', 'isCameraOpenCloud',
+                                                                'serial_number')
                 dvql = CommonService.qs_to_list(dvqs)
                 dvql = CommonService.qs_to_list(dvqs)
                 ubqs = UID_Bucket.objects.filter(uid=UID). \
                 ubqs = UID_Bucket.objects.filter(uid=UID). \
                     values('bucket__content', 'status', 'channel', 'endTime', 'uid')
                     values('bucket__content', 'status', 'channel', 'endTime', 'uid')
@@ -467,9 +468,9 @@ class EquipmentManagerV3(View):
             exception_flag = True
             exception_flag = True
             pass
             pass
         finally:
         finally:
-            if add_success_flag:    # 有一台添加成功则返回成功
+            if add_success_flag:  # 有一台添加成功则返回成功
                 return response.json(0, success_res)
                 return response.json(0, success_res)
-            if exists_flag:         # 全部设备已存在
+            if exists_flag:  # 全部设备已存在
                 return response.json(174, exists_res)
                 return response.json(174, exists_res)
             if exception_flag:
             if exception_flag:
                 return response.json(500, error_res)
                 return response.json(500, error_res)
@@ -579,7 +580,7 @@ class EquipmentManagerV3(View):
         dvqs = Device_Info.objects.filter(userID_id=userID)
         dvqs = Device_Info.objects.filter(userID_id=userID)
         # # 过滤已重置的设备
         # # 过滤已重置的设备
         dvqs = dvqs.filter(~Q(isExist=2))
         dvqs = dvqs.filter(~Q(isExist=2))
-        dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account','View_Password', 'ChannelIndex',
+        dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account', 'View_Password', 'ChannelIndex',
                            'Type', 'isShare', 'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID',
                            'Type', 'isShare', 'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID',
                            'vodPrimaryMaster', 'userID__userEmail', 'version', 'isVod', 'isExist', 'NotificationMode',
                            'vodPrimaryMaster', 'userID__userEmail', 'version', 'isVod', 'isExist', 'NotificationMode',
                            'isCameraOpenCloud', 'serial_number')
                            'isCameraOpenCloud', 'serial_number')
@@ -607,7 +608,8 @@ class EquipmentManagerV3(View):
                                                                     'TimeZone', 'TimeStatus', 'SpaceUsable',
                                                                     'TimeZone', 'TimeStatus', 'SpaceUsable',
                                                                     'SpaceSum', 'MirrorType', 'RecordType',
                                                                     'SpaceSum', 'MirrorType', 'RecordType',
                                                                     'OutdoorModel', 'WIFIName', 'isDetector',
                                                                     'OutdoorModel', 'WIFIName', 'isDetector',
-                                                                    'DetectorRank', 'is_human', 'is_custom_voice', 'is_ptz', 'double_wifi', 'is_ai')
+                                                                    'DetectorRank', 'is_human', 'is_custom_voice',
+                                                                    'is_ptz', 'double_wifi', 'is_ai', 'mobile_4g')
         uv_dict = {}
         uv_dict = {}
         for us in us_qs:
         for us in us_qs:
             uv_dict[us['uid']] = {
             uv_dict[us['uid']] = {
@@ -634,6 +636,7 @@ class EquipmentManagerV3(View):
                 'is_custom_voice': us['is_custom_voice'],
                 'is_custom_voice': us['is_custom_voice'],
                 'is_ptz': us['is_ptz'],
                 'is_ptz': us['is_ptz'],
                 'double_wifi': us['double_wifi'],
                 'double_wifi': us['double_wifi'],
+                'mobile4G': us['mobile_4g'],
                 'is_ai': us['is_ai']
                 'is_ai': us['is_ai']
             }
             }
             # 从uid_channel里面取出通道配置信息
             # 从uid_channel里面取出通道配置信息
@@ -670,14 +673,16 @@ class EquipmentManagerV3(View):
             uv_dict[us['uid']]['channels'] = channels
             uv_dict[us['uid']]['channels'] = channels
 
 
         for p in dvls:
         for p in dvls:
-            # C1返回序列号
-            if p['Type'] != 101:
-                p['serial_number'] = ''
+            if p['serial_number']:
+                u_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=p['serial_number'])
+                if u_device_info_qs.exists():
+                    p['iccid'] = u_device_info_qs.first().iccid
+
             # 获取iot_deviceInfo表的endpoint和token_iot_number
             # 获取iot_deviceInfo表的endpoint和token_iot_number
             p['iot'] = []
             p['iot'] = []
             if p['serial_number']:  # 存在序列号根据序列号查询
             if p['serial_number']:  # 存在序列号根据序列号查询
                 iotdeviceInfo_qs = iotdeviceInfoModel.objects.filter(serial_number=p['serial_number'][0:6])
                 iotdeviceInfo_qs = iotdeviceInfoModel.objects.filter(serial_number=p['serial_number'][0:6])
-            else:   # 根据uid查询
+            else:  # 根据uid查询
                 iotdeviceInfo_qs = iotdeviceInfoModel.objects.filter(uid=p['UID'])
                 iotdeviceInfo_qs = iotdeviceInfoModel.objects.filter(uid=p['UID'])
             if iotdeviceInfo_qs.exists():
             if iotdeviceInfo_qs.exists():
                 iotdeviceInfo = iotdeviceInfo_qs.values('endpoint', 'token_iot_number')
                 iotdeviceInfo = iotdeviceInfo_qs.values('endpoint', 'token_iot_number')
@@ -710,8 +715,8 @@ class EquipmentManagerV3(View):
             if p_uid in uv_dict:
             if p_uid in uv_dict:
                 # 设备版本号
                 # 设备版本号
                 uidversion = uv_dict[p_uid]['version']
                 uidversion = uv_dict[p_uid]['version']
-                if len(uidversion) >6:
-                    uidversion = uidversion[0 : uidversion.rfind('.')]
+                if len(uidversion) > 6:
+                    uidversion = uidversion[0: uidversion.rfind('.')]
                 p['uid_version'] = uidversion
                 p['uid_version'] = uidversion
                 p['ucode'] = uv_dict[p_uid]['ucode']
                 p['ucode'] = uv_dict[p_uid]['ucode']
                 p['detect_interval'] = uv_dict[p_uid]['detect_interval']
                 p['detect_interval'] = uv_dict[p_uid]['detect_interval']
@@ -735,6 +740,7 @@ class EquipmentManagerV3(View):
                 p['is_ptz'] = uv_dict[p_uid]['is_ptz']
                 p['is_ptz'] = uv_dict[p_uid]['is_ptz']
                 p['channels'] = uv_dict[p_uid]['channels']
                 p['channels'] = uv_dict[p_uid]['channels']
                 p['double_wifi'] = uv_dict[p_uid]['double_wifi']
                 p['double_wifi'] = uv_dict[p_uid]['double_wifi']
+                p['mobile4G'] = uv_dict[p_uid]['mobile4G']
                 p['is_ai'] = uv_dict[p_uid]['is_ai']
                 p['is_ai'] = uv_dict[p_uid]['is_ai']
                 # 设备昵称 调用影子信息昵称,先阶段不可
                 # 设备昵称 调用影子信息昵称,先阶段不可
                 if uv_dict[p_uid]['nickname']:
                 if uv_dict[p_uid]['nickname']:
@@ -987,16 +993,15 @@ class EquipmentManagerV3(View):
             phone = qs[0]['phone']
             phone = qs[0]['phone']
             username = qs[0]['username']
             username = qs[0]['username']
             qs = CommonService.qs_to_list(qs)
             qs = CommonService.qs_to_list(qs)
-            if NickName =='':
+            if NickName == '':
                 qs[0]['NickName'] = username
                 qs[0]['NickName'] = username
 
 
             # if userEmail =='':
             # if userEmail =='':
             #     qs[0]['userEmail'] = NickName
             #     qs[0]['userEmail'] = NickName
 
 
-            if phone =='':
+            if phone == '':
                 qs[0]['phone'] = NickName
                 qs[0]['phone'] = NickName
 
 
-
         # if not qs:
         # if not qs:
         #     uidq = UIDMainUser.objects.filter(UID=UID).values('user_id')
         #     uidq = UIDMainUser.objects.filter(UID=UID).values('user_id')
         #     if uidq.exists():
         #     if uidq.exists():
@@ -1027,9 +1032,9 @@ class EquipmentManagerV3(View):
             phone = qs[0]['phone']
             phone = qs[0]['phone']
             username = qs[0]['username']
             username = qs[0]['username']
             qs = CommonService.qs_to_list(qs)
             qs = CommonService.qs_to_list(qs)
-            if NickName =='':
+            if NickName == '':
                 qs[0]['NickName'] = username
                 qs[0]['NickName'] = username
-            if phone =='':
+            if phone == '':
                 qs[0]['phone'] = NickName
                 qs[0]['phone'] = NickName
         return response.json(0, qs)
         return response.json(0, qs)
 
 

+ 2 - 2
Controller/OrderContrller.py

@@ -128,8 +128,8 @@ class OrderView(View):
                     d['did'] = did['id']
                     d['did'] = did['id']
                     d['Type'] = did['Type']
                     d['Type'] = did['Type']
                     # 如果存在序列号返回完整序列号
                     # 如果存在序列号返回完整序列号
-                    if did['serial_number'] and did['Type'] == 101:
-                        d['UID'] = CommonService.get_full_serial_number(d['UID'], did['serial_number'], did['Type'])
+                    if did['serial_number']:
+                        d['serial_number'] = CommonService.get_full_serial_number(d['UID'], did['serial_number'], did['Type'])
                     data.append(d)
                     data.append(d)
             d['rank__content'] = d['rank__lang__content']
             d['rank__content'] = d['rank__lang__content']
             del d['rank__lang__content']
             del d['rank__lang__content']

+ 27 - 0
Controller/PaymentCycle.py

@@ -5,6 +5,7 @@ from Service.CommonService import CommonService
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 import requests
 import requests
 import time
 import time
+import datetime as date_time
 import sys
 import sys
 from Object.TokenObject import TokenObject
 from Object.TokenObject import TokenObject
 from Object.UidTokenObject import UidTokenObject
 from Object.UidTokenObject import UidTokenObject
@@ -177,6 +178,32 @@ class PaypalCycleNotify(View):
         logger.info('----订阅详情----')
         logger.info('----订阅详情----')
         logger.info(billing_agreement_response)
         logger.info(billing_agreement_response)
         agreement_id = billing_agreement_response.id
         agreement_id = billing_agreement_response.id
+        # 列出订阅的事务 https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_transactions
+        try:
+            billing_agreement = paypalrestsdk.BillingAgreement.find(agreement_id)
+            today = date_time.date.today()
+            oneday = date_time.timedelta(days=1)
+            yesterday = today - oneday
+            start_date = yesterday.strftime('%Y-%m-%d')
+            end_date = today.strftime('%Y-%m-%d')
+            transactions = billing_agreement.search_transactions(start_date, end_date)
+            if transactions.agreement_transaction_list:
+                agreement_transaction = transactions.agreement_transaction_list[0]
+                logger.info('-->订阅首次扣款,最新一条订阅事务{}'.format(agreement_transaction))
+                if agreement_transaction.status != 'Completed':
+                    logger.info('-->首次订阅扣款状态:{}'.format(agreement_transaction.status))
+                    red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                    if lang != 'cn':
+                        red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(
+                            SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                    return HttpResponseRedirect(red_url)
+        except Exception as e:
+            logger.info('出错了~查询订阅的事务异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+            if lang != 'cn':
+                red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+            return HttpResponseRedirect(red_url)
+
         order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
         order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
         order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
         order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
                                      "userID__userID",
                                      "userID__userID",

+ 8 - 2
Controller/SensorGateway/GatewayDeviceController.py

@@ -12,7 +12,7 @@ from django.views.generic.base import View
 
 
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 from Model.models import FamilyRoomDevice, FamilyRoom, GatewaySubDevice, Device_Info, UserFamily, FamilyMember, \
 from Model.models import FamilyRoomDevice, FamilyRoom, GatewaySubDevice, Device_Info, UserFamily, FamilyMember, \
-    UidSetModel, iotdeviceInfoModel
+    UidSetModel, iotdeviceInfoModel, SmartScene
 from Object.ResponseObject import ResponseObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.TokenObject import TokenObject
 
 
@@ -160,6 +160,7 @@ class GatewayDeviceView(View):
                         uid_set_qs = UidSetModel.objects.filter(uid=device_qs.first().UID)
                         uid_set_qs = UidSetModel.objects.filter(uid=device_qs.first().UID)
                         if uid_set_qs.exists():
                         if uid_set_qs.exists():
                             uid_set_qs.delete()
                             uid_set_qs.delete()
+                        SmartScene.objects.filter(device_id=device_id).delete()
                         device_qs.delete()
                         device_qs.delete()
                 elif sub_ids:
                 elif sub_ids:
                     sub_ids = sub_ids.split(',')
                     sub_ids = sub_ids.split(',')
@@ -173,6 +174,7 @@ class GatewayDeviceView(View):
                     gateway_sub_qs = GatewaySubDevice.objects.filter(id__in=ids)
                     gateway_sub_qs = GatewaySubDevice.objects.filter(id__in=ids)
                     if gateway_sub_qs.exists():
                     if gateway_sub_qs.exists():
                         gateway_sub_qs.delete()
                         gateway_sub_qs.delete()
+                    SmartScene.objects.filter(sub_device_id__in=ids).delete()
                 return response.json(0)
                 return response.json(0)
         except Exception as e:
         except Exception as e:
             print(e)
             print(e)
@@ -228,10 +230,12 @@ class GatewayDeviceView(View):
             family_device_qs = family_device_qs.filter(~Q(sub_device=0)).order_by('-created_time')
             family_device_qs = family_device_qs.filter(~Q(sub_device=0)).order_by('-created_time')
 
 
             sub_device = []
             sub_device = []
+            sub_id_list = []
             if family_device_qs.exists():
             if family_device_qs.exists():
                 family_device_qs = family_device_qs.values()
                 family_device_qs = family_device_qs.values()
                 for item in family_device_qs:
                 for item in family_device_qs:
                     sub_id = item['sub_device']
                     sub_id = item['sub_device']
+                    sub_id_list.append(sub_id)
                     gateway_sub_qs = GatewaySubDevice.objects.filter(device_id=device_id, id=sub_id).values(
                     gateway_sub_qs = GatewaySubDevice.objects.filter(device_id=device_id, id=sub_id).values(
                         'id', 'device_type',
                         'id', 'device_type',
                         'nickname',
                         'nickname',
@@ -255,7 +259,9 @@ class GatewayDeviceView(View):
                         'ieeeAddr': gateway_sub_qs['ieee_addr'],
                         'ieeeAddr': gateway_sub_qs['ieee_addr'],
                         'familyId': family_id,
                         'familyId': family_id,
                     })
                     })
-            res = {'gateway': gateway, 'sub_device': sub_device, 'sub_device_count': len(sub_device), 'scene_count': 0}
+            scene_count = SmartScene.objects.filter(Q(device_id=device_id) | Q(sub_device_id__in=sub_id_list)).count()
+            res = {'gateway': gateway, 'sub_device': sub_device, 'sub_device_count': len(sub_device),
+                   'scene_count': scene_count}
             return response.json(0, res)
             return response.json(0, res)
 
 
         except Exception as e:
         except Exception as e:

+ 8 - 2
Controller/SensorGateway/GatewayFamilyMemberController.py

@@ -13,6 +13,7 @@ import time
 from django.db import transaction
 from django.db import transaction
 from django.views.generic.base import View
 from django.views.generic.base import View
 
 
+from Ansjer.config import SERVER_DOMAIN
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 from Controller.SensorGateway.EquipmentFamilyController import EquipmentFamilyView
 from Model.models import UserFamily, FamilyMemberJoin, FamilyMember, SysMsgModel, FamilyMemberPermission, \
 from Model.models import UserFamily, FamilyMemberJoin, FamilyMember, SysMsgModel, FamilyMemberPermission, \
     Device_User, FamilyRoomDevice, FamilyRoom
     Device_User, FamilyRoomDevice, FamilyRoom
@@ -537,14 +538,19 @@ class GatewayFamilyMemberView(View):
         if not user_family_qs.exists():
         if not user_family_qs.exists():
             return response.json(173)
             return response.json(173)
         user_family_qs = user_family_qs.values('id', 'name', 'user__userEmail',
         user_family_qs = user_family_qs.values('id', 'name', 'user__userEmail',
-                                               'user__userIconUrl',
+                                               'user__userIconPath',
                                                'user__phone', 'user__NickName',
                                                'user__phone', 'user__NickName',
                                                'user__username')
                                                'user__username')
+        user_icon_url = ''
+        userIconPath = str(user_family_qs[0]['user__userIconPath'])
+        if userIconPath and userIconPath.find('static/') != -1:
+            userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+            user_icon_url = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
         return response.json(0, {
         return response.json(0, {
             'familyId': user_family_qs[0]['id'],
             'familyId': user_family_qs[0]['id'],
             'userPhone': user_family_qs[0]['user__phone'],
             'userPhone': user_family_qs[0]['user__phone'],
             'nickName': user_family_qs[0]['user__NickName'],
             'nickName': user_family_qs[0]['user__NickName'],
-            'userIconUrl': user_family_qs[0]['user__userIconUrl'],
+            'userIconUrl': user_icon_url,
             'userName': user_family_qs[0]['user__username'],
             'userName': user_family_qs[0]['user__username'],
             'familyName': user_family_qs[0]['name'],
             'familyName': user_family_qs[0]['name'],
             'userEmail': user_family_qs[0]['user__userEmail'],
             'userEmail': user_family_qs[0]['user__userEmail'],

+ 13 - 11
Controller/SensorGateway/GatewayFamilyRoomController.py

@@ -50,9 +50,9 @@ class GatewayFamilyRoomView(View):
         # 房间详情
         # 房间详情
         elif operation == 'details':
         elif operation == 'details':
             return self.get_room_details(app_user_id, request_dict, response)
             return self.get_room_details(app_user_id, request_dict, response)
-        elif operation == 'all-devices':    # 家庭所有设备
+        elif operation == 'all-devices':  # 家庭所有设备
             return self.all_devices(request_dict, response)
             return self.all_devices(request_dict, response)
-        elif operation == 'devices-sort':    # 家庭设备排序
+        elif operation == 'devices-sort':  # 家庭设备排序
             return self.devices_sort(request_dict, response)
             return self.devices_sort(request_dict, response)
         else:
         else:
             return response.json(414)
             return response.json(414)
@@ -212,21 +212,23 @@ class GatewayFamilyRoomView(View):
         if not family_id:
         if not family_id:
             return response.json(444)
             return response.json(444)
         try:
         try:
-            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, sub_device=0).\
-                annotate(type=F('device__Type'), nickname=F('device__NickName')).\
+            family_room_device_qs = FamilyRoomDevice.objects.filter(family_id=family_id, sub_device=0). \
+                annotate(type=F('device__Type'), nickname=F('device__NickName')). \
                 values('device_id', 'type', 'nickname', 'room_id').order_by('sort')
                 values('device_id', 'type', 'nickname', 'room_id').order_by('sort')
             if not family_room_device_qs.exists():
             if not family_room_device_qs.exists():
                 return response.json(0, [])
                 return response.json(0, [])
+            device_room = []
             # 查询房间名称
             # 查询房间名称
             for device in family_room_device_qs:
             for device in family_room_device_qs:
                 room_id = device['room_id']
                 room_id = device['room_id']
-                if room_id == 0:
-                    device['room'] = ''
-                else:
-                    family_room_qs = FamilyRoom.objects.filter(id=room_id).values('name')
-                    device['room'] = family_room_qs[0]['name'] if family_room_qs.exists() else ''
-                device.pop('room_id')
-            return response.json(0, list(family_room_device_qs))
+                room_name = FamilyRoom.objects.filter(id=room_id)
+                device_room.append({
+                    'deviceId': device['device_id'],
+                    'deviceType': device['type'],
+                    'nickName': device['nickname'],
+                    'roomName': room_name.first().name if room_name.exists() else '',
+                })
+            return response.json(0, device_room)
         except Exception as e:
         except Exception as e:
             return response.json(500, repr(e))
             return response.json(500, repr(e))
 
 

+ 687 - 0
Controller/SensorGateway/SmartSceneController.py

@@ -0,0 +1,687 @@
+# -*- coding: utf-8 -*-
+"""
+@Author : Rocky
+@Time : 2022/6/29 9:31
+@File :SmartSceneController.py
+"""
+import json
+import time
+
+from django.core.exceptions import ObjectDoesNotExist
+from django.db import transaction
+from django.db.models import F, Q
+from django.views import View
+
+from Model.models import FamilyRoomDevice, GatewaySubDevice, FamilyRoom, SmartScene, EffectiveTime, Device_Info, \
+    SceneLog
+from Service.CommonService import CommonService
+
+
+class SmartSceneView(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 == 'condition-devices':  # 添加条件-查询设备
+            return self.condition_devices(request_dict, response)
+        elif operation == 'task-devices':  # 添加任务-查询设备
+            return self.task_devices(request_dict, response)
+        elif operation == 'create':  # 创建智能场景
+            return self.create_smart_scene(request_dict, user_id, response)
+        elif operation == 'scene-list':  # 查询智能场景列表
+            return self.scene_list(request_dict, user_id, response)
+        elif operation == 'smart-button-scene-list':  # 查询智能按钮场景列表
+            return self.smart_button_scene_list(request_dict, user_id, response)
+        elif operation == 'update-status':  # 更新智能场景状态
+            return self.update_status(request_dict, response)
+        elif operation == 'detail':  # 查询智能场景详情
+            return self.scene_detail(request_dict, response)
+        elif operation == 'edit':  # 编辑智能场景
+            return self.edit_smart_scene(request_dict, user_id, response)
+        elif operation == 'delete':  # 删除智能场景
+            return self.delete_smart_scene(request_dict, response)
+        elif operation == 'log':  # 查询智能场景日志
+            return self.scene_log(request_dict, response)
+        else:
+            return response.json(414)
+
+    @classmethod
+    def condition_devices(cls, request_dict, response):
+        """
+        添加条件-查询设备
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关设备id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId or subDeviceId'})
+        try:
+            if sub_device_id:
+                device_id = GatewaySubDevice.objects.get(id=sub_device_id).device_id
+            gateway_sub_device_qs = GatewaySubDevice.objects.filter(device_id=device_id)
+            if not gateway_sub_device_qs.exists():
+                return response.json(173)
+            res = cls.get_sub_device_room_name(gateway_sub_device_qs)
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @classmethod
+    def task_devices(cls, request_dict, response):
+        """
+        添加任务-查询设备
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关设备id
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('subDeviceId', None)
+        device_id = request_dict.get('deviceId', None)
+
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId or subDeviceId'})
+        try:
+
+            if device_id:
+                res = [cls.get_gateway_data(device_id)]
+            else:
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device_id', 'device_type')
+                device_id = sub_device_qs[0]['device_id']
+                device_type = sub_device_qs[0]['device_type']
+
+                if device_type != 216:  # 非智能按钮只返回网关
+                    res = [cls.get_gateway_data(device_id)]
+                else:
+                    gateway_data = cls.get_gateway_data(device_id)
+                    sub_device_qs = GatewaySubDevice.objects.filter(
+                        Q(device_id=device_id) & Q(device_type=215) | Q(device_type=219)).values('id', 'nickname',
+                                                                                                 'status',
+                                                                                                 'device_type')
+                    if not sub_device_qs.exists():
+                        return response.json(173)
+                    res = cls.get_sub_device_room_name(sub_device_qs, gateway_data)
+
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_sub_device_room_name(sub_device_qs, gateway_data=None):
+        """
+        获取房间名称
+        @param sub_device_qs: 子设备信息
+        @param gateway_data: 网关参数
+        @return: sub_device_list
+        """
+        sub_device_list = []
+        if gateway_data:
+            sub_device_list.append(gateway_data)
+        sub_device_qs = sub_device_qs.annotate(gatewaySubId=F('id'),
+                                               deviceType=F('device_type'),
+                                               deviceNickName=F('nickname')). \
+            values('gatewaySubId', 'deviceType', 'deviceNickName', 'status')
+        for sub_device in sub_device_qs:
+            family_room_device_qs = FamilyRoomDevice.objects.filter(sub_device=sub_device['gatewaySubId']). \
+                values('room_id')
+            if not family_room_device_qs.exists():
+                sub_device['roomName'] = ''
+            else:
+                room_id = family_room_device_qs[0]['room_id']
+                try:
+                    sub_device['roomName'] = FamilyRoom.objects.get(id=room_id).name
+                except ObjectDoesNotExist:
+                    sub_device['roomName'] = ''
+            sub_device_list.append(sub_device)
+        return sub_device_list
+
+    @staticmethod
+    def get_gateway_data(device_id):
+        """
+        获取网关数据
+        @param device_id: 网关设备id
+        @return: res
+        """
+        device_info_qs = Device_Info.objects.filter(id=device_id).values('NickName', 'Type')
+        nickname = device_info_qs[0]['NickName']
+        device_type = device_info_qs[0]['Type']
+        room_id = FamilyRoomDevice.objects.filter(device_id=device_id).values('room_id')[0]['room_id']
+        room_id_qs = FamilyRoom.objects.filter(id=room_id).values('name')
+        room_name = room_id_qs.first()['name'] if room_id_qs.exists() else ''
+        res = {
+            'deviceNickName': nickname,
+            'deviceType': device_type,
+            'roomName': room_name,
+            'status': 1,
+        }
+        return res
+
+    @staticmethod
+    def create_smart_scene(request_dict, user_id, response):
+        """
+        创建智能场景
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict deviceId: 网关设备id
+        @request_dict subDeviceId: 子设备id
+        @request_dict sceneName: 场景名称
+        @request_dict conditions: 条件
+        @request_dict tasks: 任务
+        @request_dict isAllDay: 是否全天执行
+        @request_dict startTime: 开始时间
+        @request_dict endTime: 结束时间
+        @request_dict repeat: 重复周期
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        scene_name = request_dict.get('sceneName', None)
+        conditions = request_dict.get('conditions', None)
+        tasks = request_dict.get('tasks', None)
+        is_all_day = request_dict.get('isAllDay', None)
+
+        if not all([scene_name, conditions, tasks]):
+            return response.json(444, {'error param': 'scene_name and conditions and tasks'})
+
+        now_time = int(time.time())
+        conditions_dict = eval(conditions)
+        tasks_list = eval(tasks)
+
+        try:
+            # 判断是否已存在该场景名
+            smart_scene_qs = SmartScene.objects.filter(user_id=user_id, scene_name=scene_name)
+            if smart_scene_qs.exists():
+                return response.json(179)
+
+            smart_scene_dict = {
+                'user_id': user_id,
+                'scene_name': scene_name,
+                'conditions': conditions,
+                'tasks': tasks,
+                'created_time': now_time,
+                'updated_time': now_time,
+            }
+            msg = {}
+            # 处理设置时间
+            if is_all_day is not None:
+                is_all_day = int(is_all_day)
+                smart_scene_dict['is_all_day'] = is_all_day
+
+            # 处理传网关设备id和子设备id的情况
+            if conditions_dict['type'] == 1:  # 网关设置时间
+                if not device_id:
+                    return response.json(444, {'error param': 'deviceId'})
+                smart_scene_dict['device_id'] = device_id
+                device_info_qs = Device_Info.objects.filter(id=device_id).values('serial_number')
+                if not device_info_qs.exists():
+                    return response.json(173)
+                serial_number = device_info_qs[0]['serial_number']
+            else:  # 子设备设置场景
+                if not sub_device_id:
+                    return response.json(444, {'error param': 'subDeviceId'})
+
+                # 智能按钮不能创建触发条件相同的场景
+                device_type = conditions_dict['sensor']['device_type']
+                if device_type == '216':
+                    event_type = conditions_dict['sensor']['eventValues'][0]['event_type']
+                    smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id,
+                                                               conditions__contains=event_type)
+                    if smart_scene_qs.exists():
+                        return response.json(180)
+
+                smart_scene_dict['sub_device_id'] = sub_device_id
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device__serial_number',
+                                                                                         'src_addr')
+                if not sub_device_qs.exists():
+                    return response.json(173)
+                serial_number = sub_device_qs[0]['device__serial_number']
+                msg['scene_status'] = 1
+                msg['sensor_type'] = int(conditions_dict['sensor']['device_type'])
+                msg['sensor_src'] = int(sub_device_qs[0]['src_addr'], 16)
+                msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
+
+            with transaction.atomic():
+                if is_all_day is None:  # 不设置时间
+                    smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
+                    # 设备的time数据,分钟转为秒
+                    time_dict = {
+                        'start_time': conditions_dict['time']['minutes'] * 60,
+                        'repeat': conditions_dict['time']['repeat']
+                    }
+                elif is_all_day == 1:  # 全天
+                    smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
+                    # 设备的time数据
+                    time_dict = {
+                        'is_all_day': is_all_day
+                    }
+                elif is_all_day == 2:  # 非全天
+                    start_time = int(request_dict.get('startTime', None))
+                    end_time = int(request_dict.get('endTime', None))
+                    repeat = int(request_dict.get('repeat', None))
+                    effective_time_qs = EffectiveTime.objects.filter(start_time=start_time, end_time=end_time,
+                                                                     repeat=repeat).values('id')
+                    if effective_time_qs.exists():
+                        effective_time_id = effective_time_qs[0]['id']
+                    else:
+                        effective_time_id = EffectiveTime.objects.create(start_time=start_time, end_time=end_time,
+                                                                         repeat=repeat).id
+                    smart_scene_dict['effective_time_id'] = effective_time_id
+                    smart_scene_qs = SmartScene.objects.create(**smart_scene_dict)
+
+                    # 设备的time数据,分钟转为秒
+                    time_dict = {
+                        'is_all_day': is_all_day,
+                        'start_time': start_time * 60,
+                        'end_time': end_time * 60,
+                        'repeat': repeat
+                    }
+                else:
+                    return response.json(444, {'error param': 'invalid isAllDay'})
+
+                msg['time'] = time_dict
+                msg['smart_scene_id'] = smart_scene_qs.id
+                task_list = []
+                for task in tasks_list:
+                    task_temp = {
+                        'sensor_type': int(task['device_type']),
+                        'sensor_action': int(task['event_type'])
+                    }
+                    sub_device_id = task.get('subDeviceId', None)
+                    if sub_device_id:
+                        sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('src_addr').first()
+                        task_temp['sensor_src'] = int(sub_device_qs['src_addr'], 16)
+                    task_list.append(task_temp)
+                msg['task'] = task_list
+
+                smart_scene_qs.device_data = json.dumps(msg)
+                smart_scene_qs.save()
+                # 发布MQTT消息通知网关设备
+                thing_name = serial_number
+                topic_name = 'loocam/gateway_sensor/smart_scene/{}'.format(serial_number)
+
+                success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg)
+                try:
+                    assert success
+                except AssertionError:
+                    return response.json(10044)
+
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def scene_list(request_dict, user_id, response):
+        """
+        查询智能场景列表
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict deviceId: 网关设备id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId or subDeviceId'})
+        try:
+            if device_id:
+                sub_device_id = GatewaySubDevice.objects.filter(device_id=device_id).values('id')
+                smart_scene_qs = SmartScene.objects.filter(
+                    Q(user_id=user_id) & Q(device_id=device_id) | Q(sub_device_id__in=sub_device_id))
+            else:
+                smart_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id)
+            if not smart_scene_qs.exists():
+                return response.json(173)
+            smart_scene_qs = smart_scene_qs.values('id', 'scene_name', 'is_enable')
+            return response.json(0, list(smart_scene_qs))
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def smart_button_scene_list(request_dict, user_id, response):
+        """
+        查询智能按钮场景列表
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict subDeviceId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('subDeviceId', None)
+
+        if not sub_device_id:
+            return response.json(444, {'error param': 'subDeviceId'})
+        try:
+            click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
+                                                       conditions__contains='2161').values('id', 'scene_name',
+                                                                                           'is_enable')
+            double_click_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
+                                                              conditions__contains='2162').values('id', 'scene_name',
+                                                                                                  'is_enable')
+            press_scene_qs = SmartScene.objects.filter(user_id=user_id, sub_device_id=sub_device_id,
+                                                       conditions__contains='2163').values('id', 'scene_name',
+                                                                                           'is_enable')
+            scene_list = []
+            if click_scene_qs.exists():
+                scene_list.append({
+                    'trigger_type': 1,
+                    'id': click_scene_qs[0]['id'],
+                    'scene_name': click_scene_qs[0]['scene_name'],
+                    'is_enable': click_scene_qs[0]['is_enable']
+                })
+            if double_click_scene_qs.exists():
+                scene_list.append({
+                    'trigger_type': 2,
+                    'id': double_click_scene_qs[0]['id'],
+                    'scene_name': double_click_scene_qs[0]['scene_name'],
+                    'is_enable': double_click_scene_qs[0]['is_enable']
+                })
+            if press_scene_qs.exists():
+                scene_list.append({
+                    'trigger_type': 3,
+                    'id': press_scene_qs[0]['id'],
+                    'scene_name': press_scene_qs[0]['scene_name'],
+                    'is_enable': press_scene_qs[0]['is_enable']
+                })
+            return response.json(0, scene_list)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def update_status(request_dict, response):
+        """
+        更新智能场景状态
+        @param request_dict: 请求参数
+        @request_dict smartSceneId: 智能场景id
+        @request_dict isEnable: 状态,True or False
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_id = request_dict.get('smartSceneId', None)
+        is_enable = request_dict.get('isEnable', None)
+
+        if not all([smart_scene_id, is_enable]):
+            return response.json(444, {'error param': 'smartSceneId and status'})
+        try:
+            SmartScene.objects.filter(id=smart_scene_id).update(is_enable=is_enable)
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def scene_detail(request_dict, response):
+        """
+        查询智能场景详情
+        @param request_dict: 请求参数
+        @request_dict smartSceneId: 智能场景id
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_id = request_dict.get('smartSceneId', None)
+
+        if not smart_scene_id:
+            return response.json(444, {'error param': 'smartSceneId'})
+        try:
+            smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id).values('id', 'scene_name', 'conditions',
+                                                                                 'tasks', 'effective_time_id',
+                                                                                 'is_all_day')
+            if not smart_scene_qs.exists():
+                return response.json(173)
+            res = {
+                'scene_name': smart_scene_qs[0]['scene_name'],
+                'condition': eval(smart_scene_qs[0]['conditions']),
+                'task': eval(smart_scene_qs[0]['tasks']),
+            }
+
+            # 如果存在关联的时间数据,组织时间数据
+            is_all_day = smart_scene_qs[0]['is_all_day']
+            effectiveTime = {}
+            if is_all_day != 0:
+                effectiveTime['isAllDay'] = is_all_day
+            if is_all_day == 2:
+                try:
+                    effective_time_qs = EffectiveTime.objects.get(id=smart_scene_qs[0]['effective_time_id'])
+                    effectiveTime['startTime'] = effective_time_qs.start_time
+                    effectiveTime['endTime'] = effective_time_qs.end_time
+                    effectiveTime['repeat'] = effective_time_qs.repeat
+                except ObjectDoesNotExist:
+                    return response.json(0, res)
+            res['effectiveTime'] = effectiveTime
+            return response.json(0, res)
+
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def edit_smart_scene(request_dict, user_id, response):
+        """
+        编辑智能场景
+        @param request_dict: 请求参数
+        @param user_id: 用户id
+        @request_dict smartSceneId: 智能场景id
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_id = request_dict.get('smartSceneId', None)
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        scene_name = request_dict.get('sceneName', None)
+        conditions = request_dict.get('conditions', None)
+        tasks = request_dict.get('tasks', None)
+        is_all_day = request_dict.get('isAllDay', None)
+
+        conditions_dict = eval(conditions)
+        tasks_list = eval(tasks)
+        now_time = int(time.time())
+
+        smart_scene_qs = SmartScene.objects.filter(user_id=user_id, scene_name=scene_name).filter(~Q(id=smart_scene_id))
+        if smart_scene_qs.exists():
+            return response.json(179)
+
+        res = {
+            'scene_name': scene_name,
+            'conditions': conditions_dict,
+            'tasks': tasks_list
+        }
+        effective_time = {}
+
+        if is_all_day:
+            is_all_day = int(is_all_day)
+            effective_time['is_all_day'] = is_all_day
+
+        if not all([smart_scene_id, scene_name, conditions, tasks]):
+            return response.json(444, {'error param': 'smartSceneId,sceneName,conditions or tasks'})
+        try:
+            smart_scene_qs = SmartScene.objects.filter(id=smart_scene_id)
+            if not smart_scene_qs.exists():
+                return response.json(173)
+
+            msg = {}
+            if conditions_dict['type'] == 2:  # 条件为选择子设备
+                if not sub_device_id:
+                    return response.json(444, {'error param': 'subDeviceId'})
+
+                # 智能按钮不能创建触发条件相同的场景
+                device_type = conditions_dict['sensor']['device_type']
+                if device_type == '216':
+                    event_type = conditions_dict['sensor']['eventValues'][0]['event_type']
+                    smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id,
+                                                               conditions__contains=event_type)
+                    if smart_scene_qs.exists():
+                        return response.json(180)
+
+                device_id = ''
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('src_addr',
+                                                                                         'device__serial_number')
+                if not sub_device_qs.exists():
+                    return response.json(173)
+                serial_number = sub_device_qs[0]['device__serial_number']
+                msg['smart_scene_id'] = smart_scene_id
+                msg['scene_status'] = 1
+                msg['sensor_type'] = conditions_dict['sensor']['device_type']
+                msg['sensor_src'] = int(sub_device_qs[0]['src_addr'], 16)
+                msg['sensor_status'] = int(conditions_dict['sensor']['eventValues'][0]['event_type'])
+            else:
+                if not device_id:
+                    return response.json(444, {'error param': 'deviceId'})
+                sub_device_id = 0
+                device_qs = Device_Info.objects.filter(id=device_id).value('serial_number')
+                if not device_qs.exists():
+                    return response.json(173)
+                serial_number = device_qs[0]['serial_number']
+
+
+            task_list = []
+            for task in tasks_list:
+                task_temp = {
+                    'sensor_type': int(task['device_type']),
+                    'sensor_action': int(task['event_type'])
+                }
+                task_sub_device_id = task.get('subDeviceId', None)
+                if task_sub_device_id:
+                    sub_device_qs = GatewaySubDevice.objects.filter(id=task_sub_device_id).values('src_addr').first()
+                    task_temp['sensor_src'] = int(sub_device_qs['src_addr'], 16)
+                task_list.append(task_temp)
+            msg['task'] = task_list
+
+            with transaction.atomic():
+                smart_scene_qs.update(scene_name=scene_name, conditions=conditions, tasks=tasks,
+                                      device_data=json.dumps(msg), updated_time=now_time, device_id=device_id,
+                                      sub_device_id=sub_device_id)
+
+                if is_all_day is None:  # 不设置时间或全天
+                    smart_scene_qs.update(effective_time_id=0, is_all_day=0)
+                    time_dict = {
+                        'start_time': conditions_dict['time']['minutes'] * 60,
+                        'repeat': conditions_dict['time']['repeat']
+                    }
+                elif is_all_day == 1:
+                    smart_scene_qs.update(effective_time_id=0, is_all_day=is_all_day)
+                    time_dict = {
+                        'is_all_day': is_all_day
+                    }
+                else:
+                    start_time = int(request_dict.get('startTime', None))
+                    end_time = int(request_dict.get('endTime', None))
+                    repeat = int(request_dict.get('repeat', None))
+                    effective_time_qs = EffectiveTime.objects.filter(start_time=start_time, end_time=end_time,
+                                                                     repeat=repeat).values('id')
+                    if effective_time_qs.exists():
+                        effective_time_id = effective_time_qs[0]['id']
+                    else:
+                        effective_time_id = EffectiveTime.objects.create(start_time=start_time, end_time=end_time,
+                                                                         repeat=repeat).id
+                    smart_scene_qs.update(effective_time_id=effective_time_id, is_all_day=is_all_day)
+                    time_dict = {
+                        'is_all_day': is_all_day,
+                        'start_time': start_time * 60,
+                        'end_time': end_time * 60,
+                        'repeat': repeat
+                    }
+                    effective_time = {
+                        'isAllDay': is_all_day,
+                        'startTime': start_time,
+                        'endTime': end_time,
+                        'repeat': repeat
+                    }
+                msg['time'] = time_dict
+
+            # 通过mqtt发送设备数据
+            thing_name = serial_number
+            topic_name = 'loocam/gateway_sensor/smart_scene/{}'.format(serial_number)
+            success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg)
+
+            res['effectiveTime'] = effective_time
+            return response.json(0, res)
+
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def delete_smart_scene(request_dict, response):
+        """
+        删除智能场景
+        @param request_dict: 请求参数
+        @request_dict smartSceneIds: 智能场景id
+        @param response: 响应对象
+        @return: response
+        """
+        smart_scene_ids = request_dict.get('smartSceneIds', None)
+
+        if not smart_scene_ids:
+            return response.json(444, {'error param': 'smartSceneIds'})
+        try:
+            SmartScene.objects.filter(id__in=smart_scene_ids.split(',')).delete()
+        except Exception as e:
+            return response.json(500, repr(e))
+        else:
+            return response.json(0)
+
+    @staticmethod
+    def scene_log(request_dict, response):
+        """
+        查询场景日志
+        @param request_dict: 请求参数
+        @request_dict deviceId: 网关id
+        @request_dict subDeviceId: 子设备id
+        @request_dict page: 页数
+        @request_dict size: 条数
+        @request_dict startTime: 开始时间
+        @request_dict endTime: 结束时间
+        @param response: 响应对象
+        @return: response
+        """
+        device_id = request_dict.get('deviceId', None)
+        sub_device_id = request_dict.get('subDeviceId', None)
+        page = request_dict.get('page', None)
+        size = request_dict.get('size', None)
+        start_time = request_dict.get('startTime', None)
+        end_time = request_dict.get('endTime', None)
+
+        if not any([device_id, sub_device_id]):
+            return response.json(444, {'error param': 'deviceId and subDeviceId'})
+        if not all([page, size]):
+            return response.json(444, {'error param': 'page or size'})
+
+        device_dict = {}
+        if device_id:
+            device_dict['device_id'] = device_id
+        else:
+            device_dict['sub_device_id'] = sub_device_id
+
+        try:
+            page, size = int(page), int(size)
+            if start_time and end_time:
+                scene_log_qs = SceneLog.objects.filter(**device_dict, created_time__range=(start_time, end_time)). \
+                                   values('scene_id', 'scene_log', 'status', 'created_time').order_by(
+                    '-created_time')[(page - 1) * size:page * size]
+            else:
+                scene_log_qs = SceneLog.objects.filter(**device_dict).values('scene_id', 'scene_log', 'status',
+                                                                             'created_time').order_by(
+                    '-created_time')[(page - 1) * size:page * size]
+            if not scene_log_qs.exists():
+                return response.json(0, [])
+            for item in scene_log_qs:
+                scene_id = item['scene_id']
+                scene_name = SmartScene.objects.filter(id=scene_id)[0].scene_name
+                item['scene_name'] = scene_name
+            return response.json(0, list(scene_log_qs))
+        except Exception as e:
+            print(repr(e))
+            return response.json(500, repr(e))

+ 203 - 84
Controller/SensorGateway/SubDeviceController.py

@@ -11,9 +11,7 @@ from django.db import transaction
 from django.db.models import Count
 from django.db.models import Count
 from django.views import View
 from django.views import View
 
 
-from Model.models import Device_Info, GatewaySubDevice, FamilyRoomDevice, SensorRecord
-from Object.ResponseObject import ResponseObject
-from Object.TokenObject import TokenObject
+from Model.models import Device_Info, GatewaySubDevice, FamilyRoomDevice, SensorRecord, SmartScene
 from Service.CommonService import CommonService
 from Service.CommonService import CommonService
 
 
 
 
@@ -29,13 +27,9 @@ class GatewaySubDeviceView(View):
         return self.validation(request.POST, request, operation)
         return self.validation(request.POST, request, operation)
 
 
     def validation(self, request_dict, request, operation):
     def validation(self, request_dict, request, operation):
-        token_obj = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
-        lang = request_dict.get('lang', None)
-        response = ResponseObject(lang if lang else token_obj.lang)
-
-        if token_obj.code != 0:
-            return response.json(token_obj.code)
-        user_id = token_obj.userID
+        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 == 'add':  # 添加子设备
         if operation == 'add':  # 添加子设备
             return self.add_sub_device(request_dict, user_id, response)
             return self.add_sub_device(request_dict, user_id, response)
         elif operation == 'detail':  # 查询子设备信息
         elif operation == 'detail':  # 查询子设备信息
@@ -43,13 +37,17 @@ class GatewaySubDeviceView(View):
         elif operation == 'update':  # 更新子设备信息
         elif operation == 'update':  # 更新子设备信息
             return self.sensor_update(request_dict, response)
             return self.sensor_update(request_dict, response)
         elif operation == 'delete':  # 删除子设备
         elif operation == 'delete':  # 删除子设备
-            return self.delete(request_dict, user_id, response)
+            return self.delete_sub_device(request_dict, response)
         elif operation == 'records/tem-hum':  # 查询温湿度传感器记录
         elif operation == 'records/tem-hum':  # 查询温湿度传感器记录
             return self.records_tem_hum(request_dict, response)
             return self.records_tem_hum(request_dict, response)
         elif operation == 'records':  # 查询其他传感器记录
         elif operation == 'records':  # 查询其他传感器记录
             return self.records(request_dict, response)
             return self.records(request_dict, response)
         elif operation == 'records-date':  # 查询传感器记录日期
         elif operation == 'records-date':  # 查询传感器记录日期
             return self.records_date(request_dict, response)
             return self.records_date(request_dict, response)
+        elif operation == 'home':  # 查询传感器主页信息
+            return self.sensor_home_info(request_dict, response)
+        elif operation == 'update-emergency-status':  # 更新智能按钮紧急开关状态
+            return self.update_emergency_status(request_dict, response)
         else:
         else:
             return response.json(414)
             return response.json(414)
 
 
@@ -134,7 +132,9 @@ class GatewaySubDeviceView(View):
         try:
         try:
             gateway_sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('manufacturer',
             gateway_sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('manufacturer',
                                                                                              'device_model',
                                                                                              'device_model',
-                                                                                             'mac', 'sensor_serial')
+                                                                                             'mac', 'sensor_serial',
+                                                                                             'device_type',
+                                                                                             'is_tampered')
             if not gateway_sub_device_qs.exists():
             if not gateway_sub_device_qs.exists():
                 return response.json(173)
                 return response.json(173)
             res = {
             res = {
@@ -143,6 +143,8 @@ class GatewaySubDeviceView(View):
                 'mac': gateway_sub_device_qs[0]['mac'],
                 'mac': gateway_sub_device_qs[0]['mac'],
                 'sensor_serial': gateway_sub_device_qs[0]['sensor_serial'],
                 'sensor_serial': gateway_sub_device_qs[0]['sensor_serial'],
             }
             }
+            if gateway_sub_device_qs[0]['device_type'] == 216:  # 智能按钮返回紧急开关状态
+                res['emergency_status'] = gateway_sub_device_qs[0]['is_tampered']
             return response.json(0, res)
             return response.json(0, res)
         except Exception as e:
         except Exception as e:
             return response.json(500, repr(e))
             return response.json(500, repr(e))
@@ -177,12 +179,11 @@ class GatewaySubDeviceView(View):
             return response.json(500, repr(e))
             return response.json(500, repr(e))
 
 
     @staticmethod
     @staticmethod
-    def delete(request_dict, user_id, response):
+    def delete_sub_device(request_dict, response):
         """
         """
         更新子设备信息
         更新子设备信息
         @param request_dict: 请求参数
         @param request_dict: 请求参数
         @request_dict sub_device_id: 子设备id
         @request_dict sub_device_id: 子设备id
-        @param user_id: 用户id
         @param response: 响应对象
         @param response: 响应对象
         @return: response
         @return: response
         """
         """
@@ -191,19 +192,21 @@ class GatewaySubDeviceView(View):
         if not all([sub_device_id]):
         if not all([sub_device_id]):
             return response.json(444)
             return response.json(444)
         try:
         try:
-            GatewaySubDevice.objects.filter(id=sub_device_id).delete()
+            with transaction.atomic():
+                GatewaySubDevice.objects.filter(id=sub_device_id).delete()
+                SmartScene.objects.filter(sub_device_id=sub_device_id).delete()
             return response.json(0)
             return response.json(0)
         except Exception as e:
         except Exception as e:
             return response.json(500, repr(e))
             return response.json(500, repr(e))
 
 
-    @staticmethod
-    def records_tem_hum(request_dict, response):
+    @classmethod
+    def records_tem_hum(cls, request_dict, response):
         """
         """
         查询温湿度传感器记录
         查询温湿度传感器记录
         @param request_dict: 请求参数
         @param request_dict: 请求参数
         @request_dict gatewaySubId: 子设备id
         @request_dict gatewaySubId: 子设备id
         @request_dict cycle: 时间周期
         @request_dict cycle: 时间周期
-        @request_dict eventType: 事件类型, 18:温度,19:湿度
+        @request_dict eventType: 事件类型, 2200:温度,2201:湿度
         @param response: 响应对象
         @param response: 响应对象
         @return: response
         @return: response
         """
         """
@@ -212,75 +215,20 @@ class GatewaySubDeviceView(View):
         event_type = request_dict.get('eventType', None)
         event_type = request_dict.get('eventType', None)
         if not all([sub_device_id, cycle, event_type]):
         if not all([sub_device_id, cycle, event_type]):
             return response.json(444, {'error param': 'gatewaySubId or cycle or eventType'})
             return response.json(444, {'error param': 'gatewaySubId or cycle or eventType'})
+
         now_time = int(time.time())
         now_time = int(time.time())
+        # 判断event_type
+        event_type = int(event_type)
+        if event_type != 2200 and event_type != 2201:
+            return response.json(444, {'invalid eventType': event_type})
+
         try:
         try:
-            record_dict = OrderedDict()
+            record_dict = cls.get_record_dict(cycle, now_time, sub_device_id, event_type)
             record_list = []
             record_list = []
-            if cycle == 'Hours':
-                start_time = now_time - 24 * 60 * 60
-                sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
-                                                               event_type=event_type,
-                                                               created_time__range=(start_time, now_time)). \
-                    values('alarm', 'created_time').order_by('created_time')
-                if not sensor_record_qs.exists():
-                    return response.json(0, {'records': [], 'time': now_time})
-
-                for sensor_record in sensor_record_qs:
-                    created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
-                    hour = int(created_time[-7:-5])
-                    minute = int(created_time[-4:-2])
-                    if hour != 23 and minute > 30:  # 不为23时且分钟大于30,hour+1
-                        hour += 1
-                    alarm = float(sensor_record['alarm'])
-                    # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
-                    if str(hour) in record_dict:
-                        record_dict[str(hour)].append(alarm)
-                    else:
-                        record_dict[str(hour)] = [alarm]
-
-            elif cycle == 'Week':
-                start_time = now_time - 24 * 60 * 60 * 7
-                sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
-                                                               event_type=event_type,
-                                                               created_time__range=(start_time, now_time)). \
-                    values('alarm', 'created_time').order_by('created_time')
-                if not sensor_record_qs.exists():
-                    return response.json(0, {'records': [], 'time': now_time})
-
-                for sensor_record in sensor_record_qs:
-                    created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
-                    week = int(created_time[-1:])
-                    alarm = float(sensor_record['alarm'])
-                    # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
-                    if str(week) in record_dict:
-                        record_dict[str(week)].append(alarm)
-                    else:
-                        record_dict[str(week)] = [alarm]
-
-            elif cycle == 'Month':
-                start_time = now_time - 24 * 60 * 60 * 30
-                sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
-                                                               event_type=event_type,
-                                                               created_time__range=(start_time, now_time)). \
-                    values('alarm', 'created_time').order_by('created_time')
-                if not sensor_record_qs.exists():
-                    return response.json(0, {'records': [], 'time': now_time})
-
-                for sensor_record in sensor_record_qs:
-                    created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
-                    month = int(created_time[:2])
-                    day = int(created_time[3:5])
-                    date = str(month) + '/' + str(day)
-                    alarm = float(sensor_record['alarm'])
-                    # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
-                    if date in record_dict:
-                        record_dict[date].append(alarm)
-                    else:
-                        record_dict[date] = [alarm]
-
-            # 组织响应数据列表,value为每 小时/天 的平均值
-            for k, v in record_dict.items():
-                record_list.append({'key': k, 'value': round(sum(v) / len(v), 1)})
+            if record_dict:
+                # 组织响应数据列表,value为每 小时/天 的平均值
+                for k, v in record_dict.items():
+                    record_list.append({'key': k, 'value': round(sum(v) / len(v), 1)})
 
 
             res = {
             res = {
                 'records': record_list,
                 'records': record_list,
@@ -290,6 +238,81 @@ class GatewaySubDeviceView(View):
         except Exception as e:
         except Exception as e:
             return response.json(500, repr(e))
             return response.json(500, repr(e))
 
 
+    @staticmethod
+    def get_record_dict(cycle, now_time, sub_device_id, event_type):
+        """
+        获取记录数据
+        @param cycle: 时间周期
+        @param now_time: 当前时间
+        @param sub_device_id: 子设备id
+        @param event_type: 事件类型, 2200:温度,2201:湿度
+        @return: record_dict: 记录数据
+        """
+        record_dict = OrderedDict()
+        if cycle == 'Hours':
+            start_time = now_time - 24 * 60 * 60
+            sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                           event_type=event_type,
+                                                           created_time__range=(start_time, now_time)). \
+                values('alarm', 'created_time').order_by('created_time')
+            if not sensor_record_qs.exists():
+                return record_dict
+
+            for sensor_record in sensor_record_qs:
+                created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
+                hour = int(created_time[-7:-5])
+                minute = int(created_time[-4:-2])
+                if hour != 23 and minute > 30:  # 不为23时且分钟大于30,hour+1
+                    hour += 1
+                alarm = float(sensor_record['alarm'])
+                # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
+                if str(hour) in record_dict:
+                    record_dict[str(hour)].append(alarm)
+                else:
+                    record_dict[str(hour)] = [alarm]
+
+        elif cycle == 'Week':
+            start_time = now_time - 24 * 60 * 60 * 7
+            sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                           event_type=event_type,
+                                                           created_time__range=(start_time, now_time)). \
+                values('alarm', 'created_time').order_by('created_time')
+            if not sensor_record_qs.exists():
+                return record_dict
+
+            for sensor_record in sensor_record_qs:
+                created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
+                week = int(created_time[-1:])
+                alarm = float(sensor_record['alarm'])
+                # 组织数据,record_dict:{"0": [1.0, 2.0, 3.0], "1": [1.0, 2.0, 3.0]...}
+                if str(week) in record_dict:
+                    record_dict[str(week)].append(alarm)
+                else:
+                    record_dict[str(week)] = [alarm]
+
+        elif cycle == 'Month':
+            start_time = now_time - 24 * 60 * 60 * 30
+            sensor_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                           event_type=event_type,
+                                                           created_time__range=(start_time, now_time)). \
+                values('alarm', 'created_time').order_by('created_time')
+            if not sensor_record_qs.exists():
+                return record_dict
+
+            for sensor_record in sensor_record_qs:
+                created_time = time.strftime('%m/%d %H:%M %w', time.localtime(sensor_record['created_time']))
+                month = int(created_time[:2])
+                day = int(created_time[3:5])
+                date = str(month) + '/' + str(day)
+                alarm = float(sensor_record['alarm'])
+                # 组织数据,record_dict:{"1/1": [1.0, 2.0, 3.0], "1/2": [1.0, 2.0, 3.0]...}
+                if date in record_dict:
+                    record_dict[date].append(alarm)
+                else:
+                    record_dict[date] = [alarm]
+
+        return record_dict
+
     @staticmethod
     @staticmethod
     def records(request_dict, response):
     def records(request_dict, response):
         """
         """
@@ -360,3 +383,99 @@ class GatewaySubDeviceView(View):
             return response.json(0, record_date_list)
             return response.json(0, record_date_list)
         except Exception as e:
         except Exception as e:
             return response.json(500, repr(e))
             return response.json(500, repr(e))
+
+    @staticmethod
+    def sensor_home_info(request_dict, response):
+        """
+        查询子设备首页信息
+        @param request_dict: 请求参数
+        @request_dict gatewaySubId: 子设备id
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('gatewaySubId', None)
+        if not sub_device_id:
+            return response.json(444, {'error param': 'gatewaySubId'})
+
+        try:
+            sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id).values('device_type', 'status',
+                                                                                     'is_tampered')
+            if not sub_device_qs.exists():
+                return response.json(173)
+            scene_count = SmartScene.objects.filter(sub_device_id=sub_device_id).count()
+            res = {
+                'scene_count': scene_count,
+                'status': sub_device_qs[0]['status']
+            }
+
+            device_type = sub_device_qs[0]['device_type']
+            if device_type == 215 or device_type == 218 or device_type == 219:  # 门磁,烟雾,人体传感器返回拆动状态
+                res['is_tampered'] = sub_device_qs[0]['is_tampered']
+            elif device_type == 220:  # 温湿度传感器返回温湿度数据
+                tem_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                            event_type=2200).order_by('-created_time').values('alarm')[
+                                :1]
+                hum_record_qs = SensorRecord.objects.filter(gateway_sub_device_id=sub_device_id,
+                                                            event_type=2201).order_by('-created_time').values('alarm')[
+                                :1]
+                temperature = tem_record_qs[0]['alarm'] if tem_record_qs.exists() else ''
+                humidity = hum_record_qs[0]['alarm'] if tem_record_qs.exists() else ''
+                res['temperature'] = temperature
+                res['humidity'] = humidity
+
+            return response.json(0, res)
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def update_emergency_status(request_dict, response):
+        """
+        更新智能按钮紧急开关状态
+        @param request_dict: 请求参数
+        @request_dict gatewaySubId: 子设备id
+        @request_dict emergencyStatus: 紧急开关状态,0:关,1:开
+        @param response: 响应对象
+        @return: response
+        """
+        sub_device_id = request_dict.get('gatewaySubId', None)
+        emergency_status = request_dict.get('emergencyStatus', None)
+        if not all([sub_device_id, emergency_status]):
+            return response.json(444, {'error param': 'gatewaySubId or emergency_status'})
+
+        try:
+            with transaction.atomic():
+                # 更新智能按钮开关状态
+                sub_device_qs = GatewaySubDevice.objects.filter(id=sub_device_id)
+                if not sub_device_qs.exists():
+                    response.json(173)
+                sub_device_qs.update(status=emergency_status)
+
+                # 更新智能按钮场景状态
+                if emergency_status == '0':
+                    smart_scene_status = 0
+                else:
+                    smart_scene_status = 1
+                smart_scene_qs = SmartScene.objects.filter(sub_device_id=sub_device_id)
+                if not smart_scene_qs:
+                    return response.json(173)
+                smart_scene_qs.update(is_enable=smart_scene_status)
+
+            # 通过mqtt发送设备数据
+            sub_device_qs = sub_device_qs.values('device__serial_number')
+            if not sub_device_qs.exists():
+                return response.json(173)
+            serial_number = sub_device_qs[0]['device__serial_number']
+            thing_name = serial_number
+            topic_name = 'loocam/gateway_sensor/smart_scene/{}'.format(serial_number)
+            for item in smart_scene_qs:
+                msg = {
+                    'scene_id': item.id,
+                    'scene_status': item.is_enable
+                }
+
+                success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg)
+                time.sleep(0.3)
+
+            return response.json(0)
+        except Exception as e:
+            return response.json(500, repr(e))

+ 3 - 0
Controller/ShadowController.py

@@ -102,6 +102,7 @@ def update_device_shadow(request):
         is_human = request_dict.get('is_human', None)
         is_human = request_dict.get('is_human', None)
         is_custom_voice = request_dict.get('is_custom', None)
         is_custom_voice = request_dict.get('is_custom', None)
         double_wifi = request_dict.get('double_wifi', None)
         double_wifi = request_dict.get('double_wifi', None)
+        mobile_4g = request_dict.get('mobile4G', None)
         is_ptz = request_dict.get('is_ptz', None)
         is_ptz = request_dict.get('is_ptz', None)
         us_qs = UidSetModel.objects.filter(uid=uid)
         us_qs = UidSetModel.objects.filter(uid=uid)
         is_ai = request_dict.get('is_ai', None)
         is_ai = request_dict.get('is_ai', None)
@@ -139,6 +140,8 @@ def update_device_shadow(request):
             qs_dict['is_custom_voice'] = is_custom_voice
             qs_dict['is_custom_voice'] = is_custom_voice
         if double_wifi:
         if double_wifi:
             qs_dict['double_wifi'] = double_wifi
             qs_dict['double_wifi'] = double_wifi
+        if mobile_4g:
+            qs_dict['mobile_4g'] = int(mobile_4g)
         if is_ptz:
         if is_ptz:
             qs_dict['is_ptz'] = is_ptz
             qs_dict['is_ptz'] = is_ptz
         if is_ai:
         if is_ai:

+ 500 - 12
Controller/UnicomCombo/UnicomComboController.py

@@ -6,18 +6,25 @@
 @Email   : zhangdongming@asj6.wecom.work
 @Email   : zhangdongming@asj6.wecom.work
 @Software: PyCharm
 @Software: PyCharm
 """
 """
+import datetime
 import json
 import json
 import logging
 import logging
 import time
 import time
+import traceback
+from decimal import Decimal
 
 
 from django.db import transaction
 from django.db import transaction
-from django.http import HttpResponse
+from django.http import HttpResponse, JsonResponse
 from django.views.generic.base import View
 from django.views.generic.base import View
 
 
-from Model.models import UnicomDeviceInfo, UnicomCombo, Pay_Type
+from Model.models import UnicomDeviceInfo, UnicomCombo, Pay_Type, Order_Model, Store_Meal, AiStoreMeal, \
+    UnicomComboOrderInfo, UnicomComboExperienceHistory, UnicomDeviceStatusChangePush, SysMsgModel, UnicomFlowPush
 from Object.ResponseObject import ResponseObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.TokenObject import TokenObject
 from Object.UnicomObject import UnicomObjeect
 from Object.UnicomObject import UnicomObjeect
+from Object.utils import LocalDateTimeUtil
+from Object.utils.PayUtil import PayService
+from Service.CommonService import CommonService
 
 
 
 
 class UnicomComboView(View):
 class UnicomComboView(View):
@@ -32,25 +39,226 @@ class UnicomComboView(View):
         return self.validation(request.POST, request, operation)
         return self.validation(request.POST, request, operation)
 
 
     def validation(self, request_dict, request, operation):
     def validation(self, request_dict, request, operation):
-        if operation == 'buy-notify':
-            return self.package_callback_notify(request_dict, request)
+        response = ResponseObject('cn')
+        if operation == 'query-usage-history':
+            return self.query_device_usage_history(request_dict, response)
+        elif operation == 'test-notify':
+            order_id = request_dict.get('orderId', None)
+            activate_type = request_dict.get('activateType', 0)
+            iccid = request_dict.get('iccid', None)
+            combo_id = request_dict.get('comboId', None)
+            self.create_combo_order_info(order_id, int(activate_type), iccid, int(combo_id))
+            return HttpResponse('SUCCESS')
         elif operation == 'device-queue-monitoring':
         elif operation == 'device-queue-monitoring':
             return self.device_queue_monitoring_push(request_dict, request)
             return self.device_queue_monitoring_push(request_dict, request)
         elif operation == 'device-status-change':
         elif operation == 'device-status-change':
             return self.device_status_change_push(request_dict, request)
             return self.device_status_change_push(request_dict, request)
         elif operation == 'device-bind':
         elif operation == 'device-bind':
-            response = ResponseObject('cn')
             return self.device_add(request_dict, response)
             return self.device_add(request_dict, response)
+        elif operation == 'device-status':
+            return self.update_device_status(request_dict, response)
+        elif operation == 'xxx-sign':
+            return self.get_test_sign(request_dict, response)
         else:
         else:
             token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
             token = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
             lang = request_dict.get('lang', token.lang)
             lang = request_dict.get('lang', token.lang)
             response = ResponseObject(lang)
             response = ResponseObject(lang)
             if token.code != 0:
             if token.code != 0:
                 return response.json(token.code)
                 return response.json(token.code)
+            user_id = token.userID
             if operation == 'combo-save':
             if operation == 'combo-save':
                 return self.save_unicom_combo(request_dict, response)
                 return self.save_unicom_combo(request_dict, response)
+            elif operation == 'combo-pay':
+                return self.buy_unicom_combo(user_id, request_dict, request, response)
             elif operation == 'combo-list':
             elif operation == 'combo-list':
                 return self.query_package_list(response)
                 return self.query_package_list(response)
+            elif operation == 'get-device-info':
+                return self.get_device_info(request_dict, response)
+            elif operation == 'user-combo-query':
+                return self.user_combo_query(user_id, request_dict, response)
+
+    @classmethod
+    def user_combo_query(cls, user_id, request_dict, response):
+        """
+        查询套餐流量列表与正在使用流量详情
+        @param user_id:
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        try:
+            iccid = request_dict.get('iccid', None)
+            if not iccid:
+                return response.json(444)
+            unicom_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
+            if not unicom_device_info_qs.exists():
+                return response.json(173)
+            if not unicom_device_info_qs[0].user_id:
+                unicom_device_info_qs.update(user_id=user_id)
+            unicom_api = UnicomObjeect()
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid, status=1, is_del=False) \
+                .values('iccid', 'status', 'combo__status', 'combo__combo_name', 'combo__combo_type',
+                        'combo__flow_total', 'combo__remark', 'combo__expiration_days', 'combo__expiration_type',
+                        'year', 'month', 'flow_total_usage', 'expire_time', 'activation_time', 'combo__is_unlimited')
+            if combo_order_qs.exists():
+                combo_order = combo_order_qs.first()
+                flow_details = {
+                    'flowInvalid': 0,
+                    'iccid': iccid,
+                    'status': combo_order['status'],
+                    'isUnlimited': combo_order['combo__is_unlimited'],
+                    'comboName': combo_order['combo__combo_name'],
+                    'comboType': combo_order['combo__combo_type'],
+                    'flowTotal': combo_order['combo__flow_total'],
+                    'comboRemark': combo_order['combo__remark'],
+                    'expirationDays': combo_order['combo__expiration_days'],
+                    'expirationType': combo_order['combo__expiration_type'],
+                    'flowTotalUsage': combo_order['flow_total_usage'],
+                    'activationTime': combo_order['activation_time'],
+                    'expireTime': combo_order['expire_time'],
+                    'year': combo_order['year'],
+                    'month': combo_order['month'],
+                }
+                if flow_details['year'] == year and flow_details['month'] == month:
+                    month_flow = unicom_api.get_flow_usage_total(year, month, iccid)
+                    # 当月流量减去 套餐激活时用量
+                    month_flow = month_flow - float(flow_details['flowTotalUsage'])
+                    flow = flow_details['flowTotal'] - month_flow
+                    flow_details['usableFlow'] = flow
+                else:
+                    now_month_flow = unicom_api.get_flow_usage_total(year, month, iccid)
+                    last_month_flow = unicom_api.get_flow_usage_total(flow_details['year'], flow_details['month'],
+                                                                      iccid)
+                    flow = now_month_flow + last_month_flow - float(flow_details['flowTotalUsage'])
+                    flow_details['usableFlow'] = flow_details['flowTotal'] - flow
+
+                flow_details['usableFlow'] = \
+                    0.00 if flow_details['usableFlow'] <= 0 else flow_details['usableFlow']
+                flow_details['usableFlow'] = Decimal(flow_details['usableFlow']).quantize(Decimal('0.00'))
+                flow_details.pop('flowTotalUsage')
+                cls.update_combo_order_sort(iccid)
+                flow_details['comboList'] = cls.get_combo_order_list(iccid)
+                return response.json(0, flow_details)
+            else:
+                flow_details = {'iccid': iccid, 'flowInvalid': 1, 'comboList': cls.get_combo_order_list(iccid)}
+                cls.update_combo_order_sort(iccid)
+                return response.json(0, flow_details)
+        except Exception as e:
+            print(e.args)
+            ex = traceback.format_exc()
+            print(ex)
+            return response.json(177, ex)
+
+    @classmethod
+    def get_combo_order_list(cls, iccid):
+        """
+        查询套餐列表
+        @param iccid:
+        @return:
+        """
+        combo_list = []
+        combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid, is_del=False) \
+            .values('iccid', 'status', 'combo__combo_name', 'combo__flow_total',
+                    'combo__remark', 'combo__expiration_days', 'combo__expiration_type', 'flow_total_usage',
+                    'expire_time', 'combo__is_unlimited').order_by('sort')
+        for item in combo_order_qs:
+            combo_list.append({
+                'iccid': iccid,
+                'status': item['status'],
+                'comboName': item['combo__combo_name'],
+                'isUnlimited': item['combo__is_unlimited'],
+                'flowTotal': item['combo__flow_total'],
+                'comboRemark': item['combo__remark'],
+                'expirationDays': item['combo__expiration_days'],
+                'expirationType': item['combo__expiration_type'],
+                'expireTime': item['expire_time'],
+            })
+        return combo_list
+
+    @classmethod
+    def update_combo_order_sort(cls, iccd):
+        """
+        修改套餐排序
+        @param iccd: 联通20位ICCID
+        @return:
+        """
+        combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccd, is_del=False)
+        if combo_order_qs.exists():
+            unused_qs = combo_order_qs.filter(status=0)
+            if unused_qs.exists():
+                unused_qs.update(sort=50)
+            used_qs = combo_order_qs.filter(status=1)
+            if used_qs.exists():
+                used_qs.update(sort=1)
+            expire_qs = combo_order_qs.filter(status=2)
+            if expire_qs.exists():
+                expire_qs.update(sort=100)
+
+    @classmethod
+    def update_device_status(cls, request_dict, response):
+        """
+        修改绑定设备状态,如产生免费套餐用量则删除
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        logger = logging.getLogger('info')
+
+        serial_no = request_dict.get('serialNo', None)
+        iccid = request_dict.get('iccid', None)
+        time_stamp = request_dict.get('timeStamp', None)
+        sign = request_dict.get('sign', None)
+        if not all([iccid, serial_no, sign, time_stamp]):
+            return response.json(444)
+        logger.info('PC工具进入重置ICCID{}'.format(iccid))
+        try:
+            if not CommonService.check_time_stamp_token(sign, time_stamp):
+                return response.json(13)
+            now_time = int(time.time())
+            with transaction.atomic():
+                device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid, serial_no=serial_no)
+                if device_info_qs.exists():
+                    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)
+                    if combo_order_qs.exists():
+                        combo_order_qs.delete()
+                    combo_experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid)
+                    if combo_experience_history_qs.exists():
+                        combo_experience_history_qs.delete()
+
+                return response.json(0)
+        except Exception as e:
+            print(e.args)
+            ex = traceback.format_exc()
+            print(ex)
+            logger.info('PC工具重置异常ICCID{},msg={}'.format(iccid, ex))
+            return response.json(177, ex)
+
+    @classmethod
+    def get_device_info(cls, request_dict, response):
+        """
+        获取设备信息
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        serial_no = request_dict.get('serialNumber', None)
+        if not serial_no:
+            return response.json(444)
+        unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no).values()
+        if not unicom_device_info_qs.exists():
+            return response.json(173)
+        return response.json(0, dict(unicom_device_info_qs.first()))
 
 
     @classmethod
     @classmethod
     def device_add(cls, request_dict, response):
     def device_add(cls, request_dict, response):
@@ -62,14 +270,24 @@ class UnicomComboView(View):
         """
         """
         iccid = request_dict.get('iccid', None)
         iccid = request_dict.get('iccid', None)
         serial_no = request_dict.get('serialNo', None)
         serial_no = request_dict.get('serialNo', None)
-        if not all([iccid, serial_no]):
+        time_stamp = request_dict.get('timeStamp', None)
+        sign = request_dict.get('sign', None)
+        logger = logging.getLogger('info')
+        logger.info('--->设备调用4G注册接口')
+        if not all([iccid, serial_no, sign, time_stamp]):
             return response.json(444)
             return response.json(444)
+            # 时间戳token校验
+        if not CommonService.check_time_stamp_token(sign, time_stamp):
+            return response.json(13)
         n_time = int(time.time())
         n_time = int(time.time())
         try:
         try:
+            logger.info('--->参数验证通过,sign验证通过')
             with transaction.atomic():
             with transaction.atomic():
                 # 待完善代码 根据uid与用户id验证系统设备
                 # 待完善代码 根据uid与用户id验证系统设备
                 unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
                 unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
                 if unicom_device_qs.exists():
                 if unicom_device_qs.exists():
+                    if unicom_device_qs.first().status == 1 and unicom_device_qs.first().serial_no == serial_no:
+                        cls.user_activate_flow(iccid)
                     return response.json(174)
                     return response.json(174)
                 unicom_obj = UnicomObjeect()
                 unicom_obj = UnicomObjeect()
                 result = unicom_obj.verify_device(iccid=iccid)
                 result = unicom_obj.verify_device(iccid=iccid)
@@ -80,14 +298,57 @@ class UnicomComboView(View):
                             return response.json(173)
                             return response.json(173)
                         params = {'iccid': iccid, 'serial_no': serial_no, 'updated_time': n_time,
                         params = {'iccid': iccid, 'serial_no': serial_no, 'updated_time': n_time,
                                   'created_time': n_time}
                                   'created_time': n_time}
+                        unicom_obj.change_device_to_activate(iccid)
                         UnicomDeviceInfo.objects.create(**params)
                         UnicomDeviceInfo.objects.create(**params)
                     return response.json(0)
                     return response.json(0)
                 else:
                 else:
                     return response.json(173)
                     return response.json(173)
         except Exception as e:
         except Exception as e:
             print(e)
             print(e)
+            logger.info('--->设备调用4G注册接口异常')
             return response.json(177, repr(e))
             return response.json(177, repr(e))
 
 
+    @classmethod
+    def user_activate_flow(cls, iccid):
+        """
+        用户激活初始化流量套餐
+        @param iccid:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        try:
+            while transaction.atomic():
+                now_time = int(time.time())
+                unicom_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
+                if not unicom_device_info_qs.exists():
+                    return False
+                unicom_device_info_qs = unicom_device_info_qs.first()
+                if unicom_device_info_qs.status != 1:
+                    logger.info('---->用户激活iccid={},业务系统状态为{}'.format(iccid, unicom_device_info_qs.status))
+                    return False
+                # 联通业务逻辑
+                unicom_api = UnicomObjeect()
+                unicom_api.change_device_to_activate(iccid)
+                # 查看是否体验过免费套餐
+                experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid)
+                if not experience_history_qs.exists():
+                    logger.info('---->用户首次激活iccid={}'.format(iccid))
+                    combo_qs = UnicomCombo.objects.filter(combo_type=1, status=0, is_del=False) \
+                        .values('id', 'expiration_type', 'expiration_days', 'combo_type')
+                    if combo_qs.exists():
+                        combo_qs = combo_qs.first()
+                        # 保存体验记录
+                        experience_history_vo = {'iccid': iccid, 'experience_type': 0, 'do_time': now_time}
+                        UnicomComboExperienceHistory.objects.create(**experience_history_vo)
+                        # 保存套餐激活信息
+                        cls.create_combo_order_info('', 0, iccid, combo_qs['id'])
+                # 修改业务联通卡设备激活信息
+                UnicomDeviceInfo.objects.filter(iccid=iccid).update(status=2, updated_time=now_time)
+                return True
+        except Exception as e:
+            print(e)
+            return False
+
     @classmethod
     @classmethod
     def save_unicom_combo(cls, request_dict, response):
     def save_unicom_combo(cls, request_dict, response):
         """
         """
@@ -165,19 +426,106 @@ class UnicomComboView(View):
             return response.json(177, repr(e))
             return response.json(177, repr(e))
 
 
     @classmethod
     @classmethod
-    def buy_package(cls):
+    def buy_unicom_combo(cls, user_id, request_dict, request, response):
+        """
+        购买联通套餐
+        @return:
+        """
+        try:
+            with transaction.atomic():
+                iccid = request_dict.get('iccid', None)
+                combo_id = request_dict.get('id', None)
+                pay_type = request_dict.get('payType', None)
+                activate_type = request_dict.get('activateType', 0)
+                if not all([iccid, combo_id, pay_type]):
+                    return response.json(444)
+                combo_id = int(combo_id)
+                pay_type = int(pay_type)
+                now_time = int(time.time())
+                unicom_combo_qs = UnicomCombo.objects.filter(id=combo_id, pay_type=pay_type, is_show=1, is_del=False,
+                                                             status=0) \
+                    .values('id', 'combo_name', 'price', 'remark')
+                if not unicom_combo_qs.exists():
+                    return response.json(173)
+                unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid) \
+                    .values('serial_no')
+                if not unicom_device_qs.exists():
+                    return response.json(173)
+                unicom_combo_qs = unicom_combo_qs.first()
+                price = unicom_combo_qs['price']
+                if not price:
+                    return response.json(173)
+                unicom_device_qs = unicom_device_qs.first()
+                device_uid = CommonService.query_uid_with_serial(unicom_device_qs['serial_no'])
+                order_id = CommonService.createOrderID()
+                rank_id, ai_rank_id = cls.get_cloud_or_ai_combo()
+
+                order_dict = {'rank_id': rank_id, 'ai_rank_id': ai_rank_id, 'orderID': order_id, 'UID': device_uid,
+                              'userID_id': user_id, 'desc': unicom_combo_qs['combo_name'], 'payType': pay_type,
+                              'payTime': now_time, 'price': price, 'currency': 'CNY', 'addTime': now_time,
+                              'updTime': now_time,
+                              'unify_combo_id': str(unicom_combo_qs['id']), 'order_type': 2,
+                              }
+
+                params = 'lang=cn' + '&activateType=' + activate_type
+                result = {'result_code': 0, 'reason': 'success', 'error_code': 0}
+                if pay_type == 2:  # 支付宝
+                    pay_price = PayService.get_two_float(price, 2)
+                    notify_url = 'unicom/wap/pay/ali-notify'
+
+                    order_dict['pay_url'] = PayService.create_alipay_payment(params, order_id, pay_price,
+                                                                             unicom_combo_qs['combo_name'],
+                                                                             notify_url,
+                                                                             unicom_combo_qs['remark'], response)
+                    res_data = {'redirectUrl': order_dict['pay_url'], 'orderID': order_id}
+                elif pay_type == 3:  # 微信支付
+                    notify_url = 'unicom/wap/pay/wechat-notify'
+                    ip = CommonService.get_ip_address(request)
+                    params = 'activateType=' + activate_type
+                    sign_params = PayService.create_wechat_payment(params, order_id,
+                                                                   price, ip,
+                                                                   notify_url,
+                                                                   unicom_combo_qs['remark'],
+                                                                   response)
+                    result['result'] = sign_params
+                else:
+                    return response.json(444, {'param': 'pay_type'})
+
+                Order_Model.objects.create(**order_dict)
+                if pay_type == 3:
+                    return JsonResponse(status=200, data=result)
+                return response.json(0, res_data)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_cloud_or_ai_combo():
         """
         """
-        购买套餐
+        获取云存或者AI套餐id
         @return:
         @return:
         """
         """
-        pass
+        rank_id = Store_Meal.objects.all().order_by('sort').values().first()['id']
+        ai_rank_id = AiStoreMeal.objects.all().values().first()['id']
+        return rank_id, ai_rank_id
 
 
     @classmethod
     @classmethod
-    def query_device_usage_history(cls):
+    def query_device_usage_history(cls, request_dict, response):
         """
         """
         查询用量历史
         查询用量历史
         @return:
         @return:
         """
         """
+        today = datetime.datetime.today()
+        year = today.year
+        month = today.month
+        year = request_dict.get('year', year)
+        month = request_dict.get('month', month)
+        iccid = request_dict.get('iccid', None)
+        if not iccid:
+            return response.json(444)
+        unicom_api = UnicomObjeect()
+        flow = unicom_api.get_flow_usage_total(int(year), int(month), iccid)
+        return response.json(0, flow)
 
 
     @staticmethod
     @staticmethod
     def package_callback_notify(request_dict, request):
     def package_callback_notify(request_dict, request):
@@ -254,11 +602,151 @@ class UnicomComboView(View):
                 dict_data.pop('sign')
                 dict_data.pop('sign')
                 unicom_obj = UnicomObjeect()
                 unicom_obj = UnicomObjeect()
                 generate_sign = unicom_obj.createSign(**dict_data)
                 generate_sign = unicom_obj.createSign(**dict_data)
-                logger.info('设备状态变更推送请求签名{}'.format(sign))
-                logger.info('设备状态变更推送生成签名{}'.format(generate_sign))
+                logger.info('联通设备状态变更推送请求签名{}'.format(sign))
+                logger.info('联通设备状态变更推送生成签名{}'.format(generate_sign))
+                assert generate_sign == sign
+                now_time = int(time.time())
+                re_data = {
+                    'iccid': dict_data['iccid'],
+                    'serial_no': dict_data['serialNo'],
+                    'sign': sign,
+                    'type': dict_data['type'],
+                    'previous_val': dict_data['previousVal'],
+                    'current_val': dict_data['currentVal'],
+                    'reason': dict_data['reason'],
+                    'time': dict_data['time'],
+                    'updated_time': now_time,
+                    'created_time': now_time
+                }
+                UnicomDeviceStatusChangePush.objects.create(**re_data)
             r_data = {'success': True, 'msg': '成功'}
             r_data = {'success': True, 'msg': '成功'}
             return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8")
             return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8")
         except Exception as e:
         except Exception as e:
             print(repr(e))
             print(repr(e))
             r_data = {'success': False, 'msg': '失败'}
             r_data = {'success': False, 'msg': '失败'}
             return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8")
             return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8")
+
+    @classmethod
+    def create_combo_order_info(cls, order_id, activate_type, iccid, combo_id):
+        """
+        创建套餐生效记录
+        @param order_id: 订单id
+        @param activate_type: 激活类型
+        @param iccid: 联通20位iccid
+        @param combo_id: 套餐id
+        @return: True Or False
+        """
+        logger = logging.getLogger('info')
+        logger.info('创建联通订单套餐信息,订单id{}'.format(order_id))
+        try:
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            with transaction.atomic():
+                unicom_combo_qs = UnicomCombo.objects.filter(id=int(combo_id)).values()
+                if unicom_combo_qs.exists():
+                    unicom_combo = unicom_combo_qs.first()
+                    now_time = int(time.time())
+                    combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, iccid=iccid)
+                    status = 0
+                    if not combo_order_qs.exists():
+                        status = 1
+                    combo_order_data = {'iccid': iccid, 'status': status, 'combo_id': int(combo_id),
+                                        'updated_time': now_time,
+                                        'created_time': now_time,
+                                        'year': year, 'month': month}
+                    if order_id:
+                        combo_order_data['order_id'] = order_id
+                    # 有效期类型 1 等于自然月,0天数
+                    if unicom_combo['expiration_type'] == 1:
+                        # 激活类型 1=下月激活 否则等于当月激活
+                        if activate_type == 1:
+                            combo_order_data['next_month_activate'] = True
+                            next_start_time, end_time = cls.get_next_month_data_time()
+                            combo_order_data['activation_time'] = next_start_time
+                            combo_order_data['expire_time'] = end_time
+                            combo_order_data['status'] = 0
+                        else:
+                            start_time, month_end_time = cls.get_month_start_and_end_time()
+                            combo_order_data['activation_time'] = now_time
+                            combo_order_data['expire_time'] = month_end_time
+
+                    elif unicom_combo['expiration_type'] == 0:
+                        days = unicom_combo['expiration_days']
+                        zero_today, end_time = cls.get_data_time(days)
+                        combo_order_data['activation_time'] = now_time
+                        combo_order_data['expire_time'] = end_time
+                        # 联通业务逻辑
+                    unicom_api = UnicomObjeect()
+                    if status == 1:
+                        unicom_api.change_device_to_activate(iccid)
+                        flow_total_usage = unicom_api.get_flow_usage_total(year, month, iccid)
+                        if flow_total_usage > 0:
+                            flow_total_usage = Decimal(flow_total_usage)
+                            flow_total_usage = flow_total_usage.quantize(Decimal('0.00'))
+                        else:
+                            flow_total_usage = 0
+                        combo_order_data['flow_total_usage'] = str(flow_total_usage)
+                    UnicomComboOrderInfo.objects.create(**combo_order_data)
+                    logger.info('保存套餐支付信息success')
+                return True
+        except Exception as e:
+            print(e)
+            return False
+
+    @staticmethod
+    def get_next_month_data_time():
+        """
+        获取下个月开始时间与结束时间戳
+        @return: next_start_time,end_time
+        """
+        next_month_start = LocalDateTimeUtil.get_next_month_start()
+        next_start_time, next_end_time = LocalDateTimeUtil.get_start_and_end_time(next_month_start, '%Y-%m-%d')
+        next_month_end = LocalDateTimeUtil.get_next_month_end()
+        start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(next_month_end, '%Y-%m-%d')
+        return next_start_time, end_time
+
+    @staticmethod
+    def get_data_time(days):
+        """
+        获取今天开始时间以及days后日期结束时间戳
+        @return: next_start_time,end_time
+        """
+        zero_today, last_today = LocalDateTimeUtil.get_today_date(True)
+        now_time = int(time.time())
+        after_time = LocalDateTimeUtil.get_after_days_timestamp(now_time, days)
+        time_array = time.localtime(after_time)
+        start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(time.strftime("%Y-%m-%d", time_array),
+                                                                        '%Y-%m-%d')
+        return zero_today, end_time
+
+    @staticmethod
+    def get_month_start_and_end_time():
+        """
+        获取当天开始时间与当月结束时间戳
+        @return:
+        """
+        zero_today, last_today = LocalDateTimeUtil.get_today_date(True)
+        month_end = LocalDateTimeUtil.get_cur_month_end()
+        start_time, month_end_time = LocalDateTimeUtil.get_start_and_end_time(month_end, '%Y-%m-%d')
+        return zero_today, month_end_time
+
+    @classmethod
+    def get_test_sign(cls, request_dict, response):
+        """
+        测试盐加密解密
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        verify = request_dict.get('verify', False)
+        if verify:
+            sign = request_dict.get('sign')
+            time_stamp = request_dict.get('timeStamp')
+            sign = CommonService.check_time_stamp_token(sign, time_stamp)
+            if not sign:
+                return response.json(13)
+            return response.json(0)
+        now_time = int(time.time())
+        sign = CommonService.encode_data(str(now_time))
+        return response.json(0, {'sign': sign, 'timeStamp': now_time})

+ 189 - 0
Controller/UnicomCombo/UnicomComboPayNotifyController.py

@@ -0,0 +1,189 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : UnicomComboPayNotifyController.py
+@Time    : 2022/6/29 14:31
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import logging
+import time
+from urllib.parse import parse_qs, unquote
+
+from django.db import transaction
+from django.http import HttpResponse
+from django.views import View
+
+from Controller.UnicomCombo.UnicomComboController import UnicomComboView
+from Model.models import Order_Model, UnicomDeviceInfo
+from Object.AliPayObject import AliPayObject
+from Object.RedisObject import RedisObject
+from Object.WechatPayObject import WechatPayObject
+from Service.CommonService import CommonService
+
+
+class UnicomComboPayNotifyView(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):
+        if operation == 'ali-notify':
+            return self.alipay_notify(request_dict)
+        elif operation == 'wechat-notify':
+            return self.wechat_notify(request)
+
+    @classmethod
+    def alipay_notify(cls, request_dict):
+        """
+        支付宝网页支付异步回调通知
+        参考文档 https://opendocs.alipay.com/open/203/105286
+        @param request_dict: 请求参数
+        @return: success or fail
+        """
+        logger = logging.getLogger('info')
+        logger.info('联通套餐支付---支付宝支付回调')
+        order_id = ''
+        redisObj = RedisObject()
+        notify_key = 'ansjer:unicom:alipay:{}:str'
+        try:
+            re_data = request_dict.dict()
+            passback_params = re_data['passback_params']
+            params = dict([(k, v[0]) for k, v in parse_qs(unquote(passback_params)).items()])
+            activate_type = int(params['activateType'])
+            logger.info('支付宝异步回调参数:{},携带参数{}', re_data, params)
+            signature = re_data['sign']
+            re_data.pop('sign')
+            order_id = re_data['out_trade_no']
+
+            # redis加锁,防止订单重复  命令在指定的 key 不存在时,为 key 设置指定的值。存在则返回0
+            isLock = redisObj.CONN.setnx(notify_key.format(order_id), 1)
+            # 过期时间60秒
+            redisObj.CONN.expire(notify_key.format(order_id), 60)
+            if not isLock:
+                return HttpResponse('fail')
+
+            order_qs = Order_Model.objects.filter(orderID=order_id)
+            if not order_qs.exists():
+                logger.info('系统订单不存在:{}'.format(order_id))
+                return HttpResponse('fail')
+            order_qs = order_qs.filter(status=0)
+            if not order_qs.exists():
+                logger.info('订单已支付或退款{}'.format(order_id))
+                return HttpResponse('success')
+            aliPayObj = AliPayObject()
+            alipay = aliPayObj.conf()
+            # 异步回调验签
+            success = alipay.verify(re_data, signature)
+            if not success or re_data["trade_status"] not in ("TRADE_SUCCESS", "TRADE_FINISHED"):
+                return HttpResponse('fail')
+            return cls.order_pay_notify(order_id, re_data["trade_no"], activate_type, notify_key.format(order_id),
+                                        order_qs, redisObj)
+        except Exception as e:
+            logger.info('联通套餐订单支付宝支付回调异常:{}'.format(repr(e)))
+            redisObj.del_data(key=notify_key.format(order_id))
+            return HttpResponse('fail')
+
+    @classmethod
+    def wechat_notify(cls, request):
+        """
+        微信支付异步回调
+        参考文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
+        @param request: 回调参数 具体参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8
+        @return: SUCCESS or FAIL
+        """
+        logger = logging.getLogger('info')
+        logger.info('联通套餐支付---微信支付回调')
+        order_id = ''
+        redisObj = RedisObject()
+        notify_key = 'ansjer:unicom:wxpay:{}:str'
+        pay = WechatPayObject()
+        try:
+            re_data = pay.weixinpay_call_back(request.body)
+            attach = re_data["attach"]
+            parmap = dict([(k, v[0]) for k, v in parse_qs(unquote(attach)).items()])
+            activate_type = int(parmap['activateType'])
+            logger.info('微信异步回调参数:{},携带参数{}'.format(re_data, parmap))
+            trade_status = re_data['result_code']  # 业务结果  SUCCESS/FAIL
+            order_id = re_data['out_trade_no']  # 商户订单号
+            order_qs = Order_Model.objects.filter(orderID=order_id)
+            if not order_qs.exists():
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
+            order_qs = order_qs.filter(status=0)
+            if not order_qs.exists():
+                logger.info('订单已支付或退款{}'.format(order_id))
+                return cls.wx_return_code()
+
+            if trade_status != 'SUCCESS':
+                logger.info('微信支付回调Fail')
+                order_qs.update(status=10)
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
+            check_sign = pay.get_notifypay(re_data)
+            if not check_sign:
+                logger.info('微信支付回调签名失败')
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': '签名失败'}))
+
+            # redis加锁,防止订单重复
+            redisObj = RedisObject()
+            isLock = redisObj.CONN.setnx(notify_key.format(order_id), 1)
+            redisObj.CONN.expire(notify_key.format(order_id), 60)
+            if not isLock:
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
+
+            return cls.order_pay_notify(order_id, re_data["transaction_id"], activate_type, notify_key.format(order_id),
+                                        order_qs,
+                                        redisObj, True)
+        except Exception as e:
+            redisObj.del_data(key=notify_key.format(order_id))
+            return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': repr(e)}))
+
+    @staticmethod
+    def wx_return_code():
+        return HttpResponse("<xml>\
+                                  <return_code><![CDATA[SUCCESS]]></return_code>\
+                                  <return_msg><![CDATA[OK]]></return_msg>\
+                              </xml>")
+
+    @classmethod
+    def order_pay_notify(cls, order_id, trade_no, activate_type, request_key, order_qs, redisObj, is_wechat_pay=False):
+        """
+        订单支付通知
+        @param trade_no: 第三方交易流水号
+        @param order_id:订单编号
+        @param activate_type: 激活类型
+        @param request_key:访问缓存key
+        @param order_qs:订单对象
+        @param redisObj:缓存对象
+        @param is_wechat_pay:是否微信支付
+        @return: success or fail
+        """
+        logger = logging.getLogger('info')
+        now_time = int(time.time())
+        with transaction.atomic():
+            # 支付宝交易凭证号。
+            order_qs = order_qs.values('UID', 'unify_combo_id', 'userID_id', 'order_type')
+            device_uid = order_qs[0]['UID']
+            combo_id = order_qs[0]['unify_combo_id']
+            serial_no = CommonService.query_serial_with_uid(device_uid)
+            unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no).values('iccid')
+            if unicom_device_info_qs.exists():
+                iccid = unicom_device_info_qs[0]['iccid']
+                UnicomComboView.create_combo_order_info(order_id, activate_type,
+                                                        iccid, combo_id)
+            order_qs.update(trade_no=trade_no, status=1, payTime=now_time, updTime=now_time)
+            logger.info('购买联通套餐成功,序列号为:{}'.format(serial_no))
+        redisObj.del_data(key=request_key)
+        if is_wechat_pay:
+            return HttpResponse("<xml>\
+                          <return_code><![CDATA[SUCCESS]]></return_code>\
+                          <return_msg><![CDATA[OK]]></return_msg>\
+                        </xml>")
+        else:
+            return HttpResponse('success')

+ 291 - 0
Controller/UnicomCombo/UnicomComboTaskController.py

@@ -0,0 +1,291 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : UnicomComboTaskController.py
+@Time    : 2022/6/30 16:23
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import datetime
+import logging
+import time
+from decimal import Decimal
+
+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 Object.ResponseObject import ResponseObject
+from Object.UnicomObject import UnicomObjeect
+
+
+class UnicomComboTaskView(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()
+        print(request)
+        if operation == 'check-activate':
+            return self.check_activate_combo(request_dict, response)
+        elif operation == 'check-flow':
+            return self.check_flow_usage(response)
+        elif operation == 'check-flow-expire':
+            return self.check_flow_expire(response)
+        elif operation == 'check-expire':
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            self.query_unused_combo_and_activate(request_dict.get('iccid'), year, month, '666')
+            return response.json(0)
+
+    @classmethod
+    def check_activate_combo(cls, request_dict, response):
+        """
+        定时检查是否有次月激活套餐
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        print(request_dict)
+        logger.info('--->进入监控次月激活联通套餐')
+        now_time = int(time.time())
+        combo_order_info_qs = UnicomComboOrderInfo.objects.filter(status=0, next_month_activate=True,
+                                                                  activation_time__lte=now_time,
+                                                                  expire_time__gte=now_time, is_del=0).values()
+        if not combo_order_info_qs.exists():
+            return response.json(0)
+        try:
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            with transaction.atomic():
+                unicom_api = UnicomObjeect()
+                for item in combo_order_info_qs:
+                    if item['order_id']:
+                        order_id = item['order_id']
+                        order_qs = Order_Model.objects.filter(orderID=order_id, status=1)
+                        if not order_qs.exists():
+                            continue
+                        combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, iccid=item['iccid'])
+                        # 当前已有套餐正在使用则跳出当前循环
+                        if combo_order_qs.exists():
+                            continue
+                        combo_id = item['combo_id']
+                        combo_qs = UnicomCombo.objects.filter(id=combo_id).values()
+                        if not combo_qs.exists():
+                            continue
+                        # 查询当月用量情况
+                        flow_total_usage = unicom_api.get_flow_usage_total(year, month, item['iccid'])
+                        flow_total_usage = Decimal(flow_total_usage).quantize(
+                            Decimal('0.00')) if flow_total_usage > 0 else 0
+                        flow_total_usage = str(flow_total_usage)
+                        iccid = item['iccid']
+                        # 检查激活iccid
+                        unicom_api.change_device_to_activate(iccid)
+                        cls.query_unused_combo_and_activate(iccid, year, month, flow_total_usage)
+                        logger.info('激活成功,订单编号:{}'.format(order_id))
+            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 check_flow_usage(cls, response):
+        """
+        检查流量使用情况
+        @return:
+        """
+        logger = logging.getLogger('info')
+        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)
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            now_time = int(time.time())
+            for item in combo_order_qs:
+                iccid = item['iccid']
+                u_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
+                if not u_device_info_qs.exists():
+                    continue
+                u_device_info_qs = u_device_info_qs.first()
+                usage_flow = float(item['flow_total_usage']) if item['flow_total_usage'] else 0.0
+                combo_id = item['combo_id']
+                combo_qs = UnicomCombo.objects.filter(id=combo_id).values()
+                if not combo_qs.exists():
+                    continue
+                combo_qs = combo_qs.first()
+                flow_total = combo_qs['flow_total']
+                # 查询当前月用量历史
+                month_usage_flow = unicom_api.get_flow_usage_total(year, month, iccid)
+                logger.info('--->{}-{},iccid:{};套餐总值:{},激活时当月用量值:{},月已用量:{}'
+                            .format(year, month, iccid, flow_total, usage_flow, month_usage_flow))
+                is_expire = False
+                if item['year'] == year and item['month'] == month:
+                    if month_usage_flow > 0:
+                        # 初始套餐已使用流量 + 套餐总流量
+                        flow = usage_flow + flow_total
+                        if month_usage_flow >= flow:
+                            is_expire = True
+                    usage = (month_usage_flow - usage_flow) if month_usage_flow > usage_flow else 0
+                    cls.flow_warning_push(u_device_info_qs.user_id, u_device_info_qs.serial_no, item['id'], flow_total,
+                                          usage)
+                else:
+                    activate_year = item['year']
+                    activate_month = item['month']
+                    # 上月使用流量
+                    last_usage_flow = unicom_api.get_flow_usage_total(activate_year, activate_month, iccid)
+                    # 上月套餐实际使用量
+                    actual_usage_flow = last_usage_flow - usage_flow
+                    # 剩余
+                    surplus_flow = flow_total - actual_usage_flow
+                    if month_usage_flow > 0:
+                        if month_usage_flow >= surplus_flow:
+                            is_expire = True
+                    usage = (month_usage_flow + last_usage_flow - usage_flow) \
+                        if (month_usage_flow + last_usage_flow) > usage_flow else 0
+                    cls.flow_warning_push(u_device_info_qs.user_id, u_device_info_qs.serial_no, item['id'], flow_total,
+                                          usage)
+                # 检查是否有当月未使用套餐 没有则停卡
+                if is_expire:
+                    UnicomComboOrderInfo.objects.filter(id=item['id']).update(status=2, updated_time=now_time)
+                    activate_status = cls.query_unused_combo_and_activate(iccid, year, month,
+                                                                          month_usage_flow)
+                    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))
+
+    @staticmethod
+    def flow_warning_push(app_user_id, serial_no, combo_order_id, flow_total, flow_usage):
+        """
+        监控流量使用大于85%and小于96%进行消息推送提醒
+        @param app_user_id: app用户id
+        @param serial_no: 序列号
+        @param combo_order_id: 当前套餐订单id
+        @param flow_total: 流量总量
+        @param flow_usage: 已使用流量
+        @return:
+        """
+        logger = logging.getLogger('info')
+        try:
+            if not app_user_id:
+                return False
+            if 0 < flow_total and 0 < flow_usage < flow_total:
+                res = flow_usage / flow_total * 100
+                if 85 < res <= 95:
+                    flow_push = UnicomFlowPush.objects.filter(serial_no=serial_no, combo_order_id=combo_order_id)
+                    if not flow_push.exists():
+                        now_time = int(time.time())
+                        push_data = {'combo_order_id': str(combo_order_id), 'serial_no': serial_no,
+                                     'flow_total_usage': flow_usage, 'flow_total': flow_total, 'status': 0,
+                                     'updated_time': now_time,
+                                     'created_time': now_time, 'user_id': app_user_id}
+                        UnicomFlowPush.objects.create(**push_data)
+            return True
+        except Exception as e:
+            logger.info('出错了~异常流量监控,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def query_unused_combo_and_activate(iccid, year, month, usage_flow):
+        """
+        查询未使用套餐并激活
+        @param iccid:
+        @param year:
+        @param month:
+        @param usage_flow:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        try:
+            now_time = int(time.time())
+            combo_order_qs = UnicomComboOrderInfo.objects \
+                .filter(expire_time__gt=now_time, activation_time__lte=now_time, status=0, iccid=iccid) \
+                .order_by('created_time')
+            if not combo_order_qs.exists():
+                return False
+
+            combo_order = combo_order_qs.first()
+            if not combo_order.order_id:
+                return False
+            order_qs = Order_Model.objects.filter(orderID=combo_order.order_id, status=1)
+            if not order_qs.exists():
+                return False
+            upd_data = {
+                'status': 1,
+                'year': year,
+                'month': month,
+                'flow_total_usage': str(usage_flow),
+                'updated_time': now_time,
+            }
+            UnicomComboOrderInfo.objects.filter(id=combo_order.id).update(**upd_data)
+            return True
+        except Exception as e:
+            logger.info('出错了~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return False
+
+    @classmethod
+    def check_flow_expire(cls, response):
+        """
+        检查流量到期停卡操作
+        @param response:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        logger.info('--->进入监控流量到期停卡或激活叠加包')
+        now_time = int(time.time())
+        combo_order_qs = UnicomComboOrderInfo.objects.filter(~Q(status=2), expire_time__lte=now_time,
+                                                             is_del=False).values()
+        today = datetime.datetime.today()
+        year = today.year
+        month = today.month
+        if not combo_order_qs.exists():
+            return response.json(0)
+        iccid_list = []
+        with transaction.atomic():
+            for item in combo_order_qs:
+                try:
+                    icc_id = item['iccid']
+                    um_device_qs = UnicomDeviceInfo.objects.filter(iccid=icc_id)
+                    if not um_device_qs.exists():
+                        continue
+                    UnicomComboOrderInfo.objects.filter(id=item['id']).update(status=2)
+                    iccid_list.append(icc_id)
+                    logger.info('--->当前流量套餐已过期,iccid:{}'.format(icc_id))
+                except Exception as e:
+                    logger.info('出错了~监控流量到期异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+                    continue
+        # set无序不重复元素集
+        iccid_list = list(set(iccid_list))
+        unicom_api = UnicomObjeect()
+        for item in iccid_list:
+            activate_combo_qs = UnicomComboOrderInfo.objects.filter(iccid=item, status=1, expire_time__gt=now_time,
+                                                                    is_del=False).values()
+            if activate_combo_qs.exists():
+                continue
+            usage_flow = unicom_api.get_flow_usage_total(year, month, item)
+            result = cls.query_unused_combo_and_activate(item, year, month, usage_flow)
+            if not result:
+                # 停用设备
+                unicom_api.change_device_to_disable(item)
+            else:
+                unicom_api.change_device_to_activate(item)
+        return response.json(0)

+ 126 - 82
Controller/UserController.py

@@ -11,44 +11,47 @@
 @file: UserController.py
 @file: UserController.py
 @Contact: chanjunkai@163.com
 @Contact: chanjunkai@163.com
 """
 """
+import base64
 import datetime
 import datetime
-import traceback
-import time
 import logging
 import logging
+import random
+import threading
+import time
+import traceback
+from io import BytesIO
+
 import jwt
 import jwt
+import requests
 import simplejson
 import simplejson
 import simplejson as json
 import simplejson as json
-import requests
+from PIL import Image, ImageDraw, ImageFont
 from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
 from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
 from django.db.models import Q
 from django.db.models import Q
 from django.http import HttpResponseRedirect
 from django.http import HttpResponseRedirect
+from django.shortcuts import HttpResponse
 from django.utils.decorators import method_decorator
 from django.utils.decorators import method_decorator
 from django.utils.timezone import utc
 from django.utils.timezone import utc
 from django.views.decorators.csrf import csrf_exempt
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
 from django.views.generic import TemplateView
+from django.views.generic import View
 from jwt.algorithms import RSAAlgorithm
 from jwt.algorithms import RSAAlgorithm
 from ratelimit.decorators import ratelimit
 from ratelimit.decorators import ratelimit
 
 
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
+from Ansjer.config import BASE_DIR
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
-    UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal
+    UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal, \
+    GatewayPush
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.TokenObject import TokenObject
+from Object.UVerifyObject import UVerifyObject
 from Service.CommonService import CommonService
 from Service.CommonService import CommonService
 from Service.ModelService import ModelService
 from Service.ModelService import ModelService
 from Service.TemplateService import TemplateService
 from Service.TemplateService import TemplateService
-from django.views.generic import View
-import base64
-import random
-from io import BytesIO
-from PIL import Image, ImageDraw, ImageFont
-from django.shortcuts import HttpResponse
-from Ansjer.config import BASE_DIR
-from Object.UVerifyObject import UVerifyObject
 
 
 
 
 # 获取验证码
 # 获取验证码
@@ -290,6 +293,7 @@ class registerView(TemplateView):
         else:
         else:
             return response.json(109)
             return response.json(109)
 
 
+
 # 登出
 # 登出
 class LogoutView(TemplateView):
 class LogoutView(TemplateView):
     @method_decorator(csrf_exempt)
     @method_decorator(csrf_exempt)
@@ -310,24 +314,19 @@ class LogoutView(TemplateView):
         response = ResponseObject()
         response = ResponseObject()
         token = request_dict.get('token')
         token = request_dict.get('token')
         tko = TokenObject(token)
         tko = TokenObject(token)
-        if tko.code == 0:
-            Device_User.objects.filter(userID=tko.userID).update(online=False)
-
-            redisObj = RedisObject(db=3)
-            redisObj.del_data(key=tko.userID)
-            m_code = request_dict.get('m_code', None)
-            if m_code:
-                userID = tko.userID
-                try:
-                    UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
-                except Exception as e:
-                    pass
-                else:
-                    pass
-            return response.json(0)
-        else:
+        if tko.code != 0:
             return response.json(tko.code)
             return response.json(tko.code)
 
 
+        Device_User.objects.filter(userID=tko.userID).update(online=False)
+        redisObj = RedisObject(db=3)
+        redisObj.del_data(key=tko.userID)
+        m_code = request_dict.get('m_code', None)
+        if m_code:
+            userID = tko.userID
+            UidPushModel.objects.filter(userID_id=userID, m_code=m_code).delete()
+            GatewayPush.objects.filter(user_id=userID, m_code=m_code).update(logout=True)
+        return response.json(0)
+
 
 
 # 修改密码
 # 修改密码
 class ChangePwdView(TemplateView):
 class ChangePwdView(TemplateView):
@@ -709,7 +708,7 @@ class refreshTokenViewV3(TemplateView):
             userID = tko.userID
             userID = tko.userID
             tko.lang = lang
             tko.lang = lang
 
 
-            if password:     # 检验密码
+            if password:  # 检验密码
                 password = password.strip()
                 password = password.strip()
                 # 解密
                 # 解密
                 for i in range(1, 4):
                 for i in range(1, 4):
@@ -903,8 +902,8 @@ class v2authCodeView(TemplateView):
             msg = res["Message"]
             msg = res["Message"]
             if code == "isv.MOBILE_NUMBER_ILLEGAL":
             if code == "isv.MOBILE_NUMBER_ILLEGAL":
                 if response.lang == "cn":
                 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):
     def phoneCodeV2(self, country_code, phone, response, sign_name):
         dataValid = DataValid()
         dataValid = DataValid()
@@ -1975,28 +1974,28 @@ class v3LoginView(TemplateView):
         else:
         else:
             data_valid = DataValid()
             data_valid = DataValid()
             if data_valid.email_validate(username):
             if data_valid.email_validate(username):
-                return self.do_email_login(username, password, response, subscribe, number)
+                return self.do_email_login(username, password, response, subscribe, number, request_dict)
             elif data_valid.mobile_validate(username):
             elif data_valid.mobile_validate(username):
-                return self.do_phone_login(username, password, response, subscribe, number)
+                return self.do_phone_login(username, password, response, subscribe, number, request_dict)
             elif data_valid.name_validate(username):
             elif data_valid.name_validate(username):
-                return self.do_name_login(username, password, response, subscribe, number)
+                return self.do_name_login(username, password, response, subscribe, number, request_dict)
             else:
             else:
                 return response.json(107)
                 return response.json(107)
 
 
-    def do_email_login(self, email, password, response, subscribe, number):
+    def do_email_login(self, email, password, response, subscribe, number, request_dict):
         user_qs = Device_User.objects.filter(Q(username=email) | Q(userEmail=email))
         user_qs = Device_User.objects.filter(Q(username=email) | Q(userEmail=email))
-        return self.valid_login(user_qs, password, response, subscribe, number)
+        return self.valid_login(user_qs, password, response, subscribe, number, request_dict)
 
 
-    def do_phone_login(self, phone, password, response, subscribe, number):
+    def do_phone_login(self, phone, password, response, subscribe, number, request_dict):
         user_qs = Device_User.objects.filter(Q(phone=phone) | Q(username=phone), is_active=True, user_isValid=True)
         user_qs = Device_User.objects.filter(Q(phone=phone) | Q(username=phone), is_active=True, user_isValid=True)
-        return self.valid_login(user_qs, password, response, subscribe, number)
+        return self.valid_login(user_qs, password, response, subscribe, number, request_dict)
 
 
-    def do_name_login(self, username, password, response, subscribe, number):
+    def do_name_login(self, username, password, response, subscribe, number, request_dict):
         user_qs = Device_User.objects.filter(Q(username=username) | Q(phone=username) | Q(userEmail=username),
         user_qs = Device_User.objects.filter(Q(username=username) | Q(phone=username) | Q(userEmail=username),
                                              is_active=True, user_isValid=True)
                                              is_active=True, user_isValid=True)
-        return self.valid_login(user_qs, password, response, subscribe, number)
+        return self.valid_login(user_qs, password, response, subscribe, number, request_dict)
 
 
-    def valid_login(self, user_qs, password, response, subscribe, number):
+    def valid_login(self, user_qs, password, response, subscribe, number, request_dict):
         if not user_qs.exists():
         if not user_qs.exists():
             return response.json(104)
             return response.json(104)
         # users = user_qs.values('role__rid', 'role__roleName', 'userID', 'role', 'NickName', 'username', 'userEmail',
         # users = user_qs.values('role__rid', 'role__roleName', 'userID', 'role', 'NickName', 'username', 'userEmail',
@@ -2005,9 +2004,11 @@ class v3LoginView(TemplateView):
             user_qs.update(subscribe_email=subscribe)
             user_qs.update(subscribe_email=subscribe)
 
 
         users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
         users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
-                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key', 'subscribe_email')[0]
+                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key',
+                               'subscribe_email')[0]
         if not check_password(password, users['password']):
         if not check_password(password, users['password']):
             return response.json(111)
             return response.json(111)
+
         userID = users['userID']
         userID = users['userID']
         tko = TokenObject()
         tko = TokenObject()
         res = tko.generate(
         res = tko.generate(
@@ -2017,36 +2018,49 @@ class v3LoginView(TemplateView):
         if oauth_qs.exists():
         if oauth_qs.exists():
             auth_type = oauth_qs[0].authType
             auth_type = oauth_qs[0].authType
 
 
+        if tko.code != 0:
+            return response.json(tko.code)
 
 
-        if tko.code == 0:
-            now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
-            if not number:
-                user_qs.update(last_login=now_time, language=response.lang)
+        # 网关推送新增内容
+        app_bundle_id = request_dict.get('appBundleId', None)
+        app_type = request_dict.get('appType', None)
+        push_type = request_dict.get('pushType', None)
+        token_val = request_dict.get('tokenVal', None)
+        m_code = request_dict.get('mCode', None)
+        lang = request_dict.get('language', 'en')
+        tz = request_dict.get('tz', None)
+        if all([app_bundle_id, app_type, push_type, token_val, m_code, tz]):
+            gateway_push_qs = GatewayPush.objects.filter(user_id=userID, m_code=m_code)
+            if gateway_push_qs.exists():
+                gateway_push_qs.update(token_val=token_val, logout=False)
             else:
             else:
-                user_qs.update(last_login=now_time, language=response.lang, region_country=number)
+                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)
 
 
-            res['rid'] = users['role__rid']
-            res['roleName'] = users['role__roleName']
-            res['permList'] = ModelService.own_permission(userID)
-            res['userID'] = userID
-            # 昵称,邮箱,电话,刷新,头像
-            userIconPath = str(users['userIconPath'])
-            if userIconPath and userIconPath.find('static/') != -1:
-                userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
-                res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
-            else:
-                res['userIconUrl'] = ''
-            res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
-            res['username'] = users['username'] if users['username'] is not None else ''
-            res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
-            res['phone'] = users['phone'] if users['phone'] is not None else ''
-            # res['fingerprint_enable'] = users['fingerprint_enable']
-            # res['fingerprint_key'] = CommonService.encode_data(content=users['fingerprint_key'], start=2)
-            res['authType'] = auth_type
-            res['subscribe_email'] = users['subscribe_email'] if users['subscribe_email'] is not None else ''
-            return response.json(0, res)
+        now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
+        if not number:
+            user_qs.update(last_login=now_time, language=response.lang)
         else:
         else:
-            return response.json(tko.code)
+            user_qs.update(last_login=now_time, language=response.lang, region_country=number)
+
+        res['rid'] = users['role__rid']
+        res['roleName'] = users['role__roleName']
+        res['permList'] = ModelService.own_permission(userID)
+        res['userID'] = userID
+        # 昵称,邮箱,电话,刷新,头像
+        userIconPath = str(users['userIconPath'])
+        if userIconPath and userIconPath.find('static/') != -1:
+            userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+            res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
+        else:
+            res['userIconUrl'] = ''
+        res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
+        res['username'] = users['username'] if users['username'] is not None else ''
+        res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
+        res['phone'] = users['phone'] if users['phone'] is not None else ''
+        res['authType'] = auth_type
+        res['subscribe_email'] = users['subscribe_email'] if users['subscribe_email'] is not None else ''
+        return response.json(0, res)
 
 
 
 
 # 一键登录接口
 # 一键登录接口
@@ -2078,7 +2092,8 @@ class oneClickLoginView(TemplateView):
             if not phone:
             if not phone:
                 return response.json(102)
                 return response.json(102)
 
 
-            user_qs = Device_User.objects.filter(phone=phone).values('userID', 'username', 'NickName', 'phone', 'password')
+            user_qs = Device_User.objects.filter(phone=phone).values('userID', 'username', 'NickName', 'phone',
+                                                                     'password')
             # 用户已存在的响应
             # 用户已存在的响应
             if user_qs.exists():
             if user_qs.exists():
                 tokenObj = TokenObject()
                 tokenObj = TokenObject()
@@ -2194,6 +2209,9 @@ class InitInfoView(View):
                     return response.json(904)
                     return response.json(904)
             else:
             else:
                 return response.json(444, 'push_type')
                 return response.json(444, 'push_type')
+            asy = threading.Thread(target=self.save_push_config,
+                                   args=(userID, appBundleId, push_type, token_val, m_code, lang, tz))
+            asy.start()
             if m_code:
             if m_code:
                 # 获取设备推送状态
                 # 获取设备推送状态
                 update_dict = {
                 update_dict = {
@@ -2237,6 +2255,31 @@ class InitInfoView(View):
         res = {'usmsg': 0}  # 预留字段, 有版本app该字段去掉会报错
         res = {'usmsg': 0}  # 预留字段, 有版本app该字段去掉会报错
         return response.json(0, res)
         return response.json(0, res)
 
 
+    @staticmethod
+    def save_push_config(user_id, app_bundle_id, push_type, token_val, m_code, lang, tz):
+        """
+        异步保存新推送配置
+        @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: 时区
+        @return: None
+        """
+        try:
+            app_type = 1 if push_type == 0 else 2
+            gateway_push_qs = GatewayPush.objects.filter(user_id=user_id, m_code=m_code)
+            if gateway_push_qs.exists():
+                gateway_push_qs.update(token_val=token_val, logout=False)
+            else:
+                GatewayPush.objects.create(user_id=user_id, 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)
+        except Exception as e:
+            print('出错了~异步保存配置信息错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+
     def update_country(self, request_dict, response, request):
     def update_country(self, request_dict, response, request):
         username = request_dict.get('unique', None)
         username = request_dict.get('unique', None)
         appBundleId = request_dict.get('appBundleId', None)
         appBundleId = request_dict.get('appBundleId', None)
@@ -3066,7 +3109,8 @@ class alexaUidView(TemplateView):
                 uid_list.append(UID)
                 uid_list.append(UID)
                 uid_dict[UID] = {'nick': uid_q['NickName'], 'password': uid_q['View_Password']}
                 uid_dict[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')
+            us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=1).values('id', 'uid', 'region_alexa',
+                                                                                    'channel')
             if not us_qs.exists():
             if not us_qs.exists():
                 return response.json(173)
                 return response.json(173)
             # uid,password,region的列表
             # uid,password,region的列表
@@ -3081,7 +3125,8 @@ class alexaUidView(TemplateView):
 
 
                 # 多通道设备获取通道名
                 # 多通道设备获取通道名
                 if channel > 1:
                 if channel > 1:
-                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us['id']).values('channel', 'channel_name')
+                    uid_channel_set_qs = UidChannelSetModel.objects.filter(uid_id=us['id']).values('channel',
+                                                                                                   'channel_name')
                     if uid_channel_set_qs.exists():
                     if uid_channel_set_qs.exists():
                         # DVR设备名为 UidChannelSetModel 的 channel_name
                         # DVR设备名为 UidChannelSetModel 的 channel_name
                         for uid_channel_set in uid_channel_set_qs:
                         for uid_channel_set in uid_channel_set_qs:
@@ -3098,6 +3143,7 @@ class alexaUidView(TemplateView):
         except Exception as e:
         except Exception as e:
             return response.json(500, repr(e))
             return response.json(500, repr(e))
 
 
+
 # 登出
 # 登出
 class V2LogoutView(TemplateView):
 class V2LogoutView(TemplateView):
     @method_decorator(csrf_exempt)
     @method_decorator(csrf_exempt)
@@ -3604,7 +3650,6 @@ class v3LoginByCodeView(View):
         if oauth_qs.exists():
         if oauth_qs.exists():
             auth_type = oauth_qs[0].authType
             auth_type = oauth_qs[0].authType
 
 
-
         if tko.code == 0:
         if tko.code == 0:
             now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
             now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
             user_qs.update(last_login=now_time, language=response.lang)
             user_qs.update(last_login=now_time, language=response.lang)
@@ -4059,6 +4104,7 @@ def updateUserCountry(request):
     response = ResponseObject()
     response = ResponseObject()
     return response.json(0)
     return response.json(0)
 
 
+
 def confirmRegion(request):
 def confirmRegion(request):
     response = ResponseObject()
     response = ResponseObject()
     request.encoding = 'utf-8'
     request.encoding = 'utf-8'
@@ -4069,17 +4115,17 @@ def confirmRegion(request):
     number = request.POST.get('number', None)
     number = request.POST.get('number', None)
     selectRegion = CountryModel.objects.filter(number=number).values('region__api')
     selectRegion = CountryModel.objects.filter(number=number).values('region__api')
     if not selectRegion.exists():
     if not selectRegion.exists():
-        return response.json(0,{"request_url":"https://www.dvema.com"})
+        return response.json(0, {"request_url": "https://www.dvema.com"})
     else:
     else:
-        return response.json(0,{"request_url":selectRegion[0]['region__api']})
+        return response.json(0, {"request_url": selectRegion[0]['region__api']})
 
 
 
 
 def deleteAccount(request):
 def deleteAccount(request):
     response = ResponseObject()
     response = ResponseObject()
     request.encoding = 'utf-8'
     request.encoding = 'utf-8'
-    #test
-    token = request.POST.get('token',None)
-    password = request.POST.get('userPwd',None)
+    # test
+    token = request.POST.get('token', None)
+    password = request.POST.get('userPwd', None)
     try:
     try:
         for i in range(1, 4):
         for i in range(1, 4):
             if i == 1:
             if i == 1:
@@ -4125,8 +4171,8 @@ def deleteAccount(request):
         if hasDevices.exists():
         if hasDevices.exists():
             return response.json(10047)
             return response.json(10047)
 
 
-        orderUserIds = Order_Model.objects.filter(userID=userID,status=1).values_list('UID').distinct().order_by("UID")
-        hadUseSevice = UID_Bucket.objects.filter(uid__in=orderUserIds,use_status=1)
+        orderUserIds = Order_Model.objects.filter(userID=userID, status=1).values_list('UID').distinct().order_by("UID")
+        hadUseSevice = UID_Bucket.objects.filter(uid__in=orderUserIds, use_status=1)
         if hadUseSevice.exists():
         if hadUseSevice.exists():
             return response.json(10046)
             return response.json(10046)
 
 
@@ -4173,7 +4219,7 @@ class InitUserInformationView(View):
             now_time = int(time.time())
             now_time = int(time.time())
             if user_ex_qs.exists():
             if user_ex_qs.exists():
                 update = {
                 update = {
-                    'appBundleId':appBundleId,
+                    'appBundleId': appBundleId,
                     'updTime': now_time
                     'updTime': now_time
                 }
                 }
                 user_ex_qs.update(**update)
                 user_ex_qs.update(**update)
@@ -4184,5 +4230,3 @@ class InitUserInformationView(View):
             return response.json(0)
             return response.json(0)
         else:
         else:
             return response.json(444)
             return response.json(444)
-
-

+ 123 - 7
Model/models.py

@@ -1184,6 +1184,7 @@ class UidSetModel(models.Model):
     is_human = models.IntegerField(default=0, verbose_name='是否支持人形追踪。0:不支持,1:支持')
     is_human = models.IntegerField(default=0, verbose_name='是否支持人形追踪。0:不支持,1:支持')
     is_custom_voice = 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:支持')
     double_wifi = models.IntegerField(default=0, verbose_name='是否支持双频wifi。0:不支持,1:支持')
+    mobile_4g = models.IntegerField(default=0, verbose_name='是否支持4g。0:不支持,1:支持')
     is_ptz = models.IntegerField(default=0, verbose_name='是否支持云台。0:不支持,1:支持')
     is_ptz = models.IntegerField(default=0, verbose_name='是否支持云台。0:不支持,1:支持')
     is_ai = models.IntegerField(default=2, verbose_name='是否支持ai')  # 0,关闭,1开启,2,不支持
     is_ai = models.IntegerField(default=2, verbose_name='是否支持ai')  # 0,关闭,1开启,2,不支持
     is_notification = models.IntegerField(blank=True, default=1, verbose_name='新加-消息提醒开关')  # 0:关闭,1:开启
     is_notification = models.IntegerField(blank=True, default=1, verbose_name='新加-消息提醒开关')  # 0:关闭,1:开启
@@ -1218,6 +1219,25 @@ class UidPushModel(models.Model):
         ordering = ('-id',)
         ordering = ('-id',)
 
 
 
 
+class GatewayPush(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增id')
+    user_id = models.CharField(default='', max_length=32, verbose_name=u'用户id')
+    app_bundle_id = models.CharField(default='', max_length=32, verbose_name=u'app包id')
+    app_type = models.IntegerField(default=0, verbose_name=u'app类型')  # 1: ios, 2: 安卓
+    push_type = models.IntegerField(default=0, verbose_name=u'推送类型')  # 0: apns, 1: 安卓gcm, 2: 极光
+    token_val = models.CharField(default='', max_length=500, verbose_name=u'设备验证令牌')
+    m_code = models.CharField(default='', max_length=64, verbose_name='手机唯一标识')
+    lang = models.CharField(default='en', max_length=8, verbose_name='推送语言')
+    tz = models.CharField(default='0', max_length=8, verbose_name='时区')
+    logout = models.BooleanField(default=False, verbose_name=u'退出登录')
+
+    class Meta:
+        db_table = 'gateway_push'
+        verbose_name = '网关推送'
+        verbose_name_plural = verbose_name
+        app_label = 'PushModel'
+
+
 # 设备通道配置
 # 设备通道配置
 class UidChannelSetModel(models.Model):
 class UidChannelSetModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='自增id')
     id = models.AutoField(primary_key=True, verbose_name='自增id')
@@ -2538,7 +2558,8 @@ class GatewaySubDevice(models.Model):
     ieee_addr = models.CharField(default='', max_length=64, verbose_name=u'长地址')
     ieee_addr = models.CharField(default='', max_length=64, verbose_name=u'长地址')
     src_addr = models.CharField(default='', max_length=16, verbose_name=u'短地址')
     src_addr = models.CharField(default='', max_length=16, verbose_name=u'短地址')
     status = models.SmallIntegerField(default=0, verbose_name='状态')  # 0:关闭, 1:开启
     status = models.SmallIntegerField(default=0, verbose_name='状态')  # 0:关闭, 1:开启
-    is_tampered = models.SmallIntegerField(default=0, verbose_name='拆动状态')  # 0:正常, 1:被拆动
+    # 0:正常, 1:被拆动, 智能按钮紧急开关状态: 0:关闭, 1:开启
+    is_tampered = models.SmallIntegerField(default=0, verbose_name='拆动状态')
     mac = models.CharField(default='', max_length=32, verbose_name=u'mac地址')
     mac = models.CharField(default='', max_length=32, verbose_name=u'mac地址')
     device_model = models.CharField(default='', max_length=16, verbose_name=u'设备型号')
     device_model = models.CharField(default='', max_length=16, verbose_name=u'设备型号')
     manufacturer = models.CharField(default='', max_length=16, verbose_name=u'制造商')
     manufacturer = models.CharField(default='', max_length=16, verbose_name=u'制造商')
@@ -2603,16 +2624,69 @@ class SensorRecord(models.Model):
         app_label = 'PushModel'
         app_label = 'PushModel'
 
 
 
 
+class SmartScene(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记id')
+    user = models.ForeignKey(Device_User, to_field='userID', default='', on_delete=models.CASCADE,
+                             verbose_name='关联用户表id')
+    device_id = models.CharField(default='', max_length=32, verbose_name=u'关联设备信息id')
+    sub_device_id = models.IntegerField(default=0, verbose_name=u'关联子设备表id')
+    scene_name = models.CharField(default='', max_length=100, verbose_name=u'场景名称')
+    conditions = models.TextField(default='', verbose_name=u'条件')
+    tasks = models.TextField(default='', verbose_name=u'任务')
+    is_all_day = models.SmallIntegerField(default=0, verbose_name=u'是否全天')  # 0: 不设置时间, 1: 全天, 2: 非全天
+    effective_time_id = models.IntegerField(default=0, verbose_name=u'关联场景执行时间id')
+    is_enable = models.BooleanField(default=True, verbose_name=u'是否开启')
+    device_data = models.TextField(default='', verbose_name=u'设备场景数据')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+    updated_time = models.IntegerField(default=0, verbose_name='更新时间')
+
+    class Meta:
+        db_table = 'smart_scene'
+        verbose_name = '智能场景'
+        verbose_name_plural = verbose_name
+
+
+class EffectiveTime(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记id')
+    start_time = models.SmallIntegerField(default=0, verbose_name=u'开始时间')
+    end_time = models.SmallIntegerField(default=0, verbose_name=u'结束时间')
+    repeat = models.SmallIntegerField(default=0, verbose_name=u'重复周期')
+
+    class Meta:
+        db_table = 'effective_time'
+        verbose_name = '场景执行时间'
+        verbose_name_plural = verbose_name
+
+
+class SceneLog(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增标记ID')
+    scene_id = models.IntegerField(default=0, verbose_name='关联场景id')
+    device_id = models.CharField(default='', max_length=32, verbose_name='关联网关id')
+    sub_device_id = models.IntegerField(default=0, verbose_name='关联子设备id')
+    scene_log = models.TextField(default='', verbose_name='场景日志')
+    status = models.SmallIntegerField(default=0, verbose_name='场景状态')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'scene_log'
+        verbose_name = '场景日志'
+        verbose_name_plural = verbose_name
+        app_label = 'PushModel'
+
+
 class UnicomCombo(models.Model):
 class UnicomCombo(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     package_id = models.CharField(default='', max_length=32, verbose_name=u'联通套餐id')
     package_id = models.CharField(default='', max_length=32, verbose_name=u'联通套餐id')
     combo_name = models.CharField(default='', max_length=32, verbose_name=u'套餐名称')
     combo_name = models.CharField(default='', max_length=32, verbose_name=u'套餐名称')
     status = models.SmallIntegerField(default=0, verbose_name='状态{0:开启,1:停用}')
     status = models.SmallIntegerField(default=0, verbose_name='状态{0:开启,1:停用}')
+    # 套餐类型 0:商用,1:初始化赠送
+    combo_type = models.SmallIntegerField(default=0, verbose_name='套餐类型')
     flow_total = models.IntegerField(default=0, blank=True, verbose_name=u'流量总量值 单位(MB)')
     flow_total = models.IntegerField(default=0, blank=True, verbose_name=u'流量总量值 单位(MB)')
     expiration_days = models.IntegerField(default=0, blank=True, verbose_name=u'有效期天数')
     expiration_days = models.IntegerField(default=0, blank=True, verbose_name=u'有效期天数')
     expiration_type = models.SmallIntegerField(default=0, verbose_name=u'有效期类型,0=天,1=月,2=年')
     expiration_type = models.SmallIntegerField(default=0, verbose_name=u'有效期类型,0=天,1=月,2=年')
     pay_type = models.ManyToManyField(to='Pay_Type', verbose_name='付款类型', db_table='unicom_combo_pay_type')
     pay_type = models.ManyToManyField(to='Pay_Type', verbose_name='付款类型', db_table='unicom_combo_pay_type')
     price = models.CharField(blank=True, max_length=32, verbose_name=u'价格')
     price = models.CharField(blank=True, max_length=32, verbose_name=u'价格')
+    is_unlimited = models.SmallIntegerField(default=0, verbose_name=u'是否无限流量,,0:有限流量,1:无限流量')
     sort = models.IntegerField(default=0, blank=True, verbose_name=u'排序,越小越靠前')
     sort = models.IntegerField(default=0, blank=True, verbose_name=u'排序,越小越靠前')
     remark = models.TextField(blank=True, default='', verbose_name=u'描述信息')
     remark = models.TextField(blank=True, default='', verbose_name=u'描述信息')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
@@ -2629,12 +2703,16 @@ class UnicomCombo(models.Model):
 class UnicomComboOrderInfo(models.Model):
 class UnicomComboOrderInfo(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
     iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
-    renew_list_id = models.CharField(default='', max_length=32, verbose_name=u'联通订购成功套餐队列id')
+    renew_list_id = models.CharField(blank=True, default='', max_length=32, verbose_name=u'联通订购成功套餐队列id')
     status = models.SmallIntegerField(default=0, verbose_name='状态{0:未使用,1:已使用,2:已过期}')
     status = models.SmallIntegerField(default=0, verbose_name='状态{0:未使用,1:已使用,2:已过期}')
-    orders = models.ForeignKey(Order_Model, to_field='orderID', default='', on_delete=models.CASCADE,
-                               verbose_name='关联订单表')
+    order_id = models.CharField(blank=True, default='', max_length=32, verbose_name=u'关联订单表')
     combo = models.ForeignKey(UnicomCombo, to_field='id', default='', on_delete=models.CASCADE,
     combo = models.ForeignKey(UnicomCombo, to_field='id', default='', on_delete=models.CASCADE,
                               verbose_name=u'联通套餐表')
                               verbose_name=u'联通套餐表')
+    year = models.IntegerField(default=0, verbose_name='使用年')
+    month = models.IntegerField(default=0, verbose_name='使用月')
+    flow_total_usage = models.CharField(blank=True, default='', max_length=32, verbose_name=u'激活时当月已用流量')
+    sort = models.IntegerField(default=99, blank=True, verbose_name=u'排序')
+    next_month_activate = models.BooleanField(blank=True, default=False, verbose_name=u'下月激活')
     activation_time = models.IntegerField(default=0, verbose_name='激活时间')
     activation_time = models.IntegerField(default=0, verbose_name='激活时间')
     expire_time = models.IntegerField(default=0, verbose_name='过期时间')
     expire_time = models.IntegerField(default=0, verbose_name='过期时间')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
@@ -2649,9 +2727,12 @@ class UnicomComboOrderInfo(models.Model):
 
 
 class UnicomDeviceInfo(models.Model):
 class UnicomDeviceInfo(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
-    iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
+    iccid = models.CharField(db_index=True, unique=True, max_length=32, verbose_name=u'完整的20位纯数字ICCID')
+    status = models.SmallIntegerField(default=0, verbose_name=u'状态{0:可测试,1:测试完成,2:已使用}')
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'设备序列号')
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'设备序列号')
     user_id = models.CharField(blank=True, max_length=32, verbose_name=u'用户id')
     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'状态{0:主卡,1:拔插卡}')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     created_time = models.IntegerField(default=0, verbose_name='创建时间')
     created_time = models.IntegerField(default=0, verbose_name='创建时间')
 
 
@@ -2665,7 +2746,7 @@ class UnicomDeviceQueueMonitoringPush(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
     iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'序列号')
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'序列号')
-    sign = models.CharField(default='', max_length=32, verbose_name=u'验证签名')
+    sign = models.CharField(default='', max_length=128, verbose_name=u'验证签名')
     time = models.CharField(default='', max_length=32, verbose_name=u'推送时间(yyyymmddhhmiss)')
     time = models.CharField(default='', max_length=32, verbose_name=u'推送时间(yyyymmddhhmiss)')
     type = models.CharField(default='', max_length=32, verbose_name=u'推送类型:DEVICE_QUEUE_MONITORING:设队列监控;')
     type = models.CharField(default='', max_length=32, verbose_name=u'推送类型:DEVICE_QUEUE_MONITORING:设队列监控;')
     current_renew_list_id = models.CharField(default='', max_length=32, verbose_name=u'队列ID')
     current_renew_list_id = models.CharField(default='', max_length=32, verbose_name=u'队列ID')
@@ -2683,7 +2764,7 @@ class UnicomDeviceStatusChangePush(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记Id')
     iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
     iccid = models.CharField(default='', max_length=32, verbose_name=u'完整的20位纯数字ICCID')
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'序列号')
     serial_no = models.CharField(default='', max_length=32, verbose_name=u'序列号')
-    sign = models.CharField(default='', max_length=32, verbose_name=u'验证签名')
+    sign = models.CharField(default='', max_length=128, verbose_name=u'验证签名')
     time = models.CharField(default='', max_length=32, verbose_name=u'推送时间(yyyymmddhhmiss)')
     time = models.CharField(default='', max_length=32, verbose_name=u'推送时间(yyyymmddhhmiss)')
     # 变更类型: DEVICE_REAL_NAME_STATUS_CHANGE:实名状态变更;DEVICE_STATUS_CHANGE:设备状态变更;
     # 变更类型: DEVICE_REAL_NAME_STATUS_CHANGE:实名状态变更;DEVICE_STATUS_CHANGE:设备状态变更;
     type = models.CharField(default='', max_length=32, verbose_name=u'变更类型')
     type = models.CharField(default='', max_length=32, verbose_name=u'变更类型')
@@ -2699,3 +2780,38 @@ class UnicomDeviceStatusChangePush(models.Model):
         db_table = 'unicom_device_status_change_push'
         db_table = 'unicom_device_status_change_push'
         verbose_name = '联通设备状态变更推送表'
         verbose_name = '联通设备状态变更推送表'
         verbose_name_plural = verbose_name
         verbose_name_plural = verbose_name
+
+
+class UnicomComboExperienceHistory(models.Model):
+    id = models.AutoField(primary_key=True)
+    # 0: 免费体验, 1: 激活码
+    experience_type = models.SmallIntegerField(default=0, verbose_name='体验类型')
+    iccid = models.CharField(max_length=32, default='', verbose_name='联通20位ICCID')
+    do_time = models.IntegerField(default=0, verbose_name='激活时间')
+
+    class Meta:
+        db_table = 'unicom_combo_experience_history'
+        verbose_name = '联通套餐体验历史表'
+        verbose_name_plural = verbose_name
+
+
+class UnicomFlowPush(models.Model):
+    id = models.AutoField(primary_key=True)
+    user_id = models.CharField(default='', max_length=32, verbose_name=u'用户id')
+    # 0: 剩余10%流量预警, 1: 流量到期
+    type = models.SmallIntegerField(default=0, verbose_name='流量推送类型')
+    combo_order_id = models.CharField(max_length=32, default='', verbose_name='当前订单套餐id')
+    serial_no = models.CharField(max_length=32, default='', verbose_name='序列号')
+    flow_total_usage = models.DecimalField(default=0, max_digits=10, decimal_places=2, verbose_name=u'当月实际流量用量 单位(MB)')
+    flow_total = models.DecimalField(default=0, max_digits=10, decimal_places=2, verbose_name=u'流量总量 单位(MB)')
+    status = models.SmallIntegerField(default=0, verbose_name=u'状态{0:待推送,1:已推送}')
+    updated_time = models.IntegerField(default=0, verbose_name='更新时间')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'unicom_flow_push'
+        verbose_name = '联通流量用量推送'
+        verbose_name_plural = verbose_name
+        app_label = "PushModel"
+
+

+ 1 - 0
Object/LogsObject.py

@@ -124,6 +124,7 @@ class LogsObject(object):
             119: '二维码过期',
             119: '二维码过期',
             120: '验证码过期',
             120: '验证码过期',
             121: '验证码错了!',
             121: '验证码错了!',
+            172: '条件已存在',
             173: '数据不存在!',
             173: '数据不存在!',
             174: '数据已存在!',
             174: '数据已存在!',
             176: '删除错误',
             176: '删除错误',

+ 4 - 2
Object/ResponseObject.py

@@ -43,6 +43,7 @@ class ResponseObject(object):
             177: 'Update error',
             177: 'Update error',
             178: 'ADD error',
             178: 'ADD error',
             179: 'Nickname repeated',
             179: 'Nickname repeated',
+            180: 'Smart button scene trigger conditions cannot be repeated',
             201: 'You can only add 3 custom voice at most',
             201: 'You can only add 3 custom voice at most',
             306: 'The link has expired!',
             306: 'The link has expired!',
             309: 'Please ReLogin! errmsg token',
             309: 'Please ReLogin! errmsg token',
@@ -100,7 +101,7 @@ class ResponseObject(object):
             10041: 'This device has purchased a domestic cloud storage package, and cannot purchase a foreign cloud storage package',
             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',
             10042: 'The device has registered a certificate',
             10043: 'The device does not registered a certificate',
             10043: 'The device does not registered a certificate',
-            10044: 'Request to publish MQTT topic message failed',
+            10044: 'Failed to publish MQTT message',
             10045: 'Already the latest version',
             10045: 'Already the latest version',
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10047: 'Please delete all devices under your account first',
             10047: 'Please delete all devices under your account first',
@@ -150,6 +151,7 @@ class ResponseObject(object):
             177: '更新错误',
             177: '更新错误',
             178: '增加错误',
             178: '增加错误',
             179: '名称不能重复',
             179: '名称不能重复',
+            180: '智能按钮场景触发条件不能重复',
             201: '最多只能添加3条自定义语音',
             201: '最多只能添加3条自定义语音',
             306: '链接已超过有效期!',
             306: '链接已超过有效期!',
             309: '请重新登录!',
             309: '请重新登录!',
@@ -207,7 +209,7 @@ class ResponseObject(object):
             10041: '此设备已购买过国内云存套餐,无法购买国外云存套餐',
             10041: '此设备已购买过国内云存套餐,无法购买国外云存套餐',
             10042: '此设备已注册证书',
             10042: '此设备已注册证书',
             10043: '此设备没有注册证书',
             10043: '此设备没有注册证书',
-            10044: '请求发布MQTT主题消息失败',
+            10044: '发布MQTT消息失败',
             10045: '当前为最新版本',
             10045: '当前为最新版本',
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10047: '请先删除您当前帐户下的所有设备',
             10047: '请先删除您当前帐户下的所有设备',

+ 108 - 7
Object/UnicomObject.py

@@ -7,15 +7,17 @@
 @Software: PyCharm
 @Software: PyCharm
 """
 """
 import base64
 import base64
+import datetime
 import json
 import json
+from decimal import Decimal
 
 
 import requests
 import requests
 from Crypto.Cipher import AES
 from Crypto.Cipher import AES
-from decimal import Decimal
-from Object.utils import SM3Util
 
 
 from Ansjer.config import unicomAppUrl, unicomAppId, unicomAppSecret, unicomTenantId, \
 from Ansjer.config import unicomAppUrl, unicomAppId, unicomAppSecret, unicomTenantId, \
     unicomEncodeKey, unicomIvKey, unicomUserName, unicomPassword, unicomPushKey
     unicomEncodeKey, unicomIvKey, unicomUserName, unicomPassword, unicomPushKey
+from Object.RedisObject import RedisObject
+from Object.utils import SM3Util
 from Object.utils.SymmetricCryptoUtil import AESencrypt
 from Object.utils.SymmetricCryptoUtil import AESencrypt
 
 
 """
 """
@@ -216,8 +218,107 @@ class UnicomObjeect:
         headers['content-type'] = 'application/json'
         headers['content-type'] = 'application/json'
         return requests.post(url, data=json.dumps(re_data), headers=headers)
         return requests.post(url, data=json.dumps(re_data), headers=headers)
 
 
+    @staticmethod
+    def get_text_dict(result):
+        """
+        响应结果转字典
+        @param result:
+        @return:
+        """
+        if result.status_code == 200:
+            return json.loads(result.text)
+        return None
+
+    @staticmethod
+    def unicom_flow_usage_cache(key, expire=0, **usage_data):
+        """
+        流量用量历史优先查询缓存
+        @param key: 缓存key
+        @param expire: 失效时间
+        @param usage_data: 查询参数
+        @return: 返回结果dict
+        """
+        redis = RedisObject()
+        usage_history = redis.get_data(key)
+        if usage_history:
+            usage_history = json.loads(usage_history)
+        else:
+            usage_history = UnicomObjeect().query_device_usage_history(**usage_data)
+            usage_history = UnicomObjeect().get_text_dict(usage_history)
+            redis.set_data(key=key, val=json.dumps(usage_history), expire=expire)
+        return usage_history
+
+    @staticmethod
+    def get_flow_usage_total(usage_year, usage_month, iccid):
+        """
+        查询当月用量历史
+        @param usage_year: 使用年
+        @param usage_month: 使用月
+        @param iccid: 联通id
+        @return: flow_total_usage 当月实际使用流量
+        """
+        flow_key = 'ASJ:UNICOM:FLOW:{}'
+        usage_data = {'iccid': iccid}
+        usage_history = UnicomObjeect().unicom_flow_usage_cache(flow_key.format(iccid), (60 * 10 + 3), **usage_data)
+        # 当月实际总使用流量
+        flow_total_usage = 0
+        if usage_history and usage_history['success']:
+            device_usage_history_list = usage_history['data']['deviceUsageHistory']
+            if device_usage_history_list:
+                for item in device_usage_history_list:
+                    if item['year'] != usage_year or item['month'] != usage_month:
+                        continue
+                    flow_total_usage += item['flowTotalUsage']
+        return flow_total_usage
+
+    @staticmethod
+    def change_device_to_activate(iccid):
+        """
+        根据iccid判断是否激活,未激活则修改为激活状态
+        @param iccid:
+        @return:
+        """
+        if iccid:
+            re_data = {'iccid': iccid}
+            result = UnicomObjeect().query_device_status(**re_data)
+            res_dict = UnicomObjeect().get_text_dict(result)
+            # 状态不等于1(激活)时进行激活 1:激活;2:停用
+            if res_dict['data']['status'] != 1:
+                re_data = {"iccid": iccid, "status": 1}
+                UnicomObjeect().update_device_state(**re_data)
+            return True
+        return None
+
+    @staticmethod
+    def change_device_to_disable(iccid):
+        """
+        修改设备为停用,并查看是否修改成功
+        @param iccid:
+        @return:
+        """
+        if iccid:
+            re_data = {"iccid": iccid, "status": 2}
+            UnicomObjeect().update_device_state(**re_data)
+            # 查询是否停用成功
+            re_data.pop('status')
+            result = UnicomObjeect().query_device_status(**re_data)
+            res_dict = UnicomObjeect().get_text_dict(result)
+            if res_dict['data']['status'] != 3:
+                UnicomObjeect().update_device_state(**re_data)
+            return True
+        return None
+
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
+
+    today = datetime.datetime.today()
+    year = today.year
+    month = today.month
+    print(year)
+    print(month)
+    print(type(year))
+    if not '':
+        print('为空')
     price = '12.13'
     price = '12.13'
     print(float(price))
     print(float(price))
     discount = '6'
     discount = '6'
@@ -229,10 +330,10 @@ if __name__ == '__main__':
     print(unicom_api.createSign(**data))
     print(unicom_api.createSign(**data))
     # result = unicom_api.generate_token()
     # result = unicom_api.generate_token()
     # result = unicom_api.refresh_token('5d0c0f30-99bd-4f17-9614-3524495b05d4')
     # result = unicom_api.refresh_token('5d0c0f30-99bd-4f17-9614-3524495b05d4')
-    params = {'iccid': '89860620170009628001'}
-    response = unicom_api.verify_device(**params)
+    params = {'iccid': '89860621330065433774', 'status': 2}
+    # response = unicom_api.verify_device(**params)
     # response = unicom_api.query_device_status(**params)
     # response = unicom_api.query_device_status(**params)
-    # response = unicom_api.update_device_state(**params)
+    response = unicom_api.update_device_state(**params)
     # response = unicom_api.query_device_usage_history(**params)
     # response = unicom_api.query_device_usage_history(**params)
     # response = unicom_api.query_current_renew_list_usage_details(**params)
     # response = unicom_api.query_current_renew_list_usage_details(**params)
     # unicom_api.get_device_batch_detail()
     # unicom_api.get_device_batch_detail()
@@ -240,8 +341,8 @@ if __name__ == '__main__':
     # response = unicom_api.query_renewal_list(**params)
     # response = unicom_api.query_renewal_list(**params)
 
 
     if response.status_code == 200:
     if response.status_code == 200:
-        res_dict = json.loads(response.text)
-        print(res_dict)
+        res = json.loads(response.text)
+        print(res)
     response_json = {
     response_json = {
         "success": True,
         "success": True,
         "msg": "操作成功",
         "msg": "操作成功",

+ 159 - 2
Object/utils/LocalDateTimeUtil.py

@@ -7,9 +7,118 @@
 # @Email   : zhangdongming@asj6.wecom.work
 # @Email   : zhangdongming@asj6.wecom.work
 # @File    : LocalDateTimeUtil.py
 # @File    : LocalDateTimeUtil.py
 # @Software: PyCharm
 # @Software: PyCharm
+import calendar
 import datetime
 import datetime
 import time
 import time
 
 
+from dateutil.relativedelta import relativedelta
+
+
+def get_cur_month():
+    # 获取当前月
+    return datetime.datetime.now().strftime("%Y-%m")
+
+
+def get_last_month_num(number=1):
+    # 获取前几个月
+    month_date = datetime.datetime.now().date() - relativedelta(months=number)
+    return month_date.strftime("%Y-%m")
+
+
+def get_next_month(number=1):
+    # 获取后几个月
+    month_date = datetime.datetime.now().date() + relativedelta(months=number)
+    return month_date.strftime("%Y-%m")
+
+
+def get_cur_month_start():
+    # 获取当前月的第一天
+    month_str = datetime.datetime.now().strftime('%Y-%m')
+    return '{}-01'.format(month_str)
+
+
+def get_cur_month_end():
+    # 获取当前月的最后一天
+    """
+    param: month_str 月份,2021-04
+    """
+    # return: 格式 %Y-%m-%d
+
+    month_str = datetime.datetime.now().strftime('%Y-%m')
+    year, month = int(month_str.split('-')[0]), int(month_str.split('-')[1])
+    end = calendar.monthrange(year, month)[1]
+    return '{}-{}-{}'.format(year, month, end)
+
+
+def get_last_month_start(month_str=None):
+    # 获取上一个月的第一天
+    """
+    param: month_str 月份,2021-04
+    """
+    # return: 格式 %Y-%m-%d
+    if not month_str:
+        month_str = datetime.datetime.now().strftime('%Y-%m')
+    year, month = int(month_str.split('-')[0]), int(month_str.split('-')[1])
+    if month == 1:
+        year -= 1
+        month = 12
+    else:
+        month -= 1
+    return '{}-{}-01'.format(year, month)
+
+
+def get_next_month_start(month_str=None):
+    # 获取下一个月的第一天
+    """
+    param: month_str 月份,2021-04
+    """
+    # return: 格式 %Y-%m-%d
+    if not month_str:
+        month_str = datetime.datetime.now().strftime('%Y-%m')
+    year, month = int(month_str.split('-')[0]), int(month_str.split('-')[1])
+    if month == 12:
+        year += 1
+        month = 1
+    else:
+        month += 1
+    return '{}-{}-01'.format(year, month)
+
+
+def get_last_month_end(month_str=None):
+    # 获取上一个月的最后一天
+    """
+    param: month_str 月份,2021-04
+    """
+    # return: 格式 %Y-%m-%d
+    if not month_str:
+        month_str = datetime.datetime.now().strftime('%Y-%m')
+    year, month = int(month_str.split('-')[0]), int(month_str.split('-')[1])
+    if month == 1:
+        year -= 1
+        month = 12
+    else:
+        month -= 1
+    end = calendar.monthrange(year, month)[1]
+    return '{}-{}-{}'.format(year, month, end)
+
+
+def get_next_month_end(month_str=None):
+    # 获取下一个月的最后一天
+    """
+    param: month_str 月份,2021-04
+    """
+    # return: 格式 %Y-%m-%d
+    if not month_str:
+        month_str = datetime.datetime.now().strftime('%Y-%m')
+    year, month = int(month_str.split('-')[0]), int(month_str.split('-')[1])
+    if month == 12:
+        year += 1
+        month = 1
+    else:
+        month += 1
+    end = calendar.monthrange(year, month)[1]
+    return '{}-{}-{}'.format(year, month, end)
+
 
 
 def get_last_first_date_and_last_date(n):
 def get_last_first_date_and_last_date(n):
     """
     """
@@ -71,6 +180,21 @@ def get_before_days_timestamp(timestamp, days=1):
     return 0
     return 0
 
 
 
 
+def get_after_days_timestamp(timestamp, days=1):
+    """
+    获取之后日期时间戳-秒级
+    @param timestamp: 时间戳
+    @param days: 天数
+    @return: (timestamp + second * hour * days) 时间戳
+    """
+    if days:
+        second = 3600
+        hour = 24
+        if days > 0:
+            return timestamp + second * hour * days
+    return 0
+
+
 def date_to_week(str_date):
 def date_to_week(str_date):
     """
     """
     日期获取星期几
     日期获取星期几
@@ -110,10 +234,43 @@ def get_start_and_end_time(date, str_format):
     return 0
     return 0
 
 
 
 
-if __name__ == "__main__":
+if __name__ == '__main__':
+    zero_today, last_today = get_today_date(True)
+    month_end = get_cur_month_end()
+    start_time, month_end_time = get_start_and_end_time(month_end, '%Y-%m-%d')
+    print(zero_today)
+    print(month_end_time)
+
+
+    # # 获取当前月
+    # print('当前月', get_cur_month())
+    # # 获取上一个月
+    # print('上一个月', get_last_month_num())
+    # # 获取上两个月
+    # print('上两个月', get_last_month_num(number=2))
+    # # 获取下一个月
+    # print('下一个月', get_next_month())
+    # # 获取下两个月
+    # print('下两个月', get_next_month(number=2))
+    # # 获取当前月的第一天
+    # print('当前月的第一天', get_cur_month_start())
+    # # 获取当前月的最后一天
+    # print('当前月的最后一天', get_cur_month_end())
+    # # 获取上个月的第一天
+    # print('上个月的第一天', get_last_month_start())
+    # # 获取下个月的第一天
+    # print('下个月的第一天', get_next_month_start())
+    # # 获取上个月的最后一天
+    # print('上个月的最后一天', get_last_month_end())
+    # # 获取下个月的最后一天
+    # print('下个月的最后一天', get_next_month_end())
     dd = str(1650791368303)
     dd = str(1650791368303)
     print(dd[0:10])
     print(dd[0:10])
     print(dd[10:])
     print(dd[10:])
     dateArray = datetime.datetime.utcfromtimestamp(1650791368)
     dateArray = datetime.datetime.utcfromtimestamp(1650791368)
     print(dateArray.date())
     print(dateArray.date())
-    print(get_start_and_end_time('20220317', '%Y%m%d'))
+    next_start_time, next_end_time = get_start_and_end_time(get_next_month_start(), '%Y-%m-%d')
+    print(type(next_end_time))
+    print('下月开始时间{}'.format(next_start_time))
+    start_time, end_time = get_start_and_end_time(get_next_month_end(), '%Y-%m-%d')
+    print('下月结束时间{}'.format(end_time))

+ 80 - 0
Object/utils/PayUtil.py

@@ -0,0 +1,80 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : PayUtil.py
+@Time    : 2022/6/29 11:41
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+from urllib.parse import quote
+
+from Ansjer.config import SERVER_DOMAIN_SSL
+from Object.AliPayObject import AliPayObject
+from Object.WechatPayObject import WechatPayObject
+
+"""
+支付服务
+"""
+
+
+class PayService:
+
+    @staticmethod
+    def create_alipay_payment(passback_params, order_id, price, title, notify_url, content, response):
+        """
+        创建支付宝支付
+        @param passback_params: 携带参数支付宝回调原样返回
+        @param order_id: 订单编号
+        @param price: 价格
+        @param title: 标题
+        @param notify_url: 异步回调通知URL
+        @param content: 内容
+        @param response: 响应结果
+        @return: 网站支付链接
+        """
+        aliPayObj = AliPayObject()
+        alipay = aliPayObj.conf()
+        subject = title + content
+        order_string = alipay.api_alipay_trade_wap_pay(
+            out_trade_no=order_id,
+            total_amount=price,
+            subject=subject,
+            return_url="{}web/paid2/success.html".format(SERVER_DOMAIN_SSL),
+            notify_url="{}{}".format(SERVER_DOMAIN_SSL, notify_url),
+            quit_url="{}web/paid2/fail.html".format(SERVER_DOMAIN_SSL),
+            passback_params=quote(passback_params)
+        )
+        if not order_string:
+            return response.json(10, '生成订单错误.')
+        return aliPayObj.alipay_prefix + order_string
+
+    @staticmethod
+    def create_wechat_payment(attach, order_id, price, ip, notify_url, content, response):
+        """
+        创建微信支付
+        @param attach: 参数微信回调通知原样返回
+        @param order_id: 订单编号
+        @param price: 价格
+        @param ip: 用户支付ip地址
+        @param notify_url: 异步通知回调URL
+        @param content: 内容
+        @param response: 响应结果
+        @return: 网站支付链接
+        """
+        notify_url = "{}{}".format(SERVER_DOMAIN_SSL, notify_url)
+        pay = WechatPayObject()
+        # 统一调用接口
+        pay.get_parameter(order_id, content, float(price) * 100, ip, notify_url, quote(attach))
+        sign_params = pay.re_finall(orderid=order_id)
+        if not sign_params:
+            return response.json(10, '生成订单错误.')
+        return sign_params
+
+    @staticmethod
+    def get_two_float(f_str, n):
+        # f_str = '{}'.format(f_str) 也可以转换为字符串
+        f_str = str(f_str)
+        a, b, c = f_str.partition('.')
+        # 如论传入的函数有几位小数,在字符串后面都添加n为小数0
+        c = (c + "0" * n)[:n]
+        return ".".join([a, c])

+ 19 - 1
Service/CommonService.py

@@ -18,6 +18,8 @@ from pyipip import IPIPDatabase
 from Ansjer.config import BASE_DIR, SERVER_DOMAIN_SSL, CONFIG_INFO, CONFIG_TEST, CONFIG_CN
 from Ansjer.config import BASE_DIR, SERVER_DOMAIN_SSL, CONFIG_INFO, CONFIG_TEST, CONFIG_CN
 from Controller.CheckUserData import RandomStr
 from Controller.CheckUserData import RandomStr
 from Model.models import iotdeviceInfoModel, Device_Info, CountryModel, RegionModel, UIDModel
 from Model.models import iotdeviceInfoModel, Device_Info, CountryModel, RegionModel, UIDModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
 
 
 
 
 class CommonService:
 class CommonService:
@@ -483,7 +485,7 @@ class CommonService:
         @param msg: 消息内容
         @param msg: 消息内容
         @return: boolean
         @return: boolean
         """
         """
-        if not all([thing_name, topic_name, msg]):
+        if not all([thing_name, topic_name]):
             return False
             return False
 
 
         try:
         try:
@@ -635,3 +637,19 @@ GCqvlyw5dfxNA+EtxNE2wCW/LW7ENJlACgcfgPlBZtpLheWoZB/maw4=
                 region_qs = RegionModel.objects.filter(continent_code='NA').values("id")
                 region_qs = RegionModel.objects.filter(continent_code='NA').values("id")
                 region_id = region_qs[0]['id']
                 region_id = region_qs[0]['id']
         return region_id
         return region_id
+
+    @staticmethod
+    def verify_token_get_user_id(request_dict, request):
+        """
+        认证token,获取user id
+        @param request_dict: 请求参数
+        @param request: 请求体
+        @return: token_obj.code, token_obj.userID, response
+        """
+        try:
+            token_obj = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
+            lang = request_dict.get('lang', None)
+            response = ResponseObject(lang if lang else token_obj.lang)
+            return token_obj.code, token_obj.userID, response
+        except Exception as e:
+            print(e)

+ 3 - 3
Service/EquipmentInfoService.py

@@ -269,9 +269,9 @@ class EquipmentInfoService:
         comb_ai_event_type = []
         comb_ai_event_type = []
         for i in range(1, len(type) + 1):  # 计算所有组合,如[1, 2, 3, 4], 4取1,4取2,4取3,4取4
         for i in range(1, len(type) + 1):  # 计算所有组合,如[1, 2, 3, 4], 4取1,4取2,4取3,4取4
             for s in itertools.combinations(type, i):
             for s in itertools.combinations(type, i):
-                    s_list = list(s)
-                    s_list = [str(v) for v in s_list]
-                    comb_ai_event_type.append(s_list)
+                s_list = list(s)
+                s_list = [str(v) for v in s_list]
+                comb_ai_event_type.append(s_list)
         regroup_list = []
         regroup_list = []
         for val in comb_ai_event_type:  # 组合ai类型组合,如[[2,3],[1,3]] -> [23, 13]
         for val in comb_ai_event_type:  # 组合ai类型组合,如[[2,3],[1,3]] -> [23, 13]
             val = ''.join(val)
             val = ''.join(val)