device.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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, QXZdata_New
  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. permission_classes = []
  105. authentication_classes = []
  106. def post(self, request):
  107. # 气象站上传数据
  108. try:
  109. request_data = request.data
  110. device_id = request_data.get("StationID")
  111. uptime = request_data.get("MonitorTime")
  112. data = request_data.get("data")
  113. terminalStatus = request_data.get("terminalStatus")
  114. cmd = request_data.get("cmd")
  115. if data:
  116. qx_ek = {}
  117. for i in data:
  118. tp_value = i.get("eValue")
  119. if tp_value:
  120. qx_ek[i.get("eKey")] = tp_value
  121. if data:
  122. # 30分钟上报一次的数据
  123. qx_ek["device_id"] = device_id
  124. qx_ek["uptime"] = uptime
  125. qxz_data = QXZdata_New(**qx_ek)
  126. qxz_data.save()
  127. return Response({"code": 0, "msg": "success"})
  128. if terminalStatus:
  129. base_info_obj, is_created = MongoQXZ_Base_Info.objects.update_or_create(
  130. device_id=device_id,
  131. defaults={
  132. "volt": terminalStatus.get("VOLT"),
  133. "rssi": terminalStatus.get("RSSI"),
  134. "uptime": uptime
  135. }
  136. )
  137. iccid = terminalStatus.get("ICCID")
  138. lng = terminalStatus.get("longitude")
  139. lat = terminalStatus.get("latitude")
  140. led = terminalStatus.get("Dotled")
  141. dver = terminalStatus.get("Version")
  142. device, is_created = MongoDevice.objects.update_or_create(device_id=device_id)
  143. if iccid:
  144. base_info_obj.iccid = iccid
  145. if lng:
  146. base_info_obj.lng = lng
  147. device.lng = lng
  148. if lat:
  149. base_info_obj.lat = lat
  150. device.lat = lat
  151. if led:
  152. base_info_obj.led = led
  153. if dver:
  154. base_info_obj.dver = dver
  155. base_info_obj.save()
  156. device.save()
  157. return Response({"code": 0, "msg": "success"})
  158. if cmd:
  159. ext = request_data.get("ext")
  160. imei = ext.get("imei")
  161. device_info = MongoDevice.objects.get(device_id=imei)
  162. if cmd == "online":
  163. device_info.device_status = 1
  164. if cmd == "offline":
  165. device_info.device_status = 0
  166. device_info.save()
  167. except Exception as e:
  168. logger.error(f"气象站设备 {device_id} 处理上报数据或增加设备失败,错误原因:{e.args}")
  169. return Response({"code": 2, "msg": "failer"})
  170. class DeviceListAPIView(APIView):
  171. def post(self, request):
  172. # 设备列表
  173. request_data = request.data
  174. device_id = request_data.get("device_id")
  175. device_status = request_data.get("device_status")
  176. search = request_data.get("search")
  177. page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
  178. page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
  179. if device_id:
  180. queryset = MongoDevice.objects.filter(device_id=device_id).order_by("-uptime")
  181. elif device_status:
  182. queryset = MongoDevice.objects.filter(device_status=device_status).order_by("-uptime")
  183. elif search:
  184. queryset = MongoDevice.objects.filter(Q(device_name__icontains=search) | Q(device_id__icontains=search))
  185. else:
  186. queryset = MongoDevice.objects.all().order_by("-uptime")
  187. total_obj = queryset.count()
  188. paginator = Paginator(queryset, page_size)
  189. page_obj = paginator.get_page(page_num)
  190. serializers = DeviceSerializers(page_obj, many=True)
  191. return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})
  192. class DeviceChangeAPIView(APIView):
  193. def post(self, request):
  194. # 修改设备信息
  195. request_data = request.data
  196. device_name = request_data.get("device_name")
  197. device_id = request_data.get("device_id")
  198. lng = request_data.get("lng")
  199. lat = request_data.get("lat")
  200. device = MongoDevice.objects.get(device_id=device_id)
  201. if device_name:
  202. device.device_name = device_name
  203. if lng and lat:
  204. device.lng = lng
  205. device.lat = lat
  206. is_success, province, city, district = get_addr_by_lag_lng(lat, lng)
  207. if is_success:
  208. # 更新地理位置坐标
  209. device.province = province
  210. device.city = city
  211. device.district = district
  212. device.save()
  213. return Response({"code": 0, "msg": "success"})
  214. class DeviceListInfoAPIView(APIView):
  215. def post(self, request):
  216. # 设备列表
  217. request_data = request.data
  218. device_id = request_data.get("device_id")
  219. device_status = request_data.get("device_status")
  220. search = request_data.get("search")
  221. page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
  222. page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
  223. if device_id:
  224. queryset = MongoDevice.objects.filter(device_id=device_id).order_by("-uptime")
  225. elif device_status:
  226. queryset = MongoDevice.objects.filter(device_status=device_status).order_by("-uptime")
  227. elif search:
  228. queryset = MongoDevice.objects.filter(Q(device_name__icontains=search) | Q(device_id__icontains=search))
  229. else:
  230. queryset = MongoDevice.objects.all().order_by("-uptime")
  231. total_obj = queryset.count()
  232. paginator = Paginator(queryset, page_size)
  233. page_obj = paginator.get_page(page_num)
  234. serializers = DeviceSerializers(page_obj, many=True)
  235. return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})
  236. class DeviceListAPIView(APIView):
  237. def post(self, request):
  238. queryset = MongoDevice.objects.order_by('-id')
  239. type_dict = {d.id: d.type_name for d in MongoDeviceType.objects.all()}
  240. result = []
  241. offline_list = []
  242. type_counter = Counter()
  243. device_dict = defaultdict(list)
  244. for item in queryset:
  245. device_info = item
  246. device_type_id = device_info.device_type_id
  247. device_status = device_info.device_status
  248. is_offline = False if device_status == 1 else True
  249. device_id = device_info.device_id
  250. if is_offline:
  251. offline_list.append(device_id)
  252. type_counter[device_type_id] += 1
  253. device_dict[device_type_id].append(device_id)
  254. coordinates = ""
  255. lng = device_info.lng
  256. lat = device_info.lat
  257. if not (lng and lat):
  258. continue
  259. coordinates = f"[{str(float(lng))},{str(float(lat))}]"
  260. device_name = device_info.device_name
  261. result.append({
  262. 'ld_id': item.id,
  263. 'device_id': device_id,
  264. 'device_name': device_name or device_id,
  265. 'tpye_name': type_dict[device_info.device_type_id],
  266. 'device_type_id': device_type_id,
  267. 'coordinates': coordinates,
  268. 'offline': False if device_status == 1 else True,
  269. 'is_warning': False
  270. })
  271. statistic_list = []
  272. for k, v in type_counter.items():
  273. statistic_list.append({
  274. 'type_id': k,
  275. 'type_count': v,
  276. 'type_name': type_dict[k]
  277. })
  278. warning_model_dict = {
  279. 3: DevicePestWarning
  280. }
  281. warning_list = []
  282. for k, v in device_dict.items():
  283. try:
  284. model_obj = warning_model_dict[k]
  285. except KeyError as e:
  286. continue
  287. war_list = [d.device_id for d in model_obj.objects.filter(device_id__in=v, status=0)]
  288. if war_list:
  289. warning_list.extend(war_list)
  290. for item in result:
  291. device_id = item['device_id']
  292. if device_id in warning_list:
  293. item['is_warning'] = True
  294. warn_and_off = set(warning_list) & set(offline_list)
  295. data = {
  296. "statistic": statistic_list,
  297. 'offline': {
  298. 'count': len(offline_list),
  299. 'result': offline_list
  300. },
  301. "waring": {
  302. 'count': len(warning_list),
  303. 'result': warning_list
  304. },
  305. "warn_and_off": {
  306. 'count': len(warn_and_off),
  307. 'result': warning_list
  308. },
  309. "data": result
  310. }
  311. return Response({"code": 0, "message": "success", "data": data})