Эх сурвалжийг харах

Merge branch 'dev' into lang

lang 3 жил өмнө
parent
commit
e0626f4889

+ 91 - 1
AdminController/LogManagementController.py

@@ -9,12 +9,14 @@ import uuid
 import boto3
 import threading
 import logging
+
+import requests
 from boto3.session import Session
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 from django.views.generic.base import View
 
 from Controller.CheckUserData import date_handler
-from Model.models import Device_Info, Role, MenuModel, RequestRecordModel
+from Model.models import Device_Info, Role, MenuModel, RequestRecordModel, iotdeviceInfoModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.UidTokenObject import UidTokenObject
@@ -49,6 +51,12 @@ class LogManagementView(View):
             userID = tko.userID
             if operation == 'getRequestList':
                 return self.getRequestList(request_dict, response)
+            elif operation == 'getDeviceIotInfoList':
+                return self.getDeviceIotInfoList(request_dict, response)
+            elif operation == 'requestPublishMqtt':
+                return self.requestPublishMqtt(request_dict, response)
+            else:
+                return response.json(404)
 
     def getRequestList(self, request_dict, response):
         pageNo = request_dict.get('pageNo', None)
@@ -96,3 +104,85 @@ class LogManagementView(View):
         except Exception as e:
             print(e)
             return response.json(500, repr(e))
+
+    def getDeviceIotInfoList(self, request_dict, response):
+        serial_number = request_dict.get('serial_number', None)
+        uid = request_dict.get('uid', None)
+        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:
+            if serial_number or uid:
+                if serial_number:
+                    iot_device_info_qs = iotdeviceInfoModel.objects.filter(serial_number__contains=serial_number)
+                if uid:
+                    iot_device_info_qs = iotdeviceInfoModel.objects.filter(uid__contains=uid)
+                if not iot_device_info_qs.exists():
+                    return response.json(0)
+                total = len(iot_device_info_qs)
+                iot_device_info_qs = iot_device_info_qs.values('serial_number', 'uid', 'thing_name', 'thing_groups',
+                                                               'add_time', 'update_time')[(page - 1) * line:page * line]
+            else:
+                total = iotdeviceInfoModel.objects.filter().count()
+                iot_device_info_qs = iotdeviceInfoModel.objects.filter().values('serial_number', 'uid', 'thing_name',
+                                                                                'thing_groups', 'add_time', 'update_time')[(page - 1) * line:page * line]
+
+            iot_device_info_list = CommonService.qs_to_list(iot_device_info_qs)
+            # 获取序列号的uid
+            for iot_device_info in iot_device_info_list:
+                if not iot_device_info['uid']:
+                    device_info_qs = Device_Info.objects.filter(serial_number__contains=iot_device_info['serial_number']).values('UID')
+                    if device_info_qs.exists():
+                        iot_device_info['uid'] = device_info_qs[0]['UID']
+            return response.json(0, {'list': iot_device_info_list, 'total': total})
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    def requestPublishMqtt(self, request_dict, response):
+        # 通用发布主题通知
+        uid = request_dict.get('uid', None)
+        msg = request_dict.get('msg', None)
+        thing_name = request_dict.get('thing_name', None)
+        topic_name = request_dict.get('topic_name', None)
+        if not all([uid, msg, thing_name, topic_name]):
+            return response.json(444)
+
+        try:
+            # 设备没被添加不发送
+            device_info_qs = Device_Info.objects.filter(UID=uid).values('UID', 'serial_number')
+            if not device_info_qs.exists():
+                return response.json(10043)
+            # 获取数据组织将要请求的url
+            iot = iotdeviceInfoModel.objects.filter(thing_name=thing_name).values('endpoint', 'token_iot_number')
+            if not iot.exists():
+                return response.json(10043)
+            endpoint = iot[0]['endpoint']
+            Token = iot[0]['token_iot_number']
+
+            # api doc: https://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/http.html
+            # url: https://IoT_data_endpoint/topics/url_encoded_topic_name?qos=1
+            # post请求url发布MQTT消息
+            url = 'https://{}/topics/{}'.format(endpoint, topic_name)
+            authorizer_name = 'Ansjer_Iot_Auth'
+            signature = CommonService.rsa_sign(Token)  # Token签名
+            headers = {'x-amz-customauthorizer-name': authorizer_name, 'Token': Token,
+                       'x-amz-customauthorizer-signature': signature}
+            msg = eval(msg)
+            r = requests.post(url=url, headers=headers, json=msg, timeout=2)
+            if r.status_code == 200:
+                res = r.json()
+                if res['message'] == 'OK':
+                    return response.json(0)
+                return response.json(10044)
+            else:
+                # print('发布失败')
+                return response.json(10044)
+        except Exception as e:
+            # print(e)
+            return response.json(500, repr(e))

+ 4 - 1
Ansjer/cn_config/config_formal.py

@@ -125,7 +125,10 @@ TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'
 
 # aws api key
 AWS_ARN_S3 = 'arn:aws-cn:s3'
-AVATAR_BUCKET = 'avatar-cn'
 REGION_NAME = 'cn-northwest-1'
 ACCESS_KEY_ID = 'AKIA2MMWBR4DSFG67DTG'
 SECRET_ACCESS_KEY = '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'
