import json import logging import time import requests from django.db import transaction from django.views import View from Ansjer.config import CRCKey, CONFIG_INFO, CONFIG_TEST, CONFIG_US, \ CONFIG_CN, USED_SERIAL_REDIS_LIST, UNUSED_SERIAL_REDIS_LIST, SERVER_DOMAIN_US, REGION_ID_LIST from Model.models import SerialNumberModel, CompanySerialModel, UIDCompanySerialModel, UIDModel, Device_Info, \ iotdeviceInfoModel, LogModel, UidSetModel, UID_Bucket, \ Unused_Uid_Meal, Order_Model, StsCrdModel, VodHlsModel, ExperienceContextModel, UidUserModel, ExperienceAiModel, \ AiService, DeviceDomainRegionModel, RegionModel from Object.RedisObject import RedisObject from Object.TokenObject import TokenObject from Object.uidManageResponseObject import uidManageResponseObject from Service.AlgorithmService import AlgorithmBaseOn35 from Service.CommonService import CommonService from Service.EquipmentInfoService import EquipmentInfoService class SerialNumberView(View): def get(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation', None) request_dict = request.GET return self.validate(request_dict, operation, request) def post(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation', None) request_dict = request.POST return self.validate(request_dict, operation, request) def validate(self, request_dict, operation, request): response = uidManageResponseObject() if operation == 'attachUID': # 绑定uid return self.do_attach_uid(request_dict, response, request) elif operation == 'detachUID': # 解绑uid return self.do_detach_uid(request, request_dict, response) elif operation == 'create': # 创建序列号 return self.do_create(request_dict, response) elif operation == 'getUID': # 根据序列号获取uid return self.do_get_uid(request_dict, response) elif operation == 'getRegionInfo': # 根据序列号状态确认uid地区(PC工具使用) return self.get_region_info(request_dict, response) elif operation == 'saveRegion': # 保存设备地区信息(app使用) return self.save_region(request, request_dict, response) elif operation == 'getDomain': # 获取域名(设备使用) return self.get_domain(request_dict, response) elif operation == 'resetRegionId': # 重置地区id return self.reset_region_id(request_dict, response) else: return response.json(414) @staticmethod def do_create(request_dict, response): quantity = int(request_dict.get('quantity', 0)) if not quantity: return response.json(444) try: try: number = SerialNumberModel.objects.last().id except: number = 0 serial_number_bulk = [] now_time = int(time.time()) algorithm = AlgorithmBaseOn35() for i in range(quantity): serial_number = algorithm.getLetter(number) number += 1 # sum每次递增1 # 前面补0至六位 serial_number = (6 - len(serial_number)) * '0' + serial_number serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time)) # 开启事务写入 with transaction.atomic(): SerialNumberModel.objects.bulk_create(serial_number_bulk) return response.json(0) except Exception as e: print(e) return response.json(500, repr(e)) def do_attach_uid(self, request_dict, response, request): serial_number = request_dict.get('serial_number', None) token = request_dict.get('token', None) time_stamp = request_dict.get('time_stamp', None) if not all([serial_number, token, time_stamp]): return response.json(444) # 时间戳token校验 if not CommonService.check_time_stamp_token(token, time_stamp): return response.json(13) now_time = int(time.time()) serial = serial_number[0:6] company_identity = serial_number[6:9] full_serial = serial_number[0:9] # 根据企业标识确认企业秘钥 company_secret = '' if company_identity == '11A': company_secret = 'MTEyMTNB' elif company_identity == '11L': company_secret = 'VmXEWnBR' elif company_identity == '11Z': company_secret = 'ZsKWcxdD' try: # 判断序列号是否已和企业关联 company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial) if not company_serial_qs.exists(): return response.json(173) company_serial = company_serial_qs[0] if company_serial.status == 0: # 该序列号未绑定企业 return response.json(173) elif company_serial.status == 1: # 绑定uid # redis加锁,防止同一个序列号重复绑定 key = serial + 'do_attach_uid' redisObj = RedisObject() isLock = redisObj.CONN.setnx(key, 1) redisObj.CONN.expire(key, 60) if not isLock: return response.json(5) # 获取并判断region_id region_id = CommonService.confirm_region_id() if region_id not in REGION_ID_LIST: return response.json(444, {'invalid region_id': region_id}) p2p_type = request_dict.get('p2ptype', 1) if serial_number[9:10]: p2p_type = serial_number[9:10] p2p_type = int(p2p_type) with transaction.atomic(): count = 0 while count < 3: # 查询是否存在未绑定序列号的uid uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id, vpg__region_id=region_id, status=0, p2p_type=p2p_type). \ order_by('id') if not uid_qs.exists(): return response.json(375) uid = uid_qs[0] # 判断uid是否已绑定过序列号 uid_company_serial_qs = UIDCompanySerialModel.objects.filter(uid_id=uid.id) if uid_company_serial_qs.exists(): return response.json(377) result = UIDModel.objects.filter(id=uid.id, status=0).update(status=2, update_time=now_time) if int(result) <= 0: # 更新失败 count += 1 continue # UID关联【企业关联序列号】表创建数据 UIDCompanySerialModel.objects.create(uid_id=uid.id, company_serial_id=company_serial.id, add_time=now_time, update_time=now_time) company_serial.status = 2 company_serial.save() dev = Device_Info.objects.filter(UID=uid.uid) if dev.exists(): dev.update(serial_number=full_serial) full_uid_code = uid.full_uid_code if uid.platform in CRCKey.keys(): full_uid_code += ':' + CRCKey[uid.platform] res = { 'full_uid_code': CommonService.encode_data(full_uid_code), 'uid': CommonService.encode_data(uid.uid), 'extra': uid.uid_extra, 'platform': uid.platform, 'initString': uid.init_string, 'initStringApp': uid.init_string_app, } # 记录操作日志 ip = CommonService.get_ip_address(request) content = json.loads(json.dumps(request_dict)) log = { 'ip': ip, 'user_id': 1, 'status': 200, 'time': now_time, 'content': json.dumps(content), 'url': 'serialNumber/attachUID', 'operation': '序列号{}绑定uid: {}'.format(serial, uid.uid), } LogModel.objects.create(**log) if CONFIG_INFO != CONFIG_TEST: # 不为测试服,则序列号写入redis列表 redisObj.rpush(USED_SERIAL_REDIS_LIST, serial) redisObj.del_data(key=key) return response.json(0, res) return response.json(5) elif company_serial.status == 2: # 返回uid uid_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id) if not uid_qs.exists(): return response.json(173) uid = uid_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__full_uid_code', 'uid__platform', 'uid__init_string', 'uid__init_string_app')[0] full_uid_code = uid['uid__full_uid_code'] if uid['uid__platform'] in CRCKey.keys(): full_uid_code += ':' + CRCKey[uid['uid__platform']] res = { 'full_uid_code': CommonService.encode_data(full_uid_code), 'uid': CommonService.encode_data(uid['uid__uid']), 'extra': uid['uid__uid_extra'], 'platform': uid['uid__platform'], 'initString': uid['uid__init_string'], 'initStringApp': uid['uid__init_string_app'], } return response.json(0, res) elif company_serial.status == 3: return response.json(10042) except Exception as e: djangoLogger = logging.getLogger('django') djangoLogger.exception(repr(e)) return response.json(176, str(e)) def do_get_uid(self, request_dict, response): serial_number = request_dict.get('serial_number', None) token = request_dict.get('token', None) time_stamp = request_dict.get('time_stamp', None) if token and time_stamp and serial_number: # 时间戳token校验 if not CommonService.check_time_stamp_token(token, time_stamp): return response.json(13) mark = serial_number[6:9] serial = serial_number[0:6] uid_company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__company__mark=mark, company_serial__serial_number__serial_number=serial) if uid_company_serial_qs.exists(): uid = uid_company_serial_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra')[0] res = { 'uid': CommonService.encode_data(uid['uid__uid']), 'mac': CommonService.encode_data(uid['uid__mac']), 'extra': uid['uid__uid_extra'] } return response.json(0, res) else: return response.json(173) else: return response.json(444) def do_detach_uid(self, request, request_dict, response): token = request_dict.get('token', None) time_stamp = request_dict.get('time_stamp', None) serial_number = request_dict.get('serial_number', None) if not all([token, time_stamp, serial_number]): return response.json(444) # 时间戳token校验 if not CommonService.check_time_stamp_token(token, time_stamp): return response.json(13) now_time = int(time.time()) serial = serial_number[0:6] company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial).values('status') if not company_serial_qs.exists(): return response.json(379) status = company_serial_qs[0]['status'] if status == 1: return response.json(0, {'success': '序列号未绑定uid'}) elif status == 3: return response.json(10043) uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial) if not uid_serial_qs.exists(): return response.json(173) uid_serial = uid_serial_qs[0] redisObj = RedisObject() try: with transaction.atomic(): uid = uid_serial.uid.uid company_serial_qs.update(status=1) # 更新序列号状态 # 删除设备相关数据,参考后台的设备重置删除的数据 Device_Info.objects.filter(UID=uid).delete() UidSetModel.objects.filter(uid=uid).delete() UidUserModel.objects.filter(UID=uid).delete() iotdeviceInfoModel.objects.filter(serial_number=serial).delete() # 删除推送消息 for val in range(1, 8): EquipmentInfoService.get_equipment_info_model('', val).filter(device_uid=uid).delete() # 重置设备云存 UID_Bucket.objects.filter(uid=uid).delete() Unused_Uid_Meal.objects.filter(uid=uid).delete() Order_Model.objects.filter(UID=uid).delete() StsCrdModel.objects.filter(uid=uid).delete() VodHlsModel.objects.filter(uid=uid).delete() ExperienceContextModel.objects.filter(uid=uid).delete() # 重置AI ExperienceAiModel.objects.filter(uid=uid).delete() AiService.objects.filter(uid=uid).delete() if CONFIG_INFO != CONFIG_TEST: # 不为测试服,则序列号写入redis列表 redisObj.rpush(UNUSED_SERIAL_REDIS_LIST, serial) UIDModel.objects.filter(uid=uid).update(status=0, mac='') # 重置uid的使用状态为未使用 uid_serial.delete() # 重置region_id if CONFIG_INFO == CONFIG_US: DeviceDomainRegionModel.objects.filter(serial_number=serial).update(region_id=0) else: try: url = SERVER_DOMAIN_US + 'serialNumber/resetRegionId' data = {'serial_number': serial} r = requests.post(url, data, timeout=3) assert r.status_code == 200 res = r.json() assert res['result_code'] == 0 except (TimeoutError, AssertionError): return response.json(5) # 记录操作日志 ip = CommonService.get_ip_address(request) content = json.loads(json.dumps(request_dict)) log = { 'ip': ip, 'user_id': 1, 'status': 200, 'time': now_time, 'content': json.dumps(content), 'url': 'serialNumber/detachUID', 'operation': '序列号{}解绑uid: {}'.format(serial, uid), } LogModel.objects.create(**log) return response.json(0) except Exception as e: djangoLogger = logging.getLogger('django') djangoLogger.exception(repr(e)) return response.json(176, str(e)) @staticmethod def get_region_info(request_dict, response): """ 根据序列号状态确认uid地区 @param request_dict: 请求参数 @param response: 响应对象 @request_dict serial_number: 序列号 @return: response """ serial_number = request_dict.get('serial_number', None) if not serial_number: return response(444) company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial_number[:6]).values('status') if not company_serial_qs.exists(): return response.json(173) status = company_serial_qs[0]['status'] if status == 2: if CONFIG_INFO == CONFIG_CN: return response.json(0, {'region': 1}) elif CONFIG_INFO == CONFIG_US: return response.json(0, {'region': 3}) elif status == 3: if CONFIG_INFO == CONFIG_CN: return response.json(0, {'region': 3}) elif CONFIG_INFO == CONFIG_US: return response.json(0, {'region': 1}) return response.json(0) @staticmethod def save_region(request, request_dict, response): """ 保存设备地区信息 @param request: 请求体 @param request_dict: 请求参数 @param response: 响应对象 @request_dict token: 令牌 @request_dict time_stamp: 时间戳 @return: response """ token = request_dict.get('token', None) serial_number = request_dict.get('serial_number', None) if not all([serial_number, token]): return response(444) try: serial_number = serial_number[:6] # 不是美洲服,请求美洲域名保存数据 if CONFIG_INFO != CONFIG_US: # token认证 token_obj = TokenObject(token) if token_obj.code != 0: return response.json(token_obj.code) response.lang = token_obj.lang url = SERVER_DOMAIN_US + 'serialNumber/saveRegion' data = request_dict.dict() data['ip'] = CommonService.get_ip_address(request) data['region_id'] = CommonService.confirm_region_id() try: r = requests.post(url=url, data=data, timeout=3) assert r.status_code == 200 res = r.json() assert res['result_code'] == 0 except (TimeoutError, AssertionError): return response.json(5) # 美洲服,处理请求和保存数据 else: data = {} # 处理其他服务器发起请求的情况 region_id = request_dict.get('region_id', None) if region_id is not None: region_id = int(region_id) data['region_id'] = region_id data['ip'] = request_dict.get('ip', '') else: # token认证 token_obj = TokenObject(token) if token_obj.code != 0: return response.json(token_obj.code) response.lang = token_obj.lang region_id = CommonService.confirm_region_id() data['region_id'] = region_id data['ip'] = CommonService.get_ip_address(request) # 写入数据 device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number).\ values('region_id') if not device_domain_region_qs.exists(): data['serial_number'] = serial_number DeviceDomainRegionModel.objects.create(**data) else: # 设备解绑过uid,更新region_id if device_domain_region_qs[0]['region_id'] == 0: device_domain_region_qs.update(**data) return response.json(0) except Exception as e: return response.json(500, repr(e)) @staticmethod def get_domain(request_dict, response): """ 获取域名 @param request_dict: 请求参数 @param response: 响应对象 @request_dict serial_number: 序列号 @request_dict time_stamp_token: 时间戳token @request_dict time_stamp: 时间戳 @return: response """ serial_number = request_dict.get('serial_number', None) time_stamp_token = request_dict.get('time_stamp_token', None) time_stamp = request_dict.get('time_stamp', None) if not all([serial_number, time_stamp_token, time_stamp]): return response(444) # 时间戳token校验 if not CommonService.check_time_stamp_token(time_stamp_token, time_stamp): return response.json(13) try: serial_number = serial_number[:6] device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number).values( 'region_id') if not device_domain_region_qs.exists(): return response.json(173) region_id = device_domain_region_qs[0]['region_id'] region_qs = RegionModel.objects.filter(id=region_id).values('api') res = { 'api': region_qs[0]['api'] } return response.json(0, res) except Exception as e: return response.json(500, repr(e)) @staticmethod def reset_region_id(request_dict, response): """ 重置地区id @param request_dict: 请求参数 @param response: 响应对象 @request_dict serial_number: 序列号 @return: response """ serial_number = request_dict.get('serial_number', None) if not serial_number: return response(444) try: serial_number = serial_number[:6] DeviceDomainRegionModel.objects.filter(serial_number=serial_number).update(region_id=0) return response.json(0) except Exception as e: return response.json(500, repr(e))