UPDATE
This commit is contained in:
+154
-9
@@ -11,18 +11,163 @@ from notifications.serializers import FarmNotificationSerializer
|
||||
from soil.serializers import SoilComparisonChartSerializer, SoilRadarChartSerializer
|
||||
|
||||
from .authentication import SensorExternalAPIKeyAuthentication
|
||||
from .sensor_serializers import Sensor7In1SummarySerializer, SensorComparisonChartQuerySerializer, SensorComparisonChartResponseSerializer, SensorRadarChartQuerySerializer, SensorRadarChartResponseSerializer, SensorValuesListQuerySerializer, SensorValuesListResponseSerializer
|
||||
from .serializers import SensorCatalogSerializer, SensorExternalRequestLogQuerySerializer, SensorExternalRequestLogSerializer, SensorExternalRequestSerializer
|
||||
from .services import FarmDataForwardError, create_sensor_external_notification, forward_sensor_payload_to_farm_data, get_farm_sensor_map_for_logs, get_primary_soil_sensor, get_sensor_7_in_1_comparison_chart_data, get_sensor_7_in_1_radar_chart_data, get_sensor_7_in_1_summary_data, get_sensor_comparison_chart_data, get_sensor_external_request_logs_for_farm, get_sensor_radar_chart_data, get_sensor_values_list_data
|
||||
from .sensor_serializers import DeviceSummarySerializer, Sensor7In1SummarySerializer, SensorComparisonChartQuerySerializer, SensorComparisonChartResponseSerializer, SensorRadarChartQuerySerializer, SensorRadarChartResponseSerializer, SensorValuesListQuerySerializer, SensorValuesListResponseSerializer
|
||||
from .serializers import DeviceCatalogSerializer, DeviceCodeQuerySerializer, DeviceCommandRequestSerializer, DeviceCommandResponseSerializer, DeviceDetailSerializer, DeviceLatestPayloadSerializer, DeviceRangeQuerySerializer, SensorExternalRequestLogQuerySerializer, SensorExternalRequestLogSerializer, SensorExternalRequestSerializer
|
||||
from .services import FarmDataForwardError, build_device_comparison_chart, build_device_latest_payload, build_device_radar_chart, build_device_summary, build_device_values_list, create_sensor_external_notification, execute_device_command, forward_sensor_payload_to_farm_data, get_farm_device_by_physical_uuid, get_farm_device_map_for_logs, get_primary_soil_sensor, get_sensor_7_in_1_comparison_chart_data, get_sensor_7_in_1_radar_chart_data, get_sensor_7_in_1_summary_data, get_sensor_comparison_chart_data, get_sensor_external_request_logs_for_farm, get_sensor_radar_chart_data, get_sensor_values_list_data, validate_output_device_catalog
|
||||
|
||||
|
||||
class SensorCatalogListView(APIView):
|
||||
class DeviceCatalogListView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@extend_schema(tags=["Sensor Catalog"], responses={200: code_response("SensorCatalogListResponse", data=SensorCatalogSerializer(many=True))})
|
||||
@extend_schema(tags=["Sensor Catalog"], responses={200: code_response("DeviceCatalogListResponse", data=DeviceCatalogSerializer(many=True))})
|
||||
def get(self, request):
|
||||
from .models import SensorCatalog
|
||||
return Response({"code": 200, "msg": "success", "data": SensorCatalogSerializer(SensorCatalog.objects.order_by("code"), many=True).data}, status=status.HTTP_200_OK)
|
||||
from .models import DeviceCatalog
|
||||
return Response({"code": 200, "msg": "success", "data": DeviceCatalogSerializer(DeviceCatalog.objects.order_by("code"), many=True).data}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceBaseView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_farm_device(self, request, physical_device_uuid):
|
||||
farm_device = get_farm_device_by_physical_uuid(physical_device_uuid=physical_device_uuid, owner=request.user)
|
||||
if farm_device is None:
|
||||
raise serializers.ValidationError({"physical_device_uuid": ["Device not found."]})
|
||||
return farm_device
|
||||
|
||||
def get_device_code(self, request):
|
||||
serializer = DeviceCodeQuerySerializer(data=request.query_params)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return serializer.validated_data["device_code"]
|
||||
|
||||
|
||||
class DeviceDetailView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True)], responses={200: code_response("DeviceDetailResponse", data=DeviceDetailSerializer())})
|
||||
def get(self, request, physical_device_uuid):
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
device_code = self.get_device_code(request)
|
||||
validate_output_device_catalog(farm_device=farm_device, device_code=device_code)
|
||||
latest_payload = build_device_latest_payload(farm_device, device_code=device_code)
|
||||
serializer = DeviceDetailSerializer(farm_device, context={"latest_log": type("LatestLog", (), {"created_at": latest_payload["created_at"]})() if latest_payload["created_at"] else None})
|
||||
return Response({"code": 200, "msg": "success", "data": serializer.data}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceLatestPayloadView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True)], responses={200: code_response("DeviceLatestPayloadResponse", data=DeviceLatestPayloadSerializer())})
|
||||
def get(self, request, physical_device_uuid):
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
device_code = self.get_device_code(request)
|
||||
try:
|
||||
data = build_device_latest_payload(farm_device, device_code=device_code)
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
return Response({"code": 200, "msg": "success", "data": data}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceSummaryView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True)], responses={200: code_response("DeviceSummaryResponse", data=DeviceSummarySerializer())})
|
||||
def get(self, request, physical_device_uuid):
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
device_code = self.get_device_code(request)
|
||||
try:
|
||||
data = build_device_summary(farm_device, device_code=device_code)
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
return Response({"code": 200, "msg": "success", "data": data}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceComparisonChartView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True), OpenApiParameter(name="range", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=False, description="Chart range, supported values: 7d, 30d. Defaults to 7d.")], responses={200: SensorComparisonChartResponseSerializer})
|
||||
def get(self, request, physical_device_uuid):
|
||||
serializer = DeviceRangeQuerySerializer(data={"device_code": request.query_params.get("device_code"), "range": request.query_params.get("range", "7d")})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
try:
|
||||
data = build_device_comparison_chart(farm_device, serializer.validated_data["range"], device_code=serializer.validated_data["device_code"])
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceValuesListView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True), OpenApiParameter(name="range", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=False, description="Values list range, supported values: 1h, 24h, 7d. Defaults to 7d.")], responses={200: SensorValuesListResponseSerializer})
|
||||
def get(self, request, physical_device_uuid):
|
||||
serializer = DeviceRangeQuerySerializer(data={"device_code": request.query_params.get("device_code"), "range": request.query_params.get("range", "7d")})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
try:
|
||||
data = build_device_values_list(farm_device, serializer.validated_data["range"], device_code=serializer.validated_data["device_code"])
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceRadarChartView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True), OpenApiParameter(name="range", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=False, description="Radar chart range, supported values: today, 7d, 30d. Defaults to 7d.")], responses={200: SensorRadarChartResponseSerializer})
|
||||
def get(self, request, physical_device_uuid):
|
||||
serializer = DeviceRangeQuerySerializer(data={"device_code": request.query_params.get("device_code"), "range": request.query_params.get("range", "7d")})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
try:
|
||||
data = build_device_radar_chart(farm_device, serializer.validated_data["range"], device_code=serializer.validated_data["device_code"])
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceLogListView(DeviceBaseView):
|
||||
pagination_class = SensorExternalRequestLogPagination
|
||||
|
||||
@extend_schema(tags=["Device Hub"], parameters=[OpenApiParameter(name="device_code", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY, required=True), OpenApiParameter(name="page", type=OpenApiTypes.INT, location=OpenApiParameter.QUERY, required=True), OpenApiParameter(name="page_size", type=OpenApiTypes.INT, location=OpenApiParameter.QUERY, required=True)], responses={200: code_response("DeviceLogListResponse", data=SensorExternalRequestLogSerializer(many=True), extra_fields={"count": serializers.IntegerField(), "next": serializers.CharField(allow_null=True), "previous": serializers.CharField(allow_null=True)})})
|
||||
def get(self, request, physical_device_uuid):
|
||||
page = request.query_params.get("page", 1)
|
||||
page_size = request.query_params.get("page_size", 20)
|
||||
device_code = request.query_params.get("device_code")
|
||||
serializer = SensorExternalRequestLogQuerySerializer(
|
||||
data={
|
||||
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
||||
"page": page,
|
||||
"page_size": page_size,
|
||||
"physical_device_uuid": physical_device_uuid,
|
||||
}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
try:
|
||||
device_catalog = validate_output_device_catalog(farm_device=farm_device, device_code=device_code)
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
queryset = get_sensor_external_request_logs_for_farm(
|
||||
farm_uuid=farm_device.farm.farm_uuid,
|
||||
physical_device_uuid=farm_device.physical_device_uuid,
|
||||
)
|
||||
queryset = queryset.filter(sensor_catalog_uuid=device_catalog.uuid)
|
||||
paginator = self.pagination_class()
|
||||
paginator.page_size = serializer.validated_data["page_size"]
|
||||
page_obj = paginator.paginate_queryset(queryset, request, view=self)
|
||||
farm_device_map = get_farm_device_map_for_logs(logs=page_obj)
|
||||
data = SensorExternalRequestLogSerializer(page_obj, many=True, context={"farm_device_map": farm_device_map}).data
|
||||
return Response({"code": 200, "msg": "success", "count": paginator.page.paginator.count, "next": paginator.get_next_link(), "previous": paginator.get_previous_link(), "data": data}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class DeviceCommandView(DeviceBaseView):
|
||||
@extend_schema(tags=["Device Hub"], request=DeviceCommandRequestSerializer, responses={200: code_response("DeviceCommandResponse", data=DeviceCommandResponseSerializer())})
|
||||
def post(self, request, physical_device_uuid):
|
||||
serializer = DeviceCommandRequestSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
farm_device = self.get_farm_device(request, physical_device_uuid)
|
||||
try:
|
||||
device_catalog = farm_device.get_device_catalog_by_code(serializer.validated_data["device_code"])
|
||||
if device_catalog is None:
|
||||
raise ValueError("Device code is not attached to this farm device.")
|
||||
result = execute_device_command(
|
||||
farm_device=farm_device,
|
||||
device_code=serializer.validated_data["device_code"],
|
||||
command=serializer.validated_data["command"],
|
||||
payload=serializer.validated_data.get("payload"),
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise serializers.ValidationError({"device_code": [str(exc)]}) from exc
|
||||
return Response({"code": 200, "msg": "command accepted", "data": result}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class Sensor7In1SummaryView(APIView):
|
||||
@@ -137,6 +282,6 @@ class SensorExternalRequestLogListAPIView(APIView):
|
||||
paginator = self.pagination_class()
|
||||
paginator.page_size = serializer.validated_data["page_size"]
|
||||
page = paginator.paginate_queryset(queryset, request, view=self)
|
||||
farm_sensor_map = get_farm_sensor_map_for_logs(logs=page)
|
||||
data = SensorExternalRequestLogSerializer(page, many=True, context={"farm_sensor_map": farm_sensor_map}).data
|
||||
farm_device_map = get_farm_device_map_for_logs(logs=page)
|
||||
data = SensorExternalRequestLogSerializer(page, many=True, context={"farm_device_map": farm_device_map}).data
|
||||
return Response({"code": 200, "msg": "success", "count": paginator.page.paginator.count, "next": paginator.get_next_link(), "previous": paginator.get_previous_link(), "data": data}, status=status.HTTP_200_OK)
|
||||
|
||||
Reference in New Issue
Block a user