diff --git a/.travis.yml b/.travis.yml
index 8236818..0d42737 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,6 +42,11 @@ jobs:
- docker-compose -f docker/docker-compose.yml up -d
script:
- docker-compose -f docker/docker-compose.yml exec bite python manage.py test
+ - stage: django
+ install:
+ - pip3 -q install flake8
+ script:
+ - flake8 bite --exclude migrations,settings.py
- <<: *iot-simulator
env: IOT_TL=http
- <<: *iot-simulator
diff --git a/bite/api/views.py b/bite/api/views.py
index 77c2722..4c3bae7 100644
--- a/bite/api/views.py
+++ b/bite/api/views.py
@@ -26,16 +26,3 @@ from api.serializers import DeviceSerializer
class APISubscribe(ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
-
- # def post(self, request):
- # serializer = DeviceSerializer(data=request.data)
- # if serializer.is_valid():
- # serializer.save()
- # return Response(serializer.data, status=status.HTTP_201_CREATED)
- # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-
- # def get(self, request):
- # devices = Device.objects.all()
- # import pdb; pdb.set_trace()
- # serializer = DeviceSerializer(devices)
- # return Response(serializer.serial)
diff --git a/bite/bite/templates/swagger.html b/bite/bite/templates/swagger.html
new file mode 100644
index 0000000..b421d7b
--- /dev/null
+++ b/bite/bite/templates/swagger.html
@@ -0,0 +1,24 @@
+
+
+
+ Swagger
+
+
+
+
+
+
+
+
+
+
diff --git a/bite/bite/urls.py b/bite/bite/urls.py
index 61d2561..ba76354 100644
--- a/bite/bite/urls.py
+++ b/bite/bite/urls.py
@@ -34,6 +34,7 @@ Including another URLconf
"""
from django.contrib import admin
+from django.conf import settings
from django.urls import include, path
from api import urls as api_urls
@@ -45,3 +46,19 @@ urlpatterns = [
path('api/', include(api_urls)),
path('telemetry/', include(telemetry_urls)),
]
+
+if settings.DEBUG:
+ from django.views.generic import TemplateView
+ from rest_framework.schemas import get_schema_view
+
+ urlpatterns += [
+ path('swagger/', TemplateView.as_view(
+ template_name='swagger.html',
+ extra_context={'schema_url': 'openapi-schema'}
+ ), name='swagger'),
+ path('openapi', get_schema_view(
+ title="BITE - A Basic/IoT/Example",
+ description="BITE API for IoT",
+ version="1.0.0"
+ ), name='openapi-schema'),
+ ]
diff --git a/bite/telemetry/serializers.py b/bite/telemetry/serializers.py
index c12fb9c..1ef6c13 100644
--- a/bite/telemetry/serializers.py
+++ b/bite/telemetry/serializers.py
@@ -22,6 +22,17 @@ from api.models import Device
from telemetry.models import Telemetry
+class TelemetryStatsSerializer(serializers.Serializer):
+ count_samples = serializers.IntegerField()
+ first_sample = serializers.DateTimeField()
+ last_sample = serializers.DateTimeField()
+
+
+class TelemetrySummarySerializer(serializers.Serializer):
+ device = serializers.CharField()
+ stats = TelemetryStatsSerializer()
+
+
class TelemetrySerializer(serializers.ModelSerializer):
device = serializers.SlugRelatedField(
slug_field='serial',
diff --git a/bite/telemetry/urls.py b/bite/telemetry/urls.py
index a1889c3..ce36725 100644
--- a/bite/telemetry/urls.py
+++ b/bite/telemetry/urls.py
@@ -33,14 +33,15 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path
-from telemetry.views import TelemetryView, TelemetryLatest, TelemetryRange
+from telemetry.views import (TelemetryView, TelemetrySummaryView,
+ TelemetryLatest, TelemetryRange)
urlpatterns = [
path('',
TelemetryView.as_view({'post': 'create'}),
name='telemetry'),
path('/',
- TelemetryView.as_view({'get': 'list'}),
+ TelemetrySummaryView.as_view(),
name='device-telemetry'),
path('/last/',
TelemetryLatest.as_view({'get': 'retrieve'}),
diff --git a/bite/telemetry/views.py b/bite/telemetry/views.py
index fc10bba..9abb7e3 100644
--- a/bite/telemetry/views.py
+++ b/bite/telemetry/views.py
@@ -19,10 +19,12 @@
from datetime import datetime
from django.http import Http404
+from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from telemetry.models import Telemetry
-from telemetry.serializers import TelemetrySerializer
+from telemetry.serializers import (TelemetrySerializer,
+ TelemetrySummarySerializer)
from rest_framework.response import Response
@@ -39,15 +41,36 @@ class TelemetryView(ModelViewSet):
return Response(serializer.data)
+class TelemetrySummaryView(APIView):
+ def get(self, request, device, format=None):
+ count = Telemetry.objects.filter(device__serial=device).count()
+ if count == 0:
+ raise Http404
+ first = Telemetry.objects.filter(
+ device__serial=device).order_by('-time')[:1][0]
+ last = Telemetry.objects.filter(
+ device__serial=device).order_by('time')[:1][0]
+ data = {
+ 'device': device,
+ 'stats': {
+ 'count_samples': count,
+ 'first_sample': first.time,
+ 'last_sample': last.time}
+ }
+ serializer = TelemetrySummarySerializer(data)
+ return Response(serializer.data)
+
+
class TelemetryRange(ModelViewSet):
queryset = Telemetry.objects.all()
serializer_class = TelemetrySerializer
lookup_field = 'device'
def list(self, request, device, time_from, time_to=None):
+ time_to = datetime.now() if time_to is None else time_to
queryset = Telemetry.objects.filter(
device__serial=device,
- time__range=[time_from, datetime.now()])
+ time__range=[time_from, time_to])
if not queryset:
raise Http404
serializer = TelemetrySerializer(queryset, many=True)
@@ -61,7 +84,7 @@ class TelemetryLatest(ModelViewSet):
def retrieve(self, request, device=None):
queryset = Telemetry.objects.filter(
- device__serial=device).order_by('-time')
+ device__serial=device).order_by('-time')[:1]
if not queryset:
raise Http404
serializer = TelemetrySerializer(queryset[0])
diff --git a/docker/django/Dockerfile b/docker/django/Dockerfile
index 346f59c..bf423fb 100644
--- a/docker/django/Dockerfile
+++ b/docker/django/Dockerfile
@@ -35,6 +35,7 @@ COPY --chown=1000:1000 bite /srv/app/bite
COPY --chown=1000:1000 requirements.txt /srv/app/bite/requirements.txt
RUN pip3 install -r /srv/app/bite/requirements.txt \
+ && python3 -m compileall -q /srv/app/bite \
&& mkdir -p /srv/appdata/bite/static \
&& chown -R 1000:1000 /srv/appdata/bite
diff --git a/docker/ingress/nginx.conf b/docker/ingress/nginx.conf
index ab6f103..3e9674c 100644
--- a/docker/ingress/nginx.conf
+++ b/docker/ingress/nginx.conf
@@ -48,13 +48,13 @@ http {
'' close;
}
- upstream bite {
+ upstream django {
# We point to the Docker 'service' instead of directly to the container
# Docker does then a DNS round-robin internally
server bite:8000;
}
- upstream broker {
+ upstream mqtt {
# We point to the Docker 'service' instead of directly to the container
# Docker does then a DNS round-robin internally
server broker:9001;
@@ -69,7 +69,7 @@ http {
keepalive_timeout 60 60;
location / {
- proxy_pass http://bite;
+ proxy_pass http://django;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
@@ -85,7 +85,7 @@ http {
}
location /mqtt {
- proxy_pass http://broker;
+ proxy_pass http://mqtt;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
diff --git a/requirements.txt b/requirements.txt
index f2c9891..2b4c38d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,5 +4,7 @@ django-health-check
psycopg2-binary
paho-mqtt==1.5.0
asyncio-mqtt==0.5.0
+PyYAML
+uritemplate
pygments
gunicorn