yf_yzl 2 лет назад
Родитель
Сommit
e12264d6c8

+ 40 - 17
scripts/test/cbd_device_config.py

@@ -21,10 +21,6 @@ my_client = pymongo.MongoClient(host="8.136.98.49", port=27017, username="root",
 my_col = my_client['smartfarming']['sa_device']
 
 scd_device = {
-"866547058627400",
-"866547058637276",
-"866547058633663",
-"866547058613921",
 "865328061465380",
 "865328061478136",
 "865328061471529",
@@ -41,6 +37,30 @@ scd_device = {
 "869298052295540",
 "865328061465679",
 "865328061450044",
+"866547058627400",
+"866547058637276",
+"866547058633663",
+"866547058613921",
+"861551055315402",
+"861551056086671",
+"861551056088693",
+"861551056088479",
+"861551056088719",
+"861551055313365",
+"861551056086614",
+"861551056093800",
+"861551056095367",
+"861551056102502",
+"861551056096621",
+"861551056101785",
+"861551056086549",
+"861551055354120",
+"861551055353536",
+"861551056092018",
+"861551055319586",
+"861551056088875",
+"861551055324651",
+"861551055313423",
 "866250061217240",
 "863569067039065",
 }
@@ -63,19 +83,22 @@ def dsj_qxz_conf_info():
         device_id = device_info['id']
         data = {'d_id': device_id}
         cursor = collection1.find(data,{'_id':0,'id':0})
-        device_id = MongoDevice.objects.get(device_id=i).id 
-        for i in cursor:
-            MongoDeviceConfig.objects.get_or_create(
-                d_id=device_id,
-                defaults={
-                    "d_id": device_id,
-                    "device_config": i['device_config'],
-                    "cmd": i['cmd'],
-                    "addtime": int(time.time()),
-                    "uptime": int(time.time())
-                }
-            )
-            print(f"设备: {i} {device_id} 数据量  {cursor.count()}")
+        try:
+            device_id = MongoDevice.objects.get(device_id=i).id 
+            for i in cursor:
+                MongoDeviceConfig.objects.get_or_create(
+                    d_id=device_id,
+                    defaults={
+                        "d_id": device_id,
+                        "device_config": i['device_config'],
+                        "cmd": i['cmd'],
+                        "addtime": int(time.time()),
+                        "uptime": int(time.time())
+                    }
+                )
+                print(f"设备: {i} {device_id} 数据量  {cursor.count()}")
+        except Exception as e:
+            print(i)
     return True
 
 

+ 61 - 0
scripts/test/qx_alarm.py

@@ -0,0 +1,61 @@
+import os
+import sys
+import time
+import django
+local_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+print(local_path)
+if local_path not in sys.path:
+    sys.path.append(local_path)
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "kedong.settings")
+django.setup()
+from django.conf import settings
+from smartfarming.models.device import MongoDevice
+from smartfarming.models.weather import QXZdata_New, MongoQXZ_Alarm
+import json
+import requests
+import pymongo
+from urllib import parse
+
+
+my_client = pymongo.MongoClient(host="8.136.98.49", port=27017, username="root", password="yfkj@6020")
+my_col = my_client['smartfarming']['sa_device']
+
+qx_device = {
+"861551055315402",
+"861551056086671",
+"861551056088693",
+"861551056088479",
+"861551056088719",
+"861551055313365",
+"861551056086614",
+"861551056093800"
+}
+
+
+def dsj_qxz_conf_info():
+    user = parse.quote_plus("root")
+    passwd = parse.quote_plus("yfkj@6020")
+    # 账号密码方式连接MongoDB | "mongodb://用户名:密码@公网ip:端口/"
+    myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(user,passwd))
+    # myclient = pymongo.MongoClient("mongodb://127.0.0.1:12514/")
+    # 指定数据库
+    db = myclient.smartfarming
+    # 指定集合
+    collection1 = db.sa_qxz_alarm
+
+    for k in qx_device:
+        data = {'device_id': "862289057453835"}
+        cursor = collection1.find(data,{'_id':0,'id':0})
+        for i in cursor[:1]:
+            MongoQXZ_Alarm.objects.create(
+                    device_id =  k,
+                    conf =  i.get("conf"), 
+                    phone =  i.get("phone"), 
+                    upl_time =  i.get("upl_time")                
+            )
+        print(f"设备: {k} 数据量  {cursor.count()}")
+    return True
+
+
+if __name__ == "__main__":
+    dsj_qxz_conf_info()

+ 71 - 0
scripts/test/qx_base_info.py

@@ -0,0 +1,71 @@
+import os
+import sys
+import time
+import django
+local_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+print(local_path)
+if local_path not in sys.path:
+    sys.path.append(local_path)
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "kedong.settings")
+django.setup()
+from django.conf import settings
+from smartfarming.models.device import MongoDevice
+from smartfarming.models.weather import QXZdata_New, MongoQXZ_Base_Info
+import json
+import requests
+import pymongo
+from urllib import parse
+
+
+my_client = pymongo.MongoClient(host="8.136.98.49", port=27017, username="root", password="yfkj@6020")
+my_col = my_client['smartfarming']['sa_device']
+
+qx_device = {
+"861551055315402",
+"861551056086671",
+"861551056088693",
+"861551056088479",
+"861551056088719",
+"861551055313365",
+"861551056086614",
+"861551056093800"
+}
+
+
+def dsj_qxz_conf_info():
+    user = parse.quote_plus("root")
+    passwd = parse.quote_plus("yfkj@6020")
+    # 账号密码方式连接MongoDB | "mongodb://用户名:密码@公网ip:端口/"
+    myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(user,passwd))
+    # myclient = pymongo.MongoClient("mongodb://127.0.0.1:12514/")
+    # 指定数据库
+    db = myclient.smartfarming
+    # 指定集合
+    collection = db.sa_device
+    collection1 = db.sa_qxz_base_info
+
+    for k in qx_device:
+        data = {'device_id': k}
+        cursor = collection1.find(data,{'_id':0,'id':0})
+
+        for i in cursor:
+            qx_data, is_created = MongoQXZ_Base_Info.objects.get_or_create(
+                device_id = i.get("device_id"),
+                defaults={
+                    "volt": i.get("volt"),
+                    "rssi": i.get("rssi"),
+                    "iccid": i.get("iccid"),
+                    "lng": i.get("lng"),
+                    "lat": i.get("lat"),
+                    "led": i.get("led"),
+                    "ledinfo": i.get("ledinfo"),
+                    "dver": i.get("dver"),
+                    "uptime": i.get("uptime")                    
+                }
+            )
+        print(f"设备: {k} 数据量  {cursor.count()} {qx_data, is_created} ")
+    return True
+
+
+if __name__ == "__main__":
+    dsj_qxz_conf_info()

+ 202 - 1
smartfarming/api/views/camera/camera_manage.py

@@ -1,9 +1,11 @@
 import re
 import requests
 import time
+import ast
 from django.conf import settings
 from django.db.models import Count
 from django.core.paginator import Paginator
+from django.db import transaction
 
 from smartfarming.api.views.forecast.all_dict import insect_dict, attract_discern
 from smartfarming.models.sim_card import MongoMsg_Conf
@@ -11,6 +13,7 @@ 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 kedong.decoration import kedong_deco, PortError
 config_dict = settings.CONFIG
@@ -60,7 +63,7 @@ def list_camera(request):
 
     # total_num, data_list = MongoDevice.get_device_list(myuser, match=search_dict, page_num=page, page_size=page_size)
 
-    queryset = MongoDevice.objects.filter(device_type_id=6)
+    queryset = MongoDevice.objects.filter(device_type_id=6).order_by("-uptime")
     total_num = queryset.count()
     paginator = Paginator(queryset, page_size)
     page_obj = paginator.get_page(page)
@@ -217,4 +220,202 @@ def ctrl_camera(request):
             ctrl_url = 'https://open.ys7.com/api/lapp/device/ptz/stop'
             data = {'accessToken':accessToken, 'deviceSerial':device_id, 'channelNo':channelNo}
             res2 = requests.post(ctrl_url,data=data)
+    return True
+
+
+@kedong_deco(login_required=False)
+def see_camera_account(request):
+    """
+    查看当前绑定的萤石云账号信息\按业务员名字搜索\萤石云账号搜索
+    
+    参数:
+    account          非必传(str)          按萤石云账号名字搜索
+    salesman         非必传(str)          按业务员名字搜索
+    
+    说明:两个参数都不传为所有数据,不进行筛选操作
+
+    返回值:
+        {
+        "errorCode": 0,
+        "message": "",
+        "formError": {},
+        "data": [
+            {
+                "id": 1,                        萤石云账号id
+                "account": "hnyf"               萤石云名称
+            }
+        ],
+        "params": {}
+    }
+    """
+    account = request.POST.get("account")
+    salesman = request.POST.get("salesman")
+    camera_query = MongoCameraAccount.objects.all().order_by("-id")
+    if account:
+        camera_query = camera_query.filter(account__icontains=account)
+    if salesman:
+        camera_query = camera_query.filter(salesman__icontains=salesman)
+    data = [{'id':i.id,'account':i.account} for i in camera_query]
+    return data
+
+
+
+@kedong_deco(login_required=True)
+def add_camera_account(request):
+    """
+    添加萤石云账号
+    管理员可操作
+
+    参数:
+    account                     必传(str)               萤石云账号
+    salesman                    必传(str)               萤石云账号所相关的业务员名称
+    app_token                   必传(str)               萤石云账号 token 
+    app_key                     必传(str)               萤石云账号 appkey
+    app_secret                  必传(str)               萤石云账号 appsecret
+    
+    2022-08-19 08:54 csx 
+    增加监控账户区分,在不影响原来的功能上进行修改,增加大华乐橙云账号添加
+    account_type                非必传(number)          监控设备类型 0代表海康   1代表大华,默认是0
+    
+    
+    """
+    account = request.POST.get("account")
+    salesman = request.POST.get("salesman")
+    token = request.POST.get("app_token")
+    app_key = request.POST.get("app_key")
+    app_secret = request.POST.get("app_secret")
+    account_type = request.POST.get("account_type","0")
+    
+    
+    if account_type not in ("0","1"):
+        raise PortError("","无法识别此监控账号类型")
+
+    if not all([account,salesman,token,app_key,app_secret]):
+        raise PortError("","请把参数填写完整")
+
+    now_time = int(time.time())
+    camera_query = MongoCameraAccount.objects.filter(app_key=app_key,account_type=account_type).first()
+    if camera_query:
+        raise PortError("","此appkey已存在,请勿重复添加")
+    
+    try:
+        MongoCameraAccount.objects.create(account=account,salesman=salesman,token=token,addtime=now_time,uptime=now_time,
+                                    app_key=app_key,app_secret=app_secret,account_type=account_type)
+    except:
+        raise PortError("","添加萤石账号失败")
+    
+    return True
+
+
+
+@transaction.atomic
+@kedong_deco(login_required=True)
+def add_camera(request):
+    """
+    添加监控设备接口:
+    参数:
+    device_id          必传  (string)                  监控设备的序列号
+    camera_channel     必传  (string)                  监控通道号
+    camera_playback    必传  (string)                  是否支持回放功能,0不支持 1支持
+
+    新加参数
+    account_id         必传  (string)                  萤石云账号id
+    
+    
+    2022-08-19 08:54 csx 
+    增加监控账户区分,在不影响原来的功能上进行修改,增加大华乐橙云监控绑定
+
+    返回值:
+    {
+    "data": null,
+    "errorCode": 0,
+    "message": ,
+    "formError": {}
+    }
+
+    """
+    device_id = request.POST.get('device_id')
+    camera_channel = request.POST.get("camera_channel","0")
+    camera_playback = request.POST.get("camera_playback","0")
+    account_id = request.POST.get("account_id",1)
+    
+    if not account_id.isdigit():
+        raise PortError("account_id","无效参数")
+    
+    if not device_id:
+        raise PortError("device_id","未传设备号")
+    
+    if not camera_channel.isdigit():
+        raise PortError("camera_channel","无效参数")
+    
+    
+    if camera_playback not in ("0","1"):
+        raise PortError("camera_playback","参数超出范围")
+    
+    now_time = int(time.time())
+    camera_query = MongoCameraAccount.objects.filter(id=int(account_id)).first()
+    if not camera_query:
+        raise PortError("","未找到此账号")
+    
+    
+    device_ids = device_id + "-" + camera_channel
+    # if MongoCameraData.objects.filter(device_id=device_id).exists() or MongoDevice.objects.filter(device_id=device_id).exists():
+    #     raise PortError("","设备已存在,请勿重复添加")
+    
+    # 使用的是大华乐橙云账号监控接入,监控通道号大华的从0开始
+    if camera_query.account_type == 1:
+        appId = camera_query.app_key
+        appSecret = camera_query.app_secret
+
+        device_live_data = bindDeviceLive(appId, appSecret, device_id,camera_channel)
+        code = device_live_data["result"]["code"]
+        
+        if code == "0":
+            live_path = device_live_data["result"]["data"]["streams"][0]["hls"]
+        
+        elif code == "LV1001":
+            # 如直播地址已存在,则需要查询直播地址列表
+            live_data = getLive(appId, appSecret, device_id, camera_channel)
+            
+            if live_data["result"]["code"] == "0":
+                try:
+                    live_path = live_data["result"]["data"]["streams"][0]["hls"]
+                except:
+                    raise PortError("","获取直播地址失败")
+            else:
+                raise PortError("",live_data)
+        else:
+            msg = device_live_data["result"]["msg"]
+            raise PortError("", msg)        
+        device_info = {
+                "hls": live_path,
+                "hlsHd": live_path,
+                "rtmp": live_path,
+                "rtmpHd": live_path
+                }
+    else:
+        accessToken = camera_query.token
+        url = config_dict.get("camera").get("ys_open")
+        data = {"accessToken":accessToken,"source":"%s:%s"%(device_id,str(camera_channel))}
+        res = requests.post(url,data=data)
+        if ast.literal_eval(res.text)["code"] == "200":
+            url_1 = config_dict.get("camera").get("ys_get")
+            res_1 = requests.post(url_1,data=data)
+            try:
+                addr = ast.literal_eval(res_1.text)["data"][0]
+                device_info = {
+                    "hls": addr["hls"],
+                    "hlsHd": addr["hlsHd"],
+                    "rtmp": addr["rtmp"],
+                    "rtmpHd": addr["rtmpHd"]
+                    }
+            except Exception as e:
+                raise PortError("device_id", "解析结果异常")
+        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

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

@@ -2,7 +2,7 @@
 # @Time    : 2020/5/22 2:22 下午
 # @Author  : Creat by Han
 import json
-
+import ast
 import copy
 import datetime
 import time
@@ -13,7 +13,7 @@ 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.weather import MongoQXZ_Base_Info, QXZdata_New, MongoQXZ_Conf, QXZstatus_New
+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
 
 config_dict = settings.CONFIG
@@ -407,3 +407,61 @@ def qxz_data_chart(request):
 
     data1 = {"data":data,"conf":conf}
     return data1
+
+
+@kedong_deco(login_required=True)
+def qxz_early_warning(request):
+    """
+    气象站查看短信预警信息接口\配置预警信息接口
+    参数:
+    device_id          必传(str)                设备号
+    status             必传(str)                当status等于see查看, 当status等于save保存
+    alarm              非必传(json)             配置信息,例如:{"dat":{"e1":"1#12","e2":"0#","e3":"0#","e4":"0#","e5":"0#","e6":"0#","e7":"0#","e8":"0#","e9":"0#"},"tel":"18258845915","equip_id":"865553058440811"}
+    
+    返回值:
+    {
+        "data" 0  0 保存成功 1失败
+    }
+    """
+    status = request.POST.get("status")
+    device_id = request.POST.get("device_id")
+
+    if status == "see":
+        try:
+            qxz_alarm = MongoQXZ_Alarm.objects.get(device_id=device_id)
+            alarm = ast.literal_eval(qxz_alarm.conf)
+            phone = qxz_alarm.phone 
+        except Exception as e:
+            print(e)
+            alarm = ""
+            phone = ""
+        x = MongoQXZ_Conf.objects.get(device_id=device_id)
+        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}
+        for k in list(conf.keys()): 
+            if not conf[k]:
+                del conf[k]
+        data = {"conf":conf,"alarm":alarm,"phone":phone}
+
+    elif status == "save":
+        alarm = ast.literal_eval(request.POST.get('alarm'))
+        conf = alarm["dat"]
+        try:
+            MongoQXZ_Alarm.objects.update_or_create(
+                device_id=device_id,
+                defaults={
+                    "conf": {"dat": conf},
+                    "upl_time": int(time.time())
+                }
+            )
+            return {"code":0}
+        except Exception as e:
+            raise PortError("","更新失败") 
+    else:
+        raise PortError("","参数超出范围")
+    return data

+ 11 - 0
smartfarming/models/weather.py

@@ -112,6 +112,17 @@ class MongoQXZ_Conf(models.Model):
     class Meta:
         db_table = "sa_qxz_conf"
 
+
+# 气象站短信预警
+class MongoQXZ_Alarm(models.Model):
+    id = models.AutoField(primary_key=True)
+    device_id = models.CharField(max_length=50, default='') # 设备id
+    conf = models.TextField(u'短信配置', blank=True, null=True)
+    phone = models.CharField(u'手机号',max_length=20, blank=True)
+    upl_time = models.IntegerField(u'上报时间',default=0)
+
+    class Meta:
+        db_table = "sa_qxz_alarm"
         
         
 # 气象站短信预警

+ 18 - 4
smartfarming/urls.py

@@ -43,9 +43,7 @@ from smartfarming.views.home_land import (
     CountryModelAPIView,
     CountryModelAddAPIView,
     CountryModelUpdateAPIView,
-    CountryModelDeleteAPIView,
-    LandPlanInfoAPIView,
-    PlanNameAPIView
+    CountryModelDeleteAPIView
 )
 
 from smartfarming.views.device import (
@@ -72,7 +70,14 @@ from smartfarming.views.knowledge import (
 
 
 from smartfarming.views.pests_bank import PestBankAPIView
-from smartfarming.views.pest_image import PestImageSourceExport
+from smartfarming.views.pest_image import PestImageSourceExport, PestBaseDataExport, QxzDataExport
+from smartfarming.views.counts_views import (
+    LandPlanInfoAPIView, 
+    PlanNameAPIView, 
+    PlanAreaAPIView, 
+    DeviceCountAPIView
+)
+from smartfarming.views.weather import WeatherAPIView,QxzListAPIView,QxzShangAPIView
 
 
 urlpatterns = [
@@ -119,8 +124,15 @@ urlpatterns = [
     path("country_update", CountryModelUpdateAPIView.as_view()),  # 乡村编辑
     path("country_delete", CountryModelDeleteAPIView.as_view()),  # 乡村删除
     path("pest", PestBankAPIView.as_view()),  # 虫害列表
+
     path("plan_info", LandPlanInfoAPIView.as_view()), # 种植作物列表及统计
     path("plan_name", PlanNameAPIView.as_view()), # 作物名称数组
+    path("land_area_plan_count", PlanAreaAPIView.as_view()),  # 种植面积与作物个数统计
+    path("device_status", DeviceCountAPIView.as_view()), # 统计设备在线或离线统计
+    path("weather", WeatherAPIView.as_view()), # 天气接口
+    path("shang", QxzListAPIView.as_view()), # 墒情列表接口
+    path("shang_detail", QxzShangAPIView.as_view()), # 墒情详情
+
 
     path("knowledge", KnowledgeCategoryAPIView.as_view()),  # 知识分类列表
     path("knowledge_update", KnowledgeCategoryUpdateAPIView.as_view()),  # 知识分类编辑
@@ -138,4 +150,6 @@ urlpatterns = [
     path("information_delete", InformationDeleteAPIView.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()), # 气象站数据导出
 ]

+ 57 - 7
smartfarming/utils.py

@@ -18,6 +18,7 @@ from kedong import settings
 
 logger = logging.getLogger("other")
 redis_pool = RedisPool().get_redis_pool(settings.redis_db["jiankong"])
+config = settings.CONFIG
 
 
 def perms_pc_app(type_id=1000, perms_lst=[]):
@@ -312,7 +313,7 @@ def deviceAccessToken(appId, appSecret):
         status = 0
     
     if not status:  
-        url  = "http://172.100.91.30/openapi/openapi/accessToken"
+        url  = config.get("camera").get("lc_token")
         # 加密
         times,nonce,sign = md5value(appSecret)
         data = {
@@ -328,7 +329,7 @@ def deviceAccessToken(appId, appSecret):
 
             }
         }
-        token_data = requests.post(url,json=data)
+        token_data = requests.post(url,json=data, timeout=5)
         if token_data.status_code == 200:
             try: 
                 token_json_data = json.loads(token_data.text)
@@ -389,14 +390,10 @@ def controlMove(appId,appSecret,deviceId,operation,channelId="0"):
 }
     
     """
-
-    url = "http://172.100.91.30/openapi/openapi/controlMovePTZ"
-    
+    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",
@@ -456,6 +453,59 @@ def get_center_lnglat(lnglats_list):
     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
+        }
+    }
+    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
+        }
+    }
+    
+    live_data = requests.post(url,json=data)
+    return live_data.json()
+
+
 if __name__ == "__main__":
     t = get_recent_month(1)
     print(t)

+ 161 - 0
smartfarming/views/counts_views.py

@@ -0,0 +1,161 @@
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from smartfarming.models.ascend import MongoBase, MongoLandInfo, MongoPlantInfo, MongoAreaJob, LandPlanInfo, CountryModel, PlanWeekend
+from smartfarming.models.user import DeviceUser
+from smartfarming.models.device import MongoDevice
+from smartfarming.models.worm_forecast import MongoCBDphoto
+from smartfarming.serializers.ascend_serializers import (
+    LandPlanInfoSerializers
+)
+from django.core.paginator import Paginator
+import time
+import datetime
+from django.db.models import Q, Sum, Count
+from django.conf import settings
+
+
+class LandPlanInfoAPIView(APIView):
+
+    def post(self, request):
+        # 种植采收列表及统计信息
+        request_data = request.data 
+        plan = request_data.get("plan")
+        year = request_data.get("year")
+        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
+        start_timestamp, end_timestatmp = 0, 0
+        if year:
+            start_timestamp = datetime.datetime(int(year), 1,1,0,0).timestamp()
+            end_timestatmp = datetime.datetime(int(year), 12,31,23,59).timestamp()
+        plan_ids_head = []
+        if plan :
+            plan_ids_head = MongoPlantInfo.objects.filter(plantname__icontains=plan).values_list("id", flat=True)
+        if plan_ids_head and year:
+            queryset = LandPlanInfo.objects.filter(Q(plan_id__in = plan_ids_head) & Q(addtime__gte=start_timestamp, addtime__lte=end_timestatmp)).exclude(recovery_time=0).filter(is_delete=1).order_by("-addtime")
+        elif year:
+            queryset = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
+        elif plan_ids_head:
+            queryset = LandPlanInfo.objects.filter(plan_id__in = plan_ids_head).filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
+        else:
+            queryset = LandPlanInfo.objects.filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
+        total_obj = queryset.count()
+        paginator = Paginator(queryset, page_size)
+        page_obj = paginator.get_page(page_num)
+        serializers = LandPlanInfoSerializers(page_obj, many=True)
+        # 折线图
+        year_value = LandPlanInfo.objects.all().exclude(recovery_time=0).values_list("addtime", flat=True).order_by("-addtime")
+        years = []
+        for year in year_value:
+            y = datetime.datetime.fromtimestamp(year).year
+            if y not in years:
+                years.append(y)
+        years.reverse()
+        # 获取最近5年的作物ID
+        end = datetime.datetime(int(years[-1]) -5, 12,31,23,59).timestamp()
+        start = datetime.datetime(int(years[-1]), 12,31,23,59).timestamp()
+        plan_ids = LandPlanInfo.objects.filter(addtime__gte=end, addtime__lte=start).exclude(recovery_time=0).distinct().values_list("plan_id", flat=True).order_by("plan_id")
+        counts = []
+        # 组织具体数据
+        for i in years:
+            start_timestamp = datetime.datetime(i, 1,1,0,0).timestamp()
+            end_timestatmp = datetime.datetime(i, 12,31,23,59).timestamp()
+            plan_totals = LandPlanInfo.objects.filter(
+                addtime__gte=start_timestamp, 
+                addtime__lte=end_timestatmp).exclude(recovery_time=0).values("plan_id").annotate(total=Sum("recovery_kg")).order_by("plan_id").values_list("plan_id", "total")
+            inners = {}
+            for k in plan_totals:
+                inners[str(k[0])] = k[1]
+            pid =[]
+            for j in plan_ids:
+                pid.append(inners.get(str(j), 0))
+            counts.append(pid)
+        transpose_matrix = [[row[i] for row in counts] for i in range(len(counts[0]))]
+        plannames = []
+        # 组织农作物
+        for p in plan_ids:
+            plan_obj = MongoPlantInfo.objects.filter(id=p)
+            if plan_obj:
+                planname = plan_obj.first().plantname +"-"+ plan_obj.first().planttype
+            else:
+                planname = ""
+            plannames.append(planname)
+        return Response({
+            "code": 0, 
+            "msg": "success", 
+            "data": serializers.data, 
+            "count": total_obj, 
+            "charts": {
+                "years": years,
+                "data": transpose_matrix,
+                "plan": plannames
+            }
+        })
+
+
+class PlanNameAPIView(APIView):
+
+    def post(self, request):
+        try:
+            # 作物名字
+            plan_ids = LandPlanInfo.objects.filter(is_delete=1).exclude(recovery_time=0).values_list("plan_id", flat=True).order_by("-addtime")
+            plans = MongoPlantInfo.objects.filter(is_delete=1, id__in=plan_ids).values_list("plantname", flat=True).distinct()
+            return Response({"code": 0, "msg": "success", "data": plans})
+        except Exception as e:
+            return Response({"code": 0, "msg": "success", "data": []})
+        
+
+class PlanAreaAPIView(APIView):
+
+    def post(self, request):
+        # 种植面积与作物个数统计
+        land_plan_ids = LandPlanInfo.objects.filter(status="采收").filter(recovery_kg=0).values("land_id", "plan_id")
+        plan_land = []
+        plans = []
+        plan_area = 0
+        for i in land_plan_ids:
+            landarea = MongoLandInfo.objects.get(id=i.get("land_id")).landarea
+            plant = MongoPlantInfo.objects.get(id=i.get("plan_id"))
+            plantname = f"{plant.plantname}({plant.planttype})"
+            plan_land.append(
+                {
+                    "name": plantname,
+                    "value": round(float(landarea), 2)
+                }
+            )
+            plans.append(plantname) if plantname not in plans else None 
+            plan_area += round(float(landarea), 2)
+        return Response({"code": 0, "msg": "success", "data": {"lands_area": round(plan_area, 2), "plans_count": len(plans), "p_list": plan_land}})
+    
+
+class DeviceCountAPIView(APIView):
+
+    def post(self, request):
+        # 统计设备在线或离线统计
+        device_status = MongoDevice.objects.values("device_status").annotate(total=Count("id"))
+        online = 0
+        offline = 0
+        for k in device_status:
+            if k.get("device_status") == 1:
+                online = k.get("total")
+            if k.get("device_status") == 0:
+                offline = k.get("total")
+
+        # 设备分类 
+        device_type = MongoDevice.objects.values("device_type_id").annotate(total=Count("id"))
+        config_dict = settings.CONFIG.get("device_type_zh")
+        device_type = {config_dict.get(str(result["device_type_id"])): result["total"] for result in device_type}
+        return Response({
+            "code": 0, 
+            "msg": "success", 
+            "data": {
+                "device_status": {"online": online, "offline": offline},
+                "device_category": device_type
+                }
+            })
+
+
+class RecentPestCountAPIView(APIView):
+
+    def post(self, request):
+        # 统计最近一个月的害虫排名
+        MongoCBDphoto

+ 3 - 98
smartfarming/views/home_land.py

@@ -1,7 +1,8 @@
+import time
 from rest_framework.views import APIView
 from rest_framework.response import Response
+from django.core.paginator import Paginator
 from smartfarming.models.ascend import MongoBase, MongoLandInfo, MongoPlantInfo, MongoAreaJob, LandPlanInfo, CountryModel, PlanWeekend
-from smartfarming.models.user import DeviceUser
 from smartfarming.serializers.ascend_serializers import (
     BaseSerializers, 
     MongoLandInfoSerializers, 
@@ -9,13 +10,8 @@ from smartfarming.serializers.ascend_serializers import (
     MongoAreaJobSerializers,
     CountryModelSerializers,
     PlanWeekendSerializers,
-    MongoPlanWeekendSerializers,
-    LandPlanInfoSerializers
+    MongoPlanWeekendSerializers
 )
-from django.core.paginator import Paginator
-import time
-import datetime
-from django.db.models import Q, Sum
 
 
 class BaseAPIView(APIView):
@@ -449,94 +445,3 @@ class CountryModelDeleteAPIView(APIView):
             return Response({"code": 0, "msg": "删除成功"})
         except Exception as e:
             return Response({"code": 2, "msg": "删除失败"})
-
-
-class LandPlanInfoAPIView(APIView):
-
-    def post(self, request):
-        # 种植采收列表及统计信息
-        request_data = request.data 
-        plan = request_data.get("plan")
-        year = request_data.get("year")
-        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
-        start_timestamp, end_timestatmp = 0, 0
-        if year:
-            start_timestamp = datetime.datetime(int(year), 1,1,0,0).timestamp()
-            end_timestatmp = datetime.datetime(int(year), 12,31,23,59).timestamp()
-        plan_ids_head = []
-        if plan :
-            plan_ids_head = MongoPlantInfo.objects.filter(plantname__icontains=plan).values_list("id", flat=True)
-        if plan_ids_head and year:
-            queryset = LandPlanInfo.objects.filter(Q(plan_id__in = plan_ids_head) & Q(addtime__gte=start_timestamp, addtime__lte=end_timestatmp)).exclude(recovery_time=0).filter(is_delete=1).order_by("-addtime")
-        elif year:
-            queryset = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
-        elif plan_ids_head:
-            queryset = LandPlanInfo.objects.filter(plan_id__in = plan_ids_head).filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
-        else:
-            queryset = LandPlanInfo.objects.filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
-        total_obj = queryset.count()
-        paginator = Paginator(queryset, page_size)
-        page_obj = paginator.get_page(page_num)
-        serializers = LandPlanInfoSerializers(page_obj, many=True)
-        # 折线图
-        year_value = LandPlanInfo.objects.all().exclude(recovery_time=0).values_list("addtime", flat=True).order_by("-addtime")
-        years = []
-        for year in year_value:
-            y = datetime.datetime.fromtimestamp(year).year
-            if y not in years:
-                years.append(y)
-        years.reverse()
-        # 获取最近5年的作物ID
-        end = datetime.datetime(int(years[-1]) -5, 12,31,23,59).timestamp()
-        start = datetime.datetime(int(years[-1]), 12,31,23,59).timestamp()
-        plan_ids = LandPlanInfo.objects.filter(addtime__gte=end, addtime__lte=start).exclude(recovery_time=0).distinct().values_list("plan_id", flat=True).order_by("plan_id")
-        counts = []
-        # 组织具体数据
-        for i in years:
-            start_timestamp = datetime.datetime(i, 1,1,0,0).timestamp()
-            end_timestatmp = datetime.datetime(i, 12,31,23,59).timestamp()
-            plan_totals = LandPlanInfo.objects.filter(
-                addtime__gte=start_timestamp, 
-                addtime__lte=end_timestatmp).exclude(recovery_time=0).values("plan_id").annotate(total=Sum("recovery_kg")).order_by("plan_id").values_list("plan_id", "total")
-            inners = {}
-            for k in plan_totals:
-                inners[str(k[0])] = k[1]
-            pid =[]
-            for j in plan_ids:
-                pid.append(inners.get(str(j), 0))
-            counts.append(pid)
-        transpose_matrix = [[row[i] for row in counts] for i in range(len(counts[0]))]
-        plannames = []
-        # 组织农作物
-        for p in plan_ids:
-            plan_obj = MongoPlantInfo.objects.filter(id=p)
-            if plan_obj:
-                planname = plan_obj.first().plantname +"-"+ plan_obj.first().planttype
-            else:
-                planname = ""
-            plannames.append(planname)
-        return Response({
-            "code": 0, 
-            "msg": "success", 
-            "data": serializers.data, 
-            "count": total_obj, 
-            "charts": {
-                "years": years,
-                "data": transpose_matrix,
-                "plan": plannames
-            }
-        })
-
-
-class PlanNameAPIView(APIView):
-
-    def post(self, request):
-        try:
-            # 作物名字
-            plan_ids = LandPlanInfo.objects.filter(is_delete=1).exclude(recovery_time=0).values_list("plan_id", flat=True).order_by("-addtime")
-            plans = MongoPlantInfo.objects.filter(is_delete=1, id__in=plan_ids).values_list("plantname", flat=True).distinct()
-            return Response({"code": 0, "msg": "success", "data": plans})
-        except Exception as e:
-            return Response({"code": 0, "msg": "success", "data": []})
-

+ 682 - 150
smartfarming/views/pest_image.py

@@ -2,15 +2,16 @@ from io import BytesIO
 import json
 import time
 import pandas as pd
-import ast
+import datetime
+import xlwt
 from django.views.generic import ListView
 from django.http import HttpResponse
 from django.utils.encoding import escape_uri_path
 from django.conf import settings
 from django.db.models import Q
-from smartfarming.models.worm_forecast import MongoCBDphoto, MongoCBDphoto_B
+from smartfarming.models.worm_forecast import MongoCBDphoto
 from smartfarming.models.device import MongoDevice
-from smartfarming.models.user import DeviceUser
+from smartfarming.models.weather import QXZdata_New, MongoQXZ_Conf
 from smartfarming.api.views.forecast.all_dict import insect_dict
 from kedong.decoration import kedong_deco, PortError
 
@@ -18,124 +19,96 @@ config_dict = settings.CONFIG
 
 
 class PestImageSourceExport(ListView):
+
     def get(self, request, *args, **kwargs):
-        '''
-        测报灯害虫图像信息溯源数据导出
-        '''
+        # 测报灯害虫图像信息溯源数据导出
         parameters = request.GET
         d_ids = parameters.get("d_ids")
-        device_type = parameters.get("device_type","cbd")
-        identify_model = parameters.get("identify_model")
         start_time = int(parameters.get("start_time"))
         end_time = int(parameters.get("end_time"))
         select_name = parameters.get("pest_name")
         filename = parameters.get("filename")
-        # 获取统计模型
-        if device_type == "cbd":
-            insect_pest_dict = insect_dict
-            if identify_model:
-                model = MongoCBDphoto if identify_model == "A" else MongoCBDphoto_B
-            else:
-                return HttpResponse(json.dumps({"code":"400","type":"identify_model参数为空"},ensure_ascii=False))
+        page = int(parameters.get("page","1"))
+        page_size = 9999999
+        amend = parameters.get("amend","0")
+
+        
         # 获取统计设备列表
         if d_ids:
             d_id_list = [int(d_id) for d_id in d_ids.split(",")]
             d_id_dicts = {}
             device_queryset = MongoDevice.objects.filter(id__in=d_id_list)
             for device_object in device_queryset:
-                d_id_dicts[device_object.id] = {
-                    "location":device_object.province+device_object.city+device_object.district,
-                    "device_id":device_object.device_id,
-                    "device_code":device_object.device_code,
-                    "device_name":device_object.device_name if device_object.device_name else "测报灯"
-                }
+                d_id_dicts[device_object.id] = {"location":device_object.province+device_object.city+device_object.district,
+                                                "device_id":device_object.device_id,
+                                                "device_code":device_object.device_code,
+                                                "device_name":device_object.device_name if device_object.device_name else "测报灯"
+                                                }
         else:
             raise PortError("d_ids","参数缺失")
-        disable = 1
+        
         # 统计
-        photo_queryset = model.objects.filter(device_id__in=list(d_id_dicts.keys()))
-        photo_queryset = photo_queryset.filter(photo_status=1)
-        photo_queryset = photo_queryset.filter(addtime__gte=start_time)
-        photo_queryset = photo_queryset.filter(addtime__lte=end_time)
+        photo_queryset = MongoCBDphoto.objects.filter(device_id__in=list(d_id_dicts.keys()),photo_status=1,addtime__range=(start_time,end_time))
         if amend == "0":
-            photo_queryset = photo_queryset.exclude(indentify_result="").order_by("-addtime")
+            photo_queryset = photo_queryset.filter(~Q(indentify_result="")).order_by("-addtime")
         else:
-            photo_queryset = photo_queryset.filter(~Q(indentify_result="") | Q(is_mark=1)).order_by("-addtime")
-        save_data = dict(设备ID=[],设备名称=[],害虫名称=[],上报时间=[],设备位置=[],图像=[])
+            photo_queryset = photo_queryset.filter(~Q(indentify_result="") | ~Q(mark="")).order_by("-addtime")
+        
+        pest_image_data = []
         for photo_object in photo_queryset:
             # 单张照片结果
             indentify_result = photo_object.indentify_result
-            is_mark = photo_object.is_mark
             mark = photo_object.mark
             pest_string = ""
-            if amend == "1" and is_mark==1:
+            pest_dict = {}
+            if amend == "1" and mark:
                 if mark == "[]":
                     continue
                 else:
-                    try:
-                        mark = json.loads(mark)
-                    except:
-                        mark = ast.literal_eval(mark)
+                    mark = json.loads(mark)
                     for index,label in enumerate(mark):
                         pest_name = label.get("text")
+                        pest_num = 1
                         if pest_name not in pest_string:
                             if index != 0:
                                 pest_string += "、"
                             pest_string += pest_name
+                            
+                        if pest_name in pest_dict:
+                            pest_dict[pest_name] += pest_num
+                        else:
+                            pest_dict[pest_name] = 1
             else:
-                if disable == 1:
-                    if indentify_result and indentify_result != "0":
-                        for index, result in enumerate(indentify_result.split("#")) :
-                            if index != 0:
-                                pest_string += "、"
-                            tuple_result = result.split(",")
-                            pest_name = insect_pest_dict.get(tuple_result[0],"未命名")
-                            pest_string+=pest_name
-                    else:
-                        continue
-                else:
-                    continue
+                for index,result in enumerate(indentify_result.split("#")) :
+                    if index != 0:
+                        pest_string += "、"
+                    tuple_result = result.split(",")
+                    pest_name = insect_dict.get(tuple_result[0],"未命名")
+                    pest_string+=pest_name
+                    pest_dict[pest_name] = int(tuple_result[1])
             if select_name and select_name not in pest_string:
                 continue
             addtime = photo_object.addtime
-            time_strf = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(addtime))
             __d_id = int(photo_object.device_id)
-            device_code = d_id_dicts[__d_id]["device_code"]
-            indentify_photo = photo_object.indentify_photo
-
-            if device_type == "cbd":
-                img_path = config_dict["image_url"]["image"]
-                if identify_model == "A":
-                    indentify_path = config_dict["image_url"]["discern"]
-                elif identify_model == "B" and device_code == 4:    # 水稻
-                    indentify_path = config_dict["image_url"]["discern"]
-                else:
-                    indentify_path = config_dict["image_url"]["discernB"]
-            elif device_type == "xct":
-                indentify_path = config_dict["image_url"]["xct_photo"]
-                if indentify_photo and (indentify_photo not in ["0", ""]):
-                    indentify_path = config_dict["image_url"]["xct_discern_photo"]
-
-            if indentify_photo and (indentify_photo not in ["0", ""]):
-                if indentify_photo.startswith("http"):
-                    indentify_photo = photo_object.indentify_photo
-                elif indentify_photo.startswith('/'):
-                    indentify_photo = indentify_path + indentify_photo
-                else:
-                    indentify_photo = indentify_path + "/" + indentify_photo
-            else:
-                if photo_object.addr.startswith("http"):
-                    indentify_photo = photo_object.addr
-                elif photo_object.addr.startswith('/'):
-                    indentify_photo = indentify_path + photo_object.addr
-                else:
-                    indentify_photo = indentify_path + "/" + photo_object.addr
-            save_data["设备ID"].append(d_id_dicts[__d_id]["device_id"])
-            save_data["设备名称"].append(d_id_dicts[__d_id]["device_name"])
-            save_data["害虫名称"].append(pest_string)
-            save_data["上报时间"].append(time_strf)
-            save_data["设备位置"].append(d_id_dicts[__d_id]["location"])
-            save_data["图像"].append(indentify_photo)
+            pest_image_data.append({"deviceId":d_id_dicts[__d_id]["device_id"],
+                                    "deviceName":d_id_dicts[__d_id]["device_name"],
+                                    "pestName":pest_string,
+                                    "addtime":addtime,
+                                    "location":d_id_dicts[__d_id]["location"],
+                                    "img_url":photo_object.addr,
+                                    "indentify_photo":photo_object.indentify_photo,
+                                    "pest_dict":pest_dict
+            })
+        return_data = pest_image_data[(page-1)*page_size:page*page_size]
+        save_data = dict(设备ID=[],设备名称=[],害虫名称=[],上报时间=[],设备位置=[],图像=[])
+        for data in return_data:
+            save_data["设备ID"].append(data.get("deviceId"))
+            save_data["设备名称"].append(data.get("deviceName"))
+            save_data["害虫名称"].append(data.get("pestName"))
+            uptime = datetime.datetime.fromtimestamp(data.get("addtime")).strftime("%Y-%m-%d %H:%M:%S")
+            save_data["上报时间"].append(uptime)
+            save_data["设备位置"].append(data.get("location"))
+            save_data["图像"].append(config_dict["image_url"]["discern"] + data.get("indentify_photo"))
         df = pd.DataFrame(data=save_data)
         output = BytesIO()
         df.to_excel(output,index=False)
@@ -146,7 +119,7 @@ class PestImageSourceExport(ListView):
         return response
 
 
-class pest_base_data_export(ListView):
+class PestBaseDataExport(ListView):
     # 虫害基础数据
     def get(self, request, *args, **kwargs):
         '''
@@ -154,70 +127,34 @@ class pest_base_data_export(ListView):
         '''
         parameters = request.GET
         d_ids = parameters.get("d_ids")
-        device_type = parameters.get("device_type","cbd")
-        identify_model = parameters.get("identify_model")
         start_time = int(parameters.get("start_time"))
         end_time = int(parameters.get("end_time"))
         select_name = parameters.get("pest_name")
-        filename = parameters.get("filename")
+        page = int(parameters.get("page","1"))
+        page_size = int(parameters.get("page_size",999999))
         amend = parameters.get("amend","0")
-        uid = parameters.get("uid")
-
-        # 获取统计模型
-        if device_type == "cbd":
-            insect_pest_dict = insect_dict
-            if identify_model:
-                model = MongoCBDphoto if identify_model == "A" else MongoCBDphoto_B
-            else:
-                return HttpResponse(json.dumps({"code":"400","type":"identify_model参数为空"},ensure_ascii=False))
-        else:
-            model = MongoXCTphoto
-            insect_pest_dict = xct_pest_dict
-
+        filename = parameters.get("filename")
+        
         # 获取统计设备列表
         if d_ids:
             d_id_list = [int(d_id) for d_id in d_ids.split(",")]
         else:
             raise PortError("d_ids","参数缺失")
-
-        if device_type == "cbd":
-            myuser = DeviceUser.objects.get(uid=int(uid))
-            if myuser.user_type == 1:
-                disable = 1
-            else:
-                if len(d_id_list) == 1:
-                    # 单设备根据是否支持识别区分
-                    disable = Device.objects.get(id=d_id_list[0]).disable
-                else:
-                    # 多设备保持原逻辑不动
-                    disable = 0
-        else:
-            disable = 1
-
         # 统计
-        photo_queryset = model.objects.filter(device_id__in=d_id_list)
-        photo_queryset = photo_queryset.filter(photo_status=1)
-        # photo_queryset = photo_queryset.filter(addtime__range=(start_time, end_time))
-        photo_queryset = photo_queryset.filter(addtime__gte=start_time)
-        photo_queryset = photo_queryset.filter(addtime__lte=end_time)
+        photo_queryset = MongoCBDphoto.objects.filter(device_id__in=d_id_list,photo_status=1,addtime__range=(start_time,end_time))
         if amend == "0":
-            photo_queryset = photo_queryset.exclude(indentify_result="").order_by("-addtime")
+            photo_queryset = photo_queryset.filter(~Q(indentify_result="")).order_by("-addtime")
         else:
-            photo_queryset = photo_queryset.filter(~Q(indentify_result="") | Q(is_mark=1)).order_by("-addtime")
-        save_data = dict(害虫名称=[],害虫数量=[],上报时间=[])
+            photo_queryset = photo_queryset.filter(~Q(indentify_result="") | ~Q(mark="")).order_by("-addtime")
+        pest_base_data = []
         for photo_object in photo_queryset:
             # 单张照片结果
             indentify_result = photo_object.indentify_result
             mark = photo_object.mark
-            is_mark = photo_object.is_mark
             addtime = photo_object.addtime
-            time_strf = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(addtime))
-            if amend == "1" and is_mark==1:
-                try:
-                    mark = json.loads(mark)
-                except:
-                    mark = ast.literal_eval(mark)
-                pest_dict = {}
+            pest_dict = {}
+            if amend == "1" and mark:
+                mark = json.loads(mark)
                 for label in mark:
                     pest_name = label.get("text")
                     pest_num = 1
@@ -228,32 +165,627 @@ class pest_base_data_export(ListView):
                     else:
                         pest_dict[pest_name] = pest_num
                 for label_key,label_value in pest_dict.items():
-                    save_data["害虫名称"].append(label_key)
-                    save_data["害虫数量"].append(label_value)
-                    save_data["上报时间"].append(time_strf)
+                    pest_base_data.append(dict(pest_name=label_key,pest_num=label_value,addtime=addtime))
+            else:
+                for result in indentify_result.split("#"):
+                    tuple_result = result.split(",")
+                    pest_name = insect_dict.get(tuple_result[0],"未命名")
+                    if select_name and select_name not in pest_name:
+                        continue
+                    pest_num = int(tuple_result[1])
+                    pest_dict=dict(pest_name=pest_name,pest_num=pest_num,addtime=addtime)
+                    pest_base_data.append(pest_dict)
+        return_data = pest_base_data[(page-1)*page_size:page*page_size]
+        save_data = dict(害虫名称=[],害虫数量=[],上报时间=[])
+        for data in return_data:
+            save_data["害虫名称"].append(data.get("pest_name"))
+            save_data["害虫数量"].append(data.get("pest_num"))
+            uptime = datetime.datetime.fromtimestamp(data.get("addtime")).strftime("%Y-%m-%d %H:%M:%S")
+            save_data["上报时间"].append(uptime)  
+        df = pd.DataFrame(data=save_data)
+        output = BytesIO()
+        df.to_excel(output,index=False)
+        output.seek(0)
+        response = HttpResponse(content_type='application/vnd.ms-excel')
+        response['Content-Disposition'] = 'attachment;filename={}.xls'.format(escape_uri_path(filename))
+        response.write(output.getvalue())
+        return response
+    
+
+
+# 气象站数据导出接口
+class QxzDataExport(ListView):
+    """
+    气象站数据导出接口
+
+    参数说明:
+        device_id      必传                     设备号
+        begin          非必传                   开始时间
+        end            非必传                   结束时间
+        filename       必传                     文件名称
+
+    """
+    def get(self,request):
+        device_id = request.GET.get('device_id')
+        f_tbegin = request.GET.get('begin')
+        f_tend = request.GET.get('end')
+        filename = request.GET.get('filename')
+        device_data = QXZdata_New.objects.filter(device_id=device_id).order_by("id")
+        if f_tbegin:
+            device_data = device_data.filter(uptime__gte=f_tbegin)
+        if f_tend:
+            device_data = device_data.filter(uptime__lte=f_tend)
+        book = xlwt.Workbook() # 创建一个excel对象
+        sheet = book.add_sheet('Sheet1',cell_overwrite_ok=True) # 添加一个sheet页
+        tes = []
+        if device_data:
+            try:
+                for x  in device_data:
+                    otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(x.uptime))
+                    te = []
+                    data = [x.e1,x.e2,x.e3,x.e4,x.e5,
+                        x.e6,x.e7,x.e8,x.e9,x.e10,
+                        x.e11,x.e12,x.e13,x.e14,
+                        x.e15,x.e16,x.e17,x.e18,
+                        x.e19,x.e20,x.e21,x.e22,
+                        x.e23,x.e24,x.e25,x.e26,
+                        x.e27,x.e28,x.e29,x.e30,otherStyleTime]
+                    conf_list = [i for i in data if i !='' and i != None ]
+                    for y in conf_list:
+                        if y:
+                            num = str(y.split("#")[0])
+                            te.append(num)
+                    tes.append(te)
+                x = MongoQXZ_Conf.objects.get(device_id=device_id)
+                conf = [x.e1,x.e2,x.e3,x.e4,x.e5,
+                        x.e6,x.e7,x.e8,x.e9,x.e10,
+                        x.e11,x.e12,x.e13,x.e14,
+                        x.e15,x.e16,x.e17,x.e18,
+                        x.e19,x.e20,x.e21,x.e22,
+                        x.e23,x.e24,x.e25,x.e26,
+                        x.e27,x.e28,x.e29,x.e30]
+                conf_list = [i for i in conf if i !='' ]
+                tep = []
+                for x in conf_list:
+                    if x:
+                        tite = x.replace('#', '')
+                        tep.append(tite)
+                tep.append("采集时间")
+                for i in range(len(tep)): # 遍历列
+                    sheet.write(0,i,tep[i]) # 将title数组中的字段写入到0行i列中
+                for y in range(len(tes)):
+                    for i in range(len(tes[y])):
+                        sheet.write(y+1,i,tes[y][i])
+            except:
+                sheet.write(0,0,"错误的时间段") 
+        else:
+            sheet.write(0,0,"该时间段内没数据清重新设置时间段") # 将title数组中的字段写入到0行i列中
+        #写出到IO
+        output = BytesIO()
+        book.save(output)
+        # 重新定位到开始
+        output.seek(0)
+        response = HttpResponse(content_type='application/vnd.ms-excel')
+        response['Content-Disposition'] = 'attachment;filename={}.xls'.format(escape_uri_path(filename))
+        response.write(output.getvalue())
+        return response
+    
+
+class cbd_export(ListView):
+    """
+    设备数据导出接口
+    device_id      设备号(str)
+    start_time     开始时间(时间戳)
+    end_time       结束时间(时间戳)
+    filename       导出的文件名(str)
+    device_type    设备类型
+    """
+    def get(self,request):
+        print("cbd_export,日志数据导出")
+        device_id = request.GET.get("device_id")
+        start_time = request.GET.get("start_time")
+        end_time = request.GET.get("end_time")
+        filename = request.GET.get("filename")
+        device_type = request.GET.get("device_type")
+        username = request.GET.get("username")
+        recent_request = REDIS.get(username)
+        table_headers = request.GET.get("table_header", "")
+        table_headers_lt = table_headers.split("|")
+        if recent_request:
+            seconds = int(time.time()) - int(recent_request)
+            data = {"code":"400","type":"{}秒后重试或等待文件下载完毕".format(60-seconds)}
+            data = json.dumps(data,ensure_ascii=False)
+            return HttpResponse(data)
+        else:
+            REDIS.setex(username,60,int(time.time()))
+        book = xlwt.Workbook() 
+        sheet = book.add_sheet('Sheet1',cell_overwrite_ok=True) # 添加一个sheet页
+        try:
+            devices = Device.objects.get(id=device_id)
+        except:
+            data = {"code":"401","type":"未找到该设备"}
+            data = json.dumps(data,ensure_ascii=False)
+            return HttpResponse(data)
+        
+        try:
+            device_user = DeviceUser.objects.get(real_name=username)
+        except:
+            data = {"code":"402","type":"未找到该用户"}
+            data = json.dumps(data,ensure_ascii=False)
+            return HttpResponse(data)
+
+        if device_type == "7":
+            models = MongoBZYData
+        elif device_type == "4":
+            models = MongoXYCBData
+        elif device_type == "2":
+            models = MongoSCDData
+        elif device_type == "3":
+            models = MongoCBDData
+        elif device_type == "14":
+            models = MongoSYCBData
+        elif device_type == "12":
+            models = MongoXCTData
+        elif device_type == "8":
+            models = MongoXYThreeData
+
+        else:
+            data = {"code":"403","type":"暂不支持该设备类型"}
+            data = json.dumps(data,ensure_ascii=False)
+            return HttpResponse(data)
 
+        if device_id:
+            # device_data = DeviceData.objects.filter(device_id=device_id)
+            device_data = models.objects.filter(device_id=device_id).order_by("-id")
+            print(device_data.count())
+        else:
+            data = {"code":"400","type":"参数为空"}
+            data = json.dumps(data,ensure_ascii=False)
+            return HttpResponse(data)
+        user_type = device_user.user_type
+
+        if user_type == 1:
+            if start_time:
+                device_data = device_data.filter(addtime__range=(int(start_time), int(end_time)))
+        else:
+            if devices.device_expire == "1":
+                print("不是管理员")
+                device_data = device_data.filter(addtime__lte=int(devices.device_expire_time))
+
+                if end_time and int(end_time) > int(devices.device_expire_time):
+                    end_time = devices.device_expire_time
+                    device_data = device_data.filter(addtime__range=(int(start_time), int(end_time)))
             else:
-                if disable == 1:
-                    if indentify_result and indentify_result != "0":
-                        for result in indentify_result.split("#"):
-                            tuple_result = result.split(",")
-                            pest_name = insect_pest_dict.get(tuple_result[0],"未命名")
-                            if select_name and select_name not in pest_name:
-                                continue
-                            pest_num = int(tuple_result[1])
-
-                            save_data["害虫名称"].append(pest_name)
-                            save_data["害虫数量"].append(pest_num)
-                            save_data["上报时间"].append(time_strf)
+                if start_time and end_time:
+                    device_data = device_data.filter(addtime__range=(int(start_time), int(end_time)))
+
+        # if not myuser_type == 1 and devices.device_expire == "1":
+        #     print("不是管理员")
+        #     device_data =  device_data.filter(addtime__lte=int(devices.device_expire_time))
+        #
+        #     if end_time and int(end_time) > int(devices.device_expire_time):
+        #             end_time = devices.device_expire_time
+        #             device_data = device_data.filter(addtime__range=(int(start_time), int(end_time)))
+        # else:
+        #
+        #
+
+        sta2 = []
+        if device_data:
+            for  x in device_data:
+                times = time.localtime(x.addtime)
+                times = time.strftime("%Y-%m-%d %H:%M:%S",times)
+                sta2.append({"data": ast.literal_eval(x.device_data),
+                    "upl_time":times})
+        else:
+            sheet.write(1+1,0,"暂无数据")
+        # 测报灯
+        if device_type == "3":
+            title = ["设备ID","环境温度(℃)","环境湿度(%)","加热仓温度(℃)","雨控状态",
+                        "温控状态","光控状态","信号强度","电流mA","灯管状态", "电压V","上报时间","经度","纬度"]
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                try:
+                    if sta2[x]["data"]["rps"] == "0":
+                        rps = "正常"
                     else:
-                        continue
+                        rps = "雨控"
+                    if sta2[x]["data"]["tps"] == "0":
+                        tps = "正常"
+                    else:
+                        tps = "温控"
+                    if sta2[x]["data"]["lps"] == "0":
+                        lps = "正常"
+                    else:
+                        lps = "光控"
+                    try:
+                        lat = sta2[x]["data"]["lat"]
+                        lng = sta2[x]["data"]["lng"]
+                    except:
+                        lat = 0
+                        lng = 0
+                    try:
+                        ws = sta2[x]["data"]["ws"]
+                        if ws == "" or ws == "0":
+                            ws = True
+                        else:
+                            ws = False
+                    except:
+                        ws = False
+                    if ws:
+                        lamp = "待机"
+                    else:
+                        if sta2[x]["data"]["lamp"] == "0":
+                            lamp = "工作"
+                        else:
+                            lamp = "异常"
+
+                    sheet.write(x+1,0,devices.device_id) # 将equip_id写入到第x+1行,第0列中
+                    sheet.write(x+1,1,sta2[x]["data"]["at"])  # 环境温度
+                    sheet.write(x+1,2,sta2[x]["data"]["ah"])    # 环境湿度
+                    sheet.write(x+1,3,sta2[x]["data"]["hrt"])   # 加热仓温度
+                    sheet.write(x+1,4,rps)     # 雨控状态
+                    sheet.write(x+1,5,tps)     # 温控状态
+                    sheet.write(x+1,6,lps)     # 光控状态
+                    sheet.write(x+1,7,sta2[x]["data"]["csq"])     # 信号强度
+                    sheet.write(x+1,8,sta2[x]["data"]["current"])    # 电流
+                    sheet.write(x+1,9,lamp)    # 灯管状态
+                    sheet.write(x+1,10,sta2[x]["data"]["vbat"])    # 电压
+                    sheet.write(x+1,11,sta2[x]["upl_time"])    # 上报时间
+                    sheet.write(x+1,12,lng)    # 经度
+                    sheet.write(x+1,13,lat)    # 纬度
+                except:
+                    continue
+        # 性诱性诱测报 
+        elif device_type == "4":
+            print(f"+++++++++++++性诱测报+++++++++++++")
+            t_dict = {
+                "ds": "设备开关",
+                "ws": "工作状态",
+                "at": "环境温度(℃)",
+                "ah": "环境湿度(%)",
+                "cv": "充电电压(V)",
+                "bv": "电池电压(V)",
+                "cs": "充电状态",
+                "bs": "电池状态",
+                "infr_ct": "诱虫次数",
+                "csq": "信号强度",
+                "addtime": "上报时间"
+            }
+            title = []
+            for k in table_headers_lt:
+                title.append(t_dict.get(k))
+            title.insert(0, "设备ID")
+            # title = ["设备ID","设备开关","工作状态","环境温度(℃)","环境湿度(%)","红外计数","高压计数","充电电压(V)","电池电压(V)",
+            #             "充电状态","电池状态","信号强度","版本号","上报时间","经度","纬度"]
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                try:
+                    x_d = sta2[x]["data"]
+                    ds = "关机" if x_d["ds"] == 0 else "开机"
+                    ws = "待机" if x_d["ws"] == 0 else "工作"
+                    try:
+                        at = x_d["at"]
+                    except Exception as e:
+                        at = "0"
+                    try:
+                        ah = x_d["ah"]
+                    except Exception as e:
+                        ah = "0"
+
+                    infr_ct = x_d["infr_ct"]
+                    volt_ct = x_d["volt_ct"]
+                    try:
+                        cv = x_d["cv"]
+                    except Exception as e:
+                        cv = "0"
+
+                    try:
+                        bv = x_d["bv"]
+                    except Exception as e:
+                        bv = "0"
+
+                    cs = "非充电" if x_d["cs"] == "0" else "充电"
+                    if x_d["bs"] == "0":
+                        bs = "正常"
+                    elif x_d["bs"] == "1":
+                        bs = "欠压"
+                    else:
+                        bs = "过压"
+
+                    csq = str(x_d["csq"])
+                    dver = x_d["dver"]
+                    try:
+                        lat = x_d["lat"]
+                        lng = x_d["lng"]
+                    except Exception as e:
+                        lat = "0"
+                        lng = "0"
+                    table_value = {
+                        "设备ID": devices.device_id,
+                        "设备开关": ds,
+                        "工作状态": ws,
+                        "环境温度(℃)": at,
+                        "环境湿度(%)": ah,
+                        "充电电压(V)": cv,
+                        "电池电压(V)": bv,
+                        "充电状态": cs,
+                        "电池状态": bs,
+                        "诱虫次数": infr_ct,
+                        "信号强度": csq,
+                        "上报时间": sta2[x]["upl_time"]
+                    }
+                    for i, v in enumerate(title):
+                        sheet.write(x+1, i, table_value.get(v))
+                except:
+                    continue
+        # 杀虫灯
+        elif device_type == "2":
+            title = ["设备ID","设备开关","工作状态","雨控状态","温控状态","倾倒状态","电击次数","定时时长(h)",
+            "环境温度(℃)","环境湿度(%)","充电电压(V)","电池电压(V)","上报时间","经度","纬度"]
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                print(sta2[x]["upl_time"])
+                try:
+                    if int(sta2[x]["data"]["ds"]) == "0":
+                        ds = "关机"
+                    else:
+                        ds = "开机"
+                    if int(sta2[x]["data"]["ws"]) == "0":
+                        ws = "待机"
+                    elif int(sta2[x]["data"]["ws"]) == "2":
+                        ws = "充电"
+                    else:
+                        ws = "工作"
+
+                    if int(sta2[x]["data"]["rps"]) == "0":
+                        rps = "正常"
+                    else:
+                        rps = "雨控"
+
+                    if int(sta2[x]["data"]["tps"]) == "0":
+                        tps = "正常"
+                    else:
+                        tps = "温控"
+                    
+                    if int(sta2[x]["data"]["dps"]) == "0":
+                        dps = "正常"
+                    else:
+                        dps = "保护"
+                    
+                    try:
+                        lat = sta2[x]["data"]["lat"]
+                        lng = sta2[x]["data"]["lng"]
+                    except:
+                        lat = 0
+                        lng = 0
+                    sheet.write(x+1,0,devices.device_id) # 将equip_id写入到第x+1行,第0列中
+                    sheet.write(x+1,1,ds)  # 设备开关
+                    sheet.write(x+1,2,ws)  # 工作状态
+                    # sheet.write(x+1,3,tbs)  # 灯管状态
+                    sheet.write(x+1,3,rps)  # 雨控状态
+                    sheet.write(x+1,4,tps)  # 温控状态
+                    sheet.write(x+1,5,dps)  # 倾倒状态
+                    sheet.write(x+1,6,sta2[x]["data"]["ct"])  # 电击次数
+                    sheet.write(x+1,7,sta2[x]["data"]["tt"])  # 定时时长
+                    sheet.write(x+1,8,sta2[x]["data"]["at"])  # 环境温度
+                    sheet.write(x+1,9,sta2[x]["data"]["ah"])    # 环境湿度
+                    sheet.write(x+1,10,sta2[x]["data"]["cv"])    # 充电电压
+                    sheet.write(x+1,11,sta2[x]["data"]["bv"])    # 电池电压
+                    sheet.write(x+1,12,sta2[x]["upl_time"])    # 上报时间
+                    sheet.write(x+1,13,lng)    # 经度
+                    sheet.write(x+1,14,lat)    # 纬度
+                except:
+                    continue
+        # 孢子仪
+        elif device_type == "7":
+            title = ["设备ID","保温仓设定温度(℃)","保温仓当前温度(℃)","电池状态","雨控状态","摄像头状态", "电压(V)","信号强度",
+                     "环境温度(℃)","环境湿度(%)","设备版本","上报时间","经度","纬度"]
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                try:
+
+                    if sta2[x]["data"]["batStatus"] == "0":
+                        bat_sta = "正常"
+                    else:
+                        bat_sta = "电量过低"
+
+                    if sta2[x]["data"]["rps"] == "0":
+                        rps = "正常"
+                    else:
+                        rps = "雨控"
+
+                    if sta2[x]["data"]["usb_sta"] == "0":
+                        usb_sta = "正常"
+                    else:
+                        usb_sta = "异常"
+                    try:
+                        lat = sta2[x]["data"]["lat"]
+                        lng = sta2[x]["data"]["lng"]
+                    except:
+                        lat = 0
+                        lng = 0
+                except:
+                    continue
+                sheet.write(x+1,0,devices.device_id) # 将equip_id写入到第x+1行,第0列中
+                sheet.write(x+1,1,sta2[x]["data"]["set_temp"])  # 保温仓设定温度
+                sheet.write(x+1,2,sta2[x]["data"]["pre_temp"])  # 保温仓当前温度
+                sheet.write(x+1,3,bat_sta)  # 电池状态
+                sheet.write(x+1,4,rps)  # 雨控状态
+                sheet.write(x+1,5,usb_sta)  # 摄像头状态
+                sheet.write(x+1,6,sta2[x]["data"]["vbat"])  # 电压
+                # sheet.write(x+1,8,sta2[x]["data"]["alti"])  # 海拔高度
+                sheet.write(x+1,7,sta2[x]["data"]["csq"])  # 信号强度
+                sheet.write(x+1,8,sta2[x]["data"]["at"])  # 环境温度
+                sheet.write(x+1,9,sta2[x]["data"]["ah"])    # 环境湿度
+                sheet.write(x+1,10,sta2[x]["data"]["dver"])    # 设备版本
+                sheet.write(x+1,11,sta2[x]["upl_time"])    # 上报时间
+                sheet.write(x+1,12,lng)    # 经度
+                sheet.write(x+1,13,lat)    # 纬度
+        # 色诱
+        elif device_type == "14":
+            title = ["设备ID", "上报时间", "开机状态", "空气温度", "空气湿度"]
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                if int(sta2[x]["data"]["ds"]) == 0:
+                    ds = "关机"
                 else:
+                    ds = "开机"
+
+                try:
+                    at = str(int(sta2[x]["data"]["at"])/10)
+                    ah = str(int(sta2[x]["data"]["ah"])/10)
+                except:
+                    at = sta2[x]["data"]["at"]
+                    ah = sta2[x]["data"]["ah"]
+
+                sheet.write(x + 1, 0, devices.device_id)  # 将equip_id写入到第x+1行,第0列中
+                sheet.write(x + 1, 1, sta2[x]["upl_time"])  # 上报时间
+                sheet.write(x + 1, 2, ds)  # 开机状态
+                sheet.write(x + 1, 3, at)  # 空气温度
+                sheet.write(x + 1, 4, ah)  # 空气湿度
+        # 吸虫塔
+        elif device_type == "12":
+            title = ["设备ID","设备开关","SIM卡号","工作状态","环境温度(℃)","环境湿度(%)",
+                        "震动开关","信号强度","上报时间","经度","纬度"]
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                try:
+                    if sta2[x]["data"]["ds"] == "0":
+                        ds = "关机"
+                    else:
+                        ds = "开机"
+
+                    if sta2[x]["data"]["ws"] == "0":
+                        ws = "待机"
+                    else:
+                        ws = "工作"
+                    if sta2[x]["data"]["shake"] == "0":
+                        shake = "关"
+                    else:
+                        shake = "开"
+
+                    try:
+                        lat = sta2[x]["data"]["lat"]
+                        lng = sta2[x]["data"]["lng"]
+                    except:
+                        lat = 0
+                        lng = 0
+
+                    sheet.write(x+1,0,devices.device_id) # 将equip_id写入到第x+1行,第0列中
+                    sheet.write(x+1,1,ds)     # 设备开关:
+                    sheet.write(x+1,2,sta2[x]["data"]["iccid"])   # iccid
+                    sheet.write(x+1,3,ws)     # 工作状态
+                    sheet.write(x+1,4,sta2[x]["data"]["at"])  # 环境温度
+                    sheet.write(x+1,5,sta2[x]["data"]["ah"])    # 环境湿度
+                    sheet.write(x+1,6,shake)     # 震动开关:
+                    sheet.write(x+1,7,sta2[x]["data"]["csq"])     # 信号强度
+                    sheet.write(x+1,8,sta2[x]["upl_time"])    # 上报时间
+                    sheet.write(x+1,9,lng)    # 经度
+                    sheet.write(x+1,10,lat)    # 纬度
+                except:
                     continue
-        df = pd.DataFrame(data=save_data)
+        # 性诱3.0
+        elif device_type == "8":
+            print(f"---------------性诱3.0--------------")
+            t_dict = {
+                "ds": "设备开关",
+                "ws": "工作状态",
+                "at": "环境温度(℃)",
+                "ah": "环境湿度(%)",
+                "cc": "电流(mA)",
+                "cv": "充电电压(V)",
+                "bv": "电池电压(V)",
+                "bs": "电池状态",
+                "volt_ct": "诱虫次数",
+                "csq": "信号强度",
+                "addtime": "上报时间"
+            }
+            title = []
+            for k in table_headers_lt:
+                title.append(t_dict.get(k))
+            title.insert(0, "设备ID")
+            for i in range(len(title)): # 遍历列
+                sheet.write(0,i,title[i]) # 将title数组中的字段写入到0行i列中
+            for x in range(len(sta2)): # 遍历列表
+                try:
+                    if sta2[x]["data"]["ds"] == "0":
+                        ds = "关机"
+                    else:
+                        ds = "开机"
+                    if sta2[x]["data"]["ws"] == "0":
+                        ws = "待机"
+                    else:
+                        ws = "工作"
+                    try:
+                        at = sta2[x]["data"]["at"]
+                    except Exception as e:
+                        at = "0"
+                    try:
+                        ah = sta2[x]["data"]["ah"]
+                    except Exception as e:
+                        ah = "0"
+                    if sta2[x]["data"]["bs"] == "0":
+                        bs = "正常"
+                    elif sta2[x]["data"]["bs"] == "1":
+                        bs = "欠压"
+                    else:
+                        bs = "过压"
+
+                    try:
+                        lat = sta2[x]["data"]["lat"]
+                        lng = sta2[x]["data"]["lng"]
+                    except:
+                        lat = 0
+                        lng = 0
+                    table_value = {
+                        "设备ID": devices.device_id,
+                        "设备开关": ds,
+                        "工作状态": ws,
+                        "环境温度(℃)": at,
+                        "环境湿度(%)": ah,
+                        "电流(mA)": sta2[x]["data"]["cc"],
+                        "充电电压(V)": sta2[x]["data"]["cv"],
+                        "电池电压(V)": sta2[x]["data"].get("bv", "0"),
+                        "电池状态": "正常" if sta2[x]["data"].get("bs", "1") == "0" else "非正常",
+                        "诱虫次数": sta2[x]["data"]["volt_ct"],
+                        "信号强度": sta2[x]["data"]["csq"],
+                        "上报时间": sta2[x]["upl_time"]
+                    }
+                    for i, v in enumerate(title):
+                        sheet.write(x+1, i, table_value.get(v))
+                except Exception as e:
+                    print(e)
+                    continue
+            
+        else:
+            data = {"code":"400","type":"参数为空"}
+            data = json.dumps(data,ensure_ascii=False)
+            return HttpResponse(data)
+        sheet.col(0).width = 256 * 18
+        sheet.col(1).width = 256 * 15
+        sheet.col(2).width = 256 * 15
+        sheet.col(3).width = 256 * 15
+        sheet.col(4).width = 256 * 15
+        sheet.col(5).width = 256 * 15
+        sheet.col(6).width = 256 * 15
+        sheet.col(7).width = 256 * 15
+        sheet.col(8).width = 256 * 15
+        sheet.col(9).width = 256 * 15
+        sheet.col(10).width = 256 * 20
+        # 写出到IO
         output = BytesIO()
-        df.to_excel(output,index=False)
+        book.save(output)
+        # 重新定位到开始
         output.seek(0)
         response = HttpResponse(content_type='application/vnd.ms-excel')
         response['Content-Disposition'] = 'attachment;filename={}.xls'.format(escape_uri_path(filename))
         response.write(output.getvalue())
+        REDIS.delete(username)
         return response

+ 47 - 69
smartfarming/views/weather.py

@@ -1,81 +1,59 @@
 import requests
+import json
+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_center_lnglat
 
 
-def user_weather(request):
-    myuser = request.myuser
-    province, city, district = myuser.province, myuser.city, myuser.district
-    lnglat_list = []
-    if province and city:
-        try:
-            url = (f"https://restapi.amap.com/v3/geocode/geo?"
-                    f"key=a6919321ca5d6b4d2f11c63fe87671de&address=f{province}{city}{district}")
-            rep = requests.get(url)
-            if rep.status_code == 200:
-                result = rep.json()
-                location = result['geocodes'][0]["location"]
-                for i in location.split(';'):
-                    g, t = i.split(',')
-                    lnglat_list.append((float(g), float(t)))
-        except Exception as e:
-            pass
-    if not lnglat_list:
+class WeatherAPIView(APIView):
+
+    def post(self, request):
+        # 调用天气
         try:
             ip = request.META['HTTP_X_FORWARDED_FOR']
         except Exception as e:
             ip = request.META['REMOTE_ADDR']
-        try:
-            url = "https://restapi.amap.com/v3/ip?ip={}&output=json&key=a6919321ca5d6b4d2f11c63fe87671de".format(ip)
-            rep = requests.get(url)
-            if rep.status_code == 200:
-                result = rep.json()
-                location = result['rectangle']
-                lnglat_list = []
-                for i in location.split(';'):
-                    g, t = i.split(',')
-                    lnglat_list.append((float(g), float(t)))
-                province, city, district = result['province'], result['city'], result.get('district', '')
-        except Exception as e:
-            province, city, district = "河南省", "郑州市", "金水区"
-            lnglat_list.append((113.625368, 34.746599))
-    lng, lat = get_center_lnglat(lnglat_list)
-    data = {}
-    if lng and lat:
-        try:
-            url = "http://114.115.147.140:8080/pingpu_weather"
-            res = requests.post(url, {"lat": lat, "lng": lng})
-            rsp = res.json()['data']
-            wea_img_dict = {
-                '晴': 'qing',
-                '阴': 'yin',
-                '雨': 'yu',
-                '云': 'yun',
-                '雾': 'wu'
-            }
-            wea_img = 'yun'
-            wea = rsp['wea']
-            for k, v in wea_img_dict.items():
-                if k in wea:
-                    wea_img = v
+        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")
+        content = []
+        for i in data:
+            content.append(
+                {
+                    "week": i.get("week"),
+                    "wea_img": i.get("wea_img"),
+                    "wea_day_img": i.get("wea_day_img"),
+                    "tem": i.get("tem"),
+                    "tem1": i.get("tem1"),
+                    "tem2": i.get("tem2")
+                }
+            )
+        return Response({"code": 0, "msg": "success", "data": content})
+    
 
-            data = {
-                'region': '{}{}{}'.format(province, city, district),
-                'at': rsp['at'],
-                'ah': rsp['ah'],
-                'win_meter': rsp['win_meter'],
-                'wea': rsp['wea'],
-                'wea_img': wea_img,
-                'air': rsp['air'],
-                'air_level': rsp['air_level'],
-                'air_tips': rsp['air_tips'],
-                'alarm_type': rsp.get('alarm_type', ''),
-                'alarm_level': rsp.get('alarm_level', ''),
-                'alarm_content': rsp.get('alarm_content', ''),
-                'air_pm25': rsp.get('air_pm25', '')
-            }
+class QxzListAPIView(APIView):
 
-        except Exception as e:
-            pass
-    return Response(data=data, status=200)
+    def post(self, request):
+        shang = MongoDevice.objects.filter(device_type_id=8).values_list("device_id", flat=True)
+        return Response({"code": 0, "msg": "success", "data": shang})
+    
+class QxzShangAPIView(APIView):
+
+    def post(self, request):
+        # 墒情统计
+        request_data = request.data 
+        device_id = request_data.get("device_id")
+        qx_conf = MongoQXZ_Conf.objects.filter(device_id=device_id).values().order_by("-uptime").first()
+        qx_data = QXZdata_New.objects.filter(device_id=device_id).values().order_by("-uptime").first()
+        result = {}
+        for k, v in qx_conf.items():
+            if k.startswith("e"):
+                if qx_data.get(k):
+                    v_tp = v.split("#")
+                    result[v_tp[0]] = (qx_data.get(k)).split("#")[0] + v_tp[1]
+        return Response({"code": 0, "msg": "success", "data": result})

+ 10 - 1
test

@@ -68,6 +68,15 @@
        "6": "监控"
     },
     "image_url": {
-      "image":"http://192.168.0.36:8000"
+      "image":"http://192.168.0.36:8000",
+      "discern": "http://192.168.0.36:8000"
+    },
+    "camera": {
+      "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_controler": "https://openapi.lechange.cn/openapi/controlMovePTZ",
+      "ys_open": "https://open.ys7.com/api/lapp/live/video/open",
+      "ys_get": "https://open.ys7.com/api/lapp/live/address/get"
     }
 }