From b1b5ae5fcd89b3afd8abfaf24e16473d3889d8a1 Mon Sep 17 00:00:00 2001 From: ahhui Date: Tue, 8 Aug 2023 16:31:18 +0800 Subject: [PATCH 1/7] =?UTF-8?q?chore:=20=20=E6=9B=B4=E6=96=B0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 5500c27..f94509b 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -18,7 +18,7 @@ requests==2.28.2 typing-extensions==4.4.0 smmap==5.0.0 tzlocal==4.1 -channels==4.0.0 +channels==3.0.5 channels-redis==4.0.0 websockets==10.4 user-agents==2.2.0 From 516f0ac6758a3dd6566073cd47060a27441ad8bb Mon Sep 17 00:00:00 2001 From: ahhui Date: Tue, 8 Aug 2023 16:31:55 +0800 Subject: [PATCH 2/7] =?UTF-8?q?test:=20=E5=88=97=E6=9D=83=E9=99=90?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/utils/pagination.py | 7 +++--- backend/dvadmin/utils/viewset.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/backend/dvadmin/utils/pagination.py b/backend/dvadmin/utils/pagination.py index 40191ef..52bf143 100644 --- a/backend/dvadmin/utils/pagination.py +++ b/backend/dvadmin/utils/pagination.py @@ -76,8 +76,9 @@ class CustomPagination(PageNumberPagination): ('msg', msg), ('page', page), ('limit', limit), - ('total',total), - ('is_next',is_next), + ('total', total), + ('is_next', is_next), ('is_previous', is_previous), - ('data', data) + ('data', data), + ('permission', self.request.permission_fields) ])) diff --git a/backend/dvadmin/utils/viewset.py b/backend/dvadmin/utils/viewset.py index 47e1c6c..7f9c3a7 100644 --- a/backend/dvadmin/utils/viewset.py +++ b/backend/dvadmin/utils/viewset.py @@ -16,6 +16,8 @@ from dvadmin.utils.filters import DataLevelPermissionsFilter from dvadmin.utils.import_export_mixin import ExportSerializerMixin, ImportSerializerMixin from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse from dvadmin.utils.permission import CustomPermission +from dvadmin.utils.models import get_custom_app_models +from dvadmin.system.models import Columns from django_restql.mixins import QueryArgumentsMixin @@ -61,12 +63,45 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi def get_serializer(self, *args, **kwargs): serializer_class = self.get_serializer_class() kwargs.setdefault('context', self.get_serializer_context()) + # 全部以可见字段为准 + can_see = self.get_column_permission(serializer_class) + # 排除掉序列化器级的字段 + # sub_set = set(serializer_class._declared_fields.keys()) - set(can_see) + # for field in sub_set: + # serializer_class._declared_fields.pop(field) + # if not self.request.user.is_superuser: + # serializer_class.Meta.fields = can_see + # 在分页器中使用 + self.request.permission_fields = can_see if isinstance(self.request.data, list): with transaction.atomic(): return serializer_class(many=True, *args, **kwargs) else: return serializer_class(*args, **kwargs) + def get_column_permission(self, serializer_class): + """获取列权限""" + action_map = { + 'list': 'is_query', + 'retrieve': 'is_query', + 'create': 'is_create', + 'update': 'is_update' + } + finded = False + for app in get_custom_app_models(): + for model in app: + if model['object'] is serializer_class.Meta.model: + finded = True + break + if finded: + break + if finded is False: + return [] + column_permission = Columns.objects.filter(app=model['app'], model=model['model']) + if self.action in action_map: + return [obj.field_name for obj in column_permission if getattr(obj, action_map[self.action])] + return [] + def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data, request=request) serializer.is_valid(raise_exception=True) From f61025c6db60c1e338e7facd6ba1ff448cec665e Mon Sep 17 00:00:00 2001 From: ahhui Date: Tue, 8 Aug 2023 17:40:28 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=E7=89=A9=E8=81=94=E7=BD=91?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/routing.py | 5 +- backend/application/settings.py | 6 +-- backend/application/urls.py | 5 ++ backend/application/websocketConfig.py | 18 ++++--- backend/device/__init__.py | 0 backend/device/admin.py | 3 ++ backend/device/apps.py | 6 +++ backend/device/migrations/__init__.py | 0 backend/device/models.py | 73 ++++++++++++++++++++++++++ backend/device/routing.py | 6 +++ backend/device/tests.py | 3 ++ backend/device/urls.py | 16 ++++++ backend/device/views/gateway.py | 18 +++++++ backend/device/views/template.py | 33 ++++++++++++ backend/device/views/terminal.py | 18 +++++++ backend/device/websocket.py | 41 +++++++++++++++ 16 files changed, 238 insertions(+), 13 deletions(-) create mode 100644 backend/device/__init__.py create mode 100644 backend/device/admin.py create mode 100644 backend/device/apps.py create mode 100644 backend/device/migrations/__init__.py create mode 100644 backend/device/models.py create mode 100644 backend/device/routing.py create mode 100644 backend/device/tests.py create mode 100644 backend/device/urls.py create mode 100644 backend/device/views/gateway.py create mode 100644 backend/device/views/template.py create mode 100644 backend/device/views/terminal.py create mode 100644 backend/device/websocket.py diff --git a/backend/application/routing.py b/backend/application/routing.py index 237e5d1..6f8bf02 100644 --- a/backend/application/routing.py +++ b/backend/application/routing.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- from django.urls import path from application.websocketConfig import MegCenter +from device.routing import websocket_urlpatterns as device_ws_url websocket_urlpatterns = [ - path('ws//', MegCenter.as_asgi()), #consumers.DvadminWebSocket 是该路由的消费者 + path('ws//', MegCenter.as_asgi()), # consumers.DvadminWebSocket 是该路由的消费者 + *device_ws_url, ] - diff --git a/backend/application/settings.py b/backend/application/settings.py index f2cca95..b311bae 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -166,9 +166,9 @@ CORS_ORIGIN_ALLOW_ALL = True # 允许cookie CORS_ALLOW_CREDENTIALS = True # 指明在跨域访问中,后端是否支持对cookie的操作 -# ================================================= # +# ===================================================== # # ********************* channels配置 ******************* # -# ================================================= # +# ===================================================== # ASGI_APPLICATION = 'application.asgi.application' CHANNEL_LAYERS = { "default": { @@ -306,7 +306,7 @@ AUTHENTICATION_BACKENDS = ["dvadmin.utils.backends.CustomBackend"] # ================================================= # SIMPLE_JWT = { # token有效时长 - "ACCESS_TOKEN_LIFETIME": timedelta(minutes=120), + "ACCESS_TOKEN_LIFETIME": timedelta(minutes=1440), # token刷新后的有效时间 "REFRESH_TOKEN_LIFETIME": timedelta(days=1), # 设置前缀 diff --git a/backend/application/urls.py b/backend/application/urls.py index f7ba7cb..04297e8 100644 --- a/backend/application/urls.py +++ b/backend/application/urls.py @@ -30,6 +30,7 @@ from dvadmin.system.views.login import ( CaptchaView, ApiLogin, LogoutView, + LoginTokenView ) from dvadmin.system.views.system_config import InitSettingsViewSet from dvadmin.utils.swagger import CustomOpenAPISchemaGenerator @@ -81,6 +82,10 @@ urlpatterns = ( path("api/init/dictionary/", InitDictionaryViewSet.as_view()), path("api/init/settings/", InitSettingsViewSet.as_view()), path("apiLogin/", ApiLogin.as_view()), + path("api/device/", include("device.urls")), + + # 仅用于开发,上线需关闭 + path("api/token/", LoginTokenView.as_view()), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_URL) diff --git a/backend/application/websocketConfig.py b/backend/application/websocketConfig.py index 80515f4..c36d97a 100644 --- a/backend/application/websocketConfig.py +++ b/backend/application/websocketConfig.py @@ -122,7 +122,8 @@ class MessageCreateSerializer(CustomModelSerializer): fields = "__all__" read_only_fields = ["id"] -def websocket_push(user_id,message): + +def websocket_push(user_id, message): username = "user_" + str(user_id) channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( @@ -133,8 +134,9 @@ def websocket_push(user_id,message): } ) -def create_message_push(title: str, content: str, target_type: int=0, target_user: list=[], target_dept=None, target_role=None, - message: dict = {'contentType': 'INFO', 'content': '测试~'}, request= Request): + +def create_message_push(title: str, content: str, target_type: int = 0, target_user: list = None, target_dept=None, + target_role=None, message: dict = None, request=Request): if message is None: message = {"contentType": "INFO", "content": None} if target_role is None: @@ -145,11 +147,11 @@ def create_message_push(title: str, content: str, target_type: int=0, target_use "title": title, "content": content, "target_type": target_type, - "target_user":target_user, - "target_dept":target_dept, - "target_role":target_role + "target_user": target_user, + "target_dept": target_dept, + "target_role": target_role } - message_center_instance = MessageCreateSerializer(data=data,request=request) + message_center_instance = MessageCreateSerializer(data=data, request=request) message_center_instance.is_valid(raise_exception=True) message_center_instance.save() users = target_user or [] @@ -176,6 +178,6 @@ def create_message_push(title: str, content: str, target_type: int=0, target_use username, { "type": "push.message", - "json": {**message,'unread':unread_count} + "json": {**message, 'unread': unread_count} } ) diff --git a/backend/device/__init__.py b/backend/device/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/device/admin.py b/backend/device/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/backend/device/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/device/apps.py b/backend/device/apps.py new file mode 100644 index 0000000..af56959 --- /dev/null +++ b/backend/device/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DeviceConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'device' diff --git a/backend/device/migrations/__init__.py b/backend/device/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/device/models.py b/backend/device/models.py new file mode 100644 index 0000000..434ed6c --- /dev/null +++ b/backend/device/models.py @@ -0,0 +1,73 @@ +from django.db import models + +from dvadmin.utils.models import CoreModel, table_prefix + + +class Template(CoreModel): + CLASSIFY_CHOICE = ( + (0, "网关"), + (1, "终端设备"), + ) + classify = models.SmallIntegerField(choices=CLASSIFY_CHOICE, verbose_name="模板类别") + name = models.CharField(max_length=128, verbose_name="模板名称", unique=True) + + class Meta: + db_table = table_prefix + 'device_template' + verbose_name = "模板表" + verbose_name_plural = verbose_name + ordering = ("-id",) + + +class TemplateDetail(CoreModel): + template = models.ForeignKey(to="Template", null=False, on_delete=models.CASCADE, db_constraint=False, + verbose_name="所属模板") + key_title = models.CharField(max_length=64, verbose_name="键标题", unique=True) + key_name = models.CharField(max_length=64, verbose_name="键名") + key_type = models.CharField(max_length=32, verbose_name="键值类型") + parent_key = models.ForeignKey(to="TemplateDetail", null=True, on_delete=models.CASCADE, db_constraint=False, + verbose_name="父级键") + + class Meta: + db_table = table_prefix + 'device_template_detail' + verbose_name = "模板详情表" + verbose_name_plural = verbose_name + ordering = ("-id",) + unique_together = (('key_name', 'parent_key'),) + + +class Gateway(CoreModel): + name = models.CharField(max_length=128, verbose_name="设备名称", unique=True) + specification = models.CharField(max_length=32, verbose_name="设备型号") + mac_address = models.CharField(max_length=32, verbose_name="设备MAC地址") + version = models.CharField(max_length=64, verbose_name="设备固件版本号") + ip_address = models.CharField(max_length=32, verbose_name="设备IP地址") + physics_address = models.CharField(max_length=255, default="暂无位置信息", verbose_name="设备实际地址") + account = models.CharField(max_length=32, verbose_name="设备账号") + password = models.CharField(max_length=32, verbose_name="设备密码") + template = models.ForeignKey(to="Template", null=False, on_delete=models.CASCADE, db_constraint=False, + verbose_name="所用模板") + + class Meta: + db_table = table_prefix + 'device_gateways' + verbose_name = "网关表" + verbose_name_plural = verbose_name + ordering = ("-id",) + + +class Terminal(CoreModel): + name = models.CharField(max_length=128, verbose_name="设备名称", unique=True) + specification = models.CharField(max_length=32, verbose_name="设备型号") + identify = models.CharField(max_length=128, verbose_name="设备标识", unique=True) + physics_address = models.CharField(max_length=255, default="暂无位置信息", verbose_name="设备实际地址") + project = models.CharField(max_length=128, verbose_name="所属项目") + remark = models.CharField(max_length=255, null=True, verbose_name="设备备注") + gateway = models.ForeignKey(to=Gateway, null=True, on_delete=models.CASCADE, db_constraint=False, + verbose_name="关联网关") + template = models.ForeignKey(to="Template", null=False, on_delete=models.CASCADE, db_constraint=False, + verbose_name="所用模板") + + class Meta: + db_table = table_prefix + 'device_terminal' + verbose_name = "终端设备表" + verbose_name_plural = verbose_name + ordering = ("-id",) diff --git a/backend/device/routing.py b/backend/device/routing.py new file mode 100644 index 0000000..b7a0300 --- /dev/null +++ b/backend/device/routing.py @@ -0,0 +1,6 @@ +from django.urls import path +from device.websocket import DeviceStatusWebSocket + +websocket_urlpatterns = [ + path('ws/gateway_status//', DeviceStatusWebSocket.as_asgi()), +] diff --git a/backend/device/tests.py b/backend/device/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/backend/device/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/device/urls.py b/backend/device/urls.py new file mode 100644 index 0000000..db1e72b --- /dev/null +++ b/backend/device/urls.py @@ -0,0 +1,16 @@ +from django.urls import path +from rest_framework import routers + +from device.views.gateway import GatewayViewSet +from device.views.template import TemplateViewSet, TemplateDetailViewSet +from device.views.terminal import TerminalViewSet + + +device_url = routers.SimpleRouter() +device_url.register(r'gateway', GatewayViewSet) +device_url.register(r'template', TemplateViewSet) +device_url.register(r'template_detail', TemplateDetailViewSet) +device_url.register(r'terminal', TerminalViewSet) + +urlpatterns = [] +urlpatterns += device_url.urls diff --git a/backend/device/views/gateway.py b/backend/device/views/gateway.py new file mode 100644 index 0000000..3396af2 --- /dev/null +++ b/backend/device/views/gateway.py @@ -0,0 +1,18 @@ +from dvadmin.utils.serializers import CustomModelSerializer +from dvadmin.utils.viewset import CustomModelViewSet +from device.models import Gateway + + +class GatewaySerializer(CustomModelSerializer): + """网关管理序列化器""" + + class Meta: + model = Gateway + fields = '__all__' + read_only_fields = ['id'] + + +class GatewayViewSet(CustomModelViewSet): + """网关管理视图集""" + queryset = Gateway.objects.all() + serializer_class = GatewaySerializer diff --git a/backend/device/views/template.py b/backend/device/views/template.py new file mode 100644 index 0000000..42d2093 --- /dev/null +++ b/backend/device/views/template.py @@ -0,0 +1,33 @@ +from dvadmin.utils.serializers import CustomModelSerializer +from dvadmin.utils.viewset import CustomModelViewSet +from device.models import Template, TemplateDetail + + +class TemplateSerializer(CustomModelSerializer): + """模板管理序列化器""" + + class Meta: + model = Template + fields = '__all__' + read_only_fields = ['id'] + + +class TemplateDetailSerializer(CustomModelSerializer): + """模板详情序列化器""" + + class Meta: + model = TemplateDetail + fields = '__all__' + read_only_fields = ['id'] + + +class TemplateViewSet(CustomModelViewSet): + """模板管理视图集""" + queryset = Template.objects.all() + serializer_class = TemplateSerializer + + +class TemplateDetailViewSet(CustomModelViewSet): + """模板详情视图集""" + queryset = TemplateDetail.objects.all() + serializer_class = TemplateDetailSerializer diff --git a/backend/device/views/terminal.py b/backend/device/views/terminal.py new file mode 100644 index 0000000..8d6fb33 --- /dev/null +++ b/backend/device/views/terminal.py @@ -0,0 +1,18 @@ +from dvadmin.utils.serializers import CustomModelSerializer +from dvadmin.utils.viewset import CustomModelViewSet +from device.models import Terminal + + +class TerminalSerializer(CustomModelSerializer): + """终端设备管理序列化器""" + + class Meta: + model = Terminal + fields = '__all__' + read_only_fields = ['id'] + + +class TerminalViewSet(CustomModelViewSet): + """终端设备管理视图集""" + queryset = Terminal.objects.all() + serializer_class = TerminalSerializer diff --git a/backend/device/websocket.py b/backend/device/websocket.py new file mode 100644 index 0000000..4570787 --- /dev/null +++ b/backend/device/websocket.py @@ -0,0 +1,41 @@ +import json +from hashlib import md5 +from datetime import datetime + +import jwt +from channels.generic.websocket import AsyncJsonWebsocketConsumer + +from application.websocketConfig import set_message + + +class DeviceStatusWebSocket(AsyncJsonWebsocketConsumer): + """设备状态ws""" + chat_group = 'device_status' + + async def connect(self): + try: + print('设备ws创建连接', self.scope) + self.token = self.scope['url_route']['kwargs']['token'] + decoded_result = jwt.decode(self.token, settings.SECRET_KEY, algorithms=['HS256']) + if decoded_result: + self.uid = decoded_result.get('user_id') + self.hash = md5(str(self.token).encode('utf-8')) + self.chat_name = f'{self.chat_group}:user_{self.uid}' + await self.channel_layer.group_add(self.chat_name, self.channel_name) + await self.accept() + else: + raise jwt.InvalidSignatureError() + except jwt.InvalidSignatureError: + await self.send_json(set_message('system', 'SYSTEM', {'message': 'Token无效'}), True) + await self.disconnect(None) + except jwt.ExpiredSignatureError: + await self.send_json(set_message('system', 'SYSTEM', {'message': 'Token过期'}), True) + await self.disconnect(None) + + async def disconnect(self, code): + print('设备ws连接关闭') + await self.channel_layer.group_discard(self.chat_name, self.channel_name) + try: + await self.close(code) + except: + pass From 65af2407573c56c6be36884bac0a1c0b10fe2434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=A6=E9=94=A6=E8=BE=89?= Date: Fri, 11 Aug 2023 17:41:25 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E5=88=A0=E9=99=A4=20device?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/device/__init__.py | 0 backend/device/admin.py | 3 -- backend/device/apps.py | 6 --- backend/device/migrations/__init__.py | 0 backend/device/models.py | 73 --------------------------- backend/device/routing.py | 6 --- backend/device/tests.py | 3 -- backend/device/urls.py | 16 ------ backend/device/views/gateway.py | 18 ------- backend/device/views/template.py | 33 ------------ backend/device/views/terminal.py | 18 ------- backend/device/websocket.py | 41 --------------- 12 files changed, 217 deletions(-) delete mode 100644 backend/device/__init__.py delete mode 100644 backend/device/admin.py delete mode 100644 backend/device/apps.py delete mode 100644 backend/device/migrations/__init__.py delete mode 100644 backend/device/models.py delete mode 100644 backend/device/routing.py delete mode 100644 backend/device/tests.py delete mode 100644 backend/device/urls.py delete mode 100644 backend/device/views/gateway.py delete mode 100644 backend/device/views/template.py delete mode 100644 backend/device/views/terminal.py delete mode 100644 backend/device/websocket.py diff --git a/backend/device/__init__.py b/backend/device/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/backend/device/admin.py b/backend/device/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/backend/device/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/backend/device/apps.py b/backend/device/apps.py deleted file mode 100644 index af56959..0000000 --- a/backend/device/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class DeviceConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'device' diff --git a/backend/device/migrations/__init__.py b/backend/device/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/backend/device/models.py b/backend/device/models.py deleted file mode 100644 index 434ed6c..0000000 --- a/backend/device/models.py +++ /dev/null @@ -1,73 +0,0 @@ -from django.db import models - -from dvadmin.utils.models import CoreModel, table_prefix - - -class Template(CoreModel): - CLASSIFY_CHOICE = ( - (0, "网关"), - (1, "终端设备"), - ) - classify = models.SmallIntegerField(choices=CLASSIFY_CHOICE, verbose_name="模板类别") - name = models.CharField(max_length=128, verbose_name="模板名称", unique=True) - - class Meta: - db_table = table_prefix + 'device_template' - verbose_name = "模板表" - verbose_name_plural = verbose_name - ordering = ("-id",) - - -class TemplateDetail(CoreModel): - template = models.ForeignKey(to="Template", null=False, on_delete=models.CASCADE, db_constraint=False, - verbose_name="所属模板") - key_title = models.CharField(max_length=64, verbose_name="键标题", unique=True) - key_name = models.CharField(max_length=64, verbose_name="键名") - key_type = models.CharField(max_length=32, verbose_name="键值类型") - parent_key = models.ForeignKey(to="TemplateDetail", null=True, on_delete=models.CASCADE, db_constraint=False, - verbose_name="父级键") - - class Meta: - db_table = table_prefix + 'device_template_detail' - verbose_name = "模板详情表" - verbose_name_plural = verbose_name - ordering = ("-id",) - unique_together = (('key_name', 'parent_key'),) - - -class Gateway(CoreModel): - name = models.CharField(max_length=128, verbose_name="设备名称", unique=True) - specification = models.CharField(max_length=32, verbose_name="设备型号") - mac_address = models.CharField(max_length=32, verbose_name="设备MAC地址") - version = models.CharField(max_length=64, verbose_name="设备固件版本号") - ip_address = models.CharField(max_length=32, verbose_name="设备IP地址") - physics_address = models.CharField(max_length=255, default="暂无位置信息", verbose_name="设备实际地址") - account = models.CharField(max_length=32, verbose_name="设备账号") - password = models.CharField(max_length=32, verbose_name="设备密码") - template = models.ForeignKey(to="Template", null=False, on_delete=models.CASCADE, db_constraint=False, - verbose_name="所用模板") - - class Meta: - db_table = table_prefix + 'device_gateways' - verbose_name = "网关表" - verbose_name_plural = verbose_name - ordering = ("-id",) - - -class Terminal(CoreModel): - name = models.CharField(max_length=128, verbose_name="设备名称", unique=True) - specification = models.CharField(max_length=32, verbose_name="设备型号") - identify = models.CharField(max_length=128, verbose_name="设备标识", unique=True) - physics_address = models.CharField(max_length=255, default="暂无位置信息", verbose_name="设备实际地址") - project = models.CharField(max_length=128, verbose_name="所属项目") - remark = models.CharField(max_length=255, null=True, verbose_name="设备备注") - gateway = models.ForeignKey(to=Gateway, null=True, on_delete=models.CASCADE, db_constraint=False, - verbose_name="关联网关") - template = models.ForeignKey(to="Template", null=False, on_delete=models.CASCADE, db_constraint=False, - verbose_name="所用模板") - - class Meta: - db_table = table_prefix + 'device_terminal' - verbose_name = "终端设备表" - verbose_name_plural = verbose_name - ordering = ("-id",) diff --git a/backend/device/routing.py b/backend/device/routing.py deleted file mode 100644 index b7a0300..0000000 --- a/backend/device/routing.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.urls import path -from device.websocket import DeviceStatusWebSocket - -websocket_urlpatterns = [ - path('ws/gateway_status//', DeviceStatusWebSocket.as_asgi()), -] diff --git a/backend/device/tests.py b/backend/device/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/backend/device/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/backend/device/urls.py b/backend/device/urls.py deleted file mode 100644 index db1e72b..0000000 --- a/backend/device/urls.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.urls import path -from rest_framework import routers - -from device.views.gateway import GatewayViewSet -from device.views.template import TemplateViewSet, TemplateDetailViewSet -from device.views.terminal import TerminalViewSet - - -device_url = routers.SimpleRouter() -device_url.register(r'gateway', GatewayViewSet) -device_url.register(r'template', TemplateViewSet) -device_url.register(r'template_detail', TemplateDetailViewSet) -device_url.register(r'terminal', TerminalViewSet) - -urlpatterns = [] -urlpatterns += device_url.urls diff --git a/backend/device/views/gateway.py b/backend/device/views/gateway.py deleted file mode 100644 index 3396af2..0000000 --- a/backend/device/views/gateway.py +++ /dev/null @@ -1,18 +0,0 @@ -from dvadmin.utils.serializers import CustomModelSerializer -from dvadmin.utils.viewset import CustomModelViewSet -from device.models import Gateway - - -class GatewaySerializer(CustomModelSerializer): - """网关管理序列化器""" - - class Meta: - model = Gateway - fields = '__all__' - read_only_fields = ['id'] - - -class GatewayViewSet(CustomModelViewSet): - """网关管理视图集""" - queryset = Gateway.objects.all() - serializer_class = GatewaySerializer diff --git a/backend/device/views/template.py b/backend/device/views/template.py deleted file mode 100644 index 42d2093..0000000 --- a/backend/device/views/template.py +++ /dev/null @@ -1,33 +0,0 @@ -from dvadmin.utils.serializers import CustomModelSerializer -from dvadmin.utils.viewset import CustomModelViewSet -from device.models import Template, TemplateDetail - - -class TemplateSerializer(CustomModelSerializer): - """模板管理序列化器""" - - class Meta: - model = Template - fields = '__all__' - read_only_fields = ['id'] - - -class TemplateDetailSerializer(CustomModelSerializer): - """模板详情序列化器""" - - class Meta: - model = TemplateDetail - fields = '__all__' - read_only_fields = ['id'] - - -class TemplateViewSet(CustomModelViewSet): - """模板管理视图集""" - queryset = Template.objects.all() - serializer_class = TemplateSerializer - - -class TemplateDetailViewSet(CustomModelViewSet): - """模板详情视图集""" - queryset = TemplateDetail.objects.all() - serializer_class = TemplateDetailSerializer diff --git a/backend/device/views/terminal.py b/backend/device/views/terminal.py deleted file mode 100644 index 8d6fb33..0000000 --- a/backend/device/views/terminal.py +++ /dev/null @@ -1,18 +0,0 @@ -from dvadmin.utils.serializers import CustomModelSerializer -from dvadmin.utils.viewset import CustomModelViewSet -from device.models import Terminal - - -class TerminalSerializer(CustomModelSerializer): - """终端设备管理序列化器""" - - class Meta: - model = Terminal - fields = '__all__' - read_only_fields = ['id'] - - -class TerminalViewSet(CustomModelViewSet): - """终端设备管理视图集""" - queryset = Terminal.objects.all() - serializer_class = TerminalSerializer diff --git a/backend/device/websocket.py b/backend/device/websocket.py deleted file mode 100644 index 4570787..0000000 --- a/backend/device/websocket.py +++ /dev/null @@ -1,41 +0,0 @@ -import json -from hashlib import md5 -from datetime import datetime - -import jwt -from channels.generic.websocket import AsyncJsonWebsocketConsumer - -from application.websocketConfig import set_message - - -class DeviceStatusWebSocket(AsyncJsonWebsocketConsumer): - """设备状态ws""" - chat_group = 'device_status' - - async def connect(self): - try: - print('设备ws创建连接', self.scope) - self.token = self.scope['url_route']['kwargs']['token'] - decoded_result = jwt.decode(self.token, settings.SECRET_KEY, algorithms=['HS256']) - if decoded_result: - self.uid = decoded_result.get('user_id') - self.hash = md5(str(self.token).encode('utf-8')) - self.chat_name = f'{self.chat_group}:user_{self.uid}' - await self.channel_layer.group_add(self.chat_name, self.channel_name) - await self.accept() - else: - raise jwt.InvalidSignatureError() - except jwt.InvalidSignatureError: - await self.send_json(set_message('system', 'SYSTEM', {'message': 'Token无效'}), True) - await self.disconnect(None) - except jwt.ExpiredSignatureError: - await self.send_json(set_message('system', 'SYSTEM', {'message': 'Token过期'}), True) - await self.disconnect(None) - - async def disconnect(self, code): - print('设备ws连接关闭') - await self.channel_layer.group_discard(self.chat_name, self.channel_name) - try: - await self.close(code) - except: - pass From 689ce4b43b4fe7dd2148f898e6de12d3397a8002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=A6=E9=94=A6=E8=BE=89?= Date: Fri, 11 Aug 2023 17:41:59 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6=20urls?= =?UTF-8?q?.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/urls.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/application/urls.py b/backend/application/urls.py index 04297e8..6648052 100644 --- a/backend/application/urls.py +++ b/backend/application/urls.py @@ -82,7 +82,6 @@ urlpatterns = ( path("api/init/dictionary/", InitDictionaryViewSet.as_view()), path("api/init/settings/", InitSettingsViewSet.as_view()), path("apiLogin/", ApiLogin.as_view()), - path("api/device/", include("device.urls")), # 仅用于开发,上线需关闭 path("api/token/", LoginTokenView.as_view()), From 54501022758af8d9d3c4f5c5864c33ea292f9627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=A6=E9=94=A6=E8=BE=89?= Date: Fri, 11 Aug 2023 17:44:27 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6=20rout?= =?UTF-8?q?ing.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/routing.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/application/routing.py b/backend/application/routing.py index 6f8bf02..d4df9f8 100644 --- a/backend/application/routing.py +++ b/backend/application/routing.py @@ -1,9 +1,7 @@ # -*- coding: utf-8 -*- from django.urls import path from application.websocketConfig import MegCenter -from device.routing import websocket_urlpatterns as device_ws_url websocket_urlpatterns = [ path('ws//', MegCenter.as_asgi()), # consumers.DvadminWebSocket 是该路由的消费者 - *device_ws_url, ] From f03e61ce63148c9c9a9b11a2ff8154d25b736f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=A6=E9=94=A6=E8=BE=89?= Date: Fri, 11 Aug 2023 18:01:22 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6=20init?= =?UTF-8?q?=5Fmenu.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dvadmin/system/fixtures/init_menu.json | 61 ------------------- 1 file changed, 61 deletions(-) diff --git a/backend/dvadmin/system/fixtures/init_menu.json b/backend/dvadmin/system/fixtures/init_menu.json index 14f6520..9d514fe 100644 --- a/backend/dvadmin/system/fixtures/init_menu.json +++ b/backend/dvadmin/system/fixtures/init_menu.json @@ -738,66 +738,5 @@ } ], "menu_button": [] - }, - { - "name": "设备管理", - "icon": "iconfont icon-diannaobangong", - "sort": 4, - "is_link": false, - "is_catalog": true, - "web_path": "", - "component": "", - "component_name": "", - "status": true, - "cache": false, - "visible": true, - "children": [ - { - "name": "网关管理", - "icon": "iconfont icon-LoggedinPC", - "sort": 1, - "is_link": false, - "is_catalog": false, - "web_path": "/swg", - "component": "device/swg/index", - "component_name": "swg", - "status": true, - "cache": false, - "visible": true, - "children": [], - "menu_button": [] - }, - { - "name": "联网设备", - "icon": "iconfont icon-putong", - "sort": 2, - "is_link": false, - "is_catalog": false, - "web_path": "/networkDevice", - "component": "device/networkDevice/index", - "component_name": "networkDevice", - "status": true, - "cache": false, - "visible": true, - "children": [], - "menu_button": [] - }, - { - "name": "模板信息", - "icon": "iconfont icon-chazhaobiaodanliebiao", - "sort": 3, - "is_link": false, - "is_catalog": false, - "web_path": "/template", - "component": "device/template/index", - "component_name": "templatePage", - "status": true, - "cache": false, - "visible": true, - "children": [], - "menu_button": [] - } - ], - "menu_button": [] } ] \ No newline at end of file