Kaynağa Gözat

实现气象站数据对接主动获取方式调用数据库版本

yf_fyh 3 yıl önce
ebeveyn
işleme
4daab0dd58

+ 29 - 29
apps/Equipment/models.py

@@ -1,38 +1,38 @@
 from django.db import models
-from apps.UserApp.models import MyUser
+# from apps.UserApp.models import MyUser
 
 
 # Create your models here.
 
-class Device(models.Model):
-    TYPE_CHOICES = {
-        1: '气象站',
-    }
-    device_id = models.CharField(u'设备id', max_length=30, primary_key=True)
-    owner = models.ForeignKey(
-        MyUser, blank=True, null=True, on_delete=models.DO_NOTHING, verbose_name=u'设备所属用户')
-    device_type = models.SmallIntegerField(u'设备类型', default=1, choices=TYPE_CHOICES.items())
-    lng = models.CharField(u'经度', max_length=10, default="")
-    lat = models.CharField(u'纬度', max_length=10, default="")
-    iccid = models.CharField(u'设备卡号', max_length=20, default="")
-    volt = models.CharField(u'电压', max_length=10, default="")
-    rssi = models.CharField(u'信号强度', max_length=10, default="")
-    version = models.CharField(u'设备版本号', max_length=50, default="")
-    is_online = models.SmallIntegerField(u'是否在线', default=1)
-    upl_time = models.IntegerField(default=0)
+# class Device(models.Model):
+#     TYPE_CHOICES = {
+#         1: '气象站',
+#     }
+#     device_id = models.CharField(u'设备id', max_length=30, primary_key=True)
+#     owner = models.ForeignKey(
+#         MyUser, blank=True, null=True, on_delete=models.DO_NOTHING, verbose_name=u'设备所属用户')
+#     device_type = models.SmallIntegerField(u'设备类型', default=1, choices=TYPE_CHOICES.items())
+#     lng = models.CharField(u'经度', max_length=10, default="")
+#     lat = models.CharField(u'纬度', max_length=10, default="")
+#     iccid = models.CharField(u'设备卡号', max_length=20, default="")
+#     volt = models.CharField(u'电压', max_length=10, default="")
+#     rssi = models.CharField(u'信号强度', max_length=10, default="")
+#     version = models.CharField(u'设备版本号', max_length=50, default="")
+#     is_online = models.SmallIntegerField(u'是否在线', default=1)
+#     upl_time = models.IntegerField(default=0)
 
-    class Meta:
-        db_table = "device"
-        verbose_name = u'设备列表'
-        verbose_name_plural = verbose_name
+#     class Meta:
+#         db_table = "device"
+#         verbose_name = u'设备列表'
+#         verbose_name_plural = verbose_name
 
 
-class QXZData(models.Model):
-    device_id = models.ForeignKey(Device, on_delete=models.CASCADE)
-    device_data = models.TextField()
-    add_time = models.IntegerField(default=0)
+# class QXZData(models.Model):
+#     device_id = models.ForeignKey(Device, on_delete=models.CASCADE)
+#     device_data = models.TextField()
+#     add_time = models.IntegerField(default=0)
 
-    class Meta:
-        db_table = "qxz_data"
-        verbose_name = u'气象站数据'
-        verbose_name_plural = verbose_name
+#     class Meta:
+#         db_table = "qxz_data"
+#         verbose_name = u'气象站数据'
+#         verbose_name_plural = verbose_name

+ 13 - 13
apps/Equipment/serializers.py

@@ -1,6 +1,7 @@
 from rest_framework import serializers
-import ast
-from .models import Device
+import time
+# import ast
+# from .models import Device
 
 
 class SearchEquipSerializer(serializers.Serializer):
@@ -15,15 +16,14 @@ class SearchEquipSerializer(serializers.Serializer):
             return value
 
 
-class DeviceListSerializer(serializers.ModelSerializer):
-    class Meta:
-        model = Device
-        exclude = ('owner', 'device_type')
+class QxzDeviceDetailSerializer(serializers.Serializer):
+    device_id = serializers.CharField(help_text="设备号", required=True)
+    start_timestamp = serializers.IntegerField(help_text="开始时间戳(秒级)", required=True)
 
-
-class DeviceDetailSerializer(serializers.Serializer):
-    def to_representation(self, instance):
-        value = ast.literal_eval(instance.device_data)
-        addtime = instance.add_time
-        data = {"value": value, "time": addtime}
-        return data
+    def validate_start_timestamp(self, attrs):
+        nowtime = int(time.time())
+        if nowtime - attrs > 24*60*60:
+            raise serializers.ValidationError("非近一天内时间")
+        elif nowtime - attrs < 0:
+            raise serializers.ValidationError("请确定是否为秒级时间戳,或非近一天内时间")
+        return attrs

