diff --git a/apps/mosquito/api/pagination.py b/apps/mosquito/api/pagination.py index 97cb95d..48ae220 100644 --- a/apps/mosquito/api/pagination.py +++ b/apps/mosquito/api/pagination.py @@ -36,3 +36,9 @@ class DeviceLogHistoryPagination(PageNumberPagination): page_size_query_param = 'limit' page_query_param = 'page' max_page_size = 1000 + +class WeatherlogHistoryPagination(PageNumberPagination): + page_size = 10 + page_size_query_param = 'limit' + page_query_param = 'page' + max_page_size = 1000 \ No newline at end of file diff --git a/apps/mosquito/api/serializers.py b/apps/mosquito/api/serializers.py index 98b453d..5849829 100644 --- a/apps/mosquito/api/serializers.py +++ b/apps/mosquito/api/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from mosquito.models import Mosquito, MosqPost, DeviceTempLog +from mosquito.models import Mosquito, MosqPost, DeviceTempLog, WeatherLog from smart.api.serializers import SmartPushListSerializer @@ -47,3 +47,38 @@ class DeviceTempLogSerializer(serializers.ModelSerializer): def get_create_time(self, obj): return obj.last_time.strftime('%Y-%m-%d %H:%M:%S') + + +class WeatherLogSerializer(serializers.ModelSerializer): + 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_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') diff --git a/apps/mosquito/api/urls.py b/apps/mosquito/api/urls.py index d94165d..f0595b2 100644 --- a/apps/mosquito/api/urls.py +++ b/apps/mosquito/api/urls.py @@ -3,6 +3,7 @@ from .views import ( MosquitoListAPIView, MosquitoPostListAPIView, DeviceTempLogListAPIView, + WeatherLogListAPIView, ) @@ -11,4 +12,6 @@ urlpatterns = [ path('', MosquitoListAPIView.as_view(), name='list'), path('post/', MosquitoPostListAPIView.as_view(), name='post'), path('temp/', DeviceTempLogListAPIView.as_view(), name='temp-hum'), + path('weather/', WeatherLogListAPIView.as_view(), name='weather-log'), + ] \ No newline at end of file diff --git a/apps/mosquito/api/views.py b/apps/mosquito/api/views.py index 32464f5..01d06b0 100644 --- a/apps/mosquito/api/views.py +++ b/apps/mosquito/api/views.py @@ -15,12 +15,13 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.filters import SearchFilter, OrderingFilter from django.db.models import Q from counter.mixins.role import RoleMixin, DeviceListMixin -from ..models import Mosquito, MosqPost, DeviceTempLog -from .pagination import PostLimitOffsetPagination, DeviceLogHistoryPagination +from ..models import Mosquito, MosqPost, DeviceTempLog, WeatherLog +from .pagination import PostLimitOffsetPagination, DeviceLogHistoryPagination, WeatherlogHistoryPagination from .serializers import ( MosqListSerializer, MosqPostListSerializer, DeviceTempLogSerializer, + WeatherLogSerializer, ) @@ -103,3 +104,40 @@ class DeviceTempLogListAPIView(ListAPIView, RoleMixin, DeviceListMixin): queryset = queryset.filter(last_time__gte=start, last_time__lt=end + timedelta(days=1)) return queryset + + +class WeatherLogListAPIView(ListAPIView, RoleMixin, DeviceListMixin): + serializer_class = WeatherLogSerializer + permission_classes = [IsAuthenticated] + filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) + pagination_class = WeatherlogHistoryPagination + search_fields = ['device_id'] + filterset_fields = ['device_id'] + ordering_fields = ['data_time'] + + def get_queryset(self, *args, **kwargs): + user_roles = self.get_role() + start = self.request.GET.get('start') + end = self.request.GET.get('end') + queryset = WeatherLog.objects.get_queryset().order_by('-data_time') + + if 'staff' in user_roles or 'manager' in user_roles: + devices = self.get_device_list() + device_ids = [device.device_id for device in devices if device.org == self.request.user.org] + queryset = queryset.filter(device_id__in=device_ids) + last_day = self.request.GET.get('last_day') + if last_day == '1': + t = datetime.now().replace(tzinfo=pytz.timezone('UTC')) - timedelta(days=1) + queryset = queryset.filter(data_time__gte=t).filter(data_time__minute=0) + + if start and end: + t_pattern = re.compile(r'^2\d{3}-\d{1,2}-\d{1,2}$') + start_m = t_pattern.match(start) + end_m = t_pattern.match(end) + if not start_m or not end_m: + return Response({'detail': 'start or end must be format "yyyy-mm-dd"'}) + start = datetime.strptime(start, '%Y-%m-%d') + end = datetime.strptime(end, '%Y-%m-%d') + queryset = queryset.filter(data_time__gte=start, data_time__lt=end + timedelta(days=1)) + + return queryset diff --git a/apps/mosquito/models.py b/apps/mosquito/models.py index 8fc5a8f..ee36d20 100644 --- a/apps/mosquito/models.py +++ b/apps/mosquito/models.py @@ -116,3 +116,65 @@ class DeviceTempLog(models.Model): def __str__(self): return self.device_id + + +class WeatherLog(models.Model): + data_time = models.DateTimeField(blank=True, null=True, verbose_name='时间') + device_id = models.CharField(max_length=100, verbose_name='台站编号') + device_name = models.CharField(max_length=255, blank=True, null=True, verbose_name='台站名称') + env_temp = models.CharField(max_length=255, blank=True, null=True, verbose_name='环温') + temperature1 = models.CharField(max_length=255, blank=True, null=True, verbose_name='温度1') + temperature2 = models.CharField(max_length=255, blank=True, null=True, verbose_name='温度2') + temperature3 = models.CharField(max_length=255, blank=True, null=True, verbose_name='温度3') + temperature4 = models.CharField(max_length=255, blank=True, null=True, verbose_name='温度4') + temperature5 = models.CharField(max_length=255, blank=True, null=True, verbose_name='温度5') + dew_point_temp = models.CharField(max_length=255, blank=True, null=True, verbose_name='露点温度') + env_humi = models.CharField(max_length=255, blank=True, null=True, verbose_name='环湿') + soil_humi1 = models.CharField(max_length=255, blank=True, null=True, verbose_name='土湿1') + soil_humi2 = models.CharField(max_length=255, blank=True, null=True, verbose_name='土湿2') + soil_humi3 = models.CharField(max_length=255, blank=True, null=True, verbose_name='土湿3') + co2 = models.CharField(max_length=255, blank=True, null=True, verbose_name='CO2') + evaporation = models.CharField(max_length=255, blank=True, null=True, verbose_name='蒸发') + air_pressure = models.CharField(max_length=255, blank=True, null=True, verbose_name='气压') + total_radiation_1_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='总辐射1瞬时') + scat_radiation_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='散辐射瞬时') + direct_radiation_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='直接辐射瞬时') + total_radiation_2_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='总辐射2瞬时') + net_radiation_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='净辐射瞬时') + pho_radiation_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='光合辐射瞬时') + uv_radiation_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='紫外辐射瞬时') + wind_direction = models.CharField(max_length=255, blank=True, null=True, verbose_name='风向') + wind_speed_ins = models.CharField(max_length=255, blank=True, null=True, verbose_name='瞬时风速') + wind_speed_2mins = models.CharField(max_length=255, blank=True, null=True, verbose_name='2分钟风速') + wind_speed_10mins = models.CharField(max_length=255, blank=True, null=True, verbose_name='10分钟风速') + rainfall_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='雨量间隔累计') + sunshine_time_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='日照时间隔累计') + total_radiation_1_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='总辐射1间隔累计') + scat_radiation_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='散辐射间隔累计') + direct_radiation_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='直接辐射间隔累计') + total_radiation_2_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='总辐射2间隔累计') + net_radiation_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='净辐射间隔累计') + pho_radiation_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='光合辐射间隔累计') + uv_radiation_interval_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='紫外辐射间隔累计') + rainfall_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='雨量日累计') + sunshine_time_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='日照时日累计') + total_radiation_1_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='总辐射1日累计') + scat_radiation_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='散辐射日累计') + direct_radiation_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='直接辐射日累计') + total_radiation_2_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='总辐射2日累计') + net_radiation_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='净辐射日累计') + pho_radiation_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='光合辐射日累计') + uv_radiation_daily_cum = models.CharField(max_length=255, blank=True, null=True, verbose_name='紫外辐射日累计') + light_intensity = models.CharField(max_length=255, blank=True, null=True, verbose_name='光照度') + power = models.CharField(max_length=255, blank=True, null=True, verbose_name='电量') + pm25 = models.CharField(max_length=255, blank=True, null=True, verbose_name='PM2.5') + create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') + + class Meta: + managed = False + db_table = 'weather_log' + verbose_name = '气象台数据日志' + verbose_name_plural = verbose_name + + def __str__(self): + return self.device_id