From 7c7115f9bef366260a6997dfe6c0007d0a5f08d1 Mon Sep 17 00:00:00 2001 From: Nikos Roussos Date: Tue, 28 Mar 2017 20:39:53 +0300 Subject: [PATCH] Expose more fields to Telemetry API endpoint * Rename decoded API fields for clarity --- .travis.yml | 2 ++ db/api/serializers.py | 22 +++++++++++++++++----- db/api/tests.py | 31 +++++++++++++++++++++++++++---- db/base/models.py | 4 ++++ db/base/tests.py | 4 ++-- db/static/js/app.backbone.js | 24 ++++++++++++------------ 6 files changed, 64 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index b010b06..d9e6ee7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: python dist: trusty +notifications: + email: false python: - "2.7" install: diff --git a/db/api/serializers.py b/db/api/serializers.py index 3a7363e..ec58933 100644 --- a/db/api/serializers.py +++ b/db/api/serializers.py @@ -37,25 +37,37 @@ class TransmitterSerializer(serializers.ModelSerializer): class TelemetrySerializer(serializers.ModelSerializer): norad_cat_id = serializers.SerializerMethodField() - appendix = serializers.SerializerMethodField() - telemetry = serializers.SerializerMethodField() + transmitter = serializers.SerializerMethodField() + schema = serializers.SerializerMethodField() + decoded = serializers.SerializerMethodField() + frame = serializers.SerializerMethodField() class Meta: model = DemodData - fields = ('norad_cat_id', 'appendix', 'telemetry') + fields = ('norad_cat_id', 'transmitter', 'source', 'schema', 'decoded', 'frame', + 'observer', 'timestamp') def get_norad_cat_id(self, obj): return obj.satellite.norad_cat_id - def get_appendix(self, obj): + def get_transmitter(self, obj): + try: + return obj.transmitter.uuid + except: + return '' + + def get_schema(self, obj): try: return obj.payload_telemetry.schema except: return '' - def get_telemetry(self, obj): + def get_decoded(self, obj): return obj.payload_decoded + def get_frame(self, obj): + return obj.display_frame() + class SidsSerializer(serializers.ModelSerializer): class Meta: diff --git a/db/api/tests.py b/db/api/tests.py index 569bb47..746f5bd 100644 --- a/db/api/tests.py +++ b/db/api/tests.py @@ -3,7 +3,7 @@ import pytest from rest_framework import status from django.test import TestCase -from db.base.tests import ModeFactory, SatelliteFactory, TransmitterFactory +from db.base.tests import ModeFactory, SatelliteFactory, TransmitterFactory, DemodDataFactory @pytest.mark.django_db(transaction=True) @@ -22,7 +22,8 @@ class ModeViewApiTest(TestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) def test_retrieve(self): - response = self.client.get('/api/modes/%s/' % self.mode.id) + response = self.client.get('/api/modes/{0}/'.format(self.mode.id), + format='json') self.assertContains(response, self.mode.name) @@ -42,7 +43,8 @@ class SatelliteViewApiTest(TestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) def test_retrieve(self): - response = self.client.get('/api/satellites/%s/' % self.satellite.norad_cat_id) + response = self.client.get('/api/satellites/{0}/'.format(self.satellite.norad_cat_id), + format='json') self.assertContains(response, self.satellite.name) @@ -63,5 +65,26 @@ class TransmitterViewApiTest(TestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) def test_retrieve(self): - response = self.client.get('/api/transmitters/%s/' % self.transmitter.uuid) + response = self.client.get('/api/transmitters/{0}/'.format(self.transmitter.uuid), + format='json') self.assertContains(response, self.transmitter.description) + + +@pytest.mark.django_db(transaction=True) +class TelemetryViewApiTest(TestCase): + """ + Tests the Telemetry View API + """ + datum = None + + def setUp(self): + self.datum = DemodDataFactory() + self.datum.save() + + def test_list(self): + response = self.client.get('/api/telemetry/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_retrieve(self): + response = self.client.get('/api/telemetry/{0}/'.format(self.datum.id), format='json') + self.assertContains(response, self.datum.observer) diff --git a/db/base/models.py b/db/base/models.py index f1d87f4..9bbd8c1 100644 --- a/db/base/models.py +++ b/db/base/models.py @@ -176,5 +176,9 @@ class DemodData(models.Model): def __unicode__(self): return 'data-for-{0}'.format(self.satellite.norad_cat_id) + def display_frame(self): + with open(self.payload_frame.path) as fp: + return fp.read() + post_save.connect(_gen_observer, sender=DemodData) diff --git a/db/base/tests.py b/db/base/tests.py index d819a1f..bbcd4a7 100644 --- a/db/base/tests.py +++ b/db/base/tests.py @@ -105,8 +105,8 @@ class DemodDataFactory(factory.django.DjangoModelFactory): source = fuzzy.FuzzyChoice(choices=DATA_SOURCE_IDS) data_id = fuzzy.FuzzyInteger(0, 200) payload_frame = factory.django.FileField(filename='data.raw') - payload_decoded = None - payload_telemetry = None + payload_decoded = '{}' + payload_telemetry = factory.SubFactory(TelemetryFactory) station = fuzzy.FuzzyText() lat = fuzzy.FuzzyFloat(-20, 70) lng = fuzzy.FuzzyFloat(-180, 180) diff --git a/db/static/js/app.backbone.js b/db/static/js/app.backbone.js index 0dda666..8f1e28d 100644 --- a/db/static/js/app.backbone.js +++ b/db/static/js/app.backbone.js @@ -23,7 +23,7 @@ d3.lineChart = function(telemetry_key, unit) { var x1 = d3.scale.ordinal() .domain(_data.map(function(d){ - return parseDate(d.telemetry.observation_datetime); + return parseDate(d.decoded.observation_datetime); })) .rangePoints([0, chartW]); @@ -32,13 +32,13 @@ d3.lineChart = function(telemetry_key, unit) { switch(_data.length) { case 1: y1 = d3.scale.linear() - .domain([0, d3.max(_data, function(d){ return +d.telemetry.damod_data[telemetry_key]; })]) + .domain([0, d3.max(_data, function(d){ return +d.decoded.damod_data[telemetry_key]; })]) .range([chartH, 0]) .nice(4); break; default: y1 = d3.scale.linear() - .domain(d3.extent(_data, function(d){ return +d.telemetry.damod_data[telemetry_key]; })) + .domain(d3.extent(_data, function(d){ return +d.decoded.damod_data[telemetry_key]; })) .range([chartH, 0]) .nice(4); } @@ -102,13 +102,13 @@ d3.lineChart = function(telemetry_key, unit) { .enter().append('circle') .attr('r', 4) .attr('cx', function() { return chartW / 2 + config.margin.left; }) - .attr('cy', function(d) { return y1(d.telemetry.damod_data[telemetry_key]) + config.margin.top; }) + .attr('cy', function(d) { return y1(d.decoded.damod_data[telemetry_key]) + config.margin.top; }) .attr('class', 'circle') .on('mouseover', function(d) { div.transition() .duration(200) .style('opacity', 1); - div.html(d.telemetry.damod_data[telemetry_key] + ' (' + unit + ')') + div.html(d.decoded.damod_data[telemetry_key] + ' (' + unit + ')') .style('left', (d3.event.pageX) + 'px') .style('top', (d3.event.pageY - 26) + 'px'); }) @@ -124,7 +124,7 @@ d3.lineChart = function(telemetry_key, unit) { // Define the line var valueline = d3.svg.line() .x(function(d,i) { return (xInterval*i + config.margin.left); }) - .y(function(d) { return y1(d.telemetry.damod_data[telemetry_key]) + config.margin.top; }); + .y(function(d) { return y1(d.decoded.damod_data[telemetry_key]) + config.margin.top; }); // Add the valueline path svg.append('path') @@ -137,13 +137,13 @@ d3.lineChart = function(telemetry_key, unit) { .enter().append('circle') .attr('r', 4) .attr('cx', function(d, i) { return xInterval*i + config.margin.left; }) - .attr('cy', function(d) { return y1(d.telemetry.damod_data[telemetry_key]) + config.margin.top; }) + .attr('cy', function(d) { return y1(d.decoded.damod_data[telemetry_key]) + config.margin.top; }) .attr('class', 'circle') .on('mouseover', function(d) { div.transition() .duration(200) .style('opacity', 1); - div.html(d.telemetry.damod_data[telemetry_key] + ' (' + unit + ')') + div.html(d.decoded.damod_data[telemetry_key] + ' (' + unit + ')') .style('left', (d3.event.pageX) + 'px') .style('top', (d3.event.pageY - 26) + 'px'); }) @@ -197,18 +197,18 @@ if (has_telemetry_data) { var TelemetryDescriptors = TelemetryCollection.extend({ parse: function(response){ if(response.length !== 0) { - return response[0].appendix; + return response[0].schema; } } }); var TelemetryValues = TelemetryCollection.extend({ comparator: function(collection){ - return( collection.get('telemetry').observation_datetime ); + return( collection.get('decoded').observation_datetime ); }, byDate: function (start_date, end_date) { var filtered = this.filter(function (model) { - var date = parseDateFilter(model.get('telemetry').observation_datetime); + var date = parseDateFilter(model.get('decoded').observation_datetime); return ( date >= start_date && date <= end_date ); }); return new TelemetryValues(filtered); @@ -252,7 +252,7 @@ if (has_telemetry_data) { var data = this.collection.toJSON(); this.chartSelection = d3.select(this.el) .datum(data) - .call(d3.lineChart(data[0].appendix[0].key, data[0].appendix[0].unit)); + .call(d3.lineChart(data[0].schema[0].key, data[0].schema[0].unit)); } else { this.renderPlaceholder(); }