+
+# 存储桶名
+AVATAR_BUCKET = 'avatar-cn'         # 头像存储桶
+LOG_BUCKET = 'ansjer-statres'       # 日志存储桶

+ 4 - 1
Ansjer/cn_config/config_test.py

@@ -137,7 +137,10 @@ TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'
 
 # aws api key
 AWS_ARN_S3 = 'arn:aws-cn:s3'
-AVATAR_BUCKET = 'avatar-cn'
 REGION_NAME = 'cn-northwest-1'
 ACCESS_KEY_ID = 'AKIA2MMWBR4DSFG67DTG'
 SECRET_ACCESS_KEY = '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'
+
+# 存储桶名
+AVATAR_BUCKET = 'avatar-cn'         # 头像存储桶
+LOG_BUCKET = 'ansjer-statres'       # 日志存储桶

+ 4 - 1
Ansjer/local_config/config_local.py

@@ -58,7 +58,10 @@ TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'
 
 # aws api key
 AWS_ARN_S3 = 'arn:aws-cn:s3'
-AVATAR_BUCKET = 'avatar-cn'
 REGION_NAME = 'cn-northwest-1'
 ACCESS_KEY_ID = 'AKIA2MMWBR4DSFG67DTG'
 SECRET_ACCESS_KEY = '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'
+
+# 存储桶名
+AVATAR_BUCKET = 'avatar-cn'         # 头像存储桶
+LOG_BUCKET = 'ansjer-statres'       # 日志存储桶

+ 4 - 1
Ansjer/us_config/config_formal.py

@@ -125,7 +125,10 @@ TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'
 
 # aws api key
 AWS_ARN_S3 = 'arn:aws:s3'
-AVATAR_BUCKET = 'avatar-us'
 REGION_NAME = 'us-east-1'
 ACCESS_KEY_ID = 'AKIA2E67UIMD45Y3HL53'
 SECRET_ACCESS_KEY = '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'
+
+# 存储桶名
+AVATAR_BUCKET = 'avatar-us'         # 头像存储桶
+LOG_BUCKET = 'ansjer-statres'       # 日志存储桶

+ 4 - 1
Ansjer/us_config/config_test.py

@@ -136,7 +136,10 @@ TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'
 
 # aws api key
 AWS_ARN_S3 = 'arn:aws:s3'
-AVATAR_BUCKET = 'avatar-us'
 REGION_NAME = 'us-east-1'
 ACCESS_KEY_ID = 'AKIA2E67UIMD45Y3HL53'
 SECRET_ACCESS_KEY = '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'
+
+# 存储桶名
+AVATAR_BUCKET = 'avatar-us'         # 头像存储桶
+LOG_BUCKET = 'ansjer-statres'       # 日志存储桶

+ 3 - 2
Controller/AppLogController.py

@@ -7,7 +7,8 @@ import botocore
 import oss2
 from django.views.generic.base import View
 
-from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, REGION_NAME, ACCESS_KEY_ID, SECRET_ACCESS_KEY
+from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, REGION_NAME, ACCESS_KEY_ID, SECRET_ACCESS_KEY, \
+    LOG_BUCKET
 from Model.models import AppLogModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
