workflow admin 展示
This commit is contained in:
parent
adde4d671e
commit
7a62edb988
|
@ -0,0 +1,38 @@
|
|||
//python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./BeiHangGrpc.proto
|
||||
syntax = "proto3";
|
||||
|
||||
option java_generic_services = true;
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.lyzh.aiservice.grpc";
|
||||
option java_outer_classname = "BeiHangProto";
|
||||
|
||||
service Helmet_Reg {
|
||||
rpc sendHelmet_Info(JinYu_Request) returns (BHhelmet_Response){}
|
||||
}
|
||||
|
||||
message JinYu_Request {
|
||||
int64 zzid = 1; //业务唯一ID
|
||||
string imgsbase64 = 2 ; //图像Base64字符串
|
||||
string imgUrl = 3 ; //图像oss链接Url
|
||||
}
|
||||
|
||||
message BHhelmet_Response {
|
||||
int64 zzid = 1; //业务唯一ID
|
||||
repeated HelmetInfo helmetinfoList = 2; //0:带安全帽 1:未带安全帽
|
||||
}
|
||||
|
||||
message Point {
|
||||
double x = 1; //x坐标
|
||||
double y = 2; //y坐标
|
||||
}
|
||||
|
||||
message Rectangle {
|
||||
Point uleft = 1; //左上
|
||||
Point lright = 2; //右下
|
||||
}
|
||||
|
||||
message HelmetInfo {
|
||||
int64 head_helmet = 1; //戴头盔
|
||||
double conf = 2; //置信度
|
||||
Rectangle coord = 3; //矩形坐标
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: BeiHangGrpc.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x42\x65iHangGrpc.proto\"A\n\rJinYu_Request\x12\x0c\n\x04zzid\x18\x01 \x01(\x03\x12\x12\n\nimgsbase64\x18\x02 \x01(\t\x12\x0e\n\x06imgUrl\x18\x03 \x01(\t\"F\n\x11\x42Hhelmet_Response\x12\x0c\n\x04zzid\x18\x01 \x01(\x03\x12#\n\x0ehelmetinfoList\x18\x02 \x03(\x0b\x32\x0b.HelmetInfo\"\x1d\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\":\n\tRectangle\x12\x15\n\x05uleft\x18\x01 \x01(\x0b\x32\x06.Point\x12\x16\n\x06lright\x18\x02 \x01(\x0b\x32\x06.Point\"J\n\nHelmetInfo\x12\x13\n\x0bhead_helmet\x18\x01 \x01(\x03\x12\x0c\n\x04\x63onf\x18\x02 \x01(\x01\x12\x19\n\x05\x63oord\x18\x03 \x01(\x0b\x32\n.Rectangle2E\n\nHelmet_Reg\x12\x37\n\x0fsendHelmet_Info\x12\x0e.JinYu_Request\x1a\x12.BHhelmet_Response\"\x00\x42,\n\x17\x63om.lyzh.aiservice.grpcB\x0c\x42\x65iHangProtoP\x01\x88\x01\x01\x62\x06proto3')
|
||||
|
||||
|
||||
_JINYU_REQUEST = DESCRIPTOR.message_types_by_name['JinYu_Request']
|
||||
_BHHELMET_RESPONSE = DESCRIPTOR.message_types_by_name['BHhelmet_Response']
|
||||
_POINT = DESCRIPTOR.message_types_by_name['Point']
|
||||
_RECTANGLE = DESCRIPTOR.message_types_by_name['Rectangle']
|
||||
_HELMETINFO = DESCRIPTOR.message_types_by_name['HelmetInfo']
|
||||
JinYu_Request = _reflection.GeneratedProtocolMessageType('JinYu_Request', (_message.Message,), {
|
||||
'DESCRIPTOR': _JINYU_REQUEST,
|
||||
'__module__': 'BeiHangGrpc_pb2'
|
||||
# @@protoc_insertion_point(class_scope:JinYu_Request)
|
||||
})
|
||||
_sym_db.RegisterMessage(JinYu_Request)
|
||||
|
||||
BHhelmet_Response = _reflection.GeneratedProtocolMessageType('BHhelmet_Response', (_message.Message,), {
|
||||
'DESCRIPTOR': _BHHELMET_RESPONSE,
|
||||
'__module__': 'BeiHangGrpc_pb2'
|
||||
# @@protoc_insertion_point(class_scope:BHhelmet_Response)
|
||||
})
|
||||
_sym_db.RegisterMessage(BHhelmet_Response)
|
||||
|
||||
Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), {
|
||||
'DESCRIPTOR': _POINT,
|
||||
'__module__': 'BeiHangGrpc_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Point)
|
||||
})
|
||||
_sym_db.RegisterMessage(Point)
|
||||
|
||||
Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), {
|
||||
'DESCRIPTOR': _RECTANGLE,
|
||||
'__module__': 'BeiHangGrpc_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Rectangle)
|
||||
})
|
||||
_sym_db.RegisterMessage(Rectangle)
|
||||
|
||||
HelmetInfo = _reflection.GeneratedProtocolMessageType('HelmetInfo', (_message.Message,), {
|
||||
'DESCRIPTOR': _HELMETINFO,
|
||||
'__module__': 'BeiHangGrpc_pb2'
|
||||
# @@protoc_insertion_point(class_scope:HelmetInfo)
|
||||
})
|
||||
_sym_db.RegisterMessage(HelmetInfo)
|
||||
|
||||
_HELMET_REG = DESCRIPTOR.services_by_name['Helmet_Reg']
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\027com.lyzh.aiservice.grpcB\014BeiHangProtoP\001\210\001\001'
|
||||
_JINYU_REQUEST._serialized_start = 21
|
||||
_JINYU_REQUEST._serialized_end = 86
|
||||
_BHHELMET_RESPONSE._serialized_start = 88
|
||||
_BHHELMET_RESPONSE._serialized_end = 158
|
||||
_POINT._serialized_start = 160
|
||||
_POINT._serialized_end = 189
|
||||
_RECTANGLE._serialized_start = 191
|
||||
_RECTANGLE._serialized_end = 249
|
||||
_HELMETINFO._serialized_start = 251
|
||||
_HELMETINFO._serialized_end = 325
|
||||
_HELMET_REG._serialized_start = 327
|
||||
_HELMET_REG._serialized_end = 396
|
||||
# @@protoc_insertion_point(module_scope)
|
|
@ -0,0 +1,67 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import BeiHangGrpc_pb2 as BeiHangGrpc__pb2
|
||||
|
||||
|
||||
class Helmet_RegStub(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.sendHelmet_Info = channel.unary_unary(
|
||||
'/Helmet_Reg/sendHelmet_Info',
|
||||
request_serializer=BeiHangGrpc__pb2.JinYu_Request.SerializeToString,
|
||||
response_deserializer=BeiHangGrpc__pb2.BHhelmet_Response.FromString,
|
||||
)
|
||||
|
||||
|
||||
class Helmet_RegServicer(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def sendHelmet_Info(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_Helmet_RegServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'sendHelmet_Info': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.sendHelmet_Info,
|
||||
request_deserializer=BeiHangGrpc__pb2.JinYu_Request.FromString,
|
||||
response_serializer=BeiHangGrpc__pb2.BHhelmet_Response.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'Helmet_Reg', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
|
||||
|
||||
class Helmet_Reg(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
@staticmethod
|
||||
def sendHelmet_Info(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/Helmet_Reg/sendHelmet_Info',
|
||||
BeiHangGrpc__pb2.JinYu_Request.SerializeToString,
|
||||
BeiHangGrpc__pb2.BHhelmet_Response.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
@ -0,0 +1,29 @@
|
|||
import grpc
|
||||
import BeiHangGrpc_pb2_grpc, BeiHangGrpc_pb2
|
||||
|
||||
|
||||
|
||||
def helmet_test(ip, pic_url):
|
||||
channel = grpc.insecure_channel(ip) # 监听频道
|
||||
stub = BeiHangGrpc_pb2_grpc.Helmet_RegStub(channel) # 客户端使用Stub类发送请求,参数为频道,为了绑定链接
|
||||
image_id = 3
|
||||
|
||||
# 本地图像输入
|
||||
# image_path = "./onnx/image/single3.jpg"
|
||||
# with open(image_path, 'rb') as f:
|
||||
# image_base64 = str(base64.b64encode(f.read()), encoding='utf-8')
|
||||
# request = BeiHangGrpc_pb2.JinYu_Request(zzid=image_id,imgsbase64=image_base64)
|
||||
|
||||
request = BeiHangGrpc_pb2.JinYu_Request(zzid=image_id, imgUrl=pic_url)
|
||||
try:
|
||||
response = stub.sendHelmet_Info(request)
|
||||
print("network success! \n")
|
||||
print(response.helmetinfoList[0].head_helmet)
|
||||
except Exception:
|
||||
print("network error! \n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
helmet_test(
|
||||
ip='122.224.229.24:2000',
|
||||
pic_url='http://1.203.161.103:2800/media/2022/07/06/dsf_bf6446cc-f9cd-11ec-bd2d-e4246c7d1635_34597240_34614457.jpg')
|
|
@ -0,0 +1,2 @@
|
|||
class AiService:
|
||||
pass
|
|
@ -473,15 +473,15 @@ class FileViewSet(CustomCreateModelMixin, RetrieveModelMixin, ListModelMixin, Cu
|
|||
name = file_obj._name
|
||||
size = file_obj.size
|
||||
mime = file_obj.content_type
|
||||
file_type = '其它'
|
||||
file_type = File.FILE_TYPE_OTHER
|
||||
if 'image' in mime:
|
||||
file_type = '图片'
|
||||
file_type = File.FILE_TYPE_PIC
|
||||
elif 'video' in mime:
|
||||
file_type = '视频'
|
||||
file_type = File.FILE_TYPE_VIDEO
|
||||
elif 'audio' in mime:
|
||||
file_type = '音频'
|
||||
file_type = File.FILE_TYPE_AUDIO
|
||||
elif 'application' or 'text' in mime:
|
||||
file_type = '文档'
|
||||
file_type = File.FILE_TYPE_DOC
|
||||
instance = serializer.save(
|
||||
create_by=self.request.user, name=name, size=size, type=file_type, mime=mime)
|
||||
instance.path = settings.MEDIA_URL + instance.file.name
|
||||
|
|
|
@ -31,7 +31,7 @@ class TDevice(BaseModel):
|
|||
(DEVICE_PANEL, '面板机')
|
||||
)
|
||||
type = models.PositiveSmallIntegerField('设备类型', choices=DEVICE_CHOICE)
|
||||
code = models.CharField('设备唯一标识', max_length=50, db_index=True)
|
||||
code = models.CharField('设备唯一标识', max_length=50, db_index=True, unique=True)
|
||||
name = models.CharField('名称', max_length=50, null=True, blank=True)
|
||||
location = models.JSONField('位置信息', default=dict,
|
||||
null=False, blank=True)
|
||||
|
@ -40,14 +40,27 @@ class TDevice(BaseModel):
|
|||
areas = models.ManyToManyField(Area, verbose_name='覆盖区',
|
||||
related_name='tareas')
|
||||
obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
|
||||
employee = models.ForeignKey(Employee, verbose_name='当前绑定人员', on_delete=models.CASCADE, null=True, blank=True)
|
||||
employee = models.ForeignKey(Employee, verbose_name='当前绑定人员', on_delete=models.CASCADE,
|
||||
null=True, blank=True, related_name='td_employee')
|
||||
is_clock = models.BooleanField('是否打卡设备', default=False)
|
||||
third_info = models.JSONField('三方信息', default=dict,
|
||||
null=False, blank=True)
|
||||
|
||||
|
||||
class BltRecord(BaseModel):
|
||||
pass
|
||||
class BltBind(BaseModel):
|
||||
"""标签绑定/解绑记录
|
||||
"""
|
||||
BLT_BIND = 10
|
||||
BLT_UNBIND = 20
|
||||
BIND_TYPE_CHOICES = (
|
||||
(10, '绑定'),
|
||||
(20, '解绑')
|
||||
)
|
||||
type = models.PositiveSmallIntegerField('绑定类型', default=10, help_text='10(绑定)/20(解绑)',
|
||||
choices=BIND_TYPE_CHOICES)
|
||||
obj_cate = models.CharField('绑定对象', max_length=20, help_text='people/...', null=True, blank=True)
|
||||
blt = models.ForeignKey(TDevice, verbose_name='关联标签', on_delete=models.CASCADE)
|
||||
employee = models.ForeignKey(Employee, verbose_name='关联人员', on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
|
||||
class Tlog(BaseModel):
|
||||
|
|
|
@ -2,8 +2,9 @@ from rest_framework import serializers
|
|||
|
||||
from apps.am.models import Area
|
||||
from apps.hrm.serializers import EmployeeBaseSerializer, EmployeeSimpleSerializer
|
||||
from apps.third.models import TDevice, Tlog
|
||||
from apps.third.models import BltBind, TDevice, Tlog
|
||||
from apps.utils.serializers import CustomModelSerializer
|
||||
from django.db import transaction
|
||||
|
||||
|
||||
class PicSerializer(serializers.Serializer):
|
||||
|
@ -11,6 +12,7 @@ class PicSerializer(serializers.Serializer):
|
|||
|
||||
|
||||
class TDeviceSerializer(CustomModelSerializer):
|
||||
employee_ = EmployeeSimpleSerializer(source='employee', read_only=True)
|
||||
area_name = serializers.CharField(source='area.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
|
@ -69,10 +71,22 @@ class BltSerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = TDevice
|
||||
fields = ['code', 'obj_cate', 'employee', 'employee_']
|
||||
fields = ['code', 'obj_cate', 'employee', 'employee_', 'id']
|
||||
|
||||
|
||||
class BltQuerySerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TDevice
|
||||
fields = ['area']
|
||||
|
||||
|
||||
class BltBindCreateSerializer(serializers.ModelSerializer):
|
||||
blt = serializers.PrimaryKeyRelatedField(queryset=TDevice.objects.filter(type=TDevice.DEVICE_BLT))
|
||||
|
||||
class Meta:
|
||||
model = BltBind
|
||||
fields = ['type', 'blt', 'employee']
|
||||
|
||||
|
||||
class BltCreatesSerializer(serializers.Serializer):
|
||||
macs = serializers.ListField(child=serializers.CharField(), label='标签mac列表')
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import time
|
||||
from threading import Thread
|
||||
import uuid
|
||||
|
||||
import requests
|
||||
from rest_framework.exceptions import APIException, ParseError
|
||||
from django.conf import settings
|
||||
|
||||
from apps.third.errors import SP_REQUEST_ERROR
|
||||
from apps.third.models import Tlog
|
||||
from apps.utils.tools import print_roundtrip
|
||||
from apps.third.tapis import spapis
|
||||
from django.utils.timezone import now
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
|
@ -27,6 +30,7 @@ class SpClient:
|
|||
self.isGetingToken = False
|
||||
self.isRuning = True
|
||||
self.t = None # 线程
|
||||
self.log = {}
|
||||
self.setup()
|
||||
|
||||
def _get_token_loop(self):
|
||||
|
@ -72,47 +76,35 @@ class SpClient:
|
|||
file_path_rela=None, raise_exception=True):
|
||||
if not settings.SP_ENABLED:
|
||||
raise ParseError('音响对接未启用')
|
||||
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.get('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
|
||||
else:
|
||||
ret = r.json()
|
||||
detail = '音响错误:{}-{}'.format(str(ret.get('type', '')), str(ret.get('message', '')))
|
||||
self.log = {"requested_at": now(), "id": uuid.uuid4(), "path": url, "method": method,
|
||||
"params": params, "body": json, "target": "dahua", "result": 10}
|
||||
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.get('msg', '')))
|
||||
err_detail = dict(detail=detail, code='sp_'+str(ret['code']))
|
||||
self.handle_log(result='fail', response=ret)
|
||||
if raise_exception:
|
||||
raise ParseError(**err_detail)
|
||||
return 'fail', dict(detail=detail, code='sp_'+str(ret['code']))
|
||||
self.handle_log(result='success', response=ret)
|
||||
return 'success', ret
|
||||
self.handle_log(result='error', response=None)
|
||||
if raise_exception:
|
||||
raise APIException(**SP_REQUEST_ERROR)
|
||||
return 'error', SP_REQUEST_ERROR
|
||||
|
@ -146,3 +138,20 @@ class SpClient:
|
|||
}
|
||||
self.request(**spapis['send_to_device'], json=json)
|
||||
return
|
||||
|
||||
def _get_response_ms(self):
|
||||
"""
|
||||
Get the duration of the request response cycle is milliseconds.
|
||||
In case of negative duration 0 is returned.
|
||||
"""
|
||||
response_timedelta = now() - self.log["requested_at"]
|
||||
response_ms = int(response_timedelta.total_seconds() * 1000)
|
||||
return max(response_ms, 0)
|
||||
|
||||
def handle_log(self, result, response=None):
|
||||
self.log.update({
|
||||
"result": result,
|
||||
"response": response,
|
||||
"response_ms": self._get_response_ms()
|
||||
})
|
||||
Tlog(**self.log).save()
|
||||
|
|
|
@ -119,6 +119,14 @@ xxapis = {
|
|||
"rail_ibeacon_list": {
|
||||
"url": "/WebLocate/locateByRail",
|
||||
"method": "post"
|
||||
},
|
||||
"blt_adds": {
|
||||
"url": "/api/v4/device/blts/add",
|
||||
"method": "post"
|
||||
},
|
||||
"blt_info": {
|
||||
"url": "/api/devicesV3/bltInfoByMac",
|
||||
"method": "post"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from apps.third.models import TDevice, Tlog
|
||||
from apps.third.serializers import BindAreaSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TlogSerializer
|
||||
from apps.third.models import BltBind, TDevice, Tlog
|
||||
from apps.third.serializers import BindAreaSerializer, BltBindCreateSerializer, BltQuerySerializer, BltSerializer, LabelLocationSerializer, TDeviceSerializer, TlogSerializer
|
||||
from apps.utils.viewsets import CustomGenericViewSet
|
||||
from rest_framework.mixins import ListModelMixin, CreateModelMixin
|
||||
from apps.third.clients import xxClient, dhClient, spClient
|
||||
|
@ -10,6 +10,8 @@ from rest_framework.decorators import action
|
|||
from apps.am.models import Area
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.exceptions import ParseError
|
||||
from django.db import transaction
|
||||
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin
|
||||
|
||||
|
||||
class BltViewSet(CustomGenericViewSet):
|
||||
|
@ -36,9 +38,9 @@ class BltViewSet(CustomGenericViewSet):
|
|||
|
||||
@action(methods=['get'], detail=False, perms_map={'get': '*'})
|
||||
def count_now(self, request):
|
||||
"""统计在厂标签数
|
||||
"""统计在厂且绑定标签数
|
||||
|
||||
统计在厂标签数
|
||||
统计在厂且绑定标签数
|
||||
"""
|
||||
json = {
|
||||
"pageNum": 1,
|
||||
|
@ -108,14 +110,91 @@ class BltViewSet(CustomGenericViewSet):
|
|||
return Response(blt_list)
|
||||
|
||||
|
||||
class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
||||
class TDeviceViewSet(ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
||||
"""
|
||||
三方设备接口
|
||||
"""
|
||||
queryset = TDevice.objects.all()
|
||||
serializer_class = TDeviceSerializer
|
||||
ordering = ['code', '-create_time']
|
||||
filterset_fields = ['type']
|
||||
ordering = ['-create_time']
|
||||
filterset_fields = ['type', 'area', 'employee', 'obj_cate']
|
||||
select_related_fields = ['employee', 'area', 'employee__post', 'employee__belong_dept']
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
else:
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
data = serializer.data
|
||||
typex = self.request.query_params.get('type', None)
|
||||
if typex == str(TDevice.DEVICE_BLT): # 如果是定位标签加载三方信息
|
||||
macs = []
|
||||
for i in data:
|
||||
macs.append(i['code'])
|
||||
json = {
|
||||
"macList": macs
|
||||
}
|
||||
_, res = xxClient.request(**xxapis['blt_info'], json=json)
|
||||
macs_dict = {}
|
||||
for i in res['success']:
|
||||
macs_dict[i['mac']] = i
|
||||
for i in res['error']:
|
||||
macs_dict[i['mac']] = i
|
||||
for i in data:
|
||||
i['third_info'] = macs_dict.get(i['code'], {})
|
||||
if page is not None:
|
||||
return self.get_paginated_response(data)
|
||||
else:
|
||||
return Response(data)
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||
serializer_class=Serializer)
|
||||
@transaction.atomic
|
||||
def blt_sync(self, request):
|
||||
"""同步标签mac至平台
|
||||
|
||||
同步标签mac至平台
|
||||
"""
|
||||
json = {
|
||||
"pageNum": 1,
|
||||
"numPerPage": 1000
|
||||
}
|
||||
_, res = xxClient.request(**xxapis['blt_list'], json=json)
|
||||
blt_list = res['recordList']
|
||||
for i in blt_list:
|
||||
TDevice.objects.get_or_create(code=i['mac'], default={"code": i['mac'], "type": TDevice.DEVICE_BLT})
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||
serializer_class=BltBindCreateSerializer)
|
||||
@transaction.atomic
|
||||
def blt_bind(self, request):
|
||||
"""绑定/解绑定位卡
|
||||
|
||||
绑定/解绑定位卡
|
||||
"""
|
||||
serializer = BltBindCreateSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
vdata = serializer.validated_data
|
||||
blt = vdata['blt']
|
||||
if vdata['type'] == BltBind.BLT_BIND and vdata['employee']:
|
||||
if blt.employee:
|
||||
raise ParseError('该定位卡已绑定人员,请先解绑')
|
||||
else:
|
||||
blt.employee = vdata['employee']
|
||||
blt.obj_cate = 'people'
|
||||
blt.save()
|
||||
vdata['obj_cate'] = 'people'
|
||||
BltBind.objects.create(**vdata)
|
||||
elif vdata['type'] == BltBind.BLT_UNBIND:
|
||||
if blt.employee:
|
||||
blt.employee = None
|
||||
blt.save()
|
||||
vdata['obj_cate'] = 'people'
|
||||
BltBind.objects.create(**vdata)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||
serializer_class=Serializer)
|
||||
|
@ -128,7 +207,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
|||
macs = []
|
||||
for i in res['recordList']:
|
||||
macs.append(i['mac'])
|
||||
qs = self.queryset.filter(code__in=macs).exclude(employee=None)
|
||||
qs = self.queryset.filter(code__in=macs)
|
||||
qs_data = BltSerializer(instance=qs, many=True).data
|
||||
qs_dict = {}
|
||||
for i in qs_data:
|
||||
|
@ -158,6 +237,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
|||
for i in tds_info:
|
||||
tds_dict[i['code']] = i
|
||||
for i in res['pageData']:
|
||||
i['my_info'] = {}
|
||||
if i['channelCode'] in tds_dict:
|
||||
i['my_info'] = tds_dict[i['channelCode']]
|
||||
return Response(res)
|
||||
|
@ -179,6 +259,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
|||
for i in tds_info:
|
||||
tds_dict[i['code']] = i
|
||||
for i in res['rows']:
|
||||
i['my_info'] = {}
|
||||
if i['sn'] in tds_dict:
|
||||
i['my_info'] = tds_dict[i['sn']]
|
||||
return Response(res)
|
||||
|
@ -202,6 +283,7 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
|||
for i in tds_info:
|
||||
tds_dict[i['code']] = i
|
||||
for i in res['pageData']:
|
||||
i['my_info'] = {}
|
||||
if i['channelCode'] in tds_dict:
|
||||
i['my_info'] = tds_dict[i['channelCode']]
|
||||
return Response(res)
|
||||
|
@ -246,9 +328,9 @@ class TDeviceViewSet(ListModelMixin, CustomGenericViewSet):
|
|||
serializer_class=BindAreaSerializer)
|
||||
def bind_area(self, request):
|
||||
"""
|
||||
绑定所在区域
|
||||
批量绑定所在区域
|
||||
|
||||
绑定所在区域
|
||||
批量绑定所在区域
|
||||
"""
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from aip import AipSpeech
|
||||
from django.conf import settings
|
||||
import uuid
|
||||
import os
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
def generate_voice(msg: str, per: int = 0):
|
||||
|
@ -19,9 +21,12 @@ def generate_voice(msg: str, per: int = 0):
|
|||
result = client.synthesis(msg, 'zh', 1, {'vol': 5, 'spd': 5, 'per': per})
|
||||
# 识别正确返回语音二进制 错误则返回dict 参照下面错误码
|
||||
if not isinstance(result, dict):
|
||||
# name = '{}.mp3'.format(uuid.uuid4())
|
||||
path = '/media/voice/{}.mp3'.format(uuid.uuid4())
|
||||
with open(settings.BASE_DIR + path, 'wb') as f:
|
||||
file_name = '{}.mp3'.format(uuid.uuid4())
|
||||
path = '/media/' + timezone.now().strftime('%Y/%m/%d/')
|
||||
full_path = settings.BASE_DIR + path
|
||||
if not os.path.exists(full_path):
|
||||
os.makedirs(full_path)
|
||||
with open(full_path + file_name, 'wb') as f:
|
||||
f.write(result)
|
||||
return True, path, None
|
||||
return True, path + file_name, None
|
||||
return False, None, result
|
||||
|
|
|
@ -22,6 +22,13 @@ class Workflow(CommonAModel):
|
|||
content_template = models.CharField(
|
||||
'内容模板', max_length=1000, default='标题:{title}, 创建时间:{create_time}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:标题:{title}, 创建时间:{create_time}')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '工作流'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class State(CommonAModel):
|
||||
"""
|
||||
|
@ -99,6 +106,13 @@ class State(CommonAModel):
|
|||
participant_cc = models.JSONField('抄送给', default=list, blank=True, help_text='抄送给(userid列表)')
|
||||
on_reach_func = models.CharField('到达时调用方法', max_length=100, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '工作流节点'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return '{}-{}-{}'.format(self.id, self.workflow.name, self.name)
|
||||
|
||||
|
||||
class Transition(CommonAModel):
|
||||
"""
|
||||
|
@ -154,6 +168,13 @@ class Transition(CommonAModel):
|
|||
'是否校验必填项', default=True, help_text='默认在用户点击操作的时候需要校验工单表单的必填项,如果设置为否则不检查。用于如"退回"属性的操作,不需要填写表单内容')
|
||||
on_submit_func = models.CharField('提交操作调用方法', max_length=100, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '工作流流转'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return '{}-{}-{}'.format(self.id, self.workflow.name, self.name)
|
||||
|
||||
|
||||
class CustomField(CommonAModel):
|
||||
"""自定义字段, 设定某个工作流有哪些自定义字段"""
|
||||
|
|
|
@ -389,3 +389,7 @@ XNIU_SMS_SECRET = conf.XNIU_SMS_SECRET
|
|||
BD_SP_ID = conf.BD_SP_ID
|
||||
BD_SP_KEY = conf.BD_SP_KEY
|
||||
BD_SP_SECRET = conf.BD_SP_SECRET
|
||||
|
||||
|
||||
# 算法层
|
||||
AI_IP = conf.AI_IP
|
||||
|
|
Loading…
Reference in New Issue