This commit is contained in:
VIJAY\vijay 2023-02-13 11:55:31 +08:00
commit 0e8040e4b1
4 changed files with 265 additions and 27 deletions

View File

@ -1,12 +1,19 @@
import time import time
from typing import Optional
from django.db.models import Q, Min, Max from django.db.models import Q, Min, Max
from django.core.cache import cache from django.core.cache import cache
from rest_framework import serializers from rest_framework import serializers
from counter.models import DeviceCount, DeviceInfo from counter.models import DeviceCount, DeviceInfo
from mosquito.models import DeviceInfo as CelexDeviceInfo from mosquito.models import DeviceInfo as MosquitoDeviceInfo
from mosquito.models import MosqPostStatistic, DevicePostStatistic from mosquito.models import MosqPostStatistic, DevicePostStatistic
class DeviceSourceException(Exception):
"""
source should be counter | mosquito
"""
def get_vol(device_id, cur_vol): def get_vol(device_id, cur_vol):
vol_min_key = '{}_vol_min'.format(device_id) vol_min_key = '{}_vol_min'.format(device_id)
vol_max_key = '{}_vol_max'.format(device_id) vol_max_key = '{}_vol_max'.format(device_id)
@ -35,27 +42,59 @@ def get_latest(device_id):
return data return data
def get_device(device_id):
device_key = 'device_lon_{}'.format(device_id)
device = cache.get(device_key)
if device:
return device
qs = DeviceCount.objects.filter(~Q(longitude=0), device_id=device_id).order_by('-data_time')
if qs.count() == 0:
return None
device = qs.first()
s = DeviceCountBaseSerializer(device)
data = s.data
cache.set(device_key, data, 60 * 10)
return data
class DeviceCountBaseSerializer(serializers.ModelSerializer): class DeviceCountBaseSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = DeviceCount model = DeviceCount
fields = '__all__' fields = '__all__'
class DeviceInfoBaseSerializer(serializers.ModelSerializer):
class Meta:
model = MosquitoDeviceInfo
fields = '__all__'
device_source_map = {
'counter': DeviceCountBaseSerializer,
'mosquito': DeviceInfoBaseSerializer,
}
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 = DeviceCount.objects.filter(~Q(longitude=0),
device_id=device_id).order_by('-data_time')
elif source == 'mosquito':
qs = MosquitoDeviceInfo.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)
return data
class DeviceCountSerializer(serializers.ModelSerializer): class DeviceCountSerializer(serializers.ModelSerializer):
device_name = serializers.SerializerMethodField() device_name = serializers.SerializerMethodField()
mosq_count = serializers.SerializerMethodField() mosq_count = serializers.SerializerMethodField()
@ -103,7 +142,7 @@ class DeviceCountSerializer(serializers.ModelSerializer):
if device: if device:
self.device = device self.device = device
return device.device_name return device.device_name
qs = CelexDeviceInfo.objects.filter(device_id=device_id) qs = MosquitoDeviceInfo.objects.filter(device_id=device_id)
if qs.count() > 0: if qs.count() > 0:
device = qs[0] device = qs[0]
self.device = device self.device = device
@ -126,6 +165,50 @@ class DeviceCountSerializer(serializers.ModelSerializer):
return obj.latitude return obj.latitude
class DeviceCountWithInfoSerializer(DeviceCountSerializer):
location_id = serializers.SerializerMethodField()
point_x = serializers.SerializerMethodField()
point_y = serializers.SerializerMethodField()
class Meta:
model = DeviceCount
fields = [
'id',
'device_id',
'device_name',
'signal',
'mosq_count',
'energy',
'calc_time',
'longitude',
'latitude',
'location_id',
'point_x',
'point_y',
]
def get_location_id(self, obj):
device = self.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 DeviceInfoSerializer(serializers.ModelSerializer): class DeviceInfoSerializer(serializers.ModelSerializer):
device_name = serializers.SerializerMethodField() device_name = serializers.SerializerMethodField()
status = serializers.SerializerMethodField() status = serializers.SerializerMethodField()
@ -154,7 +237,7 @@ class DeviceInfoSerializer(serializers.ModelSerializer):
self.cur_device = None self.cur_device = None
def get_device_name(self, obj): def get_device_name(self, obj):
qs = CelexDeviceInfo.objects.filter(device_id=obj.device_id) qs = MosquitoDeviceInfo.objects.filter(device_id=obj.device_id)
if qs.count() > 0: if qs.count() > 0:
device = qs[0] device = qs[0]
self.cur_device = device self.cur_device = device
@ -164,7 +247,7 @@ class DeviceInfoSerializer(serializers.ModelSerializer):
def get_status(self, obj): def get_status(self, obj):
return obj.online return obj.online
def get_count(self, obj) ->str: def get_count(self, obj) -> str:
try: try:
# self.latest = DeviceCount.objects.filter(device_id=obj.device_id).order_by('-data_time')[0] # self.latest = DeviceCount.objects.filter(device_id=obj.device_id).order_by('-data_time')[0]
self.latest = get_latest(obj.device_id) self.latest = get_latest(obj.device_id)
@ -174,12 +257,12 @@ class DeviceInfoSerializer(serializers.ModelSerializer):
return self.latest['count'] return self.latest['count']
return '0' return '0'
def get_signal(self, obj) ->str: def get_signal(self, obj) -> str:
if self.latest: if self.latest:
return self.latest['csq'] return self.latest['csq']
return '0' return '0'
def get_energy(self, obj) ->str: def get_energy(self, obj) -> str:
if self.latest: if self.latest:
if float(self.latest['vol']) <= 100: if float(self.latest['vol']) <= 100:
return '{}{}'.format(round(float(self.latest['vol']), 1), '%') return '{}{}'.format(round(float(self.latest['vol']), 1), '%')
@ -193,7 +276,7 @@ class DeviceInfoSerializer(serializers.ModelSerializer):
return [lon, lat] return [lon, lat]
# query = DeviceCount.objects.filter(~Q(longitude=0), device_id=obj.device_id).order_by('-data_time') # query = DeviceCount.objects.filter(~Q(longitude=0), device_id=obj.device_id).order_by('-data_time')
device = get_device(obj.device_id) device = get_device(obj.device_id, source='counter')
if device: if device:
return [device['longitude'], device['latitude']] return [device['longitude'], device['latitude']]
return None return None
@ -205,7 +288,6 @@ class DeviceInfoSerializer(serializers.ModelSerializer):
class LatestDailySerializer(serializers.ModelSerializer): class LatestDailySerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = MosqPostStatistic model = MosqPostStatistic
fields = [ fields = [
@ -216,7 +298,6 @@ class LatestDailySerializer(serializers.ModelSerializer):
class DeviceLogHistorySerializer(serializers.ModelSerializer): class DeviceLogHistorySerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = DevicePostStatistic model = DevicePostStatistic
fields = [ fields = [

View File

@ -21,6 +21,7 @@ from mosquito.api.pagination import (
) )
from .serializers import ( from .serializers import (
DeviceCountSerializer, DeviceCountSerializer,
DeviceCountWithInfoSerializer,
DeviceInfoSerializer, DeviceInfoSerializer,
LatestDailySerializer, LatestDailySerializer,
DeviceLogHistorySerializer, DeviceLogHistorySerializer,
@ -32,12 +33,18 @@ from mosquito.models import DeviceInfo as CelexDeviceInfo
class DeviceLogListAPIView(ListAPIView, RoleMixin, DeviceListMixin): class DeviceLogListAPIView(ListAPIView, RoleMixin, DeviceListMixin):
serializer_class = DeviceCountSerializer # serializer_class = DeviceCountSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
filter_backends = [SearchFilter, OrderingFilter] filter_backends = [SearchFilter, OrderingFilter]
pagination_class = DeviceLogListPagination pagination_class = DeviceLogListPagination
search_fields = ['device_id'] search_fields = ['device_id']
def get_serializer_class(self):
with_device = self.request.GET.get('with_device')
if with_device == 'true':
return DeviceCountWithInfoSerializer
return DeviceCountSerializer
def get_queryset(self, *args, **kwargs): def get_queryset(self, *args, **kwargs):
user_roles = self.get_role() user_roles = self.get_role()
device = self.request.GET.get('device') device = self.request.GET.get('device')

View File

@ -1,3 +1,6 @@
import time
from typing import Optional
from django.db.models import Q, Min, Max
from rest_framework import serializers from rest_framework import serializers
from django.core.cache import cache from django.core.cache import cache
from mosquito.models import Mosquito, MosqPost, DeviceTempLog, WeatherLog, WeatherStationInfo, DeviceInfo from mosquito.models import Mosquito, MosqPost, DeviceTempLog, WeatherLog, WeatherStationInfo, DeviceInfo
@ -50,6 +53,66 @@ class DeviceTempLogSerializer(serializers.ModelSerializer):
return obj.last_time.strftime('%Y-%m-%d %H:%M:%S') 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): class WeatherLogSerializer(serializers.ModelSerializer):
power = serializers.SerializerMethodField() power = serializers.SerializerMethodField()
data_time = serializers.SerializerMethodField() data_time = serializers.SerializerMethodField()
@ -88,10 +151,90 @@ class WeatherLogSerializer(serializers.ModelSerializer):
def get_data_time(self, obj): def get_data_time(self, obj):
return obj.data_time.strftime('%Y-%m-%d %H:%M:%S') return obj.data_time.strftime('%Y-%m-%d %H:%M:%S')
def get_create_time(self, obj): def get_create_time(self, obj):
return obj.data_time.strftime('%Y-%m-%d %H:%M:%S') 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 WeatherStationInfoSerializer(serializers.ModelSerializer):
class Meta: class Meta:

View File

@ -28,6 +28,7 @@ from .serializers import (
MosqPostListSerializer, MosqPostListSerializer,
DeviceTempLogSerializer, DeviceTempLogSerializer,
WeatherLogSerializer, WeatherLogSerializer,
WeatherLogWithInfoSerializer,
DeviceInfoSerializer, DeviceInfoSerializer,
WeatherStationInfoSerializer, WeatherStationInfoSerializer,
) )
@ -115,7 +116,7 @@ class DeviceTempLogListAPIView(ListAPIView, RoleMixin, DeviceListMixin):
class WeatherLogListAPIView(ListAPIView, RoleMixin, WeatherStationListMixin): class WeatherLogListAPIView(ListAPIView, RoleMixin, WeatherStationListMixin):
serializer_class = WeatherLogSerializer #serializer_class = WeatherLogSerializer
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
pagination_class = WeatherlogHistoryPagination pagination_class = WeatherlogHistoryPagination
@ -123,6 +124,12 @@ class WeatherLogListAPIView(ListAPIView, RoleMixin, WeatherStationListMixin):
filterset_fields = ['device_id'] filterset_fields = ['device_id']
ordering_fields = ['data_time'] ordering_fields = ['data_time']
def get_serializer_class(self):
with_device = self.request.GET.get('with_device')
if with_device == 'true':
return WeatherLogWithInfoSerializer
return WeatherLogSerializer
def get_queryset(self, *args, **kwargs): def get_queryset(self, *args, **kwargs):
user_roles = self.get_role() user_roles = self.get_role()
device = self.request.GET.get('device') device = self.request.GET.get('device')