+ 3 - 3
apps/Equipment/urls.py

@@ -4,7 +4,7 @@ from . import views
 
 urlpatterns = [
     url(r'^search/$', views.SearchEquip.as_view(), name='equip_search'),
-    url(r'^qxz/$', views.ReceiveQXZ.as_view(), name='equip_search'),
-    url(r'^list/$', views.DeviceList.as_view(), name='equip_search'),
-    url(r'^detail/$', views.DeviceDetail.as_view(), name='equip_search'),
+
+    url(r'^qxz/detail/$', views.QxzDeviceDetailView.as_view(), name='qxz_detail'),
+    url(r'^qxz/list/$', views.QxzDeviceListView.as_view(), name='qxz_list'),
 ]

+ 58 - 122
apps/Equipment/views.py

@@ -1,16 +1,14 @@
 from rest_framework.views import APIView
-from rest_framework.generics import GenericAPIView
 from rest_framework.response import Response
-import time
+from django.core.cache import cache as default_cache
 
-from .serializers import SearchEquipSerializer, DeviceListSerializer, DeviceDetailSerializer
+from .serializers import SearchEquipSerializer, QxzDeviceDetailSerializer
+from utils.JWTAuthentication_diy import APIAuthentication
+from utils.permissions import QXZDeviceDetailPermission
+from utils.MyRateThrottle import QxzDeviceListRateThrottle, QxzDeviceDetailRateThrottle
 from utils.utils import get_equip_list
-from utils.JWTAuthentication_diy import MyJWTAuthentication
-from utils.permissions import ModulePermission, DeviceDetailPermission, AccessPermission
-from utils.MyRateThrottle import DeviceListRateThrottle, DeviceDetailRateThrottle
-from utils.paginations import CustomPagination
 from utils.db_utils import MongoDBTools
-from .models import Device, QXZData
+
 
 
 # Create your views here.
@@ -27,124 +25,22 @@ class SearchEquip(APIView):
         return Response(data)
 
 
-class ReceiveQXZ(APIView):
-    def post(self, request):
-        data = request.data
-        if data.get("cmd") == "offline":
-            imei = data["ext"]["imei"]
-            try:
-                device = Device.objects.get(device_id=imei)
-                device.upl_time = int(time.time())
-                device.is_online = 0
-                device.save()
-            except Exception as e:
-                print("离线数据保存异常", e)
-        elif "terminalStatus" in data:
-            imei = data["StationID"]
-            status_data = data["terminalStatus"]
-            if Device.objects.filter(device_id=imei).exists():
-                device = Device.objects.get(device_id=imei)
-            else:
-                device = Device.objects.create(
-                    device_id=imei,
-                    device_type=1
-                )
-            if status_data.get("VOLT"):
-                device.volt = status_data.get("VOLT")
-            if status_data.get("RSSI"):
-                device.rssi = status_data.get("RSSI")
-            if status_data.get("ICCID"):
-                device.iccid = status_data.get("ICCID")
-            if status_data.get("longitude"):
-                device.lng = status_data.get("longitude")
-            if status_data.get("latitude"):
-                device.lat = status_data.get("latitude")
-            if status_data.get("Version"):
-                device.version = status_data.get("Version")
-            device.is_online = 1
-            device.upl_time = int(time.time())
-            device.save()
-
-        elif 'data' in data:
-            imei = data["StationID"]
-            save_data = data["data"]
-            if Device.objects.filter(device_id=imei).exists():
-                device = Device.objects.get(device_id=imei)
-            else:
-                device = Device.objects.create(
-                    device_id=imei,
-                    device_type=1
-                )
-            device.is_online = 1
-            device.upl_time = int(time.time())
-            device.save()
-
-            QXZData.objects.create(
-                device_id=device,
-                device_data=save_data,
-                add_time=int(time.time())
-            )
-        return Response("已接收保存")
-
-
-class DeviceList(GenericAPIView):
-    authentication_classes = [MyJWTAuthentication]
-    permission_classes = [ModulePermission]
-    throttle_classes = [DeviceListRateThrottle]
-    serializer_class = DeviceListSerializer
-    queryset = Device.objects.all()
-
-    def post(self, request):
-        uid = int(request.user.get("uid"))
-        device_queryset = self.get_queryset().filter(owner=uid)
-        serializer = self.get_serializer(instance=device_queryset, many=True)
-        return Response(serializer.data)
-
-
-class DeviceDetail(GenericAPIView):
-    authentication_classes = [MyJWTAuthentication]
-    permission_classes = [DeviceDetailPermission]
-    throttle_classes = [DeviceDetailRateThrottle]
-    serializer_class = DeviceDetailSerializer
-    queryset = QXZData.objects.all().order_by("-id")
-
-    def post(self, request):
-        deviceId = request.data.get("device_id")
-        start_time = int(request.data.get("start_time"))
-        device_queryset = self.get_queryset().filter(device_id_id=deviceId, add_time__gt=start_time)
-        serializer = self.get_serializer(instance=device_queryset, many=True)
-        return Response(serializer.data)
-
-
-def get_page_or_page_size(request):
-    try:
-        page = int(request.query_params['page']) - 1
-        if page < 0:
-            page = 0
-    except Exception as e:
-        page = 0
-
-    try:
-        page_size = int(request.query_params['page_size'])
-        if page_size < 0:
-            page_size = 10
-    except Exception as e:
-        page_size = 10
-    return page, page_size
-
-
 class QxzDeviceListView(APIView):
