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 0000000..8fc1fad Binary files /dev/null and b/dcc/driver/.connector.py.swp differ diff --git a/dcc/driver/.views.py.swp b/dcc/driver/.views.py.swp new file mode 100644 index 0000000..272cf0e Binary files /dev/null and b/dcc/driver/.views.py.swp differ 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)