from rest_framework.views import APIView from rest_framework.response import Response from django.conf import settings from django.core.paginator import Paginator import time import json import logging from smartfarming.utils import get_addr_by_lag_lng from smartfarming.serializers.device_serializers import DeviceSerializers from smartfarming.models.device import MongoDevice, MongoCBDData, MongoSCDData, MongoXYCBData from smartfarming.models.weather import MongoQXZ_Base_Info, MongoQXZ_Info_Record, MongoQXZ_Conf from django.db.models import Q from smartfarming.qxz import data_deal from collections import Counter, defaultdict from smartfarming.models.device import MongoDevice, DevicePestWarning, MongoDeviceType from kedong.decoration import kedong_deco, PortError from django.core.paginator import Paginator logger = logging.getLogger("myapp") device_type_en = (settings.CONFIG).get("device_type_en") device_type_zh = (settings.CONFIG).get("device_type_zh") class CbdScdXyDeviceSaveAPIView(APIView): permission_classes = [] authentication_classes = [] def post(self, request): # 测报灯设备及数据入库 data = request.data topic = data.get("topic") payload = data.get("payload") cmd = payload.get("cmd") topic_msg = topic.split("/") now = int(time.time()) if topic_msg and len(topic_msg) == 5 and cmd: device_id = topic_msg[-1] try: device_type = topic_msg[2] device_type_id = device_type_en.get(device_type) if device_type_id == 2: model = MongoSCDData elif device_type_id == 3: model = MongoCBDData elif device_type_id == 8: model = MongoXYCBData # 在设备信息表中查找是否有数据,如果没有数据则增加 device_name = device_type_zh.get(device_type_id) device, is_created = MongoDevice.objects.get_or_create( device_id = device_id, defaults={ "device_id": device_id, "device_type_id": device_type_id, "device_name": device_name, "addtime": now } ) if is_created: logger.info(f"{device_type} 设备 {device_id} 入库成功") # 获取数据并更新设备 if cmd == "data": ext = payload.get("ext") if ext: # 增加设备数据 model.objects.create( device_id = device_id, device_data = str(ext), addtime = now ) lng = ext.get("lng") lat = ext.get("lat") dver_num = ext.get("dver") device.device_status = 1 device.uptime = now if dver_num: device.dver_num = dver_num if lng and lat and dver_num: device.lng = lng device.lat = lat # 根据经纬度获取省市级 is_success, province, city, district = get_addr_by_lag_lng(lat, lng) if is_success: # 更新地理位置坐标 device.province = province device.city = city device.district = district device.save() elif cmd == "offline": ext = data.get("ext") if ext: # 增加设备数据 model.objects.create( device_id=device_id, device_data = str(ext), addtime=now ) # 更新设备状态 device = MongoDevice.objects.filter(device_id=device_id).first() device.device_status = 0 device.save() return Response({"code": 0, "msg": "success"}) except Exception as e: logger.error(f"测报灯设备 {device_id} 处理上报数据或增加设备失败,错误原因:{e.args}") return Response({"code": 2, "msg": f"处理测报灯上报数据失败 {device_id}"}) else: return Response({"code": 2, "msg": "请核对数据结构"}) class QxzDeviceAddAPIViw(APIView): def post(self, request): # 气象站上传数据 request_data = request.data device_id = request_data.get("StationID") uptime = request_data.get("MonitorTime") data = request_data.get("data") if data: # 30分钟上报一次的数据 conf_data = data_deal(data) qxz_data = MongoQXZ_Conf() qxz_data.device_id = 2 qxz_data.e1 = data[1] qxz_data.e2 = data[2] qxz_data.e3 = data[3] qxz_data.e4 = data[4] qxz_data.e5 = data[5] qxz_data.e6 = data[6] qxz_data.e7 = data[7] qxz_data.e8 = data[8] qxz_data.e9 = data[9] qxz_data.e10 = data[10] qxz_data.e11 = data[11] qxz_data.e12 = data[12] qxz_data.e13 = data[13] qxz_data.e14 = data[14] qxz_data.e15 = data[15] qxz_data.e16 = data[16] qxz_data.e17 = data[17] qxz_data.e18 = data[18] qxz_data.e19 = data[19] qxz_data.e20 = data[20] qxz_data.e21 = data[21] qxz_data.e22 = data[22] qxz_data.e23 = data[23] qxz_data.e24 = data[24] qxz_data.e25 = data[25] qxz_data.e26 = data[26] qxz_data.e27 = data[27] qxz_data.e28 = data[28] qxz_data.e29 = data[29] qxz_data.e30 = data[30] class DeviceListAPIView(APIView): def post(self, request): # 设备列表 request_data = request.data device_id = request_data.get("device_id") device_status = request_data.get("device_status") search = request_data.get("search") 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 if device_id: queryset = MongoDevice.objects.filter(device_id=device_id).order_by("-uptime") elif device_status: queryset = MongoDevice.objects.filter(device_status=device_status).order_by("-uptime") elif search: queryset = MongoDevice.objects.filter(Q(device_name__icontains=search) | Q(device_id__icontains=search)) else: queryset = MongoDevice.objects.all().order_by("-uptime") total_obj = queryset.count() paginator = Paginator(queryset, page_size) page_obj = paginator.get_page(page_num) serializers = DeviceSerializers(page_obj, many=True) return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj}) class DeviceChangeAPIView(APIView): def post(self, request): # 修改设备信息 request_data = request.data device_name = request_data.get("device_name") device_id = request_data.get("device_id") lng = request_data.get("lng") lat = request_data.get("lat") device = MongoDevice.objects.get(device_id=device_id) if device_name: device.device_name = device_name if lng and lat: device.lng = lng device.lat = lat is_success, province, city, district = get_addr_by_lag_lng(lat, lng) if is_success: # 更新地理位置坐标 device.province = province device.city = city device.district = district device.save() return Response({"code": 0, "msg": "success"}) class DeviceListAPIView(APIView): def post(self, request): queryset = MongoDevice.objects.order_by('-id') type_dict = {d.id: d.type_name for d in MongoDeviceType.objects.all()} result = [] offline_list = [] type_counter = Counter() device_dict = defaultdict(list) for item in queryset: device_info = item device_type_id = device_info.device_type_id device_status = device_info.device_status is_offline = False if device_status == 1 else True device_id = device_info.device_id if is_offline: offline_list.append(device_id) type_counter[device_type_id] += 1 device_dict[device_type_id].append(device_id) coordinates = "" lng = device_info.lng lat = device_info.lat if not (lng and lat): continue coordinates = f"[{str(float(lng))},{str(float(lat))}]" device_name = device_info.device_name result.append({ 'ld_id': item.id, 'device_id': device_id, 'device_name': device_name or device_id, 'tpye_name': type_dict[device_info.device_type_id], 'device_type_id': device_type_id, 'coordinates': coordinates, 'offline': False if device_status == 1 else True, 'is_warning': False }) statistic_list = [] for k, v in type_counter.items(): statistic_list.append({ 'type_id': k, 'type_count': v, 'type_name': type_dict[k] }) warning_model_dict = { 3: DevicePestWarning } warning_list = [] for k, v in device_dict.items(): try: model_obj = warning_model_dict[k] except KeyError as e: continue war_list = [d.device_id for d in model_obj.objects.filter(device_id__in=v, status=0)] if war_list: warning_list.extend(war_list) for item in result: device_id = item['device_id'] if device_id in warning_list: item['is_warning'] = True warn_and_off = set(warning_list) & set(offline_list) data = { "statistic": statistic_list, 'offline': { 'count': len(offline_list), 'result': offline_list }, "waring": { 'count': len(warning_list), 'result': warning_list }, "warn_and_off": { 'count': len(warn_and_off), 'result': warning_list }, "data": result } return Response({"code": 0, "message": "success", "data": data})