import time from typing import Optional from django.db.models import Q, Min, Max from rest_framework import serializers from django.core.cache import cache from mosquito.models import Mosquito, MosqPost, DeviceTempLog, WeatherLog, WeatherStationInfo, DeviceInfo from smart.api.serializers import SmartPushListSerializer class MosqListSerializer(serializers.ModelSerializer): class Meta: model = Mosquito fields = [ 'name', 'device_id', 'region' ] class MosqPostListSerializer(serializers.ModelSerializer): smart_push = SmartPushListSerializer(read_only=True) region = serializers.SerializerMethodField() class Meta: model = MosqPost fields = [ 'id', 'mosq', 'led', 'energy', 'region', 'smart_push', 'time', ] def get_region(self, obj): return obj.mosq.region class DeviceTempLogSerializer(serializers.ModelSerializer): last_time = serializers.SerializerMethodField() create_time = serializers.SerializerMethodField() class Meta: model = DeviceTempLog fields = ['device_id', 'temperature', 'humidity', 'last_time', 'create_time'] def get_last_time(self, obj): return obj.last_time.strftime('%Y-%m-%d %H:%M:%S') def get_create_time(self, obj): return obj.last_time.strftime('%Y-%m-%d %H:%M:%S') class DeviceSourceException(Exception): """ source should be counter | mosquito """ class WeatherLogBaseSerializer(serializers.ModelSerializer): class Meta: model = WeatherLog fields = '__all__' class WeatherStationInfoBaseSerializer(serializers.ModelSerializer): class Meta: model = WeatherStationInfo fields = '__all__' device_source_map = { 'counter': WeatherLogBaseSerializer, 'mosquito': WeatherStationInfoBaseSerializer, } def get_device(device_id: str, source: str) -> Optional[dict]: """ Get device data serialized by DeviceCountBaseSerializer (counter) or DeviceInfoBaseSerializer (mosquito), For source 'counter', we get device from device_counter table not device_info, because the [lon, lat] info is located in device_counter. For source 'mosquito', we get device from mosquito/DeviceInfo model, due to the [point_x, point_y] is what we want. params: device_id, params: source, counter | mosquito return: dict """ device_key = 'device_lon_{}'.format(device_id) device = cache.get(device_key) if device: return device if source == 'counter': qs = WeatherLog.objects.filter(~Q(longitude=0), device_id=device_id).order_by('-data_time') elif source == 'mosquito': qs = WeatherStationInfo.objects.filter(device_id=device_id) else: raise DeviceSourceException("source should be counter or mosquito") if qs.count() == 0: return None device = qs.first() s = device_source_map[source](device) data = s.data cache.set(device_key, data, 60 * 10) print(data) return data class WeatherLogSerializer(serializers.ModelSerializer): power = serializers.SerializerMethodField() data_time = serializers.SerializerMethodField() create_time = serializers.SerializerMethodField() class Meta: model = WeatherLog fields = [ 'data_time', 'device_id', 'device_name', 'env_temp', 'temperature1', 'temperature2', 'temperature3', 'temperature4', 'temperature5', 'dew_point_temp', 'env_humi', 'soil_humi1', 'soil_humi2', 'soil_humi3', 'co2', 'evaporation', 'air_pressure', 'total_radiation_1_ins', 'scat_radiation_ins', 'direct_radiation_ins', 'total_radiation_2_ins', 'net_radiation_ins', 'pho_radiation_ins', 'uv_radiation_ins', 'wind_direction', 'wind_speed_ins', 'wind_speed_2mins', 'wind_speed_10mins', 'rainfall_interval_cum', 'sunshine_time_interval_cum', 'total_radiation_1_interval_cum', 'scat_radiation_interval_cum', 'direct_radiation_interval_cum', 'total_radiation_2_interval_cum', 'net_radiation_interval_cum', 'pho_radiation_interval_cum', 'uv_radiation_interval_cum', 'rainfall_daily_cum', 'sunshine_time_daily_cum', 'total_radiation_1_daily_cum', 'scat_radiation_daily_cum', 'direct_radiation_daily_cum', 'total_radiation_2_daily_cum', 'net_radiation_daily_cum', 'pho_radiation_daily_cum', 'uv_radiation_daily_cum', 'light_intensity', 'power', 'pm25', 'create_time', ] def get_power(self, obj): # power max 12.6V, min 8.5V power = int((float(obj.power) - 8.5) / 4.1 * 100) return str(power) def get_data_time(self, obj): return obj.data_time.strftime('%Y-%m-%d %H:%M:%S') def get_create_time(self, obj): return obj.data_time.strftime('%Y-%m-%d %H:%M:%S') class WeatherLogWithInfoSerializer(WeatherLogSerializer): longitude = serializers.SerializerMethodField() latitude = serializers.SerializerMethodField() location_id = serializers.SerializerMethodField() point_x = serializers.SerializerMethodField() point_y = serializers.SerializerMethodField() class Meta: model = WeatherLog fields = [ 'data_time', 'device_id', 'device_name', 'env_temp', 'temperature1', 'temperature2', 'temperature3', 'temperature4', 'temperature5', 'dew_point_temp', 'env_humi', 'soil_humi1', 'soil_humi2', 'soil_humi3', 'co2', 'evaporation', 'air_pressure', 'total_radiation_1_ins', 'scat_radiation_ins', 'direct_radiation_ins', 'total_radiation_2_ins', 'net_radiation_ins', 'pho_radiation_ins', 'uv_radiation_ins', 'wind_direction', 'wind_speed_ins', 'wind_speed_2mins', 'wind_speed_10mins', 'rainfall_interval_cum', 'sunshine_time_interval_cum', 'total_radiation_1_interval_cum', 'scat_radiation_interval_cum', 'direct_radiation_interval_cum', 'total_radiation_2_interval_cum', 'net_radiation_interval_cum', 'pho_radiation_interval_cum', 'uv_radiation_interval_cum', 'rainfall_daily_cum', 'sunshine_time_daily_cum', 'total_radiation_1_daily_cum', 'scat_radiation_daily_cum', 'direct_radiation_daily_cum', 'total_radiation_2_daily_cum', 'net_radiation_daily_cum', 'pho_radiation_daily_cum', 'uv_radiation_daily_cum', 'light_intensity', 'power', 'pm25', 'create_time', 'longitude', 'latitude', 'location_id', 'point_x', 'point_y', ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.device = None def get_longitude(self, obj): device = self.device print(device) if device: if device.longitude: return device.longitude return None def get_latitude(self, obj): device = self.device print(device) if device: if device.latitude: return device.latitude return None def get_location_id(self, obj): device = self.device print(device) if device: if device.location_id: return device.location_id return None def get_point_x(self, obj): device = self.device if device: if device.point_x: return device.point_x return None def get_point_y(self, obj): device = self.device if device: if device.point_y: return device.point_y return None class WeatherStationInfoSerializer(serializers.ModelSerializer): class Meta: model = WeatherStationInfo fields = [ 'device_id', 'device_name', 'longitude', 'latitude', 'location_id', 'point_x', 'point_y', ] class DeviceInfoSerializer(serializers.ModelSerializer): class Meta: model = DeviceInfo fields = [ 'device_id', 'device_name', 'longitude', 'latitude', 'weather_device_id', 'weather_code', 'location_id', 'point_x', 'point_y', ]