|
@@ -0,0 +1,134 @@
|
|
|
+import time
|
|
|
+
|
|
|
+from MySQLdb import DatabaseError
|
|
|
+from django.db import transaction
|
|
|
+from django.http import QueryDict
|
|
|
+from django.views import View
|
|
|
+from Ansjer.config import LOGGER
|
|
|
+from AgentModel.models import DeviceCustomUID, CustomUIDPool
|
|
|
+from Object.ResponseObject import ResponseObject
|
|
|
+from Service.CommonService import CommonService
|
|
|
+from Object.RedisObject import RedisObject
|
|
|
+
|
|
|
+
|
|
|
+class DeviceCustomUIDView(View):
|
|
|
+ def get(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ return self.validation(request.GET, request, operation)
|
|
|
+
|
|
|
+ def post(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ return self.validation(request.POST, request, operation)
|
|
|
+
|
|
|
+ def delete(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ delete = QueryDict(request.body)
|
|
|
+ if not delete:
|
|
|
+ delete = request.GET
|
|
|
+ return self.validation(delete, request, operation)
|
|
|
+
|
|
|
+ def put(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ put = QueryDict(request.body)
|
|
|
+ return self.validation(put, request, operation)
|
|
|
+
|
|
|
+ def validation(self, request_dict, request, operation):
|
|
|
+ response = ResponseObject('en')
|
|
|
+ if operation == 'getUID': # 获取电池电量列表
|
|
|
+ return self.get_custom_uid(request, request_dict, response)
|
|
|
+
|
|
|
+ @classmethod
|
|
|
+ def get_custom_uid(cls, request, request_dict, response):
|
|
|
+ ip = CommonService.get_ip_address(request)
|
|
|
+ LOGGER.info('获取定制客户UID:{},ip:{}'.format(request_dict, ip))
|
|
|
+ mac = request_dict.get('mac', None)
|
|
|
+ token = request_dict.get('token', None)
|
|
|
+ time_stamp = request_dict.get('time_stamp', None)
|
|
|
+
|
|
|
+ if not all([mac, token, time_stamp]):
|
|
|
+ LOGGER.error(f'{mac}请求绑定uid参数缺失')
|
|
|
+ return response.json(444)
|
|
|
+
|
|
|
+ # 时间戳token校验
|
|
|
+ if not CommonService.check_time_stamp_token(token, time_stamp):
|
|
|
+ LOGGER.error(f'{mac}时间戳校验失败time:{time_stamp},tk:{token}')
|
|
|
+ return response.json(13)
|
|
|
+
|
|
|
+ # 分布式锁配置
|
|
|
+ redis = RedisObject()
|
|
|
+
|
|
|
+ lock_key = f"uid_assign:{mac}"
|
|
|
+ request_id = f"{mac}_{time_stamp}"
|
|
|
+
|
|
|
+ try:
|
|
|
+ # 第一次检查现有绑定
|
|
|
+ existing_binding = DeviceCustomUID.objects.filter(
|
|
|
+ device_mac=mac,
|
|
|
+ status=1
|
|
|
+ ).select_related('uid').first()
|
|
|
+
|
|
|
+ if existing_binding:
|
|
|
+ LOGGER.info(f'{mac}已存在有效绑定')
|
|
|
+ return response.json(0, data={'uid': existing_binding.uid.uid})
|
|
|
+
|
|
|
+ # 获取分布式锁(设置5秒过期时间)
|
|
|
+ if not redis.try_lock(lock_key, request_id, expire=5, time_unit_second=1):
|
|
|
+ LOGGER.error(f'{mac}获取锁失败')
|
|
|
+ return response.json(5)
|
|
|
+
|
|
|
+ # 二次检查(防止在等待锁期间被其他请求处理)
|
|
|
+ existing_binding = DeviceCustomUID.objects.filter(
|
|
|
+ device_mac=mac,
|
|
|
+ status=1
|
|
|
+ ).select_related('uid').first()
|
|
|
+
|
|
|
+ if existing_binding:
|
|
|
+ LOGGER.info(f'{mac}二次检查存在绑定')
|
|
|
+ return response.json(0, data={'uid': existing_binding.uid.uid})
|
|
|
+
|
|
|
+ # 核心分配逻辑
|
|
|
+ with transaction.atomic():
|
|
|
+ # 获取可用UID(使用SELECT FOR UPDATE锁定行)
|
|
|
+ available_uid = CustomUIDPool.objects.select_for_update() \
|
|
|
+ .filter(status=0) \
|
|
|
+ .order_by('id') \
|
|
|
+ .first()
|
|
|
+
|
|
|
+ if not available_uid:
|
|
|
+ LOGGER.error(f'{mac}UID池已耗尽')
|
|
|
+ return response.json(173)
|
|
|
+
|
|
|
+ # 更新UID状态
|
|
|
+ n_time = int(time.time())
|
|
|
+ available_uid.status = 1
|
|
|
+ available_uid.updated_time = n_time
|
|
|
+ available_uid.save(update_fields=['status', 'updated_time'])
|
|
|
+
|
|
|
+ # 创建绑定记录
|
|
|
+ DeviceCustomUID.objects.create(
|
|
|
+ uid=available_uid,
|
|
|
+ device_mac=mac,
|
|
|
+ status=1,
|
|
|
+ created_time=n_time,
|
|
|
+ updated_time=n_time
|
|
|
+ )
|
|
|
+
|
|
|
+ LOGGER.info(f'{mac}成功分配UID: {available_uid.uid}')
|
|
|
+ return response.json(0, data={'uid': available_uid.uid})
|
|
|
+
|
|
|
+ except DatabaseError as e:
|
|
|
+ LOGGER.error(f'{mac}数据库操作异常: {str(e)}')
|
|
|
+ return response.json(18)
|
|
|
+ except Exception as e:
|
|
|
+ LOGGER.error(f'系统异常: {str(e)}')
|
|
|
+ return response.json(500)
|
|
|
+ finally:
|
|
|
+ # 确保释放锁
|
|
|
+ if redis.release_lock(lock_key, request_id):
|
|
|
+ LOGGER.debug(f'{mac}锁释放成功')
|
|
|
+ else:
|
|
|
+ LOGGER.warning(f'{mac}锁释放异常')
|