counts_views.py 14 KB

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