2026-01-29 10:02:15 +08:00

180 lines
6.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
设备模块视图 - App端
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, AllowAny
from utils.response import success, error
from utils.exceptions import ErrorCode
from apps.admins.authentication import AppJWTAuthentication
from .models import Device, UserDevice, DeviceType
from .serializers import (
DeviceSerializer,
UserDeviceSerializer,
BindDeviceSerializer,
DeviceVerifySerializer,
DeviceTypeSerializer
)
class DeviceViewSet(viewsets.ViewSet):
"""设备视图集App端"""
authentication_classes = [AppJWTAuthentication]
permission_classes = [IsAuthenticated]
@action(detail=False, methods=['get'], url_path='query-by-mac',
authentication_classes=[], permission_classes=[AllowAny])
def query_by_mac(self, request):
"""
通过MAC地址查询SN码无需登录
GET /api/v1/devices/query-by-mac?mac=AA:BB:CC:DD:EE:FF
"""
mac = request.query_params.get('mac', '')
if not mac:
return error(message='MAC地址不能为空')
# 统一格式
mac = mac.upper().replace('-', ':')
try:
device = Device.objects.select_related('device_type').get(mac_address=mac)
return success(data={
'sn': device.sn,
'mac_address': device.mac_address,
'device_type': DeviceTypeSerializer(device.device_type).data if device.device_type else None,
'status': device.status,
'is_bound': device.status == 'bound'
})
except Device.DoesNotExist:
return error(
code=404,
message='未找到对应的设备请检查MAC地址是否正确或设备是否已完成入库',
status_code=status.HTTP_404_NOT_FOUND
)
@action(detail=False, methods=['post'])
def verify(self, request):
"""
验证设备SN
POST /api/v1/devices/verify
"""
serializer = DeviceVerifySerializer(data=request.data)
if not serializer.is_valid():
return error(message=str(serializer.errors))
sn = serializer.validated_data['sn']
try:
device = Device.objects.select_related('device_type').get(sn=sn)
except Device.DoesNotExist:
return error(code=ErrorCode.DEVICE_NOT_FOUND, message='设备不存在')
# 检查是否已被绑定
is_bindable = device.status != 'bound'
return success(data={
'sn': device.sn,
'is_bindable': is_bindable,
'device_type': DeviceTypeSerializer(device.device_type).data if device.device_type else None
})
@action(detail=False, methods=['post'])
def bind(self, request):
"""
绑定设备
POST /api/v1/devices/bind
"""
serializer = BindDeviceSerializer(data=request.data)
if not serializer.is_valid():
return error(message=str(serializer.errors))
sn = serializer.validated_data['sn']
spirit_id = serializer.validated_data.get('spirit_id')
try:
device = Device.objects.get(sn=sn)
except Device.DoesNotExist:
return error(code=ErrorCode.DEVICE_NOT_FOUND, message='设备不存在')
# 检查是否已被绑定
if device.status == 'bound':
# 检查是否是当前用户绑定的
existing = UserDevice.objects.filter(device=device, is_active=True).first()
if existing and existing.user != request.user:
return error(code=ErrorCode.DEVICE_ALREADY_BOUND, message='设备已被其他用户绑定')
# 创建绑定关系
user_device, created = UserDevice.objects.update_or_create(
user=request.user,
device=device,
defaults={
'spirit_id': spirit_id,
'is_active': True
}
)
# 更新设备状态
device.status = 'bound'
device.save()
return success(
data=UserDeviceSerializer(user_device).data,
message='绑定成功' if created else '更新绑定成功'
)
@action(detail=False, methods=['get'])
def my_devices(self, request):
"""
我的设备列表
GET /api/v1/devices/my_devices
"""
user_devices = UserDevice.objects.filter(
user=request.user,
is_active=True
).select_related('device', 'device__device_type', 'spirit')
serializer = UserDeviceSerializer(user_devices, many=True)
return success(data=serializer.data)
@action(detail=True, methods=['delete'])
def unbind(self, request, pk=None):
"""
解绑设备
DELETE /api/v1/devices/{id}/unbind
"""
try:
user_device = UserDevice.objects.get(id=pk, user=request.user)
except UserDevice.DoesNotExist:
return error(code=ErrorCode.DEVICE_NOT_FOUND, message='绑定记录不存在')
# 更新绑定状态
user_device.is_active = False
user_device.save()
# 检查设备是否还有其他活跃绑定
active_bindings = UserDevice.objects.filter(device=user_device.device, is_active=True).count()
if active_bindings == 0:
user_device.device.status = 'out_stock'
user_device.device.save()
return success(message='解绑成功')
@action(detail=True, methods=['put'], url_path='update-spirit')
def update_spirit(self, request, pk=None):
"""
更新设备绑定的智能体
PUT /api/v1/devices/{id}/update-spirit
"""
try:
user_device = UserDevice.objects.get(id=pk, user=request.user, is_active=True)
except UserDevice.DoesNotExist:
return error(code=ErrorCode.DEVICE_NOT_FOUND, message='绑定记录不存在')
spirit_id = request.data.get('spirit_id')
user_device.spirit_id = spirit_id
user_device.save()
return success(data=UserDeviceSerializer(user_device).data, message='更新成功')