@@ -66,7 +67,7 @@ class AppLogView(View):
         response_url = aws_s3_client.generate_presigned_url(
             ClientMethod='put_object',
             Params={
-                'Bucket': 'ansjer-statres',
+                'Bucket': LOG_BUCKET,
                 'Key': obj
             },
             ExpiresIn=3600

+ 4 - 8
Controller/EquipmentManagerV3.py

@@ -751,6 +751,7 @@ class EquipmentManagerV3(View):
                     item['View_Password'] = self.encrypt_pwd(item['View_Password'])
                     data.append(item)
                     return response.json(0, data)
+                return response.json(0, data)
         items = []
         # print('缓存分页')
         for index, item in enumerate(result):
@@ -998,14 +999,9 @@ class EquipmentManagerV3(View):
         if not all([token, time_stamp]):
             return response.json(444)
 
-        token = int(CommonService.decode_data(token))
-        time_stamp = int(time_stamp)
-
-        now_time = int(time.time())
-        distance = now_time - time_stamp
-
-        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-            return response.json(404)
+        # 时间戳token校验
+        if not CommonService.check_time_stamp_token(token, time_stamp):
+            return response.json(13)
 
         dvq = Device_Info.objects.filter(UID=UID)
         dvq = dvq.filter(~Q(vodPrimaryUserID='')).values('vodPrimaryUserID')

+ 9 - 109
Controller/IotCoreController.py

@@ -74,13 +74,9 @@ class IotCoreView(View):
         if not all([token, time_stamp, device_version, language]):
             return response.json(444, {'param': 'token, uid_code, time_stamp, device_version, language'})
 
-        # token时间戳校验
-        token = int(CommonService.decode_data(token))
-        time_stamp = int(time_stamp)
-        now_time = int(time.time())
-        distance = now_time - time_stamp
-        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-            return response.json(404)
+        # 时间戳token校验
+        if not CommonService.check_time_stamp_token(token, time_stamp):
+            return response.json(13)
 
         if not uid:
             # 使用序列号
@@ -120,7 +116,7 @@ class IotCoreView(View):
 
             iotClient = IOTClient(region_id)
             res = iotClient.create_keys_and_certificate(ThingNameSuffix, thingGroup, response)
-            token_iot_number = hashlib.md5((str(uuid.uuid1()) + str(now_time)).encode('utf-8')).hexdigest()
+            token_iot_number = hashlib.md5((str(uuid.uuid1()) + str(int(time.time()))).encode('utf-8')).hexdigest()
 
             iotdeviceInfoModel.objects.create(uid=uid,
                                               serial_number=serial,
@@ -164,13 +160,9 @@ class IotCoreView(View):
         if not all([token, language, time_stamp, device_version]):
             return response.json(444, {'param: token, language, time_stamp, device_version'})
 
-        # 封装token认证
-        token = int(CommonService.decode_data(token))
-        time_stamp = int(time_stamp)
-        now_time = int(time.time())
-        distance = now_time - time_stamp
-        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-            return response.json(404)
+        # 时间戳token校验
+        if not CommonService.check_time_stamp_token(token, time_stamp):
+            return response.json(13)
 
         ip = CommonService.get_ip_address(request)
         region_id = Device_Region().get_device_region(ip)
@@ -242,7 +234,7 @@ class IotCoreView(View):
             return response.json(444)
 
         try:
-            # 获取检查uid的序列号,如果没有序列号,不使用MQTT下发消息
+            # 获取设备的物品名后缀
             device_info_qs = Device_Info.objects.filter(UID=UID).values('UID', 'serial_number')
             if not device_info_qs.exists():
                 return response.json(10043)
@@ -268,60 +260,7 @@ class IotCoreView(View):
             # post请求url来发布MQTT消息
             url = 'https://{}/topics/{}'.format(endpoint, topic_name)
             authorizer_name = 'Ansjer_Iot_Auth'
-            signature = self.rsa_sign(Token)  # Token签名
-            headers = {'x-amz-customauthorizer-name': authorizer_name, 'Token': Token,
-                       'x-amz-customauthorizer-signature': signature}
-            params = {'command': MSG}
-            r = requests.post(url=url, headers=headers, json=params, timeout=2)
-            if r.status_code == 200:
-                res = r.json()
-                if res['message'] == 'OK':
-                    return response.json(0)
-                return response.json(10044)
-            else:
-                # print('发布失败')
-                return response.json(10044)
-        except Exception as e:
-            # print(e)
-            return response.json(500, repr(e))
-
-    def request_publish_mqtt(self, request_dict, response, request):
-        # 通用发布主题通知
-        UID = request_dict.get('UID', None)
-        MSG = request_dict.get('MSG', None)
-        return_topic_name = request_dict.get('return_topic_name', None)
-        if not all([UID, MSG]):
-            return response.json(444)
-
-        try:
-            # 获取检查uid的序列号,如果没有序列号,不使用MQTT下发消息
-            device_info_qs = Device_Info.objects.filter(UID=UID).values('UID', 'serial_number')
-            if not device_info_qs.exists():
-                return response.json(10043)
-            uid = device_info_qs[0]['UID']
-            serial_number = device_info_qs[0]['serial_number']
-            # 如果device_info表的serial_number不为空,物品名为'Ansjer_Device_序列号'
-            thing_name_suffix = serial_number if serial_number != '' else uid
-            # 获取数据组织将要请求的url
-            iot = iotdeviceInfoModel.objects.filter(thing_name__contains=thing_name_suffix).values('thing_name',
-                                                                                                   'endpoint',
-                                                                                                   'token_iot_number')
-            if not iot.exists():
-                return response.json(10043)
-            thing_name = iot[0]['thing_name'][14:]  # IoT core上的物品名: Ansjer_Device_ + 序列号+企业编码/uid
-            endpoint = iot[0]['endpoint']
-            Token = iot[0]['token_iot_number']
-            # Token = '297a601b3925e04daab5a60280650e09'
-            topic_name = thing_name + return_topic_name     # MQTT主题
-            if return_topic_name == 'get_s3_key_return':
-                MSG = self.get_s3_key_return_msg(endpoint)
-
-            # api doc: https://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/http.html
-            # url: https://IoT_data_endpoint/topics/url_encoded_topic_name?qos=1
-            # post请求url来发布MQTT消息
-            url = 'https://{}/topics/{}'.format(endpoint, topic_name)
-            authorizer_name = 'Ansjer_Iot_Auth'
-            signature = self.rsa_sign(Token)  # Token签名
+            signature = CommonService.rsa_sign(Token)  # Token签名
             headers = {'x-amz-customauthorizer-name': authorizer_name, 'Token': Token,
                        'x-amz-customauthorizer-signature': signature}
             params = {'command': MSG}
@@ -391,42 +330,3 @@ class IotCoreView(View):
         MSG['arn'] = arn
         MSG['region_name'] = region_name
         return MSG
-
-
-    def rsa_sign(self, Token):
-        # 私钥签名Token
-        private_key_file = '''-----BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEA5iJzEDPqtGmFMggekVro6C0lrjuC2BjunGkrFNJWpDYzxCzE
-X5jf4/Fq7hcIaQd5sqHugDxPVollSLPe9zNilbrd0sZfU+Ed8gRVuKW9KwfE9XFr
-L0pt6bKRQ0IIRfiZ9TuR0tsQysvcO1GZSXcYfPue3tGM1zOnWFThWDqZ06+sOxzt
-RMRl4yNfbpCG4MfxG3itNXOfrjZv2OMLSXrxmzubSvRpUYSvQPs4fm9302SAnySY
-0MKzx6H6528ZQm/IDDSZy6EmNBIyTRDfxC56vnYcXvqedAQh7jJnjdvt6Q4MhASH
-eIYi1FBSdu2NT6wgpnrqXzx5pq9kR/lnsLID0wIDAQABAoIBAQCiF4GT1/1oNSpr
-ouxk1PNXFPWFUsVGD8mAwVJmx//eiY7MjfuCmdqYYmI+cFqsH2fIOeYSzGfVO9Dq
-9EYHN1oovAWhf7eFDPpajFMUSyiCNmazub8VAAeKowtNpCTPo9pMsDh1m3aoYA4u
-ebrN0+Sbo16y8kWRDgDAZoiR7DSMs8lczk16hwfv5mw8XpNDbaL3Coi4Koe2S1Yh
-2SX3vWFlpd7qF1ZYXuZIp+b8JPrV7n9eUKoFgzj0gqgwQK80CoexIjiOrNMPvkQa
-q+8kCvFjAzKxOK7e8gjM8lMRiGodb61kmYZkkJzFwWO4EaGbl34lfVECd1Ixp3tF
-be0OWAGBAoGBAPSteXDzzToD8ovM7LL11x0jWwI6HOiHu89kZtW566rIezjWBuA2
-TxrcYKM3h9jQRXS3CsMdoIv6XGk5lqM8ADtjn23FBWe/THYLh8bm8JOgh5RRWQDg
-SvkLfi9Ih2mM4NJfmuuDOh3Nze2efLM7+kOZWUQwF2Zx9mL5jvRBk351AoGBAPDI
-sYmT2Li+i5+0vykA2m5uPF8ZOW8BGtAfCZv0suW7BNzSgin78g9WapRd/4p0NNiL
-/nVMqPPCpd1akCUpV+GDWQt0hV+HZjxANE0KWhciQRyo2qvo51j8SWILJSgh0tXC
-aTF8qt6oGw3VN3m57vKhbrlDaz0J/NDJFci6msAnAoGBAOuG6bXPGijUj+//DYKf
-n7jOxdZ49kboEePrtAncdHzri6IEdI3z+WXT6bpzw/LzWUimwldb96WHFNm9s8Hi
-Ch8hIODbnP5naUTgiIzw1XhmONyPCewL/F+LrqX5XVA/alNX8JrwsUrrR2WLAGLQ
-Q3I69XDsEjptTU2tCO0bCs3ZAoGBAJ2lCHfm0JHET230zONvp5N9oREyVqQSuRdh
-+syc3TQDyh85w/bw+X6JOaaCFHj1tFPC9Iqf8k4GNspCLPXnp54CfR4+38O3xnvU
-HWoDSRC0YKT++IxtJGriYrlKSr2Hx54kdvLriIPW1D+uRW/xCDza7L9nIKMKEvgv
-b4/IfOEpAoGAeKM9Te7T1VzlAkS0CJOwanzwYV/zrex84WuXxlsGgPQ871lTs5AP
-H1QLfLfFXH+UVrCEC2yv4eml/cqFkpB3gE5i4MQ8GPVIOSs5tsIyl8YUA03vdNdB
-GCqvlyw5dfxNA+EtxNE2wCW/LW7ENJlACgcfgPlBZtpLheWoZB/maw4=
------END RSA PRIVATE KEY-----'''
-        # 使用密钥文件方式
-        # private_key_file_path = os.path.join(BASE_DIR, 'static/iotCore/private.pem')#.replace('\\', '/')
-        # private_key_file = open(private_key_file_path, 'r')
-        private_key = ct.load_privatekey(ct.FILETYPE_PEM, private_key_file)
-        signature = ct.sign(private_key, Token.encode('utf8'), 'sha256')
-        signature = encodebytes(signature).decode('utf8').replace('\n', '')
-        # print('signature:', signature)
-        return signature

+ 20 - 61
Controller/SerialNumberController.py

@@ -132,25 +132,21 @@ class SerialNumberView(View):
         company_id = request_dict.get('company_id', None)
         token = request_dict.get('token', None)
         time_stamp = request_dict.get('time_stamp', None)
-        DeviceSubType = request_dict.get('DeviceSubType', None)
-        p2ptype = request_dict.get('p2ptype', 1)
+        p2p_type = request_dict.get('p2ptype', 1)
+
         if not all([serial_number, company_id, token, time_stamp]):
             return response.json(444)
 
-        token = int(CommonService.decode_data(token))
-        time_stamp = int(time_stamp)
+        # 时间戳token校验
+        if not CommonService.check_time_stamp_token(token, time_stamp):
+            return response.json(13)
 
         now_time = int(time.time())
-        distance = now_time - time_stamp
-
-        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-            return response.json(404)
-
         serial = serial_number[0:6]
         full_serial = serial_number[0:9]
 
         if serial_number[9:10]:
-            p2ptype = serial_number[9:10]
+            p2p_type = serial_number[9:10]
         try:
             if not country_id:
                 ip = CommonService.get_ip_address(request)
@@ -172,44 +168,18 @@ class SerialNumberView(View):
                     while count < 3:
                         # 查询是否存在未绑定序列号的uid
                         uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id,
-                                                         vpg__region_id=country_id, status=0, p2p_type=p2ptype). \
+                                                         vpg__region_id=country_id, status=0, p2p_type=p2p_type). \
                                                          order_by('id')
                         if not uid_qs.exists():
                             return response.json(173)
 
                         uid = uid_qs[0]
