All checks were successful
Build and Deploy LTY / build-and-deploy (push) Successful in 50m22s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
128 lines
5.3 KiB
Python
128 lines
5.3 KiB
Python
import time
|
||
from rest_framework import serializers
|
||
from django.core.cache import cache
|
||
from django.utils import timezone
|
||
from .models import DeviceType, DeviceBatch, Device, UserDevice
|
||
|
||
|
||
class DeviceTypeSerializer(serializers.ModelSerializer):
|
||
class Meta:
|
||
model = DeviceType
|
||
fields = '__all__'
|
||
|
||
|
||
class DeviceBatchSerializer(serializers.ModelSerializer):
|
||
device_type_name = serializers.ReadOnlyField(source='device_type.name')
|
||
|
||
class Meta:
|
||
model = DeviceBatch
|
||
fields = '__all__'
|
||
|
||
|
||
class DeviceSerializer(serializers.ModelSerializer):
|
||
device_type_name = serializers.ReadOnlyField(source='device_type.name')
|
||
batch_number = serializers.ReadOnlyField(source='batch.batch_number')
|
||
|
||
class Meta:
|
||
model = Device
|
||
fields = '__all__'
|
||
read_only_fields = ('device_code',)
|
||
|
||
|
||
class DeviceCreateSerializer(serializers.ModelSerializer):
|
||
firmware_version = serializers.CharField(max_length=50, required=False)
|
||
wifi_name = serializers.CharField(max_length=100, required=False)
|
||
wifi_password = serializers.CharField(max_length=100, required=False)
|
||
brightness = serializers.IntegerField(min_value=0, max_value=100, required=False)
|
||
|
||
class Meta:
|
||
model = Device
|
||
fields = [
|
||
'device_type', 'batch', 'serial_number', 'mac_address',
|
||
'firmware_version', 'wifi_name', 'wifi_password', 'brightness'
|
||
]
|
||
|
||
|
||
class DeviceBatchCreateSerializer(serializers.Serializer):
|
||
device_type = serializers.PrimaryKeyRelatedField(queryset=DeviceType.objects.all())
|
||
batch = serializers.PrimaryKeyRelatedField(queryset=DeviceBatch.objects.all())
|
||
start_serial = serializers.CharField(max_length=50)
|
||
count = serializers.IntegerField(min_value=1, max_value=1000)
|
||
mac_prefix = serializers.CharField(max_length=9, required=False) # 可选,MAC地址前缀
|
||
|
||
def validate(self, data):
|
||
# 检查批次数量是否足够
|
||
batch = data['batch']
|
||
if batch.device_type.id != data['device_type'].id:
|
||
raise serializers.ValidationError("所选批次不属于所选设备类型")
|
||
|
||
# 检查设备数量是否足够
|
||
existing_devices = Device.objects.filter(batch=batch).count()
|
||
if existing_devices + data['count'] > batch.quantity:
|
||
raise serializers.ValidationError(f"批次总量为{batch.quantity},已创建{existing_devices}台,无法再创建{data['count']}台")
|
||
|
||
return data
|
||
|
||
|
||
class UserDeviceSerializer(serializers.ModelSerializer):
|
||
device_code = serializers.ReadOnlyField(source='device.device_code')
|
||
mac_address = serializers.ReadOnlyField(source='device.mac_address')
|
||
device_type = serializers.ReadOnlyField(source='device.device_type.name')
|
||
device_status = serializers.ReadOnlyField(source='device.status')
|
||
is_online = serializers.SerializerMethodField()
|
||
battery_level = serializers.ReadOnlyField(source='device.battery_level')
|
||
firmware_version = serializers.ReadOnlyField(source='device.firmware_version')
|
||
wifi_name = serializers.ReadOnlyField(source='device.wifi_name')
|
||
wifi_password = serializers.ReadOnlyField(source='device.wifi_password')
|
||
brightness = serializers.ReadOnlyField(source='device.brightness')
|
||
|
||
def get_is_online(self, obj):
|
||
"""根据Redis中的last_seen判断设备是否在线(3分钟内有上报)"""
|
||
last_seen = cache.get(f"device:last_seen:{obj.device.mac_address}")
|
||
if last_seen is None:
|
||
return False
|
||
return (time.time() - float(last_seen)) <= 180
|
||
|
||
class Meta:
|
||
model = UserDevice
|
||
fields = '__all__'
|
||
read_only_fields = ('user', 'bound_at')
|
||
|
||
|
||
class DeviceRegisterSerializer(serializers.Serializer):
|
||
mac_address = serializers.CharField(max_length=17)
|
||
device_type_code = serializers.CharField(max_length=10, required=False, default='T01')
|
||
firmware_version = serializers.CharField(max_length=50, required=False, default='')
|
||
|
||
def validate_mac_address(self, value):
|
||
if Device.objects.filter(mac_address=value).exists():
|
||
raise serializers.ValidationError("设备已注册")
|
||
return value
|
||
|
||
def validate_device_type_code(self, value):
|
||
if not DeviceType.objects.filter(code=value).exists():
|
||
raise serializers.ValidationError(f"设备类型 {value} 不存在")
|
||
return value
|
||
|
||
|
||
class DeviceBindSerializer(serializers.Serializer):
|
||
mac_address = serializers.CharField(max_length=17)
|
||
nickname = serializers.CharField(max_length=100, required=False)
|
||
is_primary = serializers.BooleanField(default=False, required=False)
|
||
|
||
def validate_mac_address(self, value):
|
||
try:
|
||
device = Device.objects.get(mac_address=value)
|
||
# 检查设备是否已被激活
|
||
if not device.is_active:
|
||
device.is_active = True
|
||
device.activated_at = timezone.now()
|
||
device.save()
|
||
except Device.DoesNotExist:
|
||
raise serializers.ValidationError("设备不存在")
|
||
|
||
# 检查设备是否已被其他用户绑定
|
||
if UserDevice.objects.filter(device=device).exists():
|
||
raise serializers.ValidationError("设备已被其他用户绑定")
|
||
|
||
return value |