增加area tdevice表
This commit is contained in:
parent
821d6cf2db
commit
0ab3ae31af
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AemConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'apps.am'
|
|
@ -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='关联岗位'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
|
@ -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']
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
|
@ -97,7 +97,7 @@ class PTaskViewSet(CustomModelViewSet):
|
||||||
interval, _ = IntervalSchedule.objects.get_or_create(
|
interval, _ = IntervalSchedule.objects.get_or_create(
|
||||||
**interval_, defaults=interval_)
|
**interval_, defaults=interval_)
|
||||||
data['interval'] = interval.id
|
data['interval'] = interval.id
|
||||||
except:
|
except Exception:
|
||||||
raise ParseError(**SCHEDULE_WRONG)
|
raise ParseError(**SCHEDULE_WRONG)
|
||||||
if timetype == 'crontab' and crontab_:
|
if timetype == 'crontab' and crontab_:
|
||||||
data['interval'] = None
|
data['interval'] = None
|
||||||
|
@ -106,7 +106,7 @@ class PTaskViewSet(CustomModelViewSet):
|
||||||
crontab, _ = CrontabSchedule.objects.get_or_create(
|
crontab, _ = CrontabSchedule.objects.get_or_create(
|
||||||
**crontab_, defaults=crontab_)
|
**crontab_, defaults=crontab_)
|
||||||
data['crontab'] = crontab.id
|
data['crontab'] = crontab.id
|
||||||
except:
|
except Exception:
|
||||||
raise ParseError(**SCHEDULE_WRONG)
|
raise ParseError(**SCHEDULE_WRONG)
|
||||||
serializer = self.get_serializer(data=data)
|
serializer = self.get_serializer(data=data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
@ -131,7 +131,7 @@ class PTaskViewSet(CustomModelViewSet):
|
||||||
interval, _ = IntervalSchedule.objects.get_or_create(
|
interval, _ = IntervalSchedule.objects.get_or_create(
|
||||||
**interval_, defaults=interval_)
|
**interval_, defaults=interval_)
|
||||||
data['interval'] = interval.id
|
data['interval'] = interval.id
|
||||||
except:
|
except Exception:
|
||||||
raise ParseError(**SCHEDULE_WRONG)
|
raise ParseError(**SCHEDULE_WRONG)
|
||||||
if timetype == 'crontab' and crontab_:
|
if timetype == 'crontab' and crontab_:
|
||||||
data['interval'] = None
|
data['interval'] = None
|
||||||
|
@ -142,7 +142,7 @@ class PTaskViewSet(CustomModelViewSet):
|
||||||
crontab, _ = CrontabSchedule.objects.get_or_create(
|
crontab, _ = CrontabSchedule.objects.get_or_create(
|
||||||
**crontab_, defaults=crontab_)
|
**crontab_, defaults=crontab_)
|
||||||
data['crontab'] = crontab.id
|
data['crontab'] = crontab.id
|
||||||
except:
|
except Exception:
|
||||||
raise ParseError(**SCHEDULE_WRONG)
|
raise ParseError(**SCHEDULE_WRONG)
|
||||||
instance = self.get_object()
|
instance = self.get_object()
|
||||||
serializer = self.get_serializer(instance, data=data)
|
serializer = self.get_serializer(instance, data=data)
|
||||||
|
@ -166,6 +166,7 @@ class PTaskResultViewSet(ListModelMixin, RetrieveModelMixin, CustomGenericViewSe
|
||||||
queryset = TaskResult.objects.all()
|
queryset = TaskResult.objects.all()
|
||||||
serializer_class = PTaskResultSerializer
|
serializer_class = PTaskResultSerializer
|
||||||
ordering = ['-date_created']
|
ordering = ['-date_created']
|
||||||
|
lookup_field = 'task_id'
|
||||||
|
|
||||||
|
|
||||||
class DictTypeViewSet(CustomModelViewSet):
|
class DictTypeViewSet(CustomModelViewSet):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from apps.utils.xunxi import XxClient
|
from apps.utils.xunxi import XxClient
|
||||||
from apps.utils.dahua import DhClient
|
from apps.utils.dahua import DhClient
|
||||||
|
from apps.utils.speaker import SpClient
|
||||||
dhClient = DhClient()
|
dhClient = DhClient()
|
||||||
xxClient = XxClient()
|
xxClient = XxClient()
|
||||||
|
spClient = SpClient()
|
||||||
|
|
|
@ -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,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,3 +1,41 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from apps.am.models import Area
|
||||||
|
|
||||||
|
from apps.utils.models import BaseModel
|
||||||
|
|
||||||
# Create your models here.
|
# 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)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.am.models import Area
|
||||||
|
|
||||||
|
|
||||||
class RequestCommonSerializer(serializers.Serializer):
|
class RequestCommonSerializer(serializers.Serializer):
|
||||||
method_choice = (
|
method_choice = (
|
||||||
|
@ -13,3 +15,21 @@ class RequestCommonSerializer(serializers.Serializer):
|
||||||
params = serializers.JSONField(label='请求参数', required=False, allow_null=True)
|
params = serializers.JSONField(label='请求参数', required=False, allow_null=True)
|
||||||
json = serializers.JSONField(label='请求body(json格式)', 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)
|
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)
|
||||||
|
|
|
@ -88,5 +88,25 @@ dhapis = {
|
||||||
|
|
||||||
# 寻息API接口
|
# 寻息API接口
|
||||||
xxapis = {
|
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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework import routers
|
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/'
|
API_BASE_URL = 'api/third/'
|
||||||
HTML_BASE_URL = 'third/'
|
HTML_BASE_URL = 'third/'
|
||||||
|
@ -8,9 +9,10 @@ HTML_BASE_URL = 'third/'
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register('xunxi', XxCommonViewSet, basename='api_xunxi')
|
router.register('xunxi', XxCommonViewSet, basename='api_xunxi')
|
||||||
router.register('dahua', DhCommonViewSet, basename='api_dahua')
|
router.register('dahua', DhCommonViewSet, basename='api_dahua')
|
||||||
|
router.register('vchannel', VChannelViewSet, basename='vchannel')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(API_BASE_URL, include(router.urls)),
|
path(API_BASE_URL, include(router.urls)),
|
||||||
path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()),
|
path(API_BASE_URL + 'dahua/test/', DahuaTestView.as_view()),
|
||||||
path(API_BASE_URL + 'xunxi/test/', XxTestView.as_view()),
|
path(API_BASE_URL + 'xunxi/test/', XxTestView.as_view()),
|
||||||
|
path(API_BASE_URL + 'speaker/test/', SpTestView.as_view()),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from rest_framework.exceptions import ParseError, APIException
|
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.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.utils.mixins import MyLoggingMixin
|
||||||
from apps.third.clients import xxClient
|
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.permissions import IsAuthenticated, IsAdminUser
|
from rest_framework.permissions import IsAuthenticated, IsAdminUser
|
||||||
|
@ -31,6 +30,22 @@ class DahuaTestView(MyLoggingMixin, APIView):
|
||||||
return Response(res)
|
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):
|
class XxTestView(APIView):
|
||||||
"""
|
"""
|
||||||
寻息测试接口
|
寻息测试接口
|
||||||
|
@ -58,11 +73,11 @@ class XxListener(stomp.ConnectionListener):
|
||||||
print('received a message "%s"' % frame.body)
|
print('received a message "%s"' % frame.body)
|
||||||
|
|
||||||
|
|
||||||
if settings.XX_ENABLED:
|
# if settings.XX_ENABLED:
|
||||||
c = stomp.Connection([(settings.XX_MQ_HOST, settings.XX_MQ_PORT)])
|
# c = stomp.Connection([(settings.XX_MQ_HOST, settings.XX_MQ_PORT)])
|
||||||
c.set_listener('', XxListener())
|
# c.set_listener('', XxListener())
|
||||||
c.connect(settings.XX_USERNAME, settings.XX_LICENCE)
|
# c.connect(settings.XX_USERNAME, settings.XX_LICENCE)
|
||||||
c.subscribe(settings.XX_QUEUE, id='')
|
# c.subscribe(settings.XX_QUEUE, id='')
|
||||||
|
|
||||||
|
|
||||||
class XxCommonViewSet(CreateModelMixin, CustomGenericViewSet):
|
class XxCommonViewSet(CreateModelMixin, CustomGenericViewSet):
|
||||||
|
@ -77,11 +92,11 @@ class XxCommonViewSet(CreateModelMixin, CustomGenericViewSet):
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
vdata = serializer.validated_data
|
vdata = serializer.validated_data
|
||||||
if vdata.get('code', ''):
|
if vdata.get('code', ''):
|
||||||
dhapi = dhapis.get(vdata['code'], None)
|
xxapi = xxapis.get(vdata['code'], None)
|
||||||
if dhapi is None:
|
if xxapi is None:
|
||||||
raise ParseError(**TAPI_CODE_WRONG)
|
raise ParseError(**TAPI_CODE_WRONG)
|
||||||
vdata['url'] = dhapi['url']
|
vdata['url'] = xxapi['url']
|
||||||
vdata['method'] = dhapi['method']
|
vdata['method'] = xxapi['method']
|
||||||
_, res = xxClient.request(
|
_, res = xxClient.request(
|
||||||
url=vdata['url'],
|
url=vdata['url'],
|
||||||
method=vdata.get('method', 'post'),
|
method=vdata.get('method', 'post'),
|
||||||
|
|
|
@ -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()
|
|
@ -88,7 +88,7 @@ class DhClient:
|
||||||
r = getattr(requests, method)('{}{}'.format(settings.DAHUA_BASE_URL, url),
|
r = getattr(requests, method)('{}{}'.format(settings.DAHUA_BASE_URL, url),
|
||||||
headers=self.headers, params=params, json=json,
|
headers=self.headers, params=params, json=json,
|
||||||
timeout=timeout, files=files, verify=False)
|
timeout=timeout, files=files, verify=False)
|
||||||
except:
|
except Exception:
|
||||||
if raise_exception:
|
if raise_exception:
|
||||||
raise APIException(**DH_REQUEST_ERROR)
|
raise APIException(**DH_REQUEST_ERROR)
|
||||||
return 'error', DH_REQUEST_ERROR
|
return 'error', DH_REQUEST_ERROR
|
||||||
|
@ -112,6 +112,3 @@ class DhClient:
|
||||||
if raise_exception:
|
if raise_exception:
|
||||||
raise APIException(**DH_REQUEST_ERROR)
|
raise APIException(**DH_REQUEST_ERROR)
|
||||||
return 'error', DH_REQUEST_ERROR
|
return 'error', DH_REQUEST_ERROR
|
||||||
|
|
||||||
|
|
||||||
dhClient = DhClient()
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
XX_REQUEST_ERROR = {"code": "xx_request_error", "detail": "寻息接口访问异常"}
|
XX_REQUEST_ERROR = {"code": "xx_request_error", "detail": "寻息接口访问异常"}
|
||||||
DH_REQUEST_ERROR = {"code": "dh_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": "签名照生成失败,请重新上传"}
|
SIGN_MAKE_FAIL = {"code": "sign_make_fail", "detail": "签名照生成失败,请重新上传"}
|
||||||
PKS_ERROR = {"code": "pks_error", "detail": "未获取到主键列表"}
|
PKS_ERROR = {"code": "pks_error", "detail": "未获取到主键列表"}
|
||||||
|
|
|
@ -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
|
|
@ -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.permission import ALL_PERMS, RbacPermission, get_user_perms_map
|
||||||
from apps.utils.queryset import get_child_queryset2
|
from apps.utils.queryset import get_child_queryset2
|
||||||
from apps.utils.serializers import PkSerializer
|
from apps.utils.serializers import PkSerializer
|
||||||
|
from rest_framework.throttling import UserRateThrottle
|
||||||
|
|
||||||
|
|
||||||
class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
||||||
|
@ -21,6 +22,7 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
||||||
增强的GenericViewSet
|
增强的GenericViewSet
|
||||||
"""
|
"""
|
||||||
perms_map = {} # 权限标识
|
perms_map = {} # 权限标识
|
||||||
|
throttle_classes = [UserRateThrottle]
|
||||||
logging_methods = ['POST', 'PUT', 'PATCH', 'DELETE']
|
logging_methods = ['POST', 'PUT', 'PATCH', 'DELETE']
|
||||||
ordering_fields = '__all__'
|
ordering_fields = '__all__'
|
||||||
filter_fields = '__all__'
|
filter_fields = '__all__'
|
||||||
|
|
|
@ -73,8 +73,8 @@ class XxClient:
|
||||||
else:
|
else:
|
||||||
r = getattr(requests, method)('{}{}'.format(settings.XX_BASE_URL, url),
|
r = getattr(requests, method)('{}{}'.format(settings.XX_BASE_URL, url),
|
||||||
params=params, json=json, timeout=timeout, verify=False)
|
params=params, json=json, timeout=timeout, verify=False)
|
||||||
# if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
# print_roundtrip(r)
|
print_roundtrip(r)
|
||||||
ret = r.json()
|
ret = r.json()
|
||||||
if ret.get('errorCode') == '1060000':
|
if ret.get('errorCode') == '1060000':
|
||||||
self.get_token() # 重新获取token
|
self.get_token() # 重新获取token
|
||||||
|
|
|
@ -53,7 +53,8 @@ INSTALLED_APPS = [
|
||||||
'apps.auth1',
|
'apps.auth1',
|
||||||
'apps.monitor',
|
'apps.monitor',
|
||||||
'apps.wf',
|
'apps.wf',
|
||||||
'apps.hrm'
|
'apps.hrm',
|
||||||
|
'apps.am'
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -180,6 +181,10 @@ REST_FRAMEWORK = {
|
||||||
# 'UNAUTHENTICATED_USER': None,
|
# 'UNAUTHENTICATED_USER': None,
|
||||||
# 'UNAUTHENTICATED_TOKEN': None,
|
# 'UNAUTHENTICATED_TOKEN': None,
|
||||||
'EXCEPTION_HANDLER': 'apps.utils.exceptions.custom_exception_hander',
|
'EXCEPTION_HANDLER': 'apps.utils.exceptions.custom_exception_hander',
|
||||||
|
'DEFAULT_THROTTLE_RATES': {
|
||||||
|
'anon': '1/second',
|
||||||
|
'user': '1/second'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
# simplejwt配置
|
# simplejwt配置
|
||||||
SIMPLE_JWT = {
|
SIMPLE_JWT = {
|
||||||
|
@ -327,6 +332,13 @@ XX_USERNAME = conf.XX_USERNAME
|
||||||
XX_BUILDID = conf.XX_BUILDID
|
XX_BUILDID = conf.XX_BUILDID
|
||||||
XX_QUEUE = conf.XX_QUEUE
|
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
|
SD_PWD = conf.SD_PWD
|
||||||
BACKUP_PATH = conf.BACKUP_PATH
|
BACKUP_PATH = conf.BACKUP_PATH
|
||||||
|
|
Loading…
Reference in New Issue