+                        # 判断uid是否已绑定过序列号
+                        uid_company_serial_qs = UIDCompanySerialModel.objects.filter(uid_id=uid.id)
+                        if uid_company_serial_qs.exists():
+                            return response.json(174)
 
-                        if DeviceSubType:
-                            # 获取最新的mac,判断分配到哪里,且进行绑定
-                            mac = MacModel.objects.filter().values('id', 'value', 'is_active')[0]
-                            current_mac = mac['value']
-                            username = 'cspublic@ansjer.com'
-                            if current_mac[-8:] == '1F:42:40':  # 一组一共1048576个,此mac是第100w个时
-                                sys_msg_text = "当前国外uid管理系统mac地址已分配到" + current_mac + ",此mac地址是当前组的第100w个,还剩下48576个可分配,mac地址即将用完。"
-                                S3Email().faEmail(sys_msg_text, username)
-                            elif current_mac[-8:] == '1F:90:60':  # 此mac是第102w个时
-                                sys_msg_text = "当前国外uid管理系统mac地址已分配到" + current_mac + ",此mac地址是当前组的第102w个,还剩下28576个可分配,mac地址即将用完。"
-                                S3Email().faEmail(sys_msg_text, username)
-                            elif not mac['is_active']:
-                                return response.json(175)
-                            elif current_mac[-8:] == '1F:FF:FF':
-                                MacModel.objects.filter().update(is_active=False)  # 更改mac可使用的状态,当再此调用接口时使用上面条件进行阻止
-                                sys_msg_text = "当前国外uid管理系统mac地址已分配到" + current_mac + ",mac地址已分配使用完,请更换分组。"
-                                S3Email().faEmail(sys_msg_text, username)
-                                return response.json(175)
-                            UIDModel.objects.filter(id=uid.id).update(mac=current_mac)  # 更新绑定uid的mac值
-                            # 绑定mac地址成功后更新mac表
-                            temp_mac = CommonService.updateMac(current_mac)  # mac地址值+1;后3个字节为FF时返回None
-                            if temp_mac:
-                                current_mac = temp_mac  # 更新赋值写入uid表
-                            else:
-                                temp_mac = current_mac  # 赋值为FF写入mac表
-                            MacModel.objects.filter().update(value=temp_mac, add_time=now_time,
-                                                             update_time=now_time)  # 更新mac表的mac地址值
-
-                        result = UIDModel.objects.filter(id=uid.id, status=0).\
-                            update(status=2, update_time=now_time)
-
+                        result = UIDModel.objects.filter(id=uid.id, status=0).update(status=2, update_time=now_time)
                         if int(result) <= 0:    # 更新失败
                             count += 1
                             continue
