diff --git a/apps/am/__init__.py b/apps/am/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/apps/am/admin.py b/apps/am/admin.py new file mode 100755 index 00000000..8c38f3f3 --- /dev/null +++ b/apps/am/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/am/apps.py b/apps/am/apps.py new file mode 100755 index 00000000..189a558b --- /dev/null +++ b/apps/am/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AemConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'apps.am' diff --git a/apps/am/migrations/0001_initial.py b/apps/am/migrations/0001_initial.py new file mode 100644 index 00000000..24964ac7 --- /dev/null +++ b/apps/am/migrations/0001_initial.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.12 on 2022-05-09 01:05 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('system', '0004_auto_20220421_1511'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Access', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('type', models.PositiveSmallIntegerField(choices=[(10, '准入'), (20, '禁入')], verbose_name='准入类型')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Area', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('name', models.CharField(max_length=20, verbose_name='名称')), + ('level', models.PositiveSmallIntegerField(verbose_name='区域等级')), + ('sort_str', models.CharField(default='1', max_length=12, verbose_name='排序字符')), + ('visitor_no', models.BooleanField(default=True, verbose_name='不准许访客')), + ('rparty_no', models.BooleanField(default=True, verbose_name='不准许相关方')), + ('third_info', models.JSONField(blank=True, default=dict, verbose_name='三方信息')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='area_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('manager', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='区域负责人')), + ('posts_access', models.ManyToManyField(through='am.Access', to='system.Post')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='area_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='access', + name='area', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='am.area', verbose_name='关联区域'), + ), + migrations.AddField( + model_name='access', + name='post', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.post', verbose_name='关联岗位'), + ), + ] diff --git a/apps/am/migrations/__init__.py b/apps/am/migrations/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/apps/am/models.py b/apps/am/models.py new file mode 100755 index 00000000..8234b9bb --- /dev/null +++ b/apps/am/models.py @@ -0,0 +1,37 @@ +from django.db import models +from apps.system.models import Post, User +from apps.utils.models import BaseModel, CommonAModel +# Create your models here. + + +class Area(CommonAModel): + """ + 地图区域 + """ + name = models.CharField('名称', max_length=20) + level = models.PositiveSmallIntegerField('区域等级') + sort_str = models.CharField('排序字符', max_length=12, default='1') + manager = models.ForeignKey(User, on_delete=models.CASCADE, + verbose_name='区域负责人') + visitor_no = models.BooleanField('不准许访客', default=True) + rparty_no = models.BooleanField('不准许相关方', default=True) + posts_access = models.ManyToManyField(Post, through='am.access') + third_info = models.JSONField('三方信息', default=dict, + null=False, blank=True) + + +class Access(BaseModel): + """ + 准入权限 + """ + ACCESS_IN_YES = 10 + ACCESS_IN_NO = 20 + ACCESS_CHOICE = ( + (ACCESS_IN_YES, '准入'), + (ACCESS_IN_NO, '禁入') + ) + type = models.PositiveSmallIntegerField('准入类型', choices=ACCESS_CHOICE) + area = models.ForeignKey(Area, verbose_name='关联区域', + on_delete=models.CASCADE) + post = models.ForeignKey(Post, verbose_name='关联岗位', + on_delete=models.CASCADE) diff --git a/apps/am/serializers.py b/apps/am/serializers.py new file mode 100644 index 00000000..59c02c21 --- /dev/null +++ b/apps/am/serializers.py @@ -0,0 +1,8 @@ +from apps.am.models import Area +from apps.utils.serializers import CustomModelSerializer + + +class AreaSimpleSerializer(CustomModelSerializer): + class Meta: + model = Area + fields = ['id', 'name', 'level'] diff --git a/apps/am/tests.py b/apps/am/tests.py new file mode 100755 index 00000000..7ce503c2 --- /dev/null +++ b/apps/am/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/am/views.py b/apps/am/views.py new file mode 100755 index 00000000..91ea44a2 --- /dev/null +++ b/apps/am/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/apps/system/views.py b/apps/system/views.py index 54177998..4748229f 100755 --- a/apps/system/views.py +++ b/apps/system/views.py @@ -97,7 +97,7 @@ class PTaskViewSet(CustomModelViewSet): interval, _ = IntervalSchedule.objects.get_or_create( **interval_, defaults=interval_) data['interval'] = interval.id - except: + except Exception: raise ParseError(**SCHEDULE_WRONG) if timetype == 'crontab' and crontab_: data['interval'] = None @@ -106,7 +106,7 @@ class PTaskViewSet(CustomModelViewSet): crontab, _ = CrontabSchedule.objects.get_or_create( **crontab_, defaults=crontab_) data['crontab'] = crontab.id - except: + except Exception: raise ParseError(**SCHEDULE_WRONG) serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) @@ -131,7 +131,7 @@ class PTaskViewSet(CustomModelViewSet): interval, _ = IntervalSchedule.objects.get_or_create( **interval_, defaults=interval_) data['interval'] = interval.id - except: + except Exception: raise ParseError(**SCHEDULE_WRONG) if timetype == 'crontab' and crontab_: data['interval'] = None @@ -142,7 +142,7 @@ class PTaskViewSet(CustomModelViewSet): crontab, _ = CrontabSchedule.objects.get_or_create( **crontab_, defaults=crontab_) data['crontab'] = crontab.id - except: + except Exception: raise ParseError(**SCHEDULE_WRONG) instance = self.get_object() serializer = self.get_serializer(instance, data=data) @@ -166,6 +166,7 @@ class PTaskResultViewSet(ListModelMixin, RetrieveModelMixin, CustomGenericViewSe queryset = TaskResult.objects.all() serializer_class = PTaskResultSerializer ordering = ['-date_created'] + lookup_field = 'task_id' class DictTypeViewSet(CustomModelViewSet): diff --git a/apps/third/clients.py b/apps/third/clients.py index ad5dd6f2..45b51fb4 100755 --- a/apps/third/clients.py +++ b/apps/third/clients.py @@ -1,5 +1,6 @@ from apps.utils.xunxi import XxClient from apps.utils.dahua import DhClient - +from apps.utils.speaker import SpClient dhClient = DhClient() xxClient = XxClient() +spClient = SpClient() diff --git a/apps/third/migrations/0001_initial.py b/apps/third/migrations/0001_initial.py new file mode 100644 index 00000000..e9ceeb61 --- /dev/null +++ b/apps/third/migrations/0001_initial.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.12 on 2022-05-09 01:05 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('am', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='TDevice', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('type', models.PositiveSmallIntegerField(choices=[(10, '定位基站'), (20, '定位信标'), (30, '定位标签'), (40, 'aoa引擎'), (50, '音响'), (60, '视频通道'), (70, '闸机通道'), (80, '面板机')], verbose_name='设备类型')), + ('code', models.CharField(max_length=20, verbose_name='设备唯一标识')), + ('location', models.JSONField(blank=True, default=dict, verbose_name='位置信息')), + ('third_info', models.JSONField(blank=True, default=dict, verbose_name='三方信息')), + ('area', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='am.area', verbose_name='所在区')), + ('areas', models.ManyToManyField(related_name='tareas', to='am.Area', verbose_name='覆盖区')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/third/models.py b/apps/third/models.py index 71a83623..9c6d31b0 100755 --- a/apps/third/models.py +++ b/apps/third/models.py @@ -1,3 +1,41 @@ from django.db import models +from apps.am.models import Area + +from apps.utils.models import BaseModel # Create your models here. + + +class TDevice(BaseModel): + """ + 三方设备补充信息 + """ + DEVICE_BLG = 10 + DEVICE_IBEACON = 20 + DEVICE_BLT = 30 + DEVICE_AOA = 40 + DEVICE_SPEAKER = 50 + DEVICE_VCHANNEL = 60 + DEVICE_DCHANNEL = 70 + DEVICE_PANEL = 80 + + DEVICE_CHOICE = ( + (DEVICE_BLG, '定位基站'), + (DEVICE_IBEACON, '定位信标'), + (DEVICE_BLT, '定位标签'), + (DEVICE_AOA, 'aoa引擎'), + (DEVICE_SPEAKER, '音响'), + (DEVICE_VCHANNEL, '视频通道'), + (DEVICE_DCHANNEL, '闸机通道'), + (DEVICE_PANEL, '面板机') + ) + type = models.PositiveSmallIntegerField('设备类型', choices=DEVICE_CHOICE) + code = models.CharField('设备唯一标识', max_length=20) + location = models.JSONField('位置信息', default=dict, + null=False, blank=True) + area = models.ForeignKey(Area, on_delete=models.CASCADE, + verbose_name='所在区', null=True, blank=True) + areas = models.ManyToManyField(Area, verbose_name='覆盖区', + related_name='tareas') + third_info = models.JSONField('三方信息', default=dict, + null=False, blank=True) diff --git a/apps/third/serializers.py b/apps/third/serializers.py index e4585089..ab473f83 100755 --- a/apps/third/serializers.py +++ b/apps/third/serializers.py @@ -1,5 +1,7 @@ from rest_framework import serializers +from apps.am.models import Area + class RequestCommonSerializer(serializers.Serializer): method_choice = ( @@ -13,3 +15,21 @@ class RequestCommonSerializer(serializers.Serializer): params = serializers.JSONField(label='请求参数', required=False, allow_null=True) json = serializers.JSONField(label='请求body(json格式)', required=False, allow_null=True) code = serializers.CharField(label='请求短标识', required=False, allow_null=True) + + +class BindAreaSerializer(serializers.Serializer): + codes = serializers.ListField(child=serializers.CharField(), label='标识列表') + area = serializers.PrimaryKeyRelatedField(queryset=Area.objects.all(), + label="区域ID") + + +class LabelLocationSerializer(serializers.Serializer): + code = serializers.CharField(label='设备唯一标识') + location = serializers.JSONField(label='坐标信息') + + +class BindAreasSerializer(serializers.Serializer): + codes = serializers.ListField(child=serializers.CharField(), label='标识列表') + areas = serializers.PrimaryKeyRelatedField(queryset=Area.objects.all(), + label="区域ID列表", + required=False, many=True) diff --git a/apps/third/tapis.py b/apps/third/tapis.py index 3d644c0b..6a16bde8 100755 --- a/apps/third/tapis.py +++ b/apps/third/tapis.py @@ -88,5 +88,25 @@ dhapis = { # 寻息API接口 xxapis = { - + "blg_list": { + "url": "/api/devicesV3/blgs", + "method": "post" + }, + "ibeacon_list": { + "url": "/api/devicesV3/ibeacons", + "method": "post" + } +} + + +# 音响API接口 +spapis = { + "user_login": { + "url": "/api/users/login", + "method": "post" + }, + "device_list": { + "url": "/api/devices", + "method": "get" + } } diff --git a/apps/third/urls.py b/apps/third/urls.py index fa2a1548..862e8f0f 100755 --- a/apps/third/urls.py +++ b/apps/third/urls.py @@ -1,6 +1,7 @@ from django.urls import path, include from rest_framework import routers -from apps.third.views import DahuaTestView, DhCommonViewSet, XxCommonViewSet, XxTestView +from apps.third.views import DahuaTestView, DhCommonViewSet, SpTestView, XxCommonViewSet, XxTestView +from apps.third.views_d import VChannelViewSet API_BASE_URL = 'api/third/' HTML_BASE_URL = 'third/' @@ -8,9 +9,10 @@ HTML_BASE_URL = 'third/' router = routers.DefaultRouter() router.register('xunxi', XxCommonViewSet, basename='api_xunxi') router.register('dahua', DhCommonViewSet, basename='api_dahua') - +router.register('vchannel', VChannelViewSet, basename='vchannel') urlpatterns = [ path(API_BASE_URL, include(router.urls)), path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()), path(API_BASE_URL + 'xunxi/test/', XxTestView.as_view()), + path(API_BASE_URL + 'speaker/test/', SpTestView.as_view()), ] diff --git a/apps/third/views.py b/apps/third/views.py index c85541d0..e7842bc5 100755 --- a/apps/third/views.py +++ b/apps/third/views.py @@ -1,9 +1,8 @@ from rest_framework.exceptions import ParseError, APIException -from apps.third.tapis import dhapis, xxapis +from apps.third.tapis import dhapis, xxapis, spapis from apps.third.erros import TAPI_CODE_WRONG -from apps.third.clients import dhClient +from apps.third.clients import dhClient, spClient, xxClient from apps.utils.mixins import MyLoggingMixin -from apps.third.clients import xxClient from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated, IsAdminUser @@ -31,6 +30,22 @@ class DahuaTestView(MyLoggingMixin, APIView): return Response(res) +class SpTestView(APIView): + """ + 音响测试接口 + """ + permission_classes = [IsAuthenticated] + + def get(self, request, *args, **kwargs): + """ + 音响测试接口 + + 音响测试接口 + """ + _, res = spClient.request(**spapis['device_list']) + return Response(res) + + class XxTestView(APIView): """ 寻息测试接口 @@ -58,11 +73,11 @@ class XxListener(stomp.ConnectionListener): print('received a message "%s"' % frame.body) -if settings.XX_ENABLED: - c = stomp.Connection([(settings.XX_MQ_HOST, settings.XX_MQ_PORT)]) - c.set_listener('', XxListener()) - c.connect(settings.XX_USERNAME, settings.XX_LICENCE) - c.subscribe(settings.XX_QUEUE, id='') +# if settings.XX_ENABLED: +# c = stomp.Connection([(settings.XX_MQ_HOST, settings.XX_MQ_PORT)]) +# c.set_listener('', XxListener()) +# c.connect(settings.XX_USERNAME, settings.XX_LICENCE) +# c.subscribe(settings.XX_QUEUE, id='') class XxCommonViewSet(CreateModelMixin, CustomGenericViewSet): @@ -77,11 +92,11 @@ class XxCommonViewSet(CreateModelMixin, CustomGenericViewSet): serializer.is_valid(raise_exception=True) vdata = serializer.validated_data if vdata.get('code', ''): - dhapi = dhapis.get(vdata['code'], None) - if dhapi is None: + xxapi = xxapis.get(vdata['code'], None) + if xxapi is None: raise ParseError(**TAPI_CODE_WRONG) - vdata['url'] = dhapi['url'] - vdata['method'] = dhapi['method'] + vdata['url'] = xxapi['url'] + vdata['method'] = xxapi['method'] _, res = xxClient.request( url=vdata['url'], method=vdata.get('method', 'post'), diff --git a/apps/third/views_d.py b/apps/third/views_d.py new file mode 100644 index 00000000..496fcd30 --- /dev/null +++ b/apps/third/views_d.py @@ -0,0 +1,116 @@ +from apps.third.models import TDevice +from apps.third.serializers import BindAreaSerializer, LabelLocationSerializer +from apps.utils.viewsets import CustomGenericViewSet +from rest_framework.mixins import ListModelMixin +from apps.third.clients import xxClient, dhClient +from apps.third.tapis import xxapis, dhapis +from rest_framework.response import Response +from rest_framework.serializers import Serializer +from rest_framework.decorators import action +from apps.am.models import Area + +# class BlgViewSet(ListModelMixin, CustomGenericViewSet): +# """ +# 定位基站接口 +# """ +# perms_map = {'get': '*'} # 权限标识 +# serializer_class = Serializer + +# def list(self, request, *args, **kwargs): +# """ +# 定位基站列表 + +# 定位基站列表 +# """ +# data = request.data +# _, res = xxClient.request(**xxapis['blg_list'], json=data) +# return Response(res) + + +# class IbeaconViewSet(CustomGenericViewSet): +# """ +# 信标接口 +# """ +# perms_map = {'get': '*'} # 权限标识 +# serializer_class = Serializer + +# def list(self, request, *args, **kwargs): +# """ +# 信标列表 + +# 定位基站列表 +# """ +# data = request.data +# _, res = xxClient.request(**xxapis['blg_list'], json=data) +# return Response(res) + + +class DChannelViewSet(CustomGenericViewSet): + """ + 闸机接口 + """ + pass + + +class VChannelViewSet(CustomGenericViewSet): + """ + 视频接口 + """ + @action(methods=['post'], detail=False, perms_map={'post': '*'}, + serializer_class=Serializer) + def page(self, request): + request.data.update({'channelTypeList': ["1"]}) + _, res = dhClient.request(**dhapis['channel_list'], json=request.data) + return Response(res) + + @action(methods=['post'], detail=False, perms_map={'post': 'dchannel:label_location'}, + serializer_class=LabelLocationSerializer) + def label_location(self, request): + """ + 标注坐标位置 + + 标注坐标位置 + """ + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.vdata + td = TDevice.objects.filter(code=vdata['code']).first() + if td: + td.location = vdata['location'] + td.update_by = request.user + td.save() + else: + td = TDevice() + td.type = TDevice.DEVICE_VCHANNEL + td.code = vdata['code'] + td.location = vdata['location'] + td.create_by = request.user + td.save() + return Response() + + @action(methods=['post'], detail=False, perms_map={'post': 'dchannel:bind_area'}, + serializer_class=BindAreaSerializer) + def bind_area(self, request): + """ + 绑定所在区域 + + 绑定所在区域 + """ + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.vdata + area = Area.objects.get(id=vdata['area']) + for i in vdata['codes']: + td = TDevice.objects.filter(code=i['code']).first() + if td: + td.area = area + td.update_by = request.user + td.save() + else: + td = TDevice() + td.type = TDevice.DEVICE_VCHANNEL + td.code = i['code'] + td.area = area + td.create_by = request.user + td.save() + return Response() diff --git a/apps/utils/dahua.py b/apps/utils/dahua.py index cad9f141..24ec1a3b 100755 --- a/apps/utils/dahua.py +++ b/apps/utils/dahua.py @@ -88,7 +88,7 @@ class DhClient: r = getattr(requests, method)('{}{}'.format(settings.DAHUA_BASE_URL, url), headers=self.headers, params=params, json=json, timeout=timeout, files=files, verify=False) - except: + except Exception: if raise_exception: raise APIException(**DH_REQUEST_ERROR) return 'error', DH_REQUEST_ERROR @@ -112,6 +112,3 @@ class DhClient: if raise_exception: raise APIException(**DH_REQUEST_ERROR) return 'error', DH_REQUEST_ERROR - - -dhClient = DhClient() diff --git a/apps/utils/errors.py b/apps/utils/errors.py index 64235130..fdfbcb60 100755 --- a/apps/utils/errors.py +++ b/apps/utils/errors.py @@ -1,4 +1,5 @@ XX_REQUEST_ERROR = {"code": "xx_request_error", "detail": "寻息接口访问异常"} DH_REQUEST_ERROR = {"code": "dh_request_error", "detail": "大华接口访问异常"} +SP_REQUEST_ERROR = {"code": "sp_request_error", "detail": "音响接口访问异常"} SIGN_MAKE_FAIL = {"code": "sign_make_fail", "detail": "签名照生成失败,请重新上传"} PKS_ERROR = {"code": "pks_error", "detail": "未获取到主键列表"} diff --git a/apps/utils/speaker.py b/apps/utils/speaker.py new file mode 100644 index 00000000..f8a4302e --- /dev/null +++ b/apps/utils/speaker.py @@ -0,0 +1,109 @@ +import time +from threading import Thread + +import requests +# from django.conf import settings +from server import settings +from rest_framework.exceptions import APIException, ParseError + +from apps.utils.errors import SP_REQUEST_ERROR +from apps.utils.tools import print_roundtrip +requests.packages.urllib3.disable_warnings() + + +class SpClient: + """ + 音响接口 + """ + + def __init__(self, username=settings.SP_USERNAME, + password=settings.SP_PASSWORD) -> None: + if not settings.SP_ENABLED: + return None + self.username = username + self.password = password + self.headers = {} + self.isGetingToken = False + self.isRuning = True + self.t = None # 线程 + self.setup() + + def _get_token_loop(self): + while self.isRuning: + params = { + "user": { + "email": self.username, + "password": self.password + } + } + r = requests.post(params=params, + url=settings.SP_BASE_URL + '/api/users/login', verify=False) + if r.status_code == 200: + ret = r.json() + self.headers['Authorization'] = 'bearer ' + ret['user']['token'] + time.sleep(3600) + + def get_token(self): + self.isGetingToken = True + params = { + 'grant_type': 'client_credentials', + 'client_id': self.client_id, + 'client_secret': self.client_secret + } + r = requests.post(params=params, url=settings.SP_BASE_URL + '/evo-apigw/evo-oauth/oauth/token', verify=False) + if r.status_code == 200: + ret = r.json() + print(ret) + self.headers['Authorization'] = 'bearer ' + ret['user']['token'] + self.isGetingToken = False + + def setup(self): + t = Thread(target=self._get_token_loop, args=(), daemon=True) + t.start() + + def __del__(self): + """ + 自定义销毁 + """ + self.isRuning = False + # self.t.join() + + def request(self, url: str, method: str, params=dict(), json=dict(), timeout=10, + file_path_rela=None, raise_exception=True): + if self.isGetingToken: + req_num = 0 + while True: + time.sleep(0.5) + if not self.isGetingToken: + self.request(url, method, params, json, timeout, file_path_rela, raise_exception) + req_num = req_num + 1 + if req_num > 4: + break + else: + files = None + if file_path_rela: # 相对路径 + files = {'file': open(settings.BASE_DIR + file_path_rela, 'rb')} + try: + if params: + url = url.format(**params) + r = getattr(requests, method)('{}{}'.format(settings.SP_BASE_URL, url), + headers=self.headers, params=params, json=json, + timeout=timeout, files=files, verify=False) + except Exception: + if raise_exception: + raise APIException(**SP_REQUEST_ERROR) + return 'error', SP_REQUEST_ERROR + # if settings.DEBUG: + # print_roundtrip(r) + if r.status_code == 200: + ret = r.json() + if 'code' in ret and ret['code'] not in ['0', '100', '00000', '1000', 0, 100, 1000]: + detail = '音响错误:{}'.format(str(ret['msg'])) + err_detail = dict(detail=detail, code='sp_'+str(ret['code'])) + if raise_exception: + raise ParseError(**err_detail) + return 'fail', dict(detail=detail, code='sp_'+str(ret['code'])) + return 'success', ret + if raise_exception: + raise APIException(**SP_REQUEST_ERROR) + return 'error', SP_REQUEST_ERROR diff --git a/apps/utils/viewsets.py b/apps/utils/viewsets.py index 63258493..4ed72006 100755 --- a/apps/utils/viewsets.py +++ b/apps/utils/viewsets.py @@ -14,6 +14,7 @@ from apps.utils.mixins import CustomDestoryModelMixin, MyLoggingMixin from apps.utils.permission import ALL_PERMS, RbacPermission, get_user_perms_map from apps.utils.queryset import get_child_queryset2 from apps.utils.serializers import PkSerializer +from rest_framework.throttling import UserRateThrottle class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): @@ -21,6 +22,7 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): 增强的GenericViewSet """ perms_map = {} # 权限标识 + throttle_classes = [UserRateThrottle] logging_methods = ['POST', 'PUT', 'PATCH', 'DELETE'] ordering_fields = '__all__' filter_fields = '__all__' diff --git a/apps/utils/xunxi.py b/apps/utils/xunxi.py index 1e29d8f0..57a062f9 100755 --- a/apps/utils/xunxi.py +++ b/apps/utils/xunxi.py @@ -73,8 +73,8 @@ class XxClient: else: r = getattr(requests, method)('{}{}'.format(settings.XX_BASE_URL, url), params=params, json=json, timeout=timeout, verify=False) - # if settings.DEBUG: - # print_roundtrip(r) + if settings.DEBUG: + print_roundtrip(r) ret = r.json() if ret.get('errorCode') == '1060000': self.get_token() # 重新获取token diff --git a/server/settings.py b/server/settings.py index 4c0f9c76..1838bf61 100755 --- a/server/settings.py +++ b/server/settings.py @@ -53,7 +53,8 @@ INSTALLED_APPS = [ 'apps.auth1', 'apps.monitor', 'apps.wf', - 'apps.hrm' + 'apps.hrm', + 'apps.am' ] MIDDLEWARE = [ @@ -180,6 +181,10 @@ REST_FRAMEWORK = { # 'UNAUTHENTICATED_USER': None, # 'UNAUTHENTICATED_TOKEN': None, 'EXCEPTION_HANDLER': 'apps.utils.exceptions.custom_exception_hander', + 'DEFAULT_THROTTLE_RATES': { + 'anon': '1/second', + 'user': '1/second' + } } # simplejwt配置 SIMPLE_JWT = { @@ -327,6 +332,13 @@ XX_USERNAME = conf.XX_USERNAME XX_BUILDID = conf.XX_BUILDID XX_QUEUE = conf.XX_QUEUE + +# 喇叭配置 +SP_ENABLED = conf.SP_ENABLED +SP_BASE_URL = conf.SP_BASE_URL +SP_USERNAME = conf.SP_USERNAME +SP_PASSWORD = conf.SP_PASSWORD + # 运维相关 SD_PWD = conf.SD_PWD BACKUP_PATH = conf.BACKUP_PATH