From a6005615e0e12d652529edd993a97d9f72f5e8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sat, 18 Dec 2021 00:33:46 +0100 Subject: [PATCH] Add driver app --- .gitignore | 2 + dcc/dcc/parsers.py | 8 +++ dcc/dcc/settings.py | 4 +- dcc/dcc/urls.py | 21 +++++- dcc/driver/.connector.py.swp | Bin 0 -> 12288 bytes dcc/driver/.views.py.swp | Bin 0 -> 12288 bytes dcc/driver/__init__.py | 0 dcc/driver/admin.py | 3 + dcc/driver/apps.py | 6 ++ dcc/driver/connector.py | 35 +++++++++ dcc/driver/migrations/__init__.py | 0 dcc/driver/models.py | 3 + dcc/driver/serializers.py | 17 +++++ dcc/driver/tests.py | 3 + dcc/driver/urls.py | 10 +++ dcc/driver/views.py | 68 ++++++++++++++++++ ...4_alter_company_options_alter_cab_image.py | 22 ++++++ dcc/roster/models.py | 2 +- 18 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 dcc/dcc/parsers.py create mode 100644 dcc/driver/.connector.py.swp create mode 100644 dcc/driver/.views.py.swp create mode 100644 dcc/driver/__init__.py create mode 100644 dcc/driver/admin.py create mode 100644 dcc/driver/apps.py create mode 100644 dcc/driver/connector.py create mode 100644 dcc/driver/migrations/__init__.py create mode 100644 dcc/driver/models.py create mode 100644 dcc/driver/serializers.py create mode 100644 dcc/driver/tests.py create mode 100644 dcc/driver/urls.py create mode 100644 dcc/driver/views.py create mode 100644 dcc/roster/migrations/0014_alter_company_options_alter_cab_image.py diff --git a/.gitignore b/.gitignore index b6e4761..914c50b 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,5 @@ dmypy.json # Pyre type checker .pyre/ + +dcc/media diff --git a/dcc/dcc/parsers.py b/dcc/dcc/parsers.py new file mode 100644 index 0000000..f46c972 --- /dev/null +++ b/dcc/dcc/parsers.py @@ -0,0 +1,8 @@ +from rest_framework.parsers import BaseParser + + +class PlainTextParser(BaseParser): + media_type = 'text/plain' + + def parse(self, stream, media_type=None, parser_context=None): + return stream.read() diff --git a/dcc/dcc/settings.py b/dcc/dcc/settings.py index 16de996..c3da72e 100644 --- a/dcc/dcc/settings.py +++ b/dcc/dcc/settings.py @@ -39,7 +39,9 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django_countries', + 'rest_framework', 'dcc', + 'driver', 'roster', ] @@ -47,7 +49,7 @@ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', + # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', diff --git a/dcc/dcc/urls.py b/dcc/dcc/urls.py index 96b5eaa..6c74fa0 100644 --- a/dcc/dcc/urls.py +++ b/dcc/dcc/urls.py @@ -16,8 +16,27 @@ Including another URLconf from django.conf import settings from django.conf.urls.static import static from django.contrib import admin -from django.urls import path +from django.urls import include, path + +from driver import urls as driver_urls urlpatterns = [ path('admin/', admin.site.urls), + path('dcc/', include(driver_urls)), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + +# 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/dcc/driver/.connector.py.swp b/dcc/driver/.connector.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..8fc1fade6e65bb6738ac9c97f26ff082ba2cc2b4 GIT binary patch literal 12288 zcmeI&J#W)M7zglwSQxNlM3)W>*K}|ywRtI2s!CfSAr(~ui6Mod3f0v2Q*&gWKD z6j+fEOo)l89|MVriO&G63=CypWI=w3lO}D6*g(%uiW1xB$NziI9-?Ho_Hgq)Tdphu zz*XSU^auWZ>J3hg3b487infT4T&N{FZLVAu*<$JDQtjNa&$5EmyPJ(_{Q1Cb@v8lV zdo6##wybLMlJ0?!Rm=B0VJTl$f}?W_5<(^uDQ96>$Bo5$@_^2kX4urVt;xY%STlZ6;f0GjE&gIg%$Wn@>gzH%KWgorRd~42SqmLV*Hh!mJIj>Mb_Elj<=eu}@1w!9n_aAbW27^@ZMAtA Sc7)pVZ6MiTclv*>U%_wrL{%>U literal 0 HcmV?d00001 diff --git a/dcc/driver/.views.py.swp b/dcc/driver/.views.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..272cf0ef2bb50b5d058f28583e032d6421aa820c GIT binary patch literal 12288 zcmeI2O^6#+9Ke6ugPnX$tUZW`GSy20X*OF58l+X2NfwEJbTg}ycYDLS3z$wlgVdyOI^Gyz8{21`2Xks`QHCAWVS0; zHZD5n%PRm6!`9=s#oZ@A=0yJ(uJAqClab`UbY;IMLN6S;^4!^Tl>>F(Objl+xY1mW zzVCWnvFu(Gem6Mnw%g0`M|rzaE$@1APnQQb4m4&k7#^Hq*g1VZ$C;I9;tl%rQ>UDh zk6eE6`wa$z!C){L3l*!iFUq ze#yaiIe0e*@8sa^9CUL~%fay+{F;T&vv4yD)hs-lg%er0lYyTz@KXl9&%h@ca5GTL zz{w2!mWD6W@I@NlNW)qho=?MbX(*;4mxenj_$mb-rQp>RoJxU{flR$J;3W$x7CdT=YV%iAAA`YQFc^+HPJ)u*Q2EY`T>^e)~ouaAn8o%CMkiuTyfAd~GOoSX^at*CA~VhWFZR_k`9?V-mp?PwqvoCcYNY zp$Lb%I=YlEG@F~Pvz1D#wzl57)Oh)FW2-sME{SuJx0cEiJ@2MeWvNu4bm?F}5&QUB zsjRft>h;EEv#~yP6mcJCt_VeGE~B{ap5IYoHmFE%YSimEGXZK~^JXkZ%{{mgv5~^s=Enc255YhegzGA)b!n!iGewK|m+h#F?L#)B z^}pC<7n z83?Vz9Tg0_JJXdsKTV=vPIWxZ<2uH3WZ!u(y98scflykiRy?hxcB;-Rn?2$AP5FAb z8H=taOLa^7ZawJth40Q)Aqvx}I`zQ!WjhR1p$Hun^qtZB;N?gj3mmUM2vj)LOw`)# z@+b&B)>w!jv8SXCTOB3(axYNV%PKkZ#y5@6f|1n)<@lxav1T#^_fs6JjLwI+K;za= r*HUSI1e6vBba5{K=_sEBP)HQw_vgzyVK^B3ojuIwl;#qMMmYZf47$i( literal 0 HcmV?d00001 diff --git a/dcc/driver/__init__.py b/dcc/driver/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dcc/driver/admin.py b/dcc/driver/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/dcc/driver/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/dcc/driver/apps.py b/dcc/driver/apps.py new file mode 100644 index 0000000..4a5df03 --- /dev/null +++ b/dcc/driver/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DriverConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'driver' diff --git a/dcc/driver/connector.py b/dcc/driver/connector.py new file mode 100644 index 0000000..48e03c0 --- /dev/null +++ b/dcc/driver/connector.py @@ -0,0 +1,35 @@ +class Connector: + + @classmethod + def __mqtt_pub(self, message): + # to be encoded + print(message) + return True + + def passthrough(self, address, data): + self.__mqtt_pub(data) + + def ops(self, address, data, function=False): + if function: + message = "".format(address, data['function'], + data['state']) + else: + message = "".format(address, data['speed'], + data['direction']) + self.__mqtt_pub(message) + return True + + def infra(self, data): + power = data['power'] + if "track" in data: + track = " {}".forma(data['track'].upper()) + else: + track = "" + + if power: + self.__mqtt_pub('<1{}>'.format(track)) + else: + self.__mqtt_pub('<0{}>'.format(track)) + + def emergency(self): + self.__mqtt_pub('') diff --git a/dcc/driver/migrations/__init__.py b/dcc/driver/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dcc/driver/models.py b/dcc/driver/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/dcc/driver/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/dcc/driver/serializers.py b/dcc/driver/serializers.py new file mode 100644 index 0000000..ed335c2 --- /dev/null +++ b/dcc/driver/serializers.py @@ -0,0 +1,17 @@ +from rest_framework import serializers + + +class FunctionSerializer(serializers.Serializer): + function = serializers.IntegerField(required=True) + state = serializers.IntegerField(required=True) + + +class CabSerializer(serializers.Serializer): + speed = serializers.IntegerField(required=True) + direction = serializers.IntegerField(required=True) + + +class InfraSerializer(serializers.Serializer): + power = serializers.BooleanField(required=True) + track = serializers.ChoiceField(choices=('main', 'prog', 'join'), + required=False) diff --git a/dcc/driver/tests.py b/dcc/driver/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/dcc/driver/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/dcc/driver/urls.py b/dcc/driver/urls.py new file mode 100644 index 0000000..b9941c5 --- /dev/null +++ b/dcc/driver/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from driver.views import SendCommand, Function, Cab, Emergency, Infra + +urlpatterns = [ + path('emergency', Emergency.as_view()), + path('infra', Infra.as_view()), + path('/command', SendCommand.as_view()), + path('/cab', Cab.as_view()), + path('/function', Function.as_view()), +] diff --git a/dcc/driver/views.py b/dcc/driver/views.py new file mode 100644 index 0000000..f5ea3b3 --- /dev/null +++ b/dcc/driver/views.py @@ -0,0 +1,68 @@ +from django.views import View +from django.http import HttpResponse +from driver.serializers import ( + FunctionSerializer, CabSerializer, InfraSerializer) +from rest_framework import status +from rest_framework.views import APIView +from rest_framework.response import Response + +from dcc.parsers import PlainTextParser +from driver.connector import Connector + +conn = Connector() + + +class SendCommand(APIView): + parser_classes = [PlainTextParser] + + def put(self, request, address): + data = request.data + conn.passthrough(address, data) + return Response(data, + status=status.HTTP_202_ACCEPTED) + + +class Function(APIView): + def put(self, request, address): + serializer = FunctionSerializer(data=request.data) + if serializer.is_valid(): + conn.ops(address, serializer.data, function=True) + return Response(serializer.data, + status=status.HTTP_202_ACCEPTED) + + return Response(serializer.errors, + status=status.HTTP_400_BAD_REQUEST) + + +class Cab(APIView): + def put(self, request, address): + serializer = CabSerializer(data=request.data) + if serializer.is_valid(): + conn.ops(address, serializer.data) + return Response(serializer.data, + status=status.HTTP_202_ACCEPTED) + + return Response(serializer.errors, + status=status.HTTP_400_BAD_REQUEST) + + +class Infra(APIView): + def put(self, request): + serializer = InfraSerializer(data=request.data) + if serializer.is_valid(): + conn.infra(serializer.data) + return Response(serializer.data, + status=status.HTTP_202_ACCEPTED) + + return Response(serializer.errors, + status=status.HTTP_400_BAD_REQUEST) + + +class Emergency(View): + def put(self, request): + conn.emergency() + return HttpResponse() + + def get(self, request): + conn.emergency() + return HttpResponse() diff --git a/dcc/roster/migrations/0014_alter_company_options_alter_cab_image.py b/dcc/roster/migrations/0014_alter_company_options_alter_cab_image.py new file mode 100644 index 0000000..9a35e0b --- /dev/null +++ b/dcc/roster/migrations/0014_alter_company_options_alter_cab_image.py @@ -0,0 +1,22 @@ +# Generated by Django 4.0 on 2021-12-17 23:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('roster', '0013_cab_company'), + ] + + operations = [ + migrations.AlterModelOptions( + name='company', + options={'verbose_name_plural': 'Companies'}, + ), + migrations.AlterField( + model_name='cab', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='media/images/'), + ), + ] diff --git a/dcc/roster/models.py b/dcc/roster/models.py index 04af4dd..7fe6469 100644 --- a/dcc/roster/models.py +++ b/dcc/roster/models.py @@ -61,7 +61,7 @@ class Cab(models.Model): purchase_date = models.DateField(null=True, blank=True) image = models.ImageField( - upload_to='images/', + upload_to='media/images/', null=True, blank=True) notes = models.TextField(blank=True)