1
0
Fork 0
satnogs-db/db/api/views.py

195 lines
7.8 KiB
Python
Raw Normal View History

"""SatNOGS DB API django rest framework Views"""
2017-03-02 10:55:10 -07:00
from django.core.files.base import ContentFile
from django.db.models import F
from rest_framework import mixins, status, viewsets
from rest_framework.parsers import FileUploadParser, FormParser, MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer
from rest_framework.response import Response
from rest_framework.serializers import ValidationError
2015-04-22 05:05:30 -06:00
from db.api import filters, pagination, serializers
from db.api.perms import SafeMethodsWithPermission
from db.api.renderers import BrowserableJSONLDRenderer, JSONLDRenderer
from db.base.helpers import gridsquare
from db.base.models import Artifact, DemodData, LatestTleSet, Mode, Satellite, Transmitter
from db.base.tasks import update_satellite
2015-04-22 05:05:30 -06:00
class ModeView(viewsets.ReadOnlyModelViewSet): # pylint: disable=R0901
"""View into the transmitter modulation modes in the SatNOGS DB database"""
renderer_classes = [
JSONRenderer, BrowsableAPIRenderer, JSONLDRenderer, BrowserableJSONLDRenderer
]
2015-08-13 06:57:04 -06:00
queryset = Mode.objects.all()
serializer_class = serializers.ModeSerializer
class SatelliteView(viewsets.ReadOnlyModelViewSet): # pylint: disable=R0901
"""View into the Satellite entities in the SatNOGS DB database"""
renderer_classes = [
JSONRenderer, BrowsableAPIRenderer, JSONLDRenderer, BrowserableJSONLDRenderer
]
2015-05-03 15:23:07 -06:00
queryset = Satellite.objects.all()
serializer_class = serializers.SatelliteSerializer
filterset_class = filters.SatelliteViewFilter
lookup_field = 'norad_cat_id'
2015-05-03 15:23:07 -06:00
class TransmitterView(viewsets.ReadOnlyModelViewSet): # pylint: disable=R0901
"""
View into the Transmitter entities in the SatNOGS DB database.
Transmitters are inclusive of Transceivers and Transponders
"""
renderer_classes = [
JSONRenderer, BrowsableAPIRenderer, JSONLDRenderer, BrowserableJSONLDRenderer
]
2015-07-23 06:48:58 -06:00
queryset = Transmitter.objects.all()
serializer_class = serializers.TransmitterSerializer
filterset_class = filters.TransmitterViewFilter
lookup_field = 'uuid'
class LatestTleSetView(viewsets.ReadOnlyModelViewSet): # pylint: disable=R0901
"""
View into the most recent two-line elements (TLE) in the SatNOGS DB database
"""
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
queryset = LatestTleSet.objects.all().select_related('satellite').exclude(
latest_distributable__isnull=True
).annotate(
tle0=F('latest_distributable__tle0'),
tle1=F('latest_distributable__tle1'),
tle2=F('latest_distributable__tle2'),
tle_source=F('latest_distributable__tle_source'),
updated=F('latest_distributable__updated')
)
serializer_class = serializers.LatestTleSetSerializer
filterset_class = filters.LatestTleSetViewFilter
def get_queryset(self):
"""
Returns latest TLE queryset depending on user permissions
"""
if self.request.user.has_perm('base.access_all_tles'):
return LatestTleSet.objects.all().select_related('satellite').exclude(
latest__isnull=True
).annotate(
tle0=F('latest__tle0'),
tle1=F('latest__tle1'),
tle2=F('latest__tle2'),
tle_source=F('latest__tle_source'),
updated=F('latest__updated')
)
return self.queryset
class TelemetryView( # pylint: disable=R0901
mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin,
viewsets.GenericViewSet):
"""
View into the Telemetry objects in the SatNOGS DB database. Currently,
this table is inclusive of all data collected from satellite downlink
observations
"""
renderer_classes = [
JSONRenderer, BrowsableAPIRenderer, JSONLDRenderer, BrowserableJSONLDRenderer
]
queryset = DemodData.objects.all()
serializer_class = serializers.TelemetrySerializer
filterset_class = filters.TelemetryViewFilter
permission_classes = [SafeMethodsWithPermission]
2017-03-02 10:55:10 -07:00
parser_classes = (FormParser, FileUploadParser)
pagination_class = pagination.LinkedHeaderPageNumberPagination
2017-03-02 10:55:10 -07:00
def create(self, request, *args, **kwargs):
"""
Creates an frame of telemetry data from a satellite observation. See
https://www.pe0sat.vgnet.nl/download/Hidden/Dombrovski-SIDS-Simple-Downlink-Share-Convention.pdf
for a description of the original protocol.
"""
2017-03-02 10:55:10 -07:00
data = {}
2017-11-24 14:58:09 -07:00
norad_cat_id = request.data.get('noradID')
if not Satellite.objects.filter(norad_cat_id=norad_cat_id).exists():
2017-11-24 14:58:09 -07:00
try:
update_satellite(norad_cat_id, update_name=True)
except LookupError:
2017-11-24 14:58:09 -07:00
return Response(status=status.HTTP_400_BAD_REQUEST)
data['satellite'] = Satellite.objects.get(norad_cat_id=norad_cat_id).id
2017-03-02 10:55:10 -07:00
data['station'] = request.data.get('source')
timestamp = request.data.get('timestamp')
data['timestamp'] = timestamp
# Convert coordinates to omit N-S and W-E designators
lat = request.data.get('latitude')
lng = request.data.get('longitude')
2017-04-05 11:28:04 -06:00
if any(x.isalpha() for x in lat):
2017-11-13 03:33:17 -07:00
data['lat'] = (-float(lat[:-1]) if ('S' in lat) else float(lat[:-1]))
2017-04-05 11:28:04 -06:00
else:
data['lat'] = float(lat)
if any(x.isalpha() for x in lng):
2017-11-13 03:33:17 -07:00
data['lng'] = (-float(lng[:-1]) if ('W' in lng) else float(lng[:-1]))
2017-04-05 11:28:04 -06:00
else:
data['lng'] = float(lng)
2017-03-02 10:55:10 -07:00
# Network or SiDS submission?
if request.data.get('satnogs_network'):
data['app_source'] = 'network'
else:
data['app_source'] = 'sids'
2017-03-02 10:55:10 -07:00
# Create file out of frame string
frame = ContentFile(request.data.get('frame'), name='sids')
data['payload_frame'] = frame
# Create observer
qth = gridsquare(data['lat'], data['lng'])
observer = '{0}-{1}'.format(data['station'], qth)
data['observer'] = observer
2017-03-02 10:55:10 -07:00
serializer = serializers.SidsSerializer(data=data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(status=status.HTTP_201_CREATED, headers=headers)
class ArtifactView( # pylint: disable=R0901
mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin,
viewsets.GenericViewSet):
"""
Artifacts are objects collected in relation to a satellite observation.
"""
queryset = Artifact.objects.all()
filterset_class = filters.ArtifactViewFilter
permission_classes = [IsAuthenticated]
parser_classes = (FormParser, MultiPartParser)
pagination_class = pagination.LinkedHeaderPageNumberPagination
def get_serializer_class(self):
"""Returns the right serializer depending on http method that is used"""
if self.action == 'create':
return serializers.NewArtifactSerializer
return serializers.ArtifactSerializer
def create(self, request, *args, **kwargs):
"""
Creates observation artifact
* Requires session or key authentication to create an artifact
"""
serializer = self.get_serializer(data=request.data)
try:
if serializer.is_valid():
data = serializer.save()
http_response = {}
http_response['id'] = data.id
response = Response(http_response, status=status.HTTP_200_OK)
else:
data = serializer.errors
response = Response(data, status=status.HTTP_400_BAD_REQUEST)
except (ValidationError, ValueError, OSError) as error:
response = Response(str(error), status=status.HTTP_400_BAD_REQUEST)
return response