@@ -232,7 +202,6 @@ class SerialNumberView(View):
                         res = {
                             'full_uid_code': CommonService.encode_data(full_uid_code),
                             'uid': CommonService.encode_data(uid.uid),
-                            'mac': CommonService.encode_data(uid.mac),
                             'extra': uid.uid_extra,
                             'platform': uid.platform,
                             'initString': uid.init_string,
@@ -267,7 +236,6 @@ class SerialNumberView(View):
                 res = {
                     'full_uid_code': CommonService.encode_data(full_uid_code),
                     'uid': CommonService.encode_data(uid['uid__uid']),
-                    'mac': CommonService.encode_data(uid['uid__mac']),
                     'extra': uid['uid__uid_extra'],
                     'platform': uid['uid__platform'],
                     'initString': uid['uid__init_string'],
@@ -284,16 +252,10 @@ class SerialNumberView(View):
         token = request_dict.get('token', None)
         time_stamp = request_dict.get('time_stamp', None)
 
-        if token and time_stamp and serial_number :
-
-            token = int(CommonService.decode_data(token))
-            time_stamp = int(time_stamp)
-
-            now_time = int(time.time())
-            distance = now_time - time_stamp
-
-            if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-                return response.json(404)
+        if token and time_stamp and serial_number:
+            # 时间戳token校验
+            if not CommonService.check_time_stamp_token(token, time_stamp):
+                return response.json(13)
 
             mark = serial_number[6:9]
             serial = serial_number[0:6]
@@ -321,15 +283,12 @@ class SerialNumberView(View):
 
         if not all([token, time_stamp, serial_number]):
             return response.json(444)
-        token = int(CommonService.decode_data(token))
-        time_stamp = int(time_stamp)
 
-        now_time = int(time.time())
-        distance = now_time - time_stamp
-
-        if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
-            return response.json(404)
+        # 时间戳token校验
+        if not CommonService.check_time_stamp_token(token, time_stamp):
+            return response.json(13)
 
+        now_time = int(time.time())
         serial = serial_number[0:6]
         uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial)
         if not uid_serial_qs.exists():

+ 4 - 2
Controller/SysManage.py

@@ -12,6 +12,7 @@
 @Contact: chanjunkai@163.com
 """
 import os
+import time
 
 from django.http import HttpResponse
 from django.views.decorators.csrf import csrf_exempt
@@ -103,9 +104,10 @@ def initMsgFunc(request):
     response.lang = tko.lang
     if tko.code == 0:
         userID = tko.userID
+        seven_days_ago = int(time.time()) - 3600 * 24 * 7   # 过滤七天前数据
         sm_count = SysMsgModel.objects.filter(userID_id=userID, status=0).count()
-        eq_count = Equipment_Info.objects.filter(userID_id=userID).filter(status=False).count()
-        rq_count = Equipment_Info.objects.filter(userID_id=userID).filter(eventType=57, status=False,).count()
+        eq_count = Equipment_Info.objects.filter(userID_id=userID, eventTime__gt=seven_days_ago, status=False).count()
+        rq_count = Equipment_Info.objects.filter(userID_id=userID, eventTime__gt=seven_days_ago, eventType=57, status=False,).count()
         uid_reset_count = Device_Info.objects.filter(userID_id=userID, isExist=2).count()
         res = {
             'sm_count': sm_count,  # 系统消息未读数量

+ 18 - 43
Controller/VPGController.py

@@ -196,9 +196,6 @@ class VPGView(View):
 @csrf_exempt
 def do_upload_uid(request):
     # 上传UID,需要request.FILES,单独提取出来
-    # perm = ModelService.check_perm_uid_manage(userID, 0)
-    # if not perm:
-    #     return response.json(309)
 
     request.encoding = 'utf-8'
     response = uidManageResponseObject()
@@ -210,66 +207,45 @@ def do_upload_uid(request):
         return response.json(444)
     file = request.FILES.get('file', None)
     vpg_id = request_dict.get('vpg_id', None)
+    p2p_type = request_dict.get('p2p_type', None)
     platform = request_dict.get('platform', '')
     init_string = request_dict.get('init_string', '')
     init_string_app = request_dict.get('init_string_app', '')
 
-    if not vpg_id:
+    if not all([vpg_id, p2p_type]):
         return response.json(444)
 
-    bulk = []
-    add_time = update_time = int(time.time())
-    MAC = MacModel.objects.filter().values('id', 'value', 'is_active')[0]   # 获取最新可用的mac
-    current_mac = MAC['value']
-    if (not MAC['is_active']) or (current_mac[-8:] == 'FF.FF.FF'):
-        return response.json(175)
-
-    area = 1 if vpg_id != '1' else 0
-    # path = '/'.join((BASE_DIR, 'static/uid')).replace('\\', '/') + '/'
-    # if not os.path.exists(path):
-    #     os.makedirs(path)
-    # full_path = path + str(file)
-    # with open(full_path, 'wb+') as uid_file:
     try:
+        bulk = []
+        p2p_type = int(p2p_type)
+        # 尚云必须输入平台和初始化字符
+        if p2p_type == 1 and (not platform or not platform or not init_string_app):
+            return response.json(444)
+        p2p = '尚云' if p2p_type == 1 else 'tutk'
+        area = 1 if vpg_id != '1' else 0    # vpg_id为'1':国内
+        add_time = update_time = int(time.time())
         for chunk in file.chunks():
-            # str_chunk = str(chunk)
-            # print('str(chunk):', str_chunk)
-            # str_chunk = re.findall("b\'(.*)\'", str_chunk)[0]
-            # str_chunk = str_chunk.split('\\r\\n')
-            # print('str(chunk):', str_chunk)
             uid_list = re.findall("b\'(.*)\'", str(chunk))[0].split('\\r\\n')
             for uid in uid_list:
                 UID = UIDModel(
-                    mac=current_mac,
+                    mac='',
                     uid_extra='',
                     status=0,
                     add_time=add_time,
                     update_time=update_time,
                     area=area,  # 关联vgp表已有区域信息,可以考虑去掉
                     vpg_id=vpg_id,
+                    p2p_type=p2p_type,
                     platform=platform,
                     init_string=init_string,
                     init_string_app=init_string_app
                 )
-                if len(uid) == 14:  # 宸云
-                    UID.p2p_type = 1
-                    UID.uid = uid
-                elif len(uid) == 20:    # tutk
-                    UID.p2p_type = 2
-                    UID.uid = uid
-                elif len(uid) == 23:    # 宸云完整uid
-                    a = uid.split('-')
-                    new_uid = a[0] + a[1] + a[2].split(',')[0]
-                    UID.p2p_type = 1
-                    UID.uid = new_uid
+                if '-' in uid:  # 尚云完整uid,eg.ACN-000005-FHCGR,VRWEDU -> ACN000005FHCGR
                     UID.full_uid_code = uid
+                    uid_split = uid.split('-')
+                    uid = uid_split[0] + uid_split[1] + uid_split[2].split(',')[0]
+                UID.uid = uid
                 bulk.append(UID)
-                temp_mac = CommonService.updateMac(current_mac)    # mac地址值+1;后3个字节为FF时返回None
-                if temp_mac:
-                    current_mac = temp_mac  # 更新赋值写入uid表
-                else:
-                    temp_mac = current_mac  # 赋值为FF写入mac表
-                    break
 
         ip = CommonService.get_ip_address(request)
         content = json.loads(json.dumps(request_dict))
@@ -280,7 +256,7 @@ def do_upload_uid(request):
             'time': add_time,
             'url': 'vpgUid/uid',
             'content': json.dumps(content),
-            'operation': '上传{}个uid到VPG ID {}'.format(len(uid_list), vpg_id),
+            'operation': '上传{}个{}uid到VPG ID {}'.format(len(uid_list), p2p, vpg_id),
         }
         
         with transaction.atomic():
@@ -288,8 +264,7 @@ def do_upload_uid(request):
             UIDModel.objects.bulk_create(bulk)  # 批量写入uid数据
             uid_count = UIDModel.objects.filter(vpg_id=vpg_id).count()  # 获取族群下uid的数量
             VPGModel.objects.filter(id=vpg_id).update(uid_count=uid_count)   # 更新vgp表的uid_count
-            MacModel.objects.filter().update(value=temp_mac)  # 更新mac表的mac地址值
         return response.json(0)
     except Exception as e:
         print(e)
-        return response.json(500, repr(e))
+        return response.json(500, repr(e))

+ 15 - 1
Model/models.py

@@ -1154,7 +1154,7 @@ class AppLogModel(models.Model):
     user = models.ForeignKey(Device_User, to_field='userID', on_delete=models.CASCADE, verbose_name='关联设备用户表')
     uid = models.CharField(max_length=20, default='', verbose_name='设备uid')
     average_delay = models.CharField(max_length=32, default='', verbose_name='最高平均延时')
-    status = models.SmallIntegerField(default=0, verbose_name='失败状态')
+    status = models.SmallIntegerField(default=0, verbose_name='失败状态')   # 0: 成功,1: 失败
     filename = models.CharField(max_length=120, default='', verbose_name='文件名')
     add_time = models.IntegerField(default=0, verbose_name='日期')
 
@@ -1164,6 +1164,20 @@ class AppLogModel(models.Model):
         verbose_name_plural = verbose_name
 
 
+class DeviceLogModel(models.Model):
+    id = models.AutoField(primary_key=True)
+    ip = models.CharField(default='', max_length=32, verbose_name='ip')
+    uid = models.CharField(max_length=32, default='', verbose_name='设备uid')
+    status = models.SmallIntegerField(default=0, verbose_name='上传状态')   # 0: 成功,1: 失败
+    filename = models.CharField(max_length=120, default='', verbose_name='文件名')
+    add_time = models.DateTimeField(blank=True, auto_now_add=True, verbose_name=u'添加时间')
+
+    class Meta:
+        db_table = 'device_log'
+        verbose_name = '设备日志表'
+        verbose_name_plural = verbose_name
+
+
 class EquipmentInfoExStatisticsModel(models.Model):
     id = models.AutoField(primary_key=True)
     push_type = models.SmallIntegerField(default=0, verbose_name='第三方推送服务器标志。0:APNS推送,1:谷歌推送,2:极光推送')

+ 2 - 0
Object/ResponseObject.py

@@ -13,6 +13,7 @@ class ResponseObject(object):
             5: 'Please try again one minute later!',
             10: res,
             12: 'You are not the primary user of the device!',
+            13: 'Timestamp token verification failed',
             14: 'Device is not belong to you',
             15: 'Device has been bound',
             16: 'WeChat has been bound, please log in and unbind using WeChat',
@@ -110,6 +111,7 @@ class ResponseObject(object):
             5: '请一分钟后再尝试',
             10: res,
             12: '非设备主用户',
+            13: '时间戳token校验失败',
             14: '设备不属于您',
             15: '设备已被绑定',
             16: '微信已被绑定,请使用微信登录并解绑',

+ 68 - 3
Service/CommonService.py

@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+# 高复用性函数封装到CommonService类
 import base64
 import datetime
 import time
@@ -10,9 +11,8 @@ from django.core import serializers
 from django.utils import timezone
 from pyipip import IPIPDatabase
 from Ansjer.config import BASE_DIR, UNICODE_ASCII_CHARACTER_SET
-
-
-# 复用性且公用较高封装代码在这
+import OpenSSL.crypto as ct
+from base64 import encodebytes
 from Controller.CheckUserData import RandomStr
 from Service.ModelService import ModelService
 
@@ -253,6 +253,8 @@ class CommonService:
 
     @staticmethod
     def decode_data(content, start=1, end=4):
+        if not content:
+            return ''
         try:
             for i in range(start, end):
                 if i == 1:
@@ -275,6 +277,8 @@ class CommonService:
 
     @staticmethod
     def encode_data(content, start=1, end=4):
+        if not content:
+            return ''
         for i in range(start, end):
             if i == 1:
                 content = RandomStr(3, False)+content+RandomStr(3, False)
@@ -385,6 +389,8 @@ class CommonService:
 
     @staticmethod
     def decode_data(content, start=1, end=4):
+        if not content:
+            return ''
         try:
             for i in range(start, end):
                 if i == 1:
@@ -408,6 +414,8 @@ class CommonService:
 
     @staticmethod
     def encode_data(content, start=1, end=4):
+        if not content:
+            return ''
         for i in range(start, end):
             if i == 1:
                 content = CommonService.RandomStr(3, False) + content + CommonService.RandomStr(3, False)
@@ -424,4 +432,61 @@ class CommonService:
     def encode_data_without_salt(content):
         return base64.b64encode(str(content).encode("utf-8")).decode('utf8')
 
+    @staticmethod
+    def check_time_stamp_token(token, time_stamp):
+        # 时间戳token校验
+        if not all([token, time_stamp]):
+            return False
+        try:
+            token = int(CommonService.decode_data(token))
+            time_stamp = int(time_stamp)
+            now_time = int(time.time())
+            distance = now_time - time_stamp
+            if token != time_stamp or distance > 60000 or distance < -60000:  # 为了全球化时间控制在一天内
+                return False
+            return True
+        except Exception as e:
+            print(e)
+            return False
+
+    @staticmethod
+    def rsa_sign(Token):
+        # 私钥签名Token
+        if not Token:
+            return ''
+        private_key_file = '''-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA5iJzEDPqtGmFMggekVro6C0lrjuC2BjunGkrFNJWpDYzxCzE
+X5jf4/Fq7hcIaQd5sqHugDxPVollSLPe9zNilbrd0sZfU+Ed8gRVuKW9KwfE9XFr
+L0pt6bKRQ0IIRfiZ9TuR0tsQysvcO1GZSXcYfPue3tGM1zOnWFThWDqZ06+sOxzt
+RMRl4yNfbpCG4MfxG3itNXOfrjZv2OMLSXrxmzubSvRpUYSvQPs4fm9302SAnySY
+0MKzx6H6528ZQm/IDDSZy6EmNBIyTRDfxC56vnYcXvqedAQh7jJnjdvt6Q4MhASH
+eIYi1FBSdu2NT6wgpnrqXzx5pq9kR/lnsLID0wIDAQABAoIBAQCiF4GT1/1oNSpr
+ouxk1PNXFPWFUsVGD8mAwVJmx//eiY7MjfuCmdqYYmI+cFqsH2fIOeYSzGfVO9Dq
+9EYHN1oovAWhf7eFDPpajFMUSyiCNmazub8VAAeKowtNpCTPo9pMsDh1m3aoYA4u
+ebrN0+Sbo16y8kWRDgDAZoiR7DSMs8lczk16hwfv5mw8XpNDbaL3Coi4Koe2S1Yh
+2SX3vWFlpd7qF1ZYXuZIp+b8JPrV7n9eUKoFgzj0gqgwQK80CoexIjiOrNMPvkQa
+q+8kCvFjAzKxOK7e8gjM8lMRiGodb61kmYZkkJzFwWO4EaGbl34lfVECd1Ixp3tF
+be0OWAGBAoGBAPSteXDzzToD8ovM7LL11x0jWwI6HOiHu89kZtW566rIezjWBuA2
+TxrcYKM3h9jQRXS3CsMdoIv6XGk5lqM8ADtjn23FBWe/THYLh8bm8JOgh5RRWQDg
+SvkLfi9Ih2mM4NJfmuuDOh3Nze2efLM7+kOZWUQwF2Zx9mL5jvRBk351AoGBAPDI
+sYmT2Li+i5+0vykA2m5uPF8ZOW8BGtAfCZv0suW7BNzSgin78g9WapRd/4p0NNiL
+/nVMqPPCpd1akCUpV+GDWQt0hV+HZjxANE0KWhciQRyo2qvo51j8SWILJSgh0tXC
+aTF8qt6oGw3VN3m57vKhbrlDaz0J/NDJFci6msAnAoGBAOuG6bXPGijUj+//DYKf
+n7jOxdZ49kboEePrtAncdHzri6IEdI3z+WXT6bpzw/LzWUimwldb96WHFNm9s8Hi
+Ch8hIODbnP5naUTgiIzw1XhmONyPCewL/F+LrqX5XVA/alNX8JrwsUrrR2WLAGLQ
+Q3I69XDsEjptTU2tCO0bCs3ZAoGBAJ2lCHfm0JHET230zONvp5N9oREyVqQSuRdh
++syc3TQDyh85w/bw+X6JOaaCFHj1tFPC9Iqf8k4GNspCLPXnp54CfR4+38O3xnvU
+HWoDSRC0YKT++IxtJGriYrlKSr2Hx54kdvLriIPW1D+uRW/xCDza7L9nIKMKEvgv
+b4/IfOEpAoGAeKM9Te7T1VzlAkS0CJOwanzwYV/zrex84WuXxlsGgPQ871lTs5AP
+H1QLfLfFXH+UVrCEC2yv4eml/cqFkpB3gE5i4MQ8GPVIOSs5tsIyl8YUA03vdNdB
+GCqvlyw5dfxNA+EtxNE2wCW/LW7ENJlACgcfgPlBZtpLheWoZB/maw4=
+-----END RSA PRIVATE KEY-----'''
+        # 使用密钥文件方式
+        # private_key_file_path = os.path.join(BASE_DIR, 'static/iotCore/private.pem')#.replace('\\', '/')
+        # private_key_file = open(private_key_file_path, 'r')
+        private_key = ct.load_privatekey(ct.FILETYPE_PEM, private_key_file)
+        signature = ct.sign(private_key, Token.encode('utf8'), 'sha256')
+        signature = encodebytes(signature).decode('utf8').replace('\n', '')
+        # print('signature:', signature)
+        return signature