yf_yzl 2 年之前
父節點
當前提交
6afbde4f09

+ 1 - 1
README.md

@@ -8,7 +8,7 @@ yum install mysql-devel -y
 气象站基础信息表      MongoQXZ_Base_Info    sa_qxz_base_info
 新气象站全部数据记录  QXZdata_New            sa_qxz_data
 新气象站配置表        MongoQXZ_Conf         sa_qxz_conf
-气象站短信预警        MongoQXZ_Alarm_New    sa_qxz_alarm_new
+气象站短信预警        MongoQXZ_Alarm_New    sa_qxz_alarm_log_new
 气象站开关配置表      MongoQXZ_Switch       sa_qxz_switch
 气象站阈值表          MongoQXZ_Auto_Switch  sa_qxz_auto_switch
 气象站开关定时表      MongoQXZ_Timing_Switch sa_qxz_timing_switch

+ 22 - 8
scripts/test/qx_base_info.py

@@ -21,14 +21,28 @@ my_client = pymongo.MongoClient(host="8.136.98.49", port=27017, username="root",
 my_col = my_client['smartfarming']['sa_device']
 
 qx_device = {
-"861551055315402",
-"861551056086671",
-"861551056088693",
-"861551056088479",
-"861551056088719",
-"861551055313365",
-"861551056086614",
-"861551056093800"
+# "861551055315402",
+# "861551056086671",
+# "861551056088693",
+# "861551056088479",
+# "861551056088719",
+# "861551055313365",
+# "861551056086614",
+# "861551056093800"
+
+
+"861551056095367",
+"861551056102502",
+"861551056096621",
+"861551056101785",
+"861551056086549",
+"861551055354120",
+"861551055353536",
+"861551056092018",
+"861551055319586",
+"861551056088875",
+"861551055324651",
+"861551055313423"
 }
 
 

+ 21 - 8
scripts/test/qx_conf.py

@@ -21,14 +21,27 @@ my_client = pymongo.MongoClient(host="8.136.98.49", port=27017, username="root",
 my_col = my_client['smartfarming']['sa_device']
 
 qx_device = {
-"861551055315402",
-"861551056086671",
-"861551056088693",
-"861551056088479",
-"861551056088719",
-"861551055313365",
-"861551056086614",
-"861551056093800"
+# "861551055315402",
+# "861551056086671",
+# "861551056088693",
+# "861551056088479",
+# "861551056088719",
+# "861551055313365",
+# "861551056086614",
+# "861551056093800"
+
+"861551056095367",
+"861551056102502",
+"861551056096621",
+"861551056101785",
+"861551056086549",
+"861551055354120",
+"861551055353536",
+"861551056092018",
+"861551055319586",
+"861551056088875",
+"861551055324651",
+"861551055313423"
 }
 
 

+ 21 - 8
scripts/test/qx_data.py

@@ -21,14 +21,27 @@ my_client = pymongo.MongoClient(host="8.136.98.49", port=27017, username="root",
 my_col = my_client['smartfarming']['sa_device']
 
 qx_device = {
-"861551055315402",
-"861551056086671",
-"861551056088693",
-"861551056088479",
-"861551056088719",
-"861551055313365",
-"861551056086614",
-"861551056093800"
+# "861551055315402",
+# "861551056086671",
+# "861551056088693",
+# "861551056088479",
+# "861551056088719",
+# "861551055313365",
+# "861551056086614",
+# "861551056093800"
+
+"861551056095367",
+"861551056102502",
+"861551056096621",
+"861551056101785",
+"861551056086549",
+"861551055354120",
+"861551055353536",
+"861551056092018",
+"861551055319586",
+"861551056088875",
+"861551055324651",
+"861551055313423"
 }
 
 

+ 140 - 5
smartfarming/api/views/camera/camera_manage.py

@@ -2,6 +2,11 @@ import re
 import requests
 import time
 import ast
+import os 
+import datetime
+import uuid
+from PIL import Image
+from io import BytesIO
 from django.conf import settings
 from django.db.models import Count
 from django.core.paginator import Paginator
@@ -12,10 +17,10 @@ from smartfarming.models.sim_card import MongoMsg_Conf
 from smartfarming.models.device import MongoDevice
 from smartfarming.models.camera import MongoCameraPhoto, MongoCameraData, MongoCameraAccount
 from smartfarming.serializers.device_serializers import DeviceSerializers
-from smartfarming.utils import controlMove
-from smartfarming.utils import bindDeviceLive, getLive
-
+from smartfarming.utils import bindDeviceLive, getLive, controlMove, modify_live_time, off_on_live, setDeviceSnap
+from kedong.tools import RedisPool
 from kedong.decoration import kedong_deco, PortError
+
 config_dict = settings.CONFIG
 
 
@@ -386,8 +391,138 @@ def add_camera(request):
         else:
             raise PortError("","Token过期,设备激活失败")
     try:
-        # MongoDevice.objects.create(device_id=device_ids,device_type_id=6,addtime=now_time,device_code=1,uptime=now_time)
         MongoCameraData.objects.create(device_id=device_ids,device_info=device_info,addtime=now_time,camera_playback=camera_playback,account_id=account_id)
     except Exception as e:
         raise PortError(" ", "添加设备失败")
-    return True
+    return True
+
+
+
+@kedong_deco(login_required=True)
+def camera_config(request):
+    """
+    监控设置
+    参数:
+    device_name                 必传(str)               设备名称
+    off_on                      必传(str)               设备开关 off 关 on 开
+    start_time                  非必传(str)             开始时间 为开时 必传
+    end_time                    非必传(str)             结束时间 为开时 必传
+    device_id                   必传(str)               设备号 
+    """
+    
+    device_id = request.POST.get("device_id") 
+    off_on = request.POST.get("off_on","")
+    start_time = request.POST.get("start_time","")
+    end_time = request.POST.get("end_time","")
+    device_ids = request.POST.get("device_id")
+    device_name = request.POST.get("device_name")
+    redis_pool = RedisPool().get_redis_pool(settings.redis_db["captcha"])
+    try:
+        device_query = MongoDevice.objects.get(device_id=device_ids)
+    except:
+        raise PortError("","未找出此设备")
+    account_id = MongoCameraData.objects.filter(device_id=device_ids).first()
+    if not account_id:
+        raise PortError("","未找到此设备")
+    camera_query = MongoCameraAccount.objects.filter(id=int(account_id.account_id)).first()
+    if not camera_query:
+        raise PortError("","未找到此账号")
+    channelNo = "1"
+    if device_ids.find("-") != -1:
+        channelNo = device_ids.split("-")[1]
+        device_id = device_ids.split("-")[0]
+    else:
+        device_id = device_ids
+    if camera_query.account_type == 1:
+        appId = camera_query.app_key
+        appSecret = camera_query.app_secret
+        live_token = redis_pool.get(device_ids)
+        if not live_token:
+            live_data = getLive(appId, appSecret, device_id, channelNo)
+            if live_data["result"]["code"] == "0":
+                try:
+                    live_token = live_data["result"]["data"]["streams"][0]["liveToken"]
+                    redis_pool.set(device_ids,live_token,60*60*23)
+                except:
+                    raise PortError("","获取liveToken失败")
+            else:
+                raise PortError("",live_data)
+    else:
+        raise PortError("","其它设备没有此功能")
+    if off_on == "on":
+        if not start_time and not end_time:
+            status = modify_live_time(appId,appSecret,live_token,start_time,end_time,"always")
+        else:
+            # 时间内开启直播
+            status = modify_live_time(appId,appSecret,live_token,start_time,end_time)
+    elif off_on == "off":
+        status = off_on_live(appId,appSecret,live_token,off_on)
+    else:
+        raise PortError("","参数超出范围")
+    if status["result"]["code"] == "0":
+        device_query.device_name = device_name
+        device_query.save()
+        config = off_on + "-" + start_time + "-" + end_time
+        redis_pool.set(device_ids+"config",config)
+        return True
+    else:
+        return status
+    
+
+@kedong_deco(login_required=True)
+def camera_takephoto(request):
+    # 监控拍照接口
+    device_id = request.POST.get("device_id")
+    if not device_id:
+        raise PortError("","设备号未传")
+    try:
+        d_id = MongoDevice.objects.get(device_id=device_id).id
+    except:
+        raise PortError("","未找出此设备")
+    account_id = MongoCameraData.objects.filter(device_id=device_id).first()
+    if not account_id:
+        raise PortError("","未找到此设备")
+    camera_query = MongoCameraAccount.objects.filter(id=int(account_id.account_id)).first()
+    if not camera_query:
+        raise PortError("","未找到此账号")
+    channelNo = "0"
+    if device_id.find("-") != -1:
+        channelNo = device_id.split("-")[1]
+        device_id = device_id.split("-")[0]
+    else:
+        device_id = device_id
+    appId = camera_query.app_key
+    appSecret = camera_query.app_secret
+    snap_url = setDeviceSnap(appId, appSecret, device_id, channelNo)
+    time.sleep(1) 
+    print(snap_url)
+    if snap_url:
+        # 图片保存位置 
+        config = settings.CONFIG
+        camera_path = config.get("media") + "/jiankong/" + device_id + "/" + time.strftime("%Y%m%d", time.localtime())
+        os.makedirs(camera_path) if not os.path.exists(camera_path) else None
+        stamp = int(time.time())
+        unique_id = uuid.uuid4()
+        combined_id = str(stamp) + "-" + str(unique_id)
+        camera_photos = camera_img_name = combined_id + ".jpg"
+        camera_path + "/" + camera_img_name
+        img_query = requests.get(snap_url)
+        if img_query.status_code == 200:
+            img = Image.open(BytesIO(img_query.content)) #获取图片
+            img.save(camera_path) #报存到文件夹
+            camera_obj = MongoCameraPhoto.objects.create(
+                device_id=d_id,
+                addr=camera_photos,
+                photo_status=1,
+                addtime=int(time.time())
+            )
+            if camera_obj:
+                return {"addr":camera_photos}
+            else:
+                raise PortError("","保存图片失败,稍后重试")
+        else:
+            raise PortError("","下载图片失败,稍后重试")
+    else:
+        raise PortError("","拍照失败,稍后重试")
+
+    

+ 62 - 0
smartfarming/api/views/forecast/forecast_serializers.py

@@ -0,0 +1,62 @@
+from rest_framework import serializers
+from smartfarming.models.device import (
+    MongoSCDData,
+    MongoCBDData,
+    MongoXYCBData,
+    MongoBZYData
+)
+
+class MongoSCDDataSerializers(serializers.ModelSerializer):
+
+    d_h_t = serializers.SerializerMethodField()
+
+    def get_d_h_t(self, obj):
+        device_data = eval(obj.device_data)
+        device_data["addtime"] = obj.addtime
+        return device_data
+
+    class Meta:
+        model = MongoSCDData
+        fields = ["d_h_t"]
+
+
+class MongoCBDDataSerializers(serializers.ModelSerializer):
+
+    d_h_t = serializers.SerializerMethodField()
+
+    def get_d_h_t(self, obj):
+        device_data = eval(obj.device_data)
+        device_data["addtime"] = obj.addtime
+        return device_data
+
+    class Meta:
+        model = MongoCBDData
+        fields = ["d_h_t"]
+
+
+class MongoXYCBDataSerializers(serializers.ModelSerializer):
+
+    d_h_t = serializers.SerializerMethodField()
+
+    def get_d_h_t(self, obj):
+        device_data = eval(obj.device_data)
+        device_data["addtime"] = obj.addtime
+        return device_data
+
+    class Meta:
+        model = MongoXYCBData
+        fields = ["d_h_t"]
+
+
+class MongoBZYDataSerializers(serializers.ModelSerializer):
+
+    d_h_t = serializers.SerializerMethodField()
+
+    def get_d_h_t(self, obj):
+        device_data = eval(obj.device_data)
+        device_data["addtime"] = obj.addtime
+        return device_data
+
+    class Meta:
+        model = MongoBZYData
+        fields = ["d_h_t"]

+ 35 - 121
smartfarming/api/views/forecast/worm_lamp.py

@@ -4,7 +4,7 @@ from json import JSONDecodeError
 import pymysql
 from django.db.models import Sum, Max
 from django.conf import settings
-
+from django.core.paginator import Paginator
 from smartfarming.models.device import (
     MongoDevice, 
     MongoCBDData, 
@@ -16,6 +16,12 @@ from smartfarming.models.device import (
 from smartfarming.models.weather import QXZThresholdWarning
 from smartfarming.models.worm_forecast import MongoCBDphoto
 from smartfarming.api.views.forecast.all_dict import insect_dict, attract_discern
+from smartfarming.api.views.forecast.forecast_serializers import (
+    MongoSCDDataSerializers, 
+    MongoCBDDataSerializers, 
+    MongoXYCBDataSerializers, 
+    MongoBZYDataSerializers
+)
 from kedong.decoration import kedong_deco, PortError
 from smartfarming.utils import expire_time
 config_dict = settings.CONFIG
@@ -250,130 +256,38 @@ def device_status_data(request):
 def device_history_data(request):
     """
     虫情测报灯/孢子仪    数据详情页面/列表展示
-    设备历史状态列表接口
-    参数:
-    device_type_id          必传(string)                  设备类型  3虫情测报灯 7孢子仪
-    device_id               非必传                          设备id
-    page                    非必传(num)                     页码,默认为1
-    page_size               非必传(num)                     每页数量,默认为10
-    start_time              必传(string 时间戳)              开始时间    (用于时间搜索)
-    end_time                必传(string 时间戳)              结束时间    (用于时间搜索)
-
-    返回值:
-    "data": {
-        "device_id": "28586565004320786510437",  设备id
-        "counts": 3,                            列表数据总长度
-        "data": [
-            {
-
-                "status": {
-                        "addtime": 1590230470,      时间
-                        "csq":29,					//信号强度
-                        "hrt":55,					//加热仓实时温度 °C
-                        "at":245,					//环境温度 °C(注:温度值为乘以 10 后的结果,需要除以 10 得到温度值)
-                        "ah":745,					//环境湿度 %RH(注:湿度值为乘以 10 后的结果,需要除以 10 得到相对湿度值)
-                        "dtype":1,					//设备类型 <测报灯设备类型为 3>
-                        "dver":"1.0.0",				//设备固件版本
-                        "rps":0,					//雨控状态 1雨控,0正常,下同
-                        "lps":0,					//光控状态 1光控,0正常
-                        "tps":0,					//温控状态 1温控,0正常
-                        "gs":0,						//通道状态 1落虫,0排水
-                        "upds":1,					//上仓门状态 1打开,0关闭
-                        "dnds":0,					//下仓门状态 1打开,0关闭
-                        "hs":0,						//加热状态 1加热,0正常
-                        "lat":"34.815187",			//纬度
-                        "lng":"113.67336",			//经度
-                        "stamp":"20180301211805",	//时间戳
-                        "ws":0,                     //工作状态0待机 1工作
-                        "vbat":"24",                 //电源电压
-                        "batStatus":0,              //电压状态0正常 1欠压
-                        "st":20,                    //时控开始时间
-                        "et":0,                     //时控结束时间
-                        "ts":1,                     //定时模式 0 光控,1时控
-                        "collt":10,                 //落虫收集时间
-                        "htim":10,                  //设定的虫体烘干时间
-                        "hst":110,                  //设定的加热温度
-                        "tph":70,                   //高温保护阀值
-                        "tpl":0,                    //低温保护阀值
-                        "boot":0,                   //禁止工作 0-正常  1-使能(禁止工作)
-                        "shake_sec":1,              //震动时间
-                        "lamp":0,                   //灯管状态0-正常,1-异常
-                        "lux":100                  //光照强度
-                }......
-            },
-        ]
-        }
-
     """
     post_info = request.POST
-    device_type_id = post_info.get("device_type_id")
-    start_time = post_info.get('start_time')
-    end_time = post_info.get('end_time')
-    if not device_type_id:
-        raise PortError("device_type_id", "没有对应型号设备")
-    _device_id = post_info.get("device_id")
-
-    if not _device_id:
-        raise PortError('device_id',"该设备不存在")
     try:
-        device = MongoDevice.objects.get(device_id=_device_id)
-    except:
-        raise PortError('device_id',"暂无此设备")
-    device_id = device.id
-
-    #  3虫情测报灯 7孢子仪
-    if device_type_id == "7":
-        models =  "sa_device_bzy_data"
-        mode = MongoBZYData
-    elif device_type_id == "3":
-        models =  "sa_device_cbd_data"
-        mode = MongoCBDData
-    elif device_type_id == "2":
-        models = "sa_device_scd_data"
-        mode = MongoSCDData
-    elif device_type_id == "4":
-        models =  "sa_device_xycb_data"
-        mode = MongoXYCBData
-    else:
-        raise PortError('device_id',"暂不支持该设备类型")
-
-    connection = pymysql.connect(**config)
-    cursor = connection.cursor()
-
-    counts = mode.objects.filter(device_id=device_id,addtime__range=(start_time,end_time)).count()
-
-    page = int(post_info.get('page', 1))
-    page_size = int(post_info.get('page_size', 10))
-    start = max((page - 1), 0) * page_size
-    where_str = ''
+        device_type_id = post_info.get("device_type_id")
+        start_time = post_info.get('start_time')
+        end_time = post_info.get('end_time')
+        d_id = post_info.get("device_id")
+        page_num = int(post_info.get('page', 1))
+        page_size = int(post_info.get('page_size', 10))
+        device = MongoDevice.objects.get(device_id=d_id)
+        device_dict = {
+            "2": [MongoSCDData, MongoSCDDataSerializers],
+            "3": [MongoCBDData, MongoCBDDataSerializers], 
+            "4": [MongoXYCBData, MongoXYCBDataSerializers],
+            "7": [MongoBZYData, MongoBZYDataSerializers]
+        }
+        models_type = device_dict.get(device_type_id)
+        queryset = models_type[0].objects.filter(
+            device_id=device.id, 
+            addtime__gte=int(start_time), 
+            addtime__lte=int(end_time)).order_by("-addtime")
+        total_obj = queryset.count()
+        paginator = Paginator(queryset, page_size)
+        page_obj = paginator.get_page(page_num)
+        serializers = models_type[1](page_obj, many=True)
+        return {
+            "data": serializers.data,
+            "counts": total_obj
+        }
+    except Exception as e:
+        raise PortError('msg', "请联系管理员")
 
-    if start_time:
-        if start_time.isdigit() and end_time.isdigit():
-            start_time = int(start_time)
-            end_time = int(end_time)
-        else:
-            raise PortError("","参数类型不对")
-        where_str += ' and (addtime  between {} and {})'.format(start_time, end_time)
-
-    sql = 'select id, device_data, addtime from {} where device_id={} {} order by addtime desc limit {},{}'.format(
-        models, device_id, where_str,start,page_size)
-    cursor.execute(sql)
-    result = cursor.fetchall()
-    _device_datas = result
-    data = []
-    if _device_datas:
-        for j in _device_datas:
-            d_h_t = eval(j["device_data"])
-            d_h_t["addtime"] = j["addtime"]
-            data.append({"d_h_t":d_h_t})
-    if cursor:
-        cursor.close()
-    if connection:
-        connection.close()
-    return {
-        "data": data,
-        "counts": counts
-    }
 
 
 

+ 447 - 2
smartfarming/api/views/weather/weather.py

@@ -7,12 +7,13 @@ import copy
 import datetime
 import time
 import os
+import pymysql
 import requests
 from django.forms.models import model_to_dict
 from django.db.models import Q
 from django.conf import settings
 from kedong.decoration import kedong_deco, PortError
-from smartfarming.models.device import MongoDevice
+from smartfarming.models.device import MongoDevice, MongoCBDData
 from smartfarming.models.weather import MongoQXZ_Base_Info, QXZdata_New, MongoQXZ_Conf, QXZstatus_New, MongoQXZ_Alarm
 from smartfarming.api.views.weather.all_dict import qxz_dict
 
@@ -273,7 +274,7 @@ def qxz_status(request):
     e_id = request.POST.get("device_id")
     if not e_id:
         raise PortError("","参数缺失")
-    qxz_list = QXZstatus_New.objects.filter(device_id=e_id).first()
+    qxz_list = QXZdata_New.objects.filter(device_id=e_id).first()
     if not qxz_list:
         raise PortError("","未找到此设备")
     data = []
@@ -465,3 +466,447 @@ def qxz_early_warning(request):
     else:
         raise PortError("","参数超出范围")
     return data
+
+
+def qxz_configs(conf,e_data,es):
+    """气象站要素配置"""
+    e3s = conf.get(es,"")
+    code = e_data.split('#')[1]
+    if e3s:
+        config = e3s.split("#")
+        config.insert(0,code)
+    else:
+        config = qxz_dict_1[e_data.split('#')[1]]
+    return config
+
+
+@kedong_deco(login_required=True)
+def qxz_day_data(request):
+    """
+    气象24H数据接口 :
+    参数:
+    device_id               必传(string)
+
+    返回值:
+    {
+        "data": {
+            "conf": {
+            "e1":x.e1,"e2":x.e2,"e3":x.e3,"e4":x.e4,"e5":x.e5,
+            "e6":x.e6,"e7":x.e7,"e8":x.e8,"e9":x.e9,"e10":x.e10,
+            "e11":x.e11,"e12":x.e12,"e13":x.e13,"e14":x.e14,
+            "e15":x.e15,"e16":x.e16,"e17":x.e17,"e18":x.e18,
+            "e19":x.e19,"e20":x.e20,"e21":x.e21,"e22":x.e22,
+            "e23":x.e23,"e24":x.e24,"e25":x.e25,"e26":x.e26,
+            "e27":x.e27,"e28":x.e28,"e29":x.e29,"e30":x.e30
+            },
+            "nums": 0,
+            "data": [
+                {
+                "e1":qxz_list.e1,"e2":qxz_list.e2,"e3":qxz_list.e3,"e4":qxz_list.e4,"e5":qxz_list.e5,
+                "e6":qxz_list.e6,"e7":qxz_list.e7,"e8":qxz_list.e8,"e9":qxz_list.e9,"e10":qxz_list.e10,
+                "e11":qxz_list.e11,"e12":qxz_list.e12,"e13":qxz_list.e13,"e14":qxz_list.e14,
+                "e15":qxz_list.e15,"e16":qxz_list.e16,"e17":qxz_list.e17,"e18":qxz_list.e18,
+                "e19":qxz_list.e19,"e20":qxz_list.e20,"e21":qxz_list.e21,"e22":qxz_list.e22,
+                "e23":qxz_list.e23,"e24":qxz_list.e24,"e25":qxz_list.e25,"e26":qxz_list.e26,
+                "e27":qxz_list.e27,"e28":qxz_list.e28,"e29":qxz_list.e29,"e30":qxz_list.e30, 
+                "upl_time":qxz_list.upl_time.strftime('%Y-%m-%d %H:%M:%S')
+                },
+                {
+                "e1":qxz_list.e1,"e2":qxz_list.e2,"e3":qxz_list.e3,"e4":qxz_list.e4,"e5":qxz_list.e5,
+                "e6":qxz_list.e6,"e7":qxz_list.e7,"e8":qxz_list.e8,"e9":qxz_list.e9,"e10":qxz_list.e10,
+                "e11":qxz_list.e11,"e12":qxz_list.e12,"e13":qxz_list.e13,"e14":qxz_list.e14,
+                "e15":qxz_list.e15,"e16":qxz_list.e16,"e17":qxz_list.e17,"e18":qxz_list.e18,
+                "e19":qxz_list.e19,"e20":qxz_list.e20,"e21":qxz_list.e21,"e22":qxz_list.e22,
+                "e23":qxz_list.e23,"e24":qxz_list.e24,"e25":qxz_list.e25,"e26":qxz_list.e26,
+                "e27":qxz_list.e27,"e28":qxz_list.e28,"e29":qxz_list.e29,"e30":qxz_list.e30, 
+                "upl_time":qxz_list.upl_time.strftime('%Y-%m-%d %H:%M:%S')
+                },...
+            ]
+            }
+        "params": {},
+        "formError": {},
+        "errorCode": 0,
+        "message": "",
+    
+    }
+
+    """
+    device_id = request.POST.get("device_id")
+    qxz_dict_1 = copy.deepcopy(qxz_dict)    # 如果不拷贝 后面折线图修改字典会导致字典内容变化   从而造成数据错误
+    
+    times = ""
+
+    try:
+        MongoDevice.objects.get(device_id=device_id)
+    except:
+        raise PortError('device_id',"暂无此设备")
+
+    qxz_list = QXZstatus_New.objects.filter(device_id=device_id).order_by("-uptime").first()
+    if qxz_list:
+        times = qxz_list.uptime
+
+
+    # 获取最新一条数据的时间然后进行时间格式转换,再获取前一天时间
+    if times:
+        otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(times))
+        times_type = datetime.datetime.strptime(str(otherStyleTime), "%Y-%m-%d %H:%M:%S")
+        now = times_type - datetime.timedelta(days=1)
+    else:
+        # 获取前一天的时间点从0点到24点时间
+        now = datetime.datetime.now()- datetime.timedelta(days=1)
+
+    zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,microseconds=now.microsecond)
+    last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
+ 
+    start_time = int(time.mktime(time.strptime(str(zero_today), "%Y-%m-%d %H:%M:%S")))
+    end_time = int(time.mktime(time.strptime(str(last_today), "%Y-%m-%d %H:%M:%S")))
+    
+    
+    sta1 = QXZdata_New.objects.filter(device_id=device_id).filter(uptime__range=(start_time,end_time)).values()
+    data = []
+    e1 = []
+    e1_time = []
+    e2 = []
+    e2_time = []
+    e3 = []
+    e3_time = []
+    e4 = []
+    e4_time = []
+    e5 = []
+    e5_time = []
+    e6 = []
+    e6_time = []
+    e7 = []
+    e7_time = []
+    e8 = []
+    e8_time = []
+    e9 = []
+    e9_time = []
+    e10 = []
+    e10_time = []
+    e11 = []
+    e11_time = []
+    e12 = []
+    e12_time = []
+    e13 = []
+    e13_time = []
+    e14 = []
+    e14_time = []
+    e15 = []
+    e15_time = []
+    e16 = []
+    e16_time = []
+    e17 = []
+    e17_time = []
+    e18 = []
+    e18_time = []
+    e19 = []
+    e19_time = []
+    e20 = []
+    e20_time = []
+    e21 = []
+    e21_time = []
+    e22 = []
+    e22_time = []
+    e23 = []
+    e23_time = []
+    e24 = []
+    e24_time = []
+    e25 = []
+    e25_time = []
+    e26 = []
+    e26_time = []
+    e27 = []
+    e27_time = []
+    e28 = []
+    e28_time = []
+    e29 = []
+    e29_time = []
+    e30 = []
+    e30_time = []
+    for i in sta1[:200]:
+        if i['e1']:
+            e1.append(float(i['e1'].split('#')[0]))
+            e1_time.append(i['uptime'])
+        if i['e2']:
+            e2.append(float(i['e2'].split('#')[0]))
+            e2_time.append(i['uptime'])
+        if i['e3']:
+            e3.append(float(i['e3'].split('#')[0]))
+            e3_time.append(i['uptime'])
+        if i['e4']:
+            e4.append(float(i['e4'].split('#')[0]))
+            e4_time.append(i['uptime'])
+        if i['e5']:
+            e5.append(float(i['e5'].split('#')[0]))
+            e5_time.append(i['uptime'])
+        if i['e6']:
+            e6.append(float(i['e6'].split('#')[0]))
+            e6_time.append(i['uptime'])
+        if i['e7']:
+            e7.append(float(i['e7'].split('#')[0]))
+            e7_time.append(i['uptime'])
+        if i['e8']:
+            e8.append(float(i['e8'].split('#')[0]))
+            e8_time.append(i['uptime'])
+        if i['e9']:
+            e9.append(float(i['e9'].split('#')[0]))
+            e9_time.append(i['uptime'])
+        if i['e10']:
+            e10.append(float(i['e10'].split('#')[0]))
+            e10_time.append(i['uptime'])
+        if i['e11']:
+            e11.append(float(i['e11'].split('#')[0]))
+            e11_time.append(i['uptime'])
+        if i['e12']:
+            e12.append(float(i['e12'].split('#')[0]))
+            e12_time.append(i['uptime'])
+        if i['e13']:
+            e13.append(float(i['e13'].split('#')[0]))
+            e13_time.append(i['uptime'])
+        if i['e14']:
+            e14.append(float(i['e14'].split('#')[0]))
+            e14_time.append(i['uptime'])
+        if i['e15']:
+            e15.append(float(i['e15'].split('#')[0]))
+            e15_time.append(i['uptime'])
+        if i['e16']:
+            e16.append(float(i['e16'].split('#')[0]))
+            e16_time.append(i['uptime'])
+        if i['e17']:
+            e17.append(float(i['e17'].split('#')[0]))
+            e17_time.append(i['uptime'])
+        if i['e18']:
+            e18.append(float(i['e18'].split('#')[0]))
+            e18_time.append(i['uptime'])
+        if i['e19']:
+            e19.append(float(i['e19'].split('#')[0]))
+            e19_time.append(i['uptime'])
+        if i['e20']:
+            e20.append(float(i['e20'].split('#')[0]))
+            e20_time.append(i['uptime'])
+        if i['e21']:
+            e21.append(float(i['e21'].split('#')[0]))
+            e21_time.append(i['uptime'])
+        if i['e22']:
+            e22.append(float(i['e22'].split('#')[0]))
+            e22_time.append(i['uptime'])
+        if i['e23']:
+            e23.append(float(i['e23'].split('#')[0]))
+            e23_time.append(i['uptime'])
+        if i['e24']:
+            e24.append(float(i['e24'].split('#')[0]))
+            e24_time.append(i['uptime'])
+        if i['e25']:
+            e25.append(float(i['e25'].split('#')[0]))
+            e25_time.append(i['uptime'])
+        if i['e26']:
+            e26.append(float(i['e26'].split('#')[0]))
+            e26_time.append(i['uptime'])
+        if i['e27']:
+            e27.append(float(i['e27'].split('#')[0]))
+            e27_time.append(i['uptime'])
+        if i['e28']:
+            e28.append(float(i['e28'].split('#')[0]))
+            e28_time.append(i['uptime'])
+        if i['e29']:
+            e29.append(float(i['e29'].split('#')[0]))
+            e29_time.append(i['uptime'])
+        if i['e30']:
+            e30.append(float(i['e30'].split('#')[0]))
+            e30_time.append(i['uptime'])
+    
+    
+    conf = {}
+    x = MongoQXZ_Conf.objects.filter(device_id=device_id).first()
+    if x:
+        conf = {"e1":x.e1,"e2":x.e2,"e3":x.e3,"e4":x.e4,"e5":x.e5,
+                "e6":x.e6,"e7":x.e7,"e8":x.e8,"e9":x.e9,"e10":x.e10,
+                "e11":x.e11,"e12":x.e12,"e13":x.e13,"e14":x.e14,
+                "e15":x.e15,"e16":x.e16,"e17":x.e17,"e18":x.e18,
+                "e19":x.e19,"e20":x.e20,"e21":x.e21,"e22":x.e22,
+                "e23":x.e23,"e24":x.e24,"e25":x.e25,"e26":x.e26,
+                "e27":x.e27,"e28":x.e28,"e29":x.e29,"e30":x.e30}
+    data = []
+    try:
+        if e1 != []:
+            config = qxz_configs(conf,i['e1'],"e1")
+            data.append({"max":max(e1),"maxtime":e1_time[e1.index(max(e1))],"min":min(e1),"mintime":e1_time[e1.index(min(e1))],"enum":config,"ekey":i['e1'].split('#')[2]})
+        if e2 != []:
+            config = qxz_configs(conf,i['e2'],"e2")
+            data.append({"max":max(e2),"maxtime":e2_time[e2.index(max(e2))],"min":min(e2),"mintime":e2_time[e2.index(min(e2))],"enum":config,"ekey":i['e2'].split('#')[2]})
+        if e3 != []:
+            config = qxz_configs(conf,i['e3'],"e3")
+            data.append({"max":max(e3),"maxtime":e3_time[e3.index(max(e3))],"min":min(e3),"mintime":e3_time[e3.index(min(e3))],"enum":config,"ekey":i['e3'].split('#')[2]})
+        if e4 != []:
+            config = qxz_configs(conf,i['e4'],"e4")
+            data.append({"max":max(e4),"maxtime":e4_time[e4.index(max(e4))],"min":min(e4),"mintime":e4_time[e4.index(min(e4))],"enum":config,"ekey":i['e4'].split('#')[2]})
+        if e5 != []:
+            config = qxz_configs(conf,i['e5'],"e5")
+            data.append({"max":max(e5),"maxtime":e5_time[e5.index(max(e5))],"min":min(e5),"mintime":e5_time[e5.index(min(e5))],"enum":config,"ekey":i['e5'].split('#')[2]})
+        if e6 != []:
+            config = qxz_configs(conf,i['e6'],"e6")
+            data.append({"max":max(e6),"maxtime":e6_time[e6.index(max(e6))],"min":min(e6),"mintime":e6_time[e6.index(min(e6))],"enum":config,"ekey":i['e6'].split('#')[2]})
+        if e7 != []:
+            config = qxz_configs(conf,i['e7'],"e7")
+            data.append({"max":max(e7),"maxtime":e7_time[e7.index(max(e7))],"min":min(e7),"mintime":e7_time[e7.index(min(e7))],"enum":config,"ekey":i['e7'].split('#')[2]})
+        if e8 != []:
+            config = qxz_configs(conf,i['e8'],"e8")
+            data.append({"max":max(e8),"maxtime":e8_time[e8.index(max(e8))],"min":min(e8),"mintime":e8_time[e8.index(min(e8))],"enum":config,"ekey":i['e8'].split('#')[2]})
+        if e9 != []:
+            config = qxz_configs(conf,i['e9'],"e9")
+            data.append({"max":max(e9),"maxtime":e9_time[e9.index(max(e9))],"min":min(e9),"mintime":e9_time[e9.index(min(e9))],"enum":config,"ekey":i['e9'].split('#')[2]})
+        if e10 != []:
+            config = qxz_configs(conf,i['e10'],"e10")
+            data.append({"max":max(e10),"maxtime":e10_time[e10.index(max(e10))],"min":min(e10),"mintime":e10_time[e10.index(min(e10))],"enum":config,"ekey":i['e10'].split('#')[2]})
+        if e11 != []:
+            config = qxz_configs(conf,i['e11'],"e11")
+            data.append({"max":max(e11),"maxtime":e11_time[e11.index(max(e11))],"min":min(e11),"mintime":e11_time[e11.index(min(e11))],"enum":config,"ekey":i['e11'].split('#')[2]})
+        if e12 != []:
+            config = qxz_configs(conf,i['e12'],"e12")
+            data.append({"max":max(e12),"maxtime":e12_time[e12.index(max(e12))],"min":min(e12),"mintime":e12_time[e12.index(min(e12))],"enum":config,"ekey":i['e12'].split('#')[2]})
+        if e13 != []:
+            config = qxz_configs(conf,i['e13'],"e13")
+            data.append({"max":max(e13),"maxtime":e13_time[e13.index(max(e13))],"min":min(e13),"mintime":e13_time[e13.index(min(e13))],"enum":config,"ekey":i['e13'].split('#')[2]})
+        if e14 != []:
+            config = qxz_configs(conf,i['e14'],"e14")
+            data.append({"max":max(e14),"maxtime":e14_time[e14.index(max(e14))],"min":min(e14),"mintime":e14_time[e14.index(min(e14))],"enum":config,"ekey":i['e14'].split('#')[2]})
+        if e15 != []:
+            config = qxz_configs(conf,i['e15'],"e15")
+            data.append({"max":max(e15),"maxtime":e15_time[e15.index(max(e15))],"min":min(e15),"mintime":e15_time[e15.index(min(e15))],"enum":config,"ekey":i['e15'].split('#')[2]})
+        if e16 != []:
+            config = qxz_configs(conf,i['e16'],"e16")
+            data.append({"max":max(e16),"maxtime":e16_time[e16.index(max(e16))],"min":min(e16),"mintime":e16_time[e16.index(min(e16))],"enum":config,"ekey":i['e16'].split('#')[2]})
+        if e17 != []:
+            config = qxz_configs(conf,i['e17'],"e17")
+            data.append({"max":max(e17),"maxtime":e17_time[e17.index(max(e17))],"min":min(e17),"mintime":e17_time[e17.index(min(e17))],"enum":config,"ekey":i['e17'].split('#')[2]})
+        if e18 != []:
+            config = qxz_configs(conf,i['e18'],"e18")
+            data.append({"max":max(e18),"maxtime":e18_time[e18.index(max(e18))],"min":min(e18),"mintime":e18_time[e18.index(min(e18))],"enum":config,"ekey":i['e18'].split('#')[2]})
+        if e19 != []:
+            config = qxz_configs(conf,i['e19'],"e19")
+            data.append({"max":max(e19),"maxtime":e19_time[e19.index(max(e19))],"min":min(e19),"mintime":e19_time[e19.index(min(e19))],"enum":config,"ekey":i['e19'].split('#')[2]})
+        if e20 != []:
+            config = qxz_configs(conf,i['e20'],"e20")
+            data.append({"max":max(e20),"maxtime":e20_time[e20.index(max(e20))],"min":min(e20),"mintime":e20_time[e20.index(min(e20))],"enum":config,"ekey":i['e20'].split('#')[2]})
+        if e21 != []:
+            config = qxz_configs(conf,i['e21'],"e21")
+            data.append({"max":max(e21),"maxtime":e21_time[e21.index(max(e21))],"min":min(e21),"mintime":e21_time[e21.index(min(e21))],"enum":config,"ekey":i['e21'].split('#')[2]})
+        if e22 != []:
+            config = qxz_configs(conf,i['e22'],"e22")
+            data.append({"max":max(e22),"maxtime":e22_time[e22.index(max(e22))],"min":min(e22),"mintime":e22_time[e22.index(min(e22))],"enum":config,"ekey":i['e22'].split('#')[2]})
+        if e23 != []:
+            config = qxz_configs(conf,i['e23'],"e23")
+            data.append({"max":max(e23),"maxtime":e23_time[e23.index(max(e23))],"min":min(e23),"mintime":e23_time[e23.index(min(e23))],"enum":config,"ekey":i['e23'].split('#')[2]})
+        if e24 != []:
+            config = qxz_configs(conf,i['e24'],"e24")
+            data.append({"max":max(e24),"maxtime":e24_time[e24.index(max(e24))],"min":min(e24),"mintime":e24_time[e24.index(min(e24))],"enum":config,"ekey":i['e24'].split('#')[2]})
+        if e25 != []:
+            config = qxz_configs(conf,i['e25'],"e25")
+            data.append({"max":max(e25),"maxtime":e25_time[e25.index(max(e25))],"min":min(e25),"mintime":e25_time[e25.index(min(e25))],"enum":config,"ekey":i['e25'].split('#')[2]})
+        if e26 != []:
+            config = qxz_configs(conf,i['e26'],"e26")
+            data.append({"max":max(e26),"maxtime":e26_time[e26.index(max(e26))],"min":min(e26),"mintime":e26_time[e26.index(min(e26))],"enum":config,"ekey":i['e26'].split('#')[2]})
+        if e27 != []:
+            config = qxz_configs(conf,i['e27'],"e27")
+            data.append({"max":max(e27),"maxtime":e27_time[e27.index(max(e27))],"min":min(e27),"mintime":e27_time[e27.index(min(e27))],"enum":config,"ekey":i['e27'].split('#')[2]})
+        if e28 != []:
+            config = qxz_configs(conf,i['e28'],"e28")
+            data.append({"max":max(e28),"maxtime":e28_time[e28.index(max(e28))],"min":min(e28),"mintime":e28_time[e28.index(min(e28))],"enum":config,"ekey":i['e28'].split('#')[2]})
+        if e29 != []:
+            config = qxz_configs(conf,i['e29'],"e29")
+            data.append({"max":max(e29),"maxtime":e29_time[e29.index(max(e29))],"min":min(e29),"mintime":e29_time[e29.index(min(e29))],"enum":config,"ekey":i['e29'].split('#')[2]})
+        if e30 != []:
+            config = qxz_configs(conf,i['e30'],"e30")
+            data.append({"max":max(e30),"maxtime":e30_time[e30.index(max(e30))],"min":min(e30),"mintime":e30_time[e30.index(min(e30))],"enum":config,"ekey":i['e30'].split('#')[2]})
+    except Exception as e:
+
+        raise PortError(" ", "计算数据失败,稍后重试")
+    dat = {"data":data,"conf":conf}
+    return dat
+
+
+@kedong_deco(login_required=False)
+def device_status_data(request):
+    """
+    虫情测报灯/数据详情
+    设备实时状态接口
+        参数:
+        device_id               必传                            设备id
+        返回值:
+        "data": {
+        "upds": 1,              上仓门状态 1打开,0关闭
+        "tpl": 5,               低温保护阈值温度
+        "dver": "1.0.0",        设备固件版本
+        "gs": 0,                通道状态 1落虫,0排水
+        "hs": 0,                加热状态 1加热,0正常
+        "dnds": 0,              下仓门状态 1打开,0关闭
+        "is_online": 0,         在线状态
+        "csq": 29,              信号强度
+        "tph": 70,              高温保护阈值温度
+        "ts": 0                 定时模式 0光控,1时控
+        "tps": 1                温控状态 1 温控,0 正常
+        "lps": 0                光控状态 1 光控,0 正常
+        "hrt": 22               加热仓实时温度
+        "device_name":"这里是设备名称",
+        "address": "这里是设备位置",
+        "iccid": 1234444  SIM卡号
+    }
+    """
+    post_info = request.POST
+    _device_id = post_info.get("device_id")
+    if not _device_id:
+        raise PortError('device_id', "该设备不存在")
+    try:
+        device = MongoDevice.objects.get(device_id=_device_id)
+    except:
+        raise PortError('device_id','暂无此设备')
+    d_id = device.id
+    device_name = device.device_name
+    province = device.province
+    city = device.city
+    district = device.district
+    device_status = device.device_status  # 在线状态
+    myuser_type = request.user_type
+    device_datas = MongoCBDData.objects.filter(device_id=d_id).order_by('-id')
+    try:
+        device_data = json.loads(device_datas[0].device_data)
+    except json.JSONDecodeError as e:
+        device_data = eval(device_datas[0].device_data)
+    except:
+        raise PortError("device_id","暂无数据")
+    
+    ds = device_data.get("ds",1 )
+    ts = device_data.get("ts",1)
+    up_st = {
+        "is_online": device_status,
+        "ts":ts,
+        "hs":device_data["hs"],
+        "upds":device_data["upds"],
+        "dnds":device_data["dnds"],
+        "csq":device_data["csq"],
+        "dver":device_data["dver"],
+        "tph":device_data["tph"],
+        "tpl":device_data["tpl"],
+        "tps":device_data["tps"],
+        "lps":device_data["lps"],
+        "hrt":device_data["hrt"],
+        "iccid":device_data["iccid"],
+        "rps":device_data["rps"],
+        "ah":device_data["ah"],
+        "at":device_data["at"],
+        "ds":ds,
+        "device_name":device_name,
+        "address": province + city + district,
+    }
+    return up_st
+
+# config = {
+#         'host': config_dict['bigdata']['django_mysql_host'],
+#         'port': int(config_dict['bigdata']['django_mysql_port']),
+#         'user': config_dict['bigdata']['django_mysql_user'],
+#         'password': config_dict['bigdata']['django_mysql_password'],
+#         'db': config_dict['bigdata']['django_mysql_db'],
+#         'charset': 'utf8mb4',
+#         'cursorclass': pymysql.cursors.DictCursor,
+#     }

+ 1 - 1
smartfarming/models/camera.py

@@ -28,7 +28,7 @@ class MongoCameraPhoto(models.Model):
         db_table = "sa_device_camera_photo"
 
 
-# 监控萤石账号
+# 监控账号
 class MongoCameraAccount(models.Model):
     id = models.AutoField(primary_key=True)
     account = models.CharField(u'账号', max_length=30, default=0)

+ 13 - 2
smartfarming/urls.py

@@ -49,6 +49,7 @@ from smartfarming.views.home_land import (
 
 from smartfarming.views.device import (
     CbdScdXyDeviceSaveAPIView,
+    DeviceListInfoAPIView,
     DeviceListAPIView,
     DeviceChangeAPIView,
     DeviceListAPIView
@@ -78,11 +79,15 @@ from smartfarming.views.counts_views import (
     PlanNameAPIView, 
     PlanAreaAPIView, 
     DeviceCountAPIView,
-    RecentPestCountAPIView
+    RecentPestCountAPIView,
+    AlermNewsAPIView,
+    QxzCameraList,
+    QxzCameraUpdate
 )
 from smartfarming.views.weather import WeatherAPIView,QxzListAPIView,QxzShangAPIView
 
 
+
 urlpatterns = [
     path('login',LoginAPIView.as_view()), # 登录
     path('captcha',CaptchaView.as_view()), # 登录验证码
@@ -121,7 +126,8 @@ urlpatterns = [
     path("weekend_add", PlanWeekendAddAPIView.as_view()),  # 生成周期增加
     path("weekend_delete", PlanWeekendDelete.as_view()),  # 生成周期删除
     path("device_add", CbdScdXyDeviceSaveAPIView.as_view()),  # 增加设备及数据接口  【提供给大数据平台】
-    path("device", DeviceListAPIView.as_view()), # 设备列表
+    path("device_info", DeviceListInfoAPIView.as_view()), # 设备信息列表
+    path("device", DeviceListAPIView.as_view()), # 设备列表(用于一张图)
     path("device_update", DeviceChangeAPIView.as_view()), # 设备更新
     path("country", CountryModelAPIView.as_view()),  # 乡村列表
     path("country_add", CountryModelAddAPIView.as_view()),  # 乡村增加
@@ -138,6 +144,7 @@ urlpatterns = [
     path("shang_detail", QxzShangAPIView.as_view()), # 墒情详情
     path("pest_month", RecentPestCountAPIView.as_view()), # 最近一个月害虫统计
     path("land_deivce", DeviceListAPIView.as_view()),  # 设备绑定地块
+    path("alarm_news", AlermNewsAPIView.as_view()), # 滚动预警信息
 
 
     path("knowledge", KnowledgeCategoryAPIView.as_view()),  # 知识分类列表
@@ -155,6 +162,10 @@ urlpatterns = [
     path("information_add", InformationAddAPIView.as_view()), # 研判信息新增
     path("information_delete", InformationDeleteAPIView.as_view()), # 研判信息删除
 
+    path("qx_ca_lst", QxzCameraList.as_view()),  # 气象摄像列表
+    path("qx_ca_update", QxzCameraUpdate.as_view()),  # 气象摄像位置更新
+
+
     url(r'^pest_image_source_export$', PestImageSourceExport.as_view()), # 测报灯数据导出
     url(r'^pest_base_data_export$', PestBaseDataExport.as_view()), # 虫害基础数据导出
     url(r'^qxz_data_export$', QxzDataExport.as_view()), # 气象站数据导出

+ 112 - 160
smartfarming/utils.py

@@ -255,46 +255,58 @@ def get_weather_info(lng=None, lat=None):
     return data
 
 
+def expire_time(times):
+    data_time = datetime.datetime.now()
+    cultivate_time_expire = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(times))
+    time1 = datetime.datetime.strptime(cultivate_time_expire,"%Y-%m-%d %H:%M:%S")
+    num=(time1-data_time).days
+    print("设备到期天数---",num)
+    if int(num) <=7 and int(num) >= 0:
+        print("即将到期")
+        status = 2
+        
+    elif int(num) < 0:
+        print("已到期")
+        status = 1
+    else:
+        print("未到期")
+        status = 0
+        
+    return status
+
+
+def get_center_lnglat(lnglats_list):
+    x, y, z = 0, 0, 0
+    length = len(lnglats_list)
+    for n, a in lnglats_list:
+        g, t = math.radians(float(n)), math.radians(float(a))
+        x += math.cos(t) * math.cos(g)
+        y += math.cos(t) * math.sin(g)
+        z += math.sin(t)
+
+    x = float(x / length)
+    y = float(y / length)
+    z = float(z / length)
+
+    lng = round(math.degrees(math.atan2(y, x)), 4)
+    lat = round(math.degrees(math.atan2(z, math.sqrt(x*x + y*y))), 4)
+    return lng, lat
+
+
 def md5value(appSecret):
     """sign加密"""
-
     times = int(time.time())
-
     # 随机生成32位字符串
     nonce = ''.join(random.sample(string.ascii_letters + string.digits, 32))
-
     sign = "time:{},nonce:{},appSecret:{}".format(times, nonce, appSecret)
-    
     input_name = hashlib.md5()
     input_name.update(sign.encode("utf-8"))
     sign = (input_name.hexdigest()).lower()
-
     return times,nonce,sign
 
 
-
 def deviceAccessToken(appId, appSecret):
-    """ 
-    乐橙云账号秘钥
-    appSecret  
-    appId
-    
-    
-    使用乐橙云账号的appid和appSecret获取监控token
-    
-    请求时数据格式
-    {
-    "id":"98a7a257-c4e4-4db3-a2d3-d97a3836b87c",
-    "system":{
-        "ver":"1.0",
-        "appId":"lcdxxxxxxxxx",
-        "sign":"b7e5bbcc6cc07941725d9ad318883d8e",
-        "time":1599013514,
-        "nonce":"fbf19fc6-17a1-4f73-a967-75eadbc805a2"},
-    "params":{}
-    }
-    签名原始串为:"time:1531401328,nonce:61f38836685b66f3201469543d8365f7,appSecret:12459ac547434b3ea83db5e6d56789"
-    """
+    # 乐橙云账号秘钥
     # 先从redis 中获取token
     tokens = redis_pool.get(appId)
     if tokens and tokens !=None:
@@ -311,23 +323,14 @@ def deviceAccessToken(appId, appSecret):
         return redis_jk_data
     else:
         status = 0
-    
     if not status:  
         url  = config.get("camera").get("lc_token")
         # 加密
         times,nonce,sign = md5value(appSecret)
         data = {
-            "system":{
-                "ver":"1.0",
-                "appId":appId,
-                "sign":sign,
-                "time":times,
-                "nonce":nonce
-            },
+            "system":{"ver":"1.0","appId":appId,"sign":sign,"time":times,"nonce":nonce},
             "id":nonce,
-            "params":{
-
-            }
+            "params":{}
         }
         token_data = requests.post(url,json=data, timeout=5)
         if token_data.status_code == 200:
@@ -342,170 +345,119 @@ def deviceAccessToken(appId, appSecret):
         else:
             token_json_data = {"status":0}
             expireTime = 5
-        
-        redis_pool.set(appId,token_json_data,expireTime)
+        redis_pool.set(appId,str(token_json_data),expireTime)
         return token_json_data
-    
 
 
 def device_config(appId,appSecret):
-    """ 
-    配置项
-    """
+    # 配置项
     time,nonce,sign = md5value(appSecret)
-    
     token_data = deviceAccessToken(appId, appSecret)
-    
     if token_data.get("status","0"):
         token = token_data["result"]["data"]["accessToken"]
     else:
         token = ""
-
     return time,nonce,sign,token
 
+
 def controlMove(appId,appSecret,deviceId,operation,channelId="0"):
-    """ 
-    云台控制接口
-    
-    
-    请求样例:
-    operation   0-上,1-下,2-左,3-右8-放大9-缩小10-停止
-    
-    {
-    "id":"d5c287b4-5b2f-4f03-baf5-8032c5c354af",
-    "system":{
-        "ver":"1.0",
-        "appId":"lcdxxxxxxxxx",
-        "sign":"74bc756ebd53e9eef2836f8cf1730c10",
-        "time":1599031074,
-        "nonce":"8ec8a7bd1d1c95420de20d92422d457d"
-    },
-    "params":{
-        "token":"At_00006acr3456d12312d3grf60147de7ec",
-        "deviceId":"MEGREZ0000001842",
-        "channelId":"0",
-        "operation":"1",
-        "duration":"1000"  # 移动持续时间,单位毫秒
-    }
-}
-    
-    """
+    # 云台控制接口
     url = config.get("camera").get("lc_controler")
     time,nonce,sign,token = device_config(appId, appSecret)
     if not token:
         return {"msg":"控制失败"}
     data = {
-        "system":{
-            "ver":"1.0",
-            "appId":appId,
-            "sign":sign,
-            "time":time,
-            "nonce":nonce
-        },
+        "system":{"ver":"1.0","appId":appId,"sign":sign,"time":time,"nonce":nonce},
         "id":nonce,
-        "params":{
-            
-            "token":token,
-            "deviceId":deviceId,
-            "channelId":channelId,
-            "operation":operation,
-            "duration":"1000"
-        }
+        "params":{"token":token,"deviceId":deviceId,"channelId":channelId,"operation":operation,"duration":"1000"}
     }
     control_Move = requests.post(url,json=data)
     return control_Move.json()
 
-def expire_time(times):
-    data_time = datetime.datetime.now()
-    cultivate_time_expire = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(times))
-    time1 = datetime.datetime.strptime(cultivate_time_expire,"%Y-%m-%d %H:%M:%S")
-    num=(time1-data_time).days
-    print("设备到期天数---",num)
-    if int(num) <=7 and int(num) >= 0:
-        print("即将到期")
-        status = 2
-        
-    elif int(num) < 0:
-        print("已到期")
-        status = 1
-    else:
-        print("未到期")
-        status = 0
-        
-    return status
-
-
-def get_center_lnglat(lnglats_list):
-    x, y, z = 0, 0, 0
-    length = len(lnglats_list)
-    for n, a in lnglats_list:
-        g, t = math.radians(float(n)), math.radians(float(a))
-        x += math.cos(t) * math.cos(g)
-        y += math.cos(t) * math.sin(g)
-        z += math.sin(t)
-
-    x = float(x / length)
-    y = float(y / length)
-    z = float(z / length)
-
-    lng = round(math.degrees(math.atan2(y, x)), 4)
-    lat = round(math.degrees(math.atan2(z, math.sqrt(x*x + y*y))), 4)
-    return lng, lat
-
-
 
 def bindDeviceLive(appId,appSecret,deviceId,channelId="0"):
-    """ 
-    获取直播地址
-    """
+    # 获取直播地址
     url = config.get("camera").get("lc_addr")
     time,nonce,sign,token = device_config(appId, appSecret)
     data = {
-        "system":{
-            "ver":"1.0",
-            "appId":appId,
-            "sign":sign,
-            "time":time,
-            "nonce":nonce
-        },
-        "id":nonce,
-        "params":{
-            "streamId":1,
-            "deviceId":deviceId,
-            "channelId":channelId,
-            "token":token
-        }
+        "system":{"ver":"1.0","appId":appId,"sign":sign,"time":time,"nonce":nonce},
+        "params":{"streamId":1,"deviceId":deviceId,"channelId":channelId,"token":token},
+        "id":nonce
     }
     device_live_data = requests.post(url,json=data)
     return device_live_data.json()
 
 
 def getLive(appId,appSecret,deviceId,channelId="0"):
-    """ 
-    查询监控地址 用于设备直播地址创建后再次查询使用
-    """
+    # 查询监控地址 用于设备直播地址创建后再次查询使用
     url = config.get("camera").get("lc_stream")
     time,nonce,sign,token = device_config(appId, appSecret)
     data = {
-    "system":{
-        "ver":"1.0",
-        "appId":appId,
-        "sign":sign,
-        "time":time,
-        "nonce":nonce
-    },
-    "id":nonce,
-    "params":{
-        "deviceId":deviceId,
-        "channelId":channelId,
-        "token":token
-        }
+        "system":{"ver":"1.0","appId":appId,"sign":sign,"time":time,"nonce":nonce},
+        "params":{"deviceId":deviceId, "channelId":channelId,"token":token},
+        "id":nonce
     }
-    
     live_data = requests.post(url,json=data)
     return live_data.json()
 
 
+def modify_live_time(appId,appSecret,liveToken,start_time,end_time,period="everyday"):
+    # 开启,修改直播计划时间
+    # period 直播周期,always:永久,once:指定某天, everyday:每天
+    url = config.get("camera").get("lc_modify_live_plan")
+    time,nonce,sign,token = device_config(appId, appSecret)
+    if not token:
+        return {'result': {'msg': '获取token失败。', 'code': '1'}, 'id': 'rWfBFgohj7VwkxsqbM5p4JKDOtQNU2XA'}
+    data = {
+        "system":{"ver":"1.0","appId":appId,"sign":sign,"time":time,"nonce":nonce},
+        "id":nonce,
+        "params":{"token":token,"period":period,"liveToken":liveToken,"beginTime":start_time,"endTime": end_time}
+    }
+    if period == "always":
+        del data["params"]["beginTime"]
+        del data["params"]["endTime"]
+    device_live_data = requests.post(url,json=data).json()
+    return device_live_data
+
+
+def off_on_live(appId,appSecret,liveToken,status):
+    # 关闭、开启当前直播
+    url = config.get("camera").get("lc_modify_live_plan_status")
+    time,nonce,sign,token = device_config(appId, appSecret)
+    if not token:
+        return {'result': {'msg': '获取token失败。', 'code': '1'}, 'id': 'rWfBFgohj7VwkxsqbM5p4JKDOtQNU2XA'}
+    data = {
+        "system":{"ver":"1.0","appId":appId,"sign":sign,"time":time,"nonce":nonce},
+        "params":{"token":token,"liveToken":liveToken,"status":status},
+        "id":nonce
+    }
+    device_live_data = requests.post(url,json=data).json()
+    return device_live_data
+
+
+def setDeviceSnap(appId,appSecret,deviceId,channelId="0"):
+    # 抓图接口
+    url = config.get("camera").get("lc_device_snap_enhanced")
+    time,nonce,sign,token = device_config(appId, appSecret)
+    if not token:
+        return {"msg": "抓图失败"}
+    data = {
+        "system":{"ver":"1.0", "appId":appId,"sign":sign,"time":time,"nonce":nonce},
+        "params":{"deviceId":deviceId,"channelId":channelId,"token":token},
+        "id":nonce
+    }
+    img_data = requests.post(url,json=data)
+    result = img_data.json()
+    if result.get("result").get("code") == "0":
+        return result.get("result").get("data").get("url")
+
+
+def get_weather(ip):
+    # 获取天气
+    res = requests.get("https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=69334222&appsecret=2u4bHXHD&ext=")
+    response = json.loads(res.text)
+    return response.get("data")
+
 if __name__ == "__main__":
     t = get_recent_month(1)
     print(t)

+ 80 - 1
smartfarming/views/counts_views.py

@@ -10,9 +10,12 @@ from smartfarming.models.ascend import MongoBase, MongoLandInfo, MongoPlantInfo,
 from smartfarming.models.user import DeviceUser
 from smartfarming.models.device import MongoDevice
 from smartfarming.models.worm_forecast import MongoCBDphoto
+from smartfarming.models.pest_count import MongoCBDPestWarning
+from smartfarming.models.weather import MongoQXZ_Alarm_Log_New
 from smartfarming.serializers.ascend_serializers import LandPlanInfoSerializers
-from smartfarming.utils import get_recent_month
+from smartfarming.utils import get_recent_month, get_weather
 from smartfarming.api.views.forecast.all_dict import insect_dict
+from smartfarming.models.device import MongoDevice
 
 
 class LandPlanInfoAPIView(APIView):
@@ -179,3 +182,79 @@ class RecentPestCountAPIView(APIView):
             return Response({"code": 0, "msg": "success", "data": result})
         except Exception as e:
             return Response({"code": 2, "msg": "数据有误,请核查"})
+
+
+# 网站顶部滚动预警信息
+class AlermNewsAPIView(APIView):
+
+    def post(self, request):
+        try:
+            myuser = request.myuser
+            try:
+                ip = request.META['HTTP_X_FORWARDED_FOR']
+            except Exception as e:
+                ip = request.META['REMOTE_ADDR']
+            # 获取天气预警
+            weather_data = get_weather(ip)
+            weather = []
+            for i in weather_data:
+                alarm = i.get("alarm")
+                if alarm:
+                    for k in alarm:
+                        weather.append(k.get("alarm_content"))
+            # 获取虫睛预警
+            user_id = str(myuser.id)
+            pest_query = MongoCBDPestWarning.objects.all().order_by("-id")[:3]
+            pest = []
+            for p in pest_query:
+                content = p.warning_content
+                pest.append(content.replace("【云飞科技】尊敬的用户:", "").replace(",(详情请登陆http://hnyfwlw.com查看)", "").replace(",请注意防范(详情请登陆http://hnyfwlw.com查看)", ""))
+            # 气象预警
+            qx_query = MongoQXZ_Alarm_Log_New.objects.filter(user_id=user_id).order_by('-id')[:3]
+            qx = []
+            for q in qx_query:
+                qx.append(q.warning_content)
+            data = []
+            if weather:
+                for i in weather:
+                    data.append(i)
+            if pest:
+                for i in pest:
+                    data.append(i)
+            if qx:
+                for i in qx:
+                    data.append(i)
+            return Response({"code": 0,"msg":"success", "data": data})
+        except Exception as e:
+            print(e)
+            return Response({"code": 2, "msg": "获取数据失败"})
+        
+
+class QxzCameraList(APIView):
+    permission_classes = []
+    authentication_classes = []
+    def post(self, request):
+        # 气象与监控绑定列表
+        qxz_ids = MongoDevice.objects.filter(device_type_id__in = [5, 8]).values("device_id")
+        cam_ids = MongoDevice.objects.filter(device_type_id = 6).values_list("device_id", flat=True)
+        return Response({"code": 0,"msg":"success", "data": {"qxz_ids": qxz_ids, "cam_ids": cam_ids}})
+    
+
+class QxzCameraUpdate(APIView):
+    permission_classes = []
+    authentication_classes = []
+    def post(self, request):
+        # 气象与监控更新
+        request_data = request.data 
+        try:
+            qx_id = request_data.get("qx_id")
+            ca_id = request_data.get("ca_id")
+            qx_lng_lat = MongoDevice.objects.filter(device_id=qx_id).values_list("lng", "lat")
+            ca_obj = MongoDevice.objects.get(device_id=ca_id)
+            if qx_lng_lat:
+                ca_obj.lng = float(qx_lng_lat[0][0]) + 0.00004
+                ca_obj.lat = float(qx_lng_lat[0][1]) + 0.00004
+                ca_obj.save()
+            return Response({"code": 0,"msg":"success"})
+        except Exception as e:
+            return Response({"code": 2,"msg":"失败"})

+ 25 - 0
smartfarming/views/device.py

@@ -202,6 +202,31 @@ class DeviceChangeAPIView(APIView):
                 device.district = district
         device.save()
         return Response({"code": 0, "msg": "success"})
+    
+
+class DeviceListInfoAPIView(APIView):
+
+    def post(self, request):
+        # 设备列表
+        request_data = request.data
+        device_id = request_data.get("device_id")
+        device_status = request_data.get("device_status")
+        search = request_data.get("search")
+        page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
+        page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
+        if device_id:
+            queryset = MongoDevice.objects.filter(device_id=device_id).order_by("-uptime")
+        elif device_status:
+            queryset = MongoDevice.objects.filter(device_status=device_status).order_by("-uptime")
+        elif search:
+            queryset = MongoDevice.objects.filter(Q(device_name__icontains=search) | Q(device_id__icontains=search))
+        else:
+            queryset = MongoDevice.objects.all().order_by("-uptime")
+        total_obj = queryset.count()
+        paginator = Paginator(queryset, page_size)
+        page_obj = paginator.get_page(page_num)
+        serializers = DeviceSerializers(page_obj, many=True)
+        return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})     
 
 
 class DeviceListAPIView(APIView):

+ 2 - 4
smartfarming/views/weather.py

@@ -4,6 +4,7 @@ from rest_framework.views import APIView
 from rest_framework.response import Response
 from smartfarming.models.device import MongoDevice
 from smartfarming.models.weather import QXZdata_New, MongoQXZ_Conf
+from smartfarming.utils import get_weather
 
 from smartfarming.utils import get_center_lnglat
 
@@ -16,11 +17,8 @@ class WeatherAPIView(APIView):
             ip = request.META['HTTP_X_FORWARDED_FOR']
         except Exception as e:
             ip = request.META['REMOTE_ADDR']
-        print(ip)
         # ip 转化为 省市县
-        res = requests.get("https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=69334222&appsecret=2u4bHXHD&ext=")
-        response = json.loads(res.text)
-        data = response.get("data")
+        data = get_weather(ip)
         content = []
         for i in data:
             content.append(

+ 4 - 0
test

@@ -75,7 +75,11 @@
       "lc_addr": "https://openapi.lechange.cn/openapi/bindDeviceLive",
       "lc_stream": "https://openapi.lechange.cn/openapi/getLiveStreamInfo",
       "lc_token": "https://openapi.lechange.cn/openapi/accessToken",
+      "lc_device_snap": "https://openapi.lechange.cn/openapi/setDeviceSnap",
+      "lc_device_snap_enhanced": "https://openapi.lechange.cn/openapi/setDeviceSnapEnhanced",
       "lc_controler": "https://openapi.lechange.cn/openapi/controlMovePTZ",
+      "lc_modify_live_plan": "https://openapi.lechange.cn/openapi/modifyLivePlan",
+      "lc_modify_live_plan_status": "https://openapi.lechange.cn/modifyLivePlanStatus",  
       "ys_open": "https://open.ys7.com/api/lapp/live/video/open",
       "ys_get": "https://open.ys7.com/api/lapp/live/address/get"
     }