device.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from django.conf import settings
  4. from django.core.paginator import Paginator
  5. import time
  6. import json
  7. import logging
  8. from smartfarming.utils import get_addr_by_lag_lng
  9. from smartfarming.serializers.device_serializers import DeviceSerializers
  10. from smartfarming.models.device import MongoDevice, MongoCBDData, MongoSCDData, MongoXYCBData
  11. from smartfarming.models.weather import MongoQXZ_Base_Info, MongoQXZ_Info_Record, MongoQXZ_Conf
  12. from django.db.models import Q
  13. from smartfarming.qxz import data_deal
  14. from collections import Counter, defaultdict
  15. from smartfarming.models.device import MongoDevice, DevicePestWarning, MongoDeviceType
  16. from kedong.decoration import kedong_deco, PortError
  17. from django.core.paginator import Paginator
  18. logger = logging.getLogger("myapp")
  19. device_type_en = (settings.CONFIG).get("device_type_en")
  20. device_type_zh = (settings.CONFIG).get("device_type_zh")
  21. class CbdScdXyDeviceSaveAPIView(APIView):
  22. permission_classes = []
  23. authentication_classes = []
  24. def post(self, request):
  25. # 测报灯设备及数据入库
  26. data = request.data
  27. topic = data.get("topic")
  28. payload = data.get("payload")
  29. cmd = payload.get("cmd")
  30. topic_msg = topic.split("/")
  31. now = int(time.time())
  32. if topic_msg and len(topic_msg) == 5 and cmd:
  33. device_id = topic_msg[-1]
  34. try:
  35. device_type = topic_msg[2]
  36. device_type_id = device_type_en.get(device_type)
  37. if device_type_id == 2:
  38. model = MongoSCDData
  39. elif device_type_id == 3:
  40. model = MongoCBDData
  41. elif device_type_id == 8:
  42. model = MongoXYCBData
  43. # 在设备信息表中查找是否有数据,如果没有数据则增加
  44. device_name = device_type_zh.get(device_type_id)
  45. device, is_created = MongoDevice.objects.get_or_create(
  46. device_id = device_id,
  47. defaults={
  48. "device_id": device_id,
  49. "device_type_id": device_type_id,
  50. "device_name": device_name,
  51. "addtime": now
  52. }
  53. )
  54. if is_created:
  55. logger.info(f"{device_type} 设备 {device_id} 入库成功")
  56. # 获取数据并更新设备
  57. if cmd == "data":
  58. ext = payload.get("ext")
  59. if ext:
  60. # 增加设备数据
  61. model.objects.create(
  62. device_id = device_id,
  63. device_data = str(ext),
  64. addtime = now
  65. )
  66. lng = ext.get("lng")
  67. lat = ext.get("lat")
  68. dver_num = ext.get("dver")
  69. device.device_status = 1
  70. device.uptime = now
  71. if dver_num:
  72. device.dver_num = dver_num
  73. if lng and lat and dver_num:
  74. device.lng = lng
  75. device.lat = lat
  76. # 根据经纬度获取省市级
  77. is_success, province, city, district = get_addr_by_lag_lng(lat, lng)
  78. if is_success:
  79. # 更新地理位置坐标
  80. device.province = province
  81. device.city = city
  82. device.district = district
  83. device.save()
  84. elif cmd == "offline":
  85. ext = data.get("ext")
  86. if ext:
  87. # 增加设备数据
  88. model.objects.create(
  89. device_id=device_id,
  90. device_data = str(ext),
  91. addtime=now
  92. )
  93. # 更新设备状态
  94. device = MongoDevice.objects.filter(device_id=device_id).first()
  95. device.device_status = 0
  96. device.save()
  97. return Response({"code": 0, "msg": "success"})
  98. except Exception as e:
  99. logger.error(f"测报灯设备 {device_id} 处理上报数据或增加设备失败,错误原因:{e.args}")
  100. return Response({"code": 2, "msg": f"处理测报灯上报数据失败 {device_id}"})
  101. else:
  102. return Response({"code": 2, "msg": "请核对数据结构"})
  103. class QxzDeviceAddAPIViw(APIView):
  104. def post(self, request):
  105. # 气象站上传数据
  106. request_data = request.data
  107. device_id = request_data.get("StationID")
  108. uptime = request_data.get("MonitorTime")
  109. data = request_data.get("data")
  110. if data:
  111. # 30分钟上报一次的数据
  112. conf_data = data_deal(data)
  113. qxz_data = MongoQXZ_Conf()
  114. qxz_data.device_id = 2
  115. qxz_data.e1 = data[1]
  116. qxz_data.e2 = data[2]
  117. qxz_data.e3 = data[3]
  118. qxz_data.e4 = data[4]
  119. qxz_data.e5 = data[5]
  120. qxz_data.e6 = data[6]
  121. qxz_data.e7 = data[7]
  122. qxz_data.e8 = data[8]
  123. qxz_data.e9 = data[9]
  124. qxz_data.e10 = data[10]
  125. qxz_data.e11 = data[11]
  126. qxz_data.e12 = data[12]
  127. qxz_data.e13 = data[13]
  128. qxz_data.e14 = data[14]
  129. qxz_data.e15 = data[15]
  130. qxz_data.e16 = data[16]
  131. qxz_data.e17 = data[17]
  132. qxz_data.e18 = data[18]
  133. qxz_data.e19 = data[19]
  134. qxz_data.e20 = data[20]
  135. qxz_data.e21 = data[21]
  136. qxz_data.e22 = data[22]
  137. qxz_data.e23 = data[23]
  138. qxz_data.e24 = data[24]
  139. qxz_data.e25 = data[25]
  140. qxz_data.e26 = data[26]
  141. qxz_data.e27 = data[27]
  142. qxz_data.e28 = data[28]
  143. qxz_data.e29 = data[29]
  144. qxz_data.e30 = data[30]
  145. class DeviceListAPIView(APIView):
  146. def post(self, request):
  147. # 设备列表
  148. request_data = request.data
  149. device_id = request_data.get("device_id")
  150. device_status = request_data.get("device_status")
  151. search = request_data.get("search")
  152. page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
  153. page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
  154. if device_id:
  155. queryset = MongoDevice.objects.filter(device_id=device_id).order_by("-uptime")
  156. elif device_status:
  157. queryset = MongoDevice.objects.filter(device_status=device_status).order_by("-uptime")
  158. elif search:
  159. queryset = MongoDevice.objects.filter(Q(device_name__icontains=search) | Q(device_id__icontains=search))
  160. else:
  161. queryset = MongoDevice.objects.all().order_by("-uptime")
  162. total_obj = queryset.count()
  163. paginator = Paginator(queryset, page_size)
  164. page_obj = paginator.get_page(page_num)
  165. serializers = DeviceSerializers(page_obj, many=True)
  166. return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})
  167. class DeviceChangeAPIView(APIView):
  168. def post(self, request):
  169. # 修改设备信息
  170. request_data = request.data
  171. device_name = request_data.get("device_name")
  172. device_id = request_data.get("device_id")
  173. lng = request_data.get("lng")
  174. lat = request_data.get("lat")
  175. device = MongoDevice.objects.get(device_id=device_id)
  176. if device_name:
  177. device.device_name = device_name
  178. if lng and lat:
  179. device.lng = lng
  180. device.lat = lat
  181. is_success, province, city, district = get_addr_by_lag_lng(lat, lng)
  182. if is_success:
  183. # 更新地理位置坐标
  184. device.province = province
  185. device.city = city
  186. device.district = district
  187. device.save()
  188. return Response({"code": 0, "msg": "success"})
  189. class DeviceListAPIView(APIView):
  190. def post(self, request):
  191. queryset = MongoDevice.objects.order_by('-id')
  192. type_dict = {d.id: d.type_name for d in MongoDeviceType.objects.all()}
  193. result = []
  194. offline_list = []
  195. type_counter = Counter()
  196. device_dict = defaultdict(list)
  197. for item in queryset:
  198. device_info = item
  199. device_type_id = device_info.device_type_id
  200. device_status = device_info.device_status
  201. is_offline = False if device_status == 1 else True
  202. device_id = device_info.device_id
  203. if is_offline:
  204. offline_list.append(device_id)
  205. type_counter[device_type_id] += 1
  206. device_dict[device_type_id].append(device_id)
  207. coordinates = ""
  208. lng = device_info.lng
  209. lat = device_info.lat
  210. if not (lng and lat):
  211. continue
  212. coordinates = f"[{str(float(lng))},{str(float(lat))}]"
  213. device_name = device_info.device_name
  214. result.append({
  215. 'ld_id': item.id,
  216. 'device_id': device_id,
  217. 'device_name': device_name or device_id,
  218. 'tpye_name': type_dict[device_info.device_type_id],
  219. 'device_type_id': device_type_id,
  220. 'coordinates': coordinates,
  221. 'offline': False if device_status == 1 else True,
  222. 'is_warning': False
  223. })
  224. statistic_list = []
  225. for k, v in type_counter.items():
  226. statistic_list.append({
  227. 'type_id': k,
  228. 'type_count': v,
  229. 'type_name': type_dict[k]
  230. })
  231. warning_model_dict = {
  232. 3: DevicePestWarning
  233. }
  234. warning_list = []
  235. for k, v in device_dict.items():
  236. try:
  237. model_obj = warning_model_dict[k]
  238. except KeyError as e:
  239. continue
  240. war_list = [d.device_id for d in model_obj.objects.filter(device_id__in=v, status=0)]
  241. if war_list:
  242. warning_list.extend(war_list)
  243. for item in result:
  244. device_id = item['device_id']
  245. if device_id in warning_list:
  246. item['is_warning'] = True
  247. warn_and_off = set(warning_list) & set(offline_list)
  248. data = {
  249. "statistic": statistic_list,
  250. 'offline': {
  251. 'count': len(offline_list),
  252. 'result': offline_list
  253. },
  254. "waring": {
  255. 'count': len(warning_list),
  256. 'result': warning_list
  257. },
  258. "warn_and_off": {
  259. 'count': len(warn_and_off),
  260. 'result': warning_list
  261. },
  262. "data": result
  263. }
  264. return Response({"code": 0, "message": "success", "data": data})