Просмотр исходного кода

增加经纬度转换与导出数据

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

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
gcj02.json


+ 88 - 0
kedong/utils.py

@@ -6,6 +6,8 @@ import base64
 import configparser
 import configparser
 import os
 import os
 import json
 import json
+import math
+import copy
 
 
 environ = None
 environ = None
 try:
 try:
@@ -67,3 +69,89 @@ class Aescrypt():
 
 
 
 
 PrAes = Aescrypt('yf7232275', 'ECB', '', 'gbk')
 PrAes = Aescrypt('yf7232275', 'ECB', '', 'gbk')
+
+
+
+# 简单判断坐标点是否在中国
+# 不在的话返回True
+# 在的话返回False
+def judge_China(lon, lat):
+    if lon < 70 or lon > 140:
+        return True
+    if lat < 0 or lat > 55:
+        return True
+    return False
+
+
+# 设置常量
+pi = 3.141592653589793234  # π
+r_pi = pi * 3000.0 / 180.0
+la = 6378245.0  # 长半轴
+ob = 0.00669342162296594323  # 扁率
+
+
+# 经纬度计算功能类
+def transformlat(lon, lat):
+    r = -100.0 + 2.0 * lon + 3.0 * lat + 0.2 * lat * lat + 0.1 * lon * lat + 0.2 * math.sqrt(math.fabs(lon))
+    r += (20.0 * math.sin(6.0 * lon * pi) + 20.0 * math.sin(2.0 * lon * pi)) * 2.0 / 3.0
+    r += (20.0 * math.sin(lat * pi) + 40.0 * math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
+    r += (160.0 * math.sin(lat / 12.0 * pi) + 320 * math.sin(lat * pi / 30.0)) * 2.0 / 3.0
+    return r
+
+def transformlng(lon, lat):
+    r = 300.0 + lon + 2.0 * lat + 0.1 * lon * lon + 0.1 * lon * lat + 0.1 * math.sqrt(math.fabs(lon))
+    r += (20.0 * math.sin(6.0 * lon * pi) + 20.0 * math.sin(2.0 * lon * pi)) * 2.0 / 3.0
+    r += (20.0 * math.sin(lon * pi) + 40.0 * math.sin(lon / 3.0 * pi)) * 2.0 / 3.0
+    r += (150.0 * math.sin(lon / 12.0 * pi) + 300.0 * math.sin(lon / 30.0 * pi)) * 2.0 / 3.0
+    return r
+
+# wgs84 -> gcj02
+# lng为wgs84的经度
+# lat为wgs84的纬度
+# 返回值为转换后坐标的列表形式,[经度, 纬度]
+def wgs84_gcj02(lon_wgs84, lat_wgs84):
+    if judge_China(lon_wgs84, lat_wgs84):  # 判断是否在国内
+        return [lon_wgs84, lat_wgs84]
+    tlat = transformlat(lon_wgs84 - 105.0, lat_wgs84 - 35.0)
+    tlng = transformlng(lon_wgs84 - 105.0, lat_wgs84 - 35.0)
+    rlat = lat_wgs84 / 180.0 * pi
+    m = math.sin(rlat)
+    m = 1 - ob * m * m
+    sm = math.sqrt(m)
+    tlat = (tlat * 180.0) / ((la * (1 - ob)) / (m * sm) * pi)
+    tlng = (tlng * 180.0) / (la / sm * math.cos(rlat) * pi)
+    lat_gcj02 = lat_wgs84 + tlat
+    lon_gcj02 = lon_wgs84 + tlng
+    return [lon_gcj02, lat_gcj02]
+
+
+def wgs84_to_gcj02():
+    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+    with open(os.path.join(BASE_DIR, "base.json"), 'r', encoding='utf-8') as fg:
+        wgs84 = json.load(fg)
+    wgs84_copy = copy.deepcopy(wgs84)
+    features = wgs84.get("features")
+    new_out_features = []
+    for f in features:
+        new_in_features = {
+            "geometry": {},
+            "attributes": f.get("attributes")
+        }
+        rings = f.get("geometry").get("rings")
+        new_rings = []
+        for r in rings:
+            temp = []
+            for i in r:
+                # print(i)
+                # print('--------------------')
+                result = wgs84_gcj02(i[0], i[1])
+                # print(result)
+                temp.append(result)
+            new_rings.append(temp)
+        new_in_features["geometry"] = {"rings": new_rings}
+        new_out_features.append(new_in_features)
+    wgs84_copy["features"] = new_out_features
+    with open(os.path.join(BASE_DIR, "gcj02.json"), 'w', encoding='utf-8', ) as fk:
+        json.dump(wgs84_copy, fk, ensure_ascii=False)
+
+wgs84_to_gcj02()

+ 1 - 1
smartfarming/api/views/forecast/worm_lamp.py

@@ -790,7 +790,7 @@ def pest_statistics_char_new(request):
             ah_avg = int(sum(ah_day_info)//len(ah_day_info)) if len(ah_day_info)!=0 else 30
             ah_avg = int(sum(ah_day_info)//len(ah_day_info)) if len(ah_day_info)!=0 else 30
             at_ah_info.append({"addtime":time_recording,"at":at_avg,"ah":ah_avg})
             at_ah_info.append({"addtime":time_recording,"at":at_avg,"ah":ah_avg})
     # 字典排序
     # 字典排序
-    pest_info_total = dict(sorted(pest_info_total.items(),key=lambda x:x[1],reverse=True))
+    pest_info_total = dict(sorted(pest_info_total.items(),key=lambda x:x[1],reverse=False))
     data = {"char_data":chart_info,"pest_total":pest_info_total}
     data = {"char_data":chart_info,"pest_total":pest_info_total}
     if len(d_id_list) == 1:
     if len(d_id_list) == 1:
         data["at_ah_info"] = at_ah_info
         data["at_ah_info"] = at_ah_info

+ 2 - 2
smartfarming/serializers/ascend_serializers.py

@@ -15,7 +15,7 @@ class BaseSerializers(serializers.ModelSerializer):
     def base_info(self):
     def base_info(self):
         BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
         BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
         try:
         try:
-            with open(os.path.join(BASE_DIR, "base.json"), 'r', encoding="utf-8") as f:
+            with open(os.path.join(BASE_DIR, "gcj02.json"), 'r', encoding="utf-8") as f:
                 base = json.load(f)
                 base = json.load(f)
             features = base.get("features")
             features = base.get("features")
             base_size = 0
             base_size = 0
@@ -191,7 +191,7 @@ class LandPlanInfoSerializers(serializers.ModelSerializer):
         if plan_id:
         if plan_id:
             plan = MongoPlantInfo.objects.filter(id=obj.plan_id)
             plan = MongoPlantInfo.objects.filter(id=obj.plan_id)
             if plan:
             if plan:
-                return plan.first().plantname
+                return plan.first().plantname +"-"+ plan.first().planttype
             else:
             else:
                 return ""
                 return ""
         else:
         else:

+ 7 - 1
smartfarming/urls.py

@@ -1,5 +1,6 @@
 # coding=utf-8
 # coding=utf-8
 from django.urls import path, re_path
 from django.urls import path, re_path
+from django.conf.urls import url
 from smartfarming.views.upload_file import FileUploadView
 from smartfarming.views.upload_file import FileUploadView
 
 
 from smartfarming.views.user import (
 from smartfarming.views.user import (
@@ -43,7 +44,8 @@ from smartfarming.views.home_land import (
     CountryModelAddAPIView,
     CountryModelAddAPIView,
     CountryModelUpdateAPIView,
     CountryModelUpdateAPIView,
     CountryModelDeleteAPIView,
     CountryModelDeleteAPIView,
-    LandPlanInfoAPIView
+    LandPlanInfoAPIView,
+    PlanNameAPIView
 )
 )
 
 
 from smartfarming.views.device import (
 from smartfarming.views.device import (
@@ -70,6 +72,7 @@ from smartfarming.views.knowledge import (
 
 
 
 
 from smartfarming.views.pests_bank import PestBankAPIView
 from smartfarming.views.pests_bank import PestBankAPIView
+from smartfarming.views.pest_image import PestImageSourceExport
 
 
 
 
 urlpatterns = [
 urlpatterns = [
@@ -117,6 +120,7 @@ urlpatterns = [
     path("country_delete", CountryModelDeleteAPIView.as_view()),  # 乡村删除
     path("country_delete", CountryModelDeleteAPIView.as_view()),  # 乡村删除
     path("pest", PestBankAPIView.as_view()),  # 虫害列表
     path("pest", PestBankAPIView.as_view()),  # 虫害列表
     path("plan_info", LandPlanInfoAPIView.as_view()), # 种植作物列表及统计
     path("plan_info", LandPlanInfoAPIView.as_view()), # 种植作物列表及统计
+    path("plan_name", PlanNameAPIView.as_view()), # 作物名称数组
 
 
     path("knowledge", KnowledgeCategoryAPIView.as_view()),  # 知识分类列表
     path("knowledge", KnowledgeCategoryAPIView.as_view()),  # 知识分类列表
     path("knowledge_update", KnowledgeCategoryUpdateAPIView.as_view()),  # 知识分类编辑
     path("knowledge_update", KnowledgeCategoryUpdateAPIView.as_view()),  # 知识分类编辑
@@ -132,4 +136,6 @@ urlpatterns = [
     path("information_update", InformationUpdateAPIView.as_view()),  # 研判信息编辑
     path("information_update", InformationUpdateAPIView.as_view()),  # 研判信息编辑
     path("information_add", InformationAddAPIView.as_view()), # 研判信息新增
     path("information_add", InformationAddAPIView.as_view()), # 研判信息新增
     path("information_delete", InformationDeleteAPIView.as_view()), # 研判信息删除
     path("information_delete", InformationDeleteAPIView.as_view()), # 研判信息删除
+
+    url(r'^pest_image_source_export$', PestImageSourceExport.as_view()), # 测报灯数据导出
 ]
 ]

+ 20 - 0
smartfarming/utils.py

@@ -5,6 +5,7 @@ import json
 import logging
 import logging
 import time
 import time
 import hashlib
 import hashlib
+import math
 from captcha.image import ImageCaptcha
 from captcha.image import ImageCaptcha
 from io import BytesIO
 from io import BytesIO
 import base64
 import base64
@@ -436,6 +437,25 @@ def expire_time(times):
         
         
     return status
     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
+
+
 if __name__ == "__main__":
 if __name__ == "__main__":
     t = get_recent_month(1)
     t = get_recent_month(1)
     print(t)
     print(t)

+ 44 - 22
smartfarming/views/home_land.py

@@ -15,7 +15,7 @@ from smartfarming.serializers.ascend_serializers import (
 from django.core.paginator import Paginator
 from django.core.paginator import Paginator
 import time
 import time
 import datetime
 import datetime
-from django.db.models import Q, Count
+from django.db.models import Q, Sum
 
 
 
 
 class BaseAPIView(APIView):
 class BaseAPIView(APIView):
@@ -457,51 +457,62 @@ class LandPlanInfoAPIView(APIView):
         # 种植采收列表及统计信息
         # 种植采收列表及统计信息
         request_data = request.data 
         request_data = request.data 
         plan = request_data.get("plan")
         plan = request_data.get("plan")
-        year = int(request_data.get("year"))
+        year = request_data.get("year")
         page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
         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
         page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
-        start_timestamp = datetime.datetime(year, 1,1,0,0).timestamp()
-        end_timestatmp = datetime.datetime(year, 12,31,23,59).timestamp()
-        plan_ids = []
-        if plan:
-            plan_ids = MongoPlantInfo.objects.filter(plantname__icontains=plan).values_list("id", flat=True)
-        if plan_ids and year:
-            queryset = LandPlanInfo.objects.filter(Q(plan_id__in = plan_ids) & Q(addtime__gte=start_timestamp, addtime__lte=end_timestatmp)).filter(is_delete=1).order_by("-addtime")
+        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:
         elif year:
-            queryset = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).filter(is_delete=1).order_by("-addtime")
-        elif plan_ids:
-            queryset = LandPlanInfo.objects.filter(plan_id__in = plan_ids).filter(is_delete=1).order_by("-addtime")
+            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()
         total_obj = queryset.count()
         paginator = Paginator(queryset, page_size)
         paginator = Paginator(queryset, page_size)
         page_obj = paginator.get_page(page_num)
         page_obj = paginator.get_page(page_num)
         serializers = LandPlanInfoSerializers(page_obj, many=True)
         serializers = LandPlanInfoSerializers(page_obj, many=True)
         # 折线图
         # 折线图
-        year_value = LandPlanInfo.objects.all().values_list("addtime", flat=True).order_by("-addtime")
+        year_value = LandPlanInfo.objects.all().exclude(recovery_time=0).values_list("addtime", flat=True).order_by("-addtime")
         years = []
         years = []
         for year in year_value:
         for year in year_value:
             y = datetime.datetime.fromtimestamp(year).year
             y = datetime.datetime.fromtimestamp(year).year
             if y not in years:
             if y not in years:
                 years.append(y)
                 years.append(y)
-        years = years[:5]
+        years.reverse()
         # 获取最近5年的作物ID
         # 获取最近5年的作物ID
-        plan_ids = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).distinct().values_list("plan_id", flat=True).order_by("plan_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 = []
         counts = []
+        # 组织具体数据
         for i in years:
         for i in years:
             start_timestamp = datetime.datetime(i, 1,1,0,0).timestamp()
             start_timestamp = datetime.datetime(i, 1,1,0,0).timestamp()
             end_timestatmp = datetime.datetime(i, 12,31,23,59).timestamp()
             end_timestatmp = datetime.datetime(i, 12,31,23,59).timestamp()
-            plan_totals = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).values("plan_id").annotate(total=Count("plan_id")).order_by("plan_id").values_list("plan_id", "total")
+            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 = {}
             inners = {}
             for k in plan_totals:
             for k in plan_totals:
                 inners[str(k[0])] = k[1]
                 inners[str(k[0])] = k[1]
             pid =[]
             pid =[]
-            for id in plan_ids:
-                pid.append(inners.get(str(id), 0))
+            for j in plan_ids:
+                pid.append(inners.get(str(j), 0))
             counts.append(pid)
             counts.append(pid)
+        transpose_matrix = [[row[i] for row in counts] for i in range(len(counts[0]))]
         plannames = []
         plannames = []
+        # 组织农作物
         for p in plan_ids:
         for p in plan_ids:
-            plan = MongoPlantInfo.objects.filter(id=p)
-            if plan:
-                planname = plan.first().plantname + plan.first().planttype
+            plan_obj = MongoPlantInfo.objects.filter(id=p)
+            if plan_obj:
+                planname = plan_obj.first().plantname +"-"+ plan_obj.first().planttype
             else:
             else:
                 planname = ""
                 planname = ""
             plannames.append(planname)
             plannames.append(planname)
@@ -512,9 +523,20 @@ class LandPlanInfoAPIView(APIView):
             "count": total_obj, 
             "count": total_obj, 
             "charts": {
             "charts": {
                 "years": years,
                 "years": years,
-                "data": counts,
+                "data": transpose_matrix,
                 "plan": plannames
                 "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": []})
+

+ 259 - 0
smartfarming/views/pest_image.py

@@ -0,0 +1,259 @@
+from io import BytesIO
+import json
+import time
+import pandas as pd
+import ast
+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.device import MongoDevice
+from smartfarming.models.user import DeviceUser
+from smartfarming.api.views.forecast.all_dict import insect_dict
+from kedong.decoration import kedong_deco, PortError
+
+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))
+        # 获取统计设备列表
+        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 "测报灯"
+                }
+        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)
+        if amend == "0":
+            photo_queryset = photo_queryset.exclude(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=[],设备名称=[],害虫名称=[],上报时间=[],设备位置=[],图像=[])
+        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:
+                if mark == "[]":
+                    continue
+                else:
+                    try:
+                        mark = json.loads(mark)
+                    except:
+                        mark = ast.literal_eval(mark)
+                    for index,label in enumerate(mark):
+                        pest_name = label.get("text")
+                        if pest_name not in pest_string:
+                            if index != 0:
+                                pest_string += "、"
+                            pest_string += pest_name
+            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
+            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)
+        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 pest_base_data_export(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")
+        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
+
+        # 获取统计设备列表
+        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)
+        if amend == "0":
+            photo_queryset = photo_queryset.exclude(indentify_result="").order_by("-addtime")
+        else:
+            photo_queryset = photo_queryset.filter(~Q(indentify_result="") | Q(is_mark=1)).order_by("-addtime")
+        save_data = dict(害虫名称=[],害虫数量=[],上报时间=[])
+        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 = {}
+                for label in mark:
+                    pest_name = label.get("text")
+                    pest_num = 1
+                    if select_name and select_name not in pest_name:
+                        continue
+                    if pest_name in pest_dict:
+                        pest_dict[pest_name] += pest_num
+                    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)
+
+            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)
+                    else:
+                        continue
+                else:
+                    continue
+        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

+ 81 - 0
smartfarming/views/weather.py

@@ -0,0 +1,81 @@
+import requests
+from rest_framework.response import Response
+
+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:
+        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
+
+            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', '')
+            }
+
+        except Exception as e:
+            pass
+    return Response(data=data, status=200)