-    permission_classes = [AccessPermission]
+    authentication_classes = APIAuthentication
+    throttle_classes = [QxzDeviceListRateThrottle]
 
     def get(self, request, *args, **kwargs):
         """获取气象站设备列表接口"""
-        uid = request.uid
+        uid = request.user
+        # uid = 896
+        
         wheres = {
+            "device_type_id":5,
             '$or': [
                 {'owner_uid': uid},
                 {'user_dealer': uid}
             ]
-        },
+        }
         project = {
             'device_id': '$device_id',
             'uptime': '$uptime',
@@ -152,13 +48,53 @@ class QxzDeviceListView(APIView):
             'lng': '$lng',
             'lat': '$lat'
         }
-        page, page_size = get_page_or_page_size(request)
-        skip, limit = page * page_size, page_size
         m = MongoDBTools(db_name='smartfarming', table_name='sa_device')
-        data = m.find_many(wheres=wheres, options=project, skip=skip, limit=limit)
-        result = []
+        data = m.find_many(wheres=wheres, options=project)
+        if data:
+            total_counts = data.count()
+        else:
+            total_counts = 0
+        result = {"total_counts":total_counts,"items":[]}
+        qxz_list_cache = []
         for item in data:
-            result.append(item)
+            result["items"].append(item)
+            qxz_list_cache.append(item["device_id"])
+        default_cache.set(str(uid)+"_qxz_list", qxz_list_cache,60*5)
         return Response(result)
 
 
+class QxzDeviceDetailView(APIView):
+    authentication_classes = [APIAuthentication]
+    permission_classes = [QXZDeviceDetailPermission]
+    throttle_classes = [QxzDeviceDetailRateThrottle]
+    
+    def get(self, request, *args, **kwargs):
+        serializer = QxzDeviceDetailSerializer(data=request.query_params)
+        serializer.is_valid(raise_exception=True)
+        request_data = serializer.validated_data
+        start_time, device_id = request_data["start_timestamp"], request_data["device_id"]
+            
+        conf_wheres = {
+            "device_id":device_id,
+        }
+        conf_m = MongoDBTools(db_name='smartfarming', table_name='sa_qxz_conf')
+        conf_data = conf_m.find_one(wheres=conf_wheres)
+        conf_data.pop("id")
+        conf_data.pop("device_id")
+        conf_data.pop("uptime")
+        conf_data = dict(sorted(conf_data.items(), key=lambda e:int(e[0].split("e")[1])))
+        result = {"conf":conf_data,"items":[]}
+
+        data_m = MongoDBTools(db_name='smartfarming', table_name='sa_qxz_data')
+        data_wheres = {
+            "device_id": device_id,
+            "uptime": {"$gt":start_time}
+        }
+        data = data_m.find_many(wheres=data_wheres)
+
+        for item in data:
+            item.pop("id")
+            item.pop("device_id")
+            result["items"].append(item)
+        return Response(result)
+

+ 1 - 2
apps/UserApp/models.py

@@ -6,8 +6,7 @@ from django.contrib.auth.models import AbstractUser
 
 class MyUser(AbstractUser):
     USERMODULES_CHOICES = {
-        1: 'equipment',
-        2: 'PestAnalysis'
+        1: 'PestAnalysis',
     }
 
     user_remark = models.TextField(u'用户备注', max_length=200, blank=True)

+ 1 - 1
apps/UserApp/urls.py

@@ -4,5 +4,5 @@ from . import views
 
 urlpatterns = [
     url(r'^login/$', views.LoginView.as_view(), name='login'),
-    url(r'^register/$', views.RegisterView.as_view(), name='login'),
+    url(r'^register/$', views.RegisterView.as_view(), name='register'),
 ]

+ 1 - 13
apps/UserApp/views.py

@@ -3,9 +3,9 @@ from rest_framework.generics import GenericAPIView
 from rest_framework.response import Response
 from rest_framework import status
 from django.contrib.auth import authenticate
+
 from utils.JWTAuthentication_diy import get_token, MyJWTAuthentication
 from utils.permissions import RegisterViewPermission
-from utils.MyRateThrottle import LoginRateThrottle
 from .serializers import RegisterViewSerializer
 
 
@@ -13,7 +13,6 @@ from .serializers import RegisterViewSerializer
 
 
 class LoginView(APIView):
-    throttle_classes = [LoginRateThrottle, ]
 
     def post(self, request):
         username = request.data.get('username')
@@ -36,14 +35,3 @@ class RegisterView(GenericAPIView):
         serializer.is_valid()
         serializer.save()
         return Response(serializer.data)
-
-# class UserShowView(APIView):
-#     #局部配置
-#     authentication_classes = [MyJWTAuthentication]
-#     def post(self,request):
-#         token = request.auth
-#         user = request.user
-#         print(token)
-#         print(user)
-#         # print(user["user_modules"])
-#         return Response("认证成功")

+ 5 - 6
bigdataAPI/settings.py

@@ -23,7 +23,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 SECRET_KEY = '$rs)*w)9gh)nkf1=@r$2xguf1b(qz8ba!%hm8lwt54ti3_da^b'
 
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = False
+DEBUG = True
 
 ALLOWED_HOSTS = ['*']
 
@@ -81,13 +81,13 @@ WSGI_APPLICATION = 'bigdataAPI.wsgi.application'
 if DEBUG:
     USER_CONFIG = {
         'mysql': {
-            'host': 'localhost',
+            'host': '114.115.147.140',
             'user': 'root',
             'pwd': 'yfkj@6020',
             'port': 3306
         },
         'mongodb': {
-            'host': 'localhost',
+            'host': '114.115.147.140',
             'user': 'root',
             'pwd': 'yfkj@6020',
             'port': 27017
@@ -168,9 +168,8 @@ REST_FRAMEWORK = {
         'utils.rendererresponse.CustomRender',
     ),
     'DEFAULT_THROTTLE_RATES': {
-        'login': '10/m',
-        'devicelist': '10/h',
-        'devicedetail': '10/h'
+        'devicelist': '1/m',
+        'devicedetail': '1/m'
     }
 }
 

+ 33 - 1
utils/JWTAuthentication_diy.py

@@ -3,8 +3,11 @@ from rest_framework.authentication import BaseAuthentication
 from rest_framework.exceptions import AuthenticationFailed
 import jwt
 from .AESencipher import aescrypt
+from .db_utils import MySQLTool
+from bigdataAPI.settings import SECRET_KEY
+from django.core.cache import cache as default_cache
 
-PrAes = aescrypt('yf7232275', 'ECB', '', 'gbk')
+PrAes = aescrypt(SECRET_KEY, 'ECB', '', 'gbk')
 
 
 def get_token(user):
@@ -42,3 +45,32 @@ class MyJWTAuthentication(BaseAuthentication):
                 msg = str(e)
                 raise AuthenticationFailed(msg)
         raise AuthenticationFailed('token为空')
+
+
+def API_get_uid(token):
+    sql = f'''select uid from sa_device_user where api_token={token}'''
+    m = MySQLTool()
+    result = m.execute_by_one(sql)
+    if result:
+        uid = result['uid']
+    else:
+        uid = ""
+    return uid    
+
+
+class APIAuthentication(BaseAuthentication):
+    cache = default_cache
+    def authenticate(self, request):
+        token = request.META.get('HTTP_AUTHORIZATION')
+        if token:
+            # uid_sql = 896
+            uid_cache = self.cache.get(token)
+            if uid_cache:
+                return (uid_cache,token)
+            uid_sql = API_get_uid(token)
+            if uid_sql:
+                self.cache.set(token,uid_sql,60*1)
+                return (uid_sql,token)
+            
+            raise AuthenticationFailed("校验失败")
+        raise AuthenticationFailed('Authorization为空')

+ 9 - 17
utils/MyRateThrottle.py

@@ -1,27 +1,19 @@
 from rest_framework.throttling import SimpleRateThrottle
 
-
-class LoginRateThrottle(SimpleRateThrottle):
-    scope = "login"
-
-    def get_cache_key(self, request, view):
-        return self.get_ident(request)
-
-
-class DeviceListRateThrottle(SimpleRateThrottle):
+class QxzDeviceListRateThrottle(SimpleRateThrottle):
     scope = "devicelist"
 
     def get_cache_key(self, request, view):
-        user = request.user
-        uid = user["uid"]
-        return uid
+        uid = request.user
+        key = str(uid) + "_qxzlist_rate"
+        return key
 
 
-class DeviceDetailRateThrottle(SimpleRateThrottle):
+class QxzDeviceDetailRateThrottle(SimpleRateThrottle):
     scope = "devicedetail"
 
     def get_cache_key(self, request, view):
-        user = request.user
-        uid = user["uid"]
-        deviceId = request.data.get("device_id")
-        return uid + deviceId
+        uid = request.user
+        device_id = request.query_params.get("device_id","")
+        key = str(uid) + device_id + "detail_rate"
+        return key

+ 1 - 1
utils/db_utils.py

@@ -48,7 +48,7 @@ class MongoDBTools:
             result = {}
         return result
 
-    def find_many(self, wheres, options=None, is_reverse=True, skip=0, limit=10, sort=None):
+    def find_many(self, wheres, options=None, is_reverse=True, skip=0, limit=0, sort=None):
         if not options:
             options = {}
         projection = {'_id': 0}

+ 34 - 42
utils/permissions.py

@@ -1,8 +1,6 @@
-# coding:utf-8
-
 from rest_framework.permissions import BasePermission
-from apps.Equipment.models import Device
-from .db_utils import MySQLTool
+from django.core.cache import cache as default_cache
+from utils.db_utils import MongoDBTools
 
 
 class RegisterViewPermission(BasePermission):
@@ -31,45 +29,39 @@ class ModulePermission(BasePermission):
             return False
 
 
-class DeviceDetailPermission(BasePermission):
+class QXZDeviceDetailPermission(BasePermission):
+    message = "非此账户下设备"
+    
     def has_permission(self, request, view):
-        try:
-            user = request.user
-            uid = user.get("uid")
-            user_modules = user.get("user_modules")
-            deviceId = request.data.get("device_id")
-            device = Device.objects.filter(device_id=deviceId, owner_id=int(uid))
-            if user_modules == "1" and device.exists():
+        uid = request.user
+        # uid = 896
+        device_id = request.query_params.get("device_id")
+        if device_id is None:
+            return True
+        qxz_list_cache = default_cache.get(str(uid)+"_qxz_list")
+        if qxz_list_cache:
+            if device_id in qxz_list_cache:
+                return True
+            else:
+                return False
+        else:
+            wheres = {
+                "device_type_id":5,
+                '$or': [
+                    {'owner_uid': uid},
+                    {'user_dealer': uid}
+                ]
+            }
+            project = {
+                'device_id': '$device_id',
+            }
+            m = MongoDBTools(db_name='smartfarming', table_name='sa_device')
+            data = m.find_many(wheres=wheres, options=project)
+            qxz_list_cache = []
+            for item in data:
+                qxz_list_cache.append(item["device_id"])
+            default_cache.set(str(uid)+"_qxz_list", qxz_list_cache,60*5)
+            if device_id in qxz_list_cache:
                 return True
             else:
                 return False
-        except:
-            return False
-
-
-def get_bigdata_user_uid(token):
-    sql = f'''select uid from sa_device_user where api_token={token}'''
-    m = MySQLTool()
-    result = m.execute_by_one(sql)
-    uid = result['uid']
-    return uid
-
-
-class AccessPermission(BasePermission):
-    def has_permission(self, request, view):
-        try:
-            auth = request.MATE['HTTP_AUTHORIZATION']
-            temp_list = auth.split()
-            if temp_list[0] != 'Bearer':
-                raise Exception()
-            token = temp_list[1]
-            try:
-                uid = request.session['bigdata_uid']
-            except KeyError as e:
-                uid = get_bigdata_user_uid(token)
-                request.session['bigdata_uid'] = uid
-                request.session.save()
-            request.bigdata_uid = uid
-        except Exception as e:
-            return False
-        return True