counts_views.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. from django.core.paginator import Paginator
  2. import logging
  3. import datetime
  4. from operator import itemgetter
  5. from django.db.models import Q, Sum, Count
  6. from django.db.models.functions import Cast
  7. from djongo import models
  8. from django.conf import settings
  9. from rest_framework.views import APIView
  10. from rest_framework.response import Response
  11. from smartfarming.models.ascend import MongoBase, MongoLandInfo, MongoPlantInfo, MongoAreaJob, LandPlanInfo, CountryModel, PlanWeekend
  12. from smartfarming.models.user import DeviceUser
  13. from smartfarming.models.device import MongoDevice
  14. from smartfarming.models.worm_forecast import MongoCBDphoto
  15. from smartfarming.models.pest_count import MongoCBDPestWarning
  16. from smartfarming.models.weather import MongoQXZ_Alarm_Log_New
  17. from smartfarming.serializers.ascend_serializers import LandPlanInfoSerializers
  18. from smartfarming.serializers.pests_serializers import MongoCBDPestWarningSerializers, MongoQXZAlarmLogNewSerializers
  19. from smartfarming.utils import get_recent_month, get_weather
  20. from smartfarming.api.views.forecast.all_dict import insect_dict
  21. from smartfarming.models.device import MongoDevice
  22. from smartfarming.models.ascend import MongoBase
  23. logger = logging.getLogger("myapp")
  24. class LandPlanInfoAPIView(APIView):
  25. def post(self, request):
  26. # 种植采收列表及统计信息
  27. request_data = request.data
  28. plan = request_data.get("plan")
  29. year = request_data.get("year")
  30. page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
  31. page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
  32. start_timestamp, end_timestatmp = 0, 0
  33. queryset = LandPlanInfo.objects.filter(is_delete=1).exclude(recovery_time=0).order_by("-addtime")
  34. if year:
  35. start_timestamp = datetime.datetime(int(year), 1,1,0,0).timestamp()
  36. end_timestatmp = datetime.datetime(int(year), 12,31,23,59).timestamp()
  37. queryset = queryset.filter(recovery_time__gte=start_timestamp, recovery_time__lte=end_timestatmp)
  38. if plan:
  39. ids_lst = MongoPlantInfo.objects.filter(plantname__icontains=plan).values_list("id", flat=True)
  40. queryset = queryset.filter(plan_id__in = ids_lst)
  41. total_obj = queryset.count()
  42. paginator = Paginator(queryset, page_size)
  43. page_obj = paginator.get_page(page_num)
  44. serializers = LandPlanInfoSerializers(page_obj, many=True)
  45. # 折线图
  46. # 获取最近5年年份列表
  47. current_year = datetime.datetime.now().year
  48. year_list = [year for year in range(current_year, current_year - 6, -1)]
  49. year_value = LandPlanInfo.objects.all().exclude(recovery_time=0).values_list("recovery_time", flat=True).order_by("-recovery_time")
  50. years = []
  51. all_year = []
  52. for year in year_value:
  53. y = datetime.datetime.fromtimestamp(year).year
  54. if y not in years and y in year_list:
  55. years.append(y)
  56. if y not in all_year:
  57. all_year.append(y)
  58. years.reverse()
  59. all_year.reverse()
  60. # 获取最近5年的作物ID
  61. if years:
  62. end = datetime.datetime(int(years[-1]) -6, 12,31,23,59).timestamp()
  63. start = datetime.datetime(int(years[-1]), 12,31,23,59).timestamp()
  64. plan_ids = LandPlanInfo.objects.filter(recovery_time__gte=end, recovery_time__lte=start).exclude(recovery_time=0).distinct().values_list("plan_id", flat=True).order_by("plan_id")
  65. counts = []
  66. # 组织具体数据
  67. for i in years:
  68. start_timestamp = datetime.datetime(i, 1,1,0,0).timestamp()
  69. end_timestatmp = datetime.datetime(i, 12,31,23,59).timestamp()
  70. plan_totals = LandPlanInfo.objects.filter(
  71. recovery_time__gte=start_timestamp,
  72. recovery_time__lte=end_timestatmp).exclude(recovery_time=0).values("plan_id").annotate(
  73. total=Sum(Cast('recovery_kg', output_field=models.FloatField()))).order_by("plan_id").values_list("plan_id", "total")
  74. # 作物 id:总质量
  75. inners = {}
  76. for k in plan_totals:
  77. inners[str(k[0])] = k[1]
  78. pid =[]
  79. for j in plan_ids:
  80. pid.append(inners.get(str(j), 0))
  81. counts.append(pid)
  82. transpose_matrix = [[row[i] for row in counts] for i in range(len(counts[0]))]
  83. plannames = []
  84. # 组织农作物
  85. for p in plan_ids:
  86. plan_obj = MongoPlantInfo.objects.filter(id=p)
  87. if plan_obj:
  88. planname = plan_obj.first().plantname +"-"+ plan_obj.first().planttype
  89. else:
  90. planname = ""
  91. plannames.append(planname)
  92. return Response({
  93. "code": 0,
  94. "msg": "success",
  95. "data": serializers.data,
  96. "years": all_year,
  97. "count": total_obj,
  98. "charts": {
  99. "years": years,
  100. "data": transpose_matrix,
  101. "plan": plannames
  102. }
  103. })
  104. else:
  105. return Response({
  106. "code": 0,
  107. "msg": "success",
  108. "data": [],
  109. "count": 0,
  110. "charts": {
  111. "years": [],
  112. "data": [],
  113. "plan": []
  114. }
  115. })
  116. class PlanNameAPIView(APIView):
  117. def post(self, request):
  118. try:
  119. # 作物名字
  120. plan_ids = LandPlanInfo.objects.filter(is_delete=1).exclude(recovery_time=0).values_list("plan_id", flat=True).order_by("-addtime")
  121. plans = MongoPlantInfo.objects.filter(is_delete=1, id__in=plan_ids).values_list("plantname", flat=True).distinct()
  122. return Response({"code": 0, "msg": "success", "data": plans})
  123. except Exception as e:
  124. logger.error(e)
  125. return Response({"code": 0, "msg": "success", "data": []})
  126. class PlanAreaAPIView(APIView):
  127. def post(self, request):
  128. # 种植面积与作物个数统计
  129. try:
  130. land_plan_ids = LandPlanInfo.objects.filter(status="采收").filter(recovery_kg=0).values("land_id", "plan_id")
  131. plan_land = []
  132. plans = []
  133. plan_area = 0
  134. for i in land_plan_ids:
  135. landarea = MongoLandInfo.objects.get(id=i.get("land_id")).landarea
  136. plant = MongoPlantInfo.objects.get(id=i.get("plan_id"))
  137. plantname = f"{plant.plantname}({plant.planttype})"
  138. plan_land.append(
  139. {
  140. "name": plantname,
  141. "value": round(float(landarea), 2)
  142. }
  143. )
  144. plans.append(plantname) if plantname not in plans else None
  145. plan_area += round(float(landarea), 2)
  146. return Response({"code": 0, "msg": "success", "data": {"lands_area": int(plan_area), "plans_count": len(plans), "p_list": plan_land}})
  147. except Exception as e:
  148. logger.error(e)
  149. return Response({"code": 0, "msg": "请检查数据"})
  150. class DeviceCountAPIView(APIView):
  151. def post(self, request):
  152. # 统计设备在线或离线统计
  153. device_status = MongoDevice.objects.values("device_status").annotate(total=Count("id"))
  154. online = 0
  155. offline = 0
  156. for k in device_status:
  157. if k.get("device_status") == 1:
  158. online = k.get("total")
  159. if k.get("device_status") == 0:
  160. offline = k.get("total")
  161. # 设备分类
  162. device_type = MongoDevice.objects.values("device_type_id").annotate(total=Count("id"))
  163. config_dict = settings.CONFIG.get("device_type_zh")
  164. device_type = {config_dict.get(str(result["device_type_id"])): result["total"] for result in device_type}
  165. return Response({
  166. "code": 0,
  167. "msg": "success",
  168. "data": {
  169. "device_status": {"online": online, "offline": offline},
  170. "device_category": device_type
  171. }
  172. })
  173. class RecentPestCountAPIView(APIView):
  174. def post(self, request):
  175. # 统计最近一个月的害虫排名
  176. start = get_recent_month(1)
  177. data = MongoCBDphoto.objects.filter(uptime__gte=start).values_list("indentify_result", flat=True)
  178. try:
  179. pest_count = {}
  180. for i in data:
  181. tp_lst = i.split("#")
  182. for k in tp_lst:
  183. if k:
  184. pest = k.split(",")
  185. if len(pest) == 2:
  186. p_0 = pest[0]
  187. p_1 = pest[1]
  188. p_name = insect_dict.get(p_0)
  189. if p_name not in pest_count.keys():
  190. pest_count[p_name] = int(p_1)
  191. else:
  192. pest_count[p_name] += int(p_1)
  193. else:
  194. logger.error(f"害虫识别格式有误:{k}")
  195. result = sorted(pest_count.items(), key=itemgetter(1), reverse=False)
  196. result = {m[0]:m[1] for m in result[-10:]}
  197. return Response({"code": 0, "msg": "success", "data": result})
  198. except Exception as e:
  199. logger.error(e)
  200. return Response({"code": 2, "msg": "数据有误,请核查"})
  201. # 网站顶部滚动预警信息
  202. class AlermNewsAPIView(APIView):
  203. def post(self, request):
  204. try:
  205. myuser = request.myuser
  206. try:
  207. ip = request.META['HTTP_X_FORWARDED_FOR']
  208. except Exception as e:
  209. ip = request.META['REMOTE_ADDR']
  210. # 获取天气预警
  211. weather_data = get_weather(ip)
  212. weather = []
  213. for i in weather_data:
  214. alarm = i.get("alarm")
  215. if alarm:
  216. for k in alarm:
  217. weather.append(k.get("alarm_content"))
  218. # 获取虫睛预警
  219. user_id = str(myuser.id)
  220. pest_query = MongoCBDPestWarning.objects.all().order_by("-id")[:3]
  221. pest = []
  222. for p in pest_query:
  223. content = p.warning_content
  224. pest.append(content.replace("【云飞科技】尊敬的用户:", "").replace(",(详情请登陆http://hnyfwlw.com查看)", "").replace(",请注意防范(详情请登陆http://hnyfwlw.com查看)", ""))
  225. # 气象预警
  226. qx_query = MongoQXZ_Alarm_Log_New.objects.filter(user_id=user_id).order_by('-id')[:3]
  227. qx = []
  228. for q in qx_query:
  229. qx.append(q.warning_content)
  230. data = []
  231. if weather:
  232. for i in weather:
  233. data.append(i)
  234. if pest:
  235. for i in pest:
  236. data.append(i)
  237. if qx:
  238. for i in qx:
  239. data.append(i)
  240. return Response({"code": 0,"msg":"success", "data": data})
  241. except Exception as e:
  242. logger.error(e)
  243. return Response({"code": 2, "msg": "获取数据失败"})
  244. class APPAlarmAPIView(APIView):
  245. def post(self, request):
  246. # 气象站与测报预警
  247. request_data = request.data
  248. type_id = request_data.get("type_id")
  249. device_id = request_data.get("device_id", "")
  250. page_num = int(request_data.get("page", 1)) if request_data.get("page") else 1
  251. page_size = int(request_data.get("page_size", 10)) if request_data.get("page_size") else 10
  252. data = {}
  253. total_obj = 0
  254. if type_id == "3":
  255. # 虫情
  256. queryset = MongoCBDPestWarning.objects.all().order_by("-upltime")
  257. if device_id:
  258. queryset = queryset.filter(device_id=device_id)
  259. total_obj = queryset.count()
  260. paginator = Paginator(queryset, page_size)
  261. page_obj = paginator.get_page(page_num)
  262. pest_serializers = MongoCBDPestWarningSerializers(page_obj, many=True)
  263. data = pest_serializers.data
  264. elif type_id == "5":
  265. queryset = MongoQXZ_Alarm_Log_New.objects.filter(warning_name="5").order_by("-upl_time")
  266. if device_id:
  267. d_id = MongoDevice.objects.get(device_id=device_id).id
  268. queryset = queryset.filter(device_id=d_id)
  269. total_obj = queryset.count()
  270. paginator = Paginator(queryset, page_size)
  271. page_obj = paginator.get_page(page_num)
  272. qxz_serializers = MongoQXZAlarmLogNewSerializers(page_obj, many=True)
  273. data = qxz_serializers.data
  274. elif type_id == "8":
  275. queryset = MongoQXZ_Alarm_Log_New.objects.filter(warning_name="8").order_by("-upl_time")
  276. if device_id:
  277. d_id = MongoDevice.objects.get(device_id=device_id).id
  278. queryset = queryset.filter(device_id=d_id)
  279. total_obj = queryset.count()
  280. paginator = Paginator(queryset, page_size)
  281. page_obj = paginator.get_page(page_num)
  282. qxz_serializers = MongoQXZAlarmLogNewSerializers(page_obj, many=True)
  283. data = qxz_serializers.data
  284. return Response({"code": 0, "msg": "success", "data": data, "nums": total_obj})
  285. class QxzCameraList(APIView):
  286. permission_classes = []
  287. authentication_classes = []
  288. def post(self, request):
  289. # 气象与监控绑定列表
  290. qxz_ids = MongoDevice.objects.filter(device_type_id__in = [5, 8]).values("device_id")
  291. cam_ids = MongoDevice.objects.filter(device_type_id = 6).values_list("device_id", flat=True)
  292. return Response({"code": 0,"msg":"success", "data": {"qxz_ids": qxz_ids, "cam_ids": cam_ids}})
  293. class QxzCameraUpdate(APIView):
  294. permission_classes = []
  295. authentication_classes = []
  296. def post(self, request):
  297. # 气象与监控更新
  298. request_data = request.data
  299. try:
  300. qx_id = request_data.get("qx_id")
  301. ca_id = request_data.get("ca_id")
  302. qx_lng_lat = MongoDevice.objects.filter(device_id=qx_id).values_list("lng", "lat")
  303. ca_obj = MongoDevice.objects.get(device_id=ca_id)
  304. if qx_lng_lat:
  305. ca_obj.lng = float(qx_lng_lat[0][0]) + 0.00004
  306. ca_obj.lat = float(qx_lng_lat[0][1]) + 0.00004
  307. ca_obj.save()
  308. return Response({"code": 0,"msg":"success"})
  309. except Exception as e:
  310. logger.error(e)
  311. return Response({"code": 2,"msg":"失败"})
  312. class KeDongOverAPIView(APIView):
  313. def post(self, request):
  314. # 我的信息
  315. try:
  316. country_count = CountryModel.objects.filter(is_delete=1).count()
  317. area = MongoBase.objects.all().first().base_area
  318. device = MongoDevice.objects.all().count()
  319. return Response({
  320. "code": 0,
  321. "msg":"success",
  322. "data": {
  323. "country_count": country_count,
  324. "area": area,
  325. "device": device
  326. }
  327. })
  328. except Exception as e:
  329. logger.error(e)
  330. return Response({"code": 2,"msg":"失败"})