SerialNumberController.py 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312
  1. import json
  2. import logging
  3. import threading
  4. import time
  5. from datetime import datetime
  6. import requests
  7. from django.db import transaction
  8. from django.db.models import Q
  9. from django.views import View
  10. from Ansjer.config import CRCKey, CONFIG_INFO, CONFIG_US, CONFIG_EUR, \
  11. CONFIG_CN, USED_SERIAL_REDIS_LIST, UNUSED_SERIAL_REDIS_LIST, SERVER_DOMAIN_US, REGION_ID_LIST, SERVER_DOMAIN_TEST, \
  12. SERVER_DOMAIN_LIST, SERVER_DOMAIN_CN, SERVER_DOMAIN_EUR, RESET_REGION_ID_SERIAL_REDIS_LIST, LOGGER, CONFIG_TEST, \
  13. SERVER_DOMAIN, HUAWEICLOUD_OBS_SERVER, HUAWEICLOUD_BAIDU_BIG_MODEL_LICENSE_BUKET
  14. from Controller.CheckUserData import DataValid
  15. from Controller.UnicomCombo.UnicomComboController import UnicomComboView
  16. from Model.models import SerialNumberModel, CompanySerialModel, UIDCompanySerialModel, UIDModel, Device_Info, \
  17. iotdeviceInfoModel, LogModel, UidSetModel, UID_Bucket, \
  18. Unused_Uid_Meal, Order_Model, StsCrdModel, VodHlsModel, ExperienceContextModel, UidUserModel, ExperienceAiModel, \
  19. AiService, DeviceDomainRegionModel, RegionModel, UidPushModel, AppScannedSerial, Device_User, SerialUnbindUID, \
  20. DeviceNetInfo, BaiduBigModelLicense, Instavision
  21. from Object.AWS.S3Email import S3Email
  22. from Object.RedisObject import RedisObject
  23. from Object.TokenObject import TokenObject
  24. from Object.uidManageResponseObject import uidManageResponseObject
  25. from Service.AlgorithmService import AlgorithmBaseOn35
  26. from Service.CommonService import CommonService
  27. from AdminController.CloudServiceManage.AgentDeviceController import AgentDeviceView
  28. from django.conf import settings
  29. HUAWEICLOUD_AK = settings.HUAWEICLOUD_AK
  30. HUAWEICLOUD_SK = settings.HUAWEICLOUD_SK
  31. class SerialNumberView(View):
  32. def get(self, request, *args, **kwargs):
  33. request.encoding = 'utf-8'
  34. operation = kwargs.get('operation', None)
  35. request_dict = request.GET
  36. return self.validate(request_dict, operation, request)
  37. def post(self, request, *args, **kwargs):
  38. request.encoding = 'utf-8'
  39. operation = kwargs.get('operation', None)
  40. request_dict = request.POST
  41. return self.validate(request_dict, operation, request)
  42. def validate(self, request_dict, operation, request):
  43. response = uidManageResponseObject()
  44. if operation == 'attachUID': # 绑定uid
  45. return self.do_attach_uid(request_dict, response, request)
  46. elif operation == 'detachUID': # 解绑uid
  47. return self.do_detach_uid(request, request_dict, response)
  48. elif operation == 'get-uid': # app获取uid
  49. token_code, user_id, res = CommonService.verify_token_get_user_id(request_dict, request)
  50. return self.get_uid(request_dict, response, request, user_id)
  51. elif operation == 'create': # 创建序列号
  52. return self.do_create(request_dict, response)
  53. elif operation == 'getUID': # 根据序列号获取uid
  54. return self.do_get_uid(request_dict, response)
  55. elif operation == 'getRegionInfo': # 根据序列号状态确认uid地区(PC工具使用)
  56. return self.get_region_info(request_dict, response)
  57. elif operation == 'saveRegion': # 保存设备地区信息(app使用)
  58. return self.save_region(request, request_dict, response)
  59. elif operation == 'getDomain': # 获取域名(设备使用)
  60. return self.get_domain(request_dict, response)
  61. elif operation == 'resetRegionId': # 重置地区id
  62. return self.reset_region_id(request_dict, response)
  63. elif operation == 'get-status': # 获取序列号绑定信息
  64. return self.check_serial_status(request_dict, response)
  65. elif operation == 'getUidRegion': # 根据序列号获取uid地区
  66. return self.get_uid_region(request_dict, response)
  67. elif operation == 'getGlobalUidRegion': # 获取序列号在全球服绑定uid的地区
  68. return self.get_global_uid_region(request_dict, response)
  69. elif operation == 'getIoTCoreBySerialNumber': # 根据序列号获取iot core
  70. return self.get_iot_core_by_serial_number(request_dict, response)
  71. elif operation == 'saveUserNetInfo':
  72. return self.save_user_net_info(request_dict, response)
  73. elif operation == 'getBaiduBigModelLicenseUrl':
  74. return self.get_baidu_big_model_license_url(request_dict, response)
  75. elif operation == 'getInstavision':
  76. return self.get_instavision(request_dict, response, request)
  77. elif operation == 'getInstaVisionV2':
  78. return self.get_insta_vision_v2(request_dict, response, request)
  79. else:
  80. return response.json(414)
  81. @staticmethod
  82. def do_create(request_dict, response):
  83. quantity = int(request_dict.get('quantity', 0))
  84. if not quantity:
  85. return response.json(444)
  86. try:
  87. try:
  88. number = SerialNumberModel.objects.last().id
  89. except:
  90. number = 0
  91. serial_number_bulk = []
  92. now_time = int(time.time())
  93. algorithm = AlgorithmBaseOn35()
  94. for i in range(quantity):
  95. serial_number = algorithm.getLetter(number)
  96. number += 1 # sum每次递增1
  97. # 前面补0至六位
  98. serial_number = (6 - len(serial_number)) * '0' + serial_number
  99. serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time))
  100. # 开启事务写入
  101. with transaction.atomic():
  102. SerialNumberModel.objects.bulk_create(serial_number_bulk)
  103. return response.json(0)
  104. except Exception as e:
  105. print(e)
  106. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  107. def do_attach_uid(self, request_dict, response, request):
  108. serial_number = request_dict.get('serial_number', None)
  109. token = request_dict.get('token', None)
  110. time_stamp = request_dict.get('time_stamp', None)
  111. is_verify = request_dict.get('is_verify', None)
  112. if not all([serial_number, token, time_stamp]):
  113. LOGGER.error(f'{serial_number}请求绑定uid参数缺失')
  114. return response.json(444)
  115. # 时间戳token校验
  116. if not CommonService.check_time_stamp_token(token, time_stamp):
  117. LOGGER.error(f'{serial_number}时间戳校验失败time:{time_stamp},tk:{token}')
  118. return response.json(13)
  119. now_time = int(time.time())
  120. serial = serial_number[0:6]
  121. company_identity = serial_number[6:9]
  122. full_serial = serial_number[0:9]
  123. # 根据企业标识确认企业秘钥
  124. company_secret = ''
  125. if company_identity == '11A':
  126. company_secret = 'MTEyMTNB'
  127. elif company_identity == '11L':
  128. company_secret = 'VmXEWnBR'
  129. elif company_identity == '11Z':
  130. company_secret = 'ZsKWcxdD'
  131. try:
  132. redisObj = RedisObject()
  133. # 查询app是否已扫码,未扫码不能进行绑定
  134. # 如果没扫码设置24小时的缓存,扫码后删除缓存
  135. scanned_serial_key = serial + 'scanned_serial'
  136. if redisObj.get_data(scanned_serial_key):
  137. return response.json(5)
  138. app_scanned_serial_qs = AppScannedSerial.objects.filter(serial=serial).values('region_country')
  139. if not app_scanned_serial_qs.exists() and is_verify != '1':
  140. redisObj.set_data(scanned_serial_key, 1, 24*60*60)
  141. LOGGER.info(f'{serial}当前序列号未进行APP扫码')
  142. return response.json(5)
  143. # 判断序列号是否刚解绑,刚解绑1分钟内不能进行绑定
  144. unused_serial_redis_list = redisObj.lrange(UNUSED_SERIAL_REDIS_LIST, 0, -1)
  145. unused_serial_redis_list = [str(i, 'utf-8') for i in unused_serial_redis_list]
  146. if serial in unused_serial_redis_list:
  147. return response.json(5)
  148. # 判断序列号是否未清除uid数据
  149. serial_unbind_uid_qs = SerialUnbindUID.objects.filter(serial=serial, status=0)
  150. if serial_unbind_uid_qs.exists():
  151. return response.json(5)
  152. # redis加锁,防止同一个序列号重复绑定
  153. key = serial + 'do_attach_uid'
  154. is_lock = redisObj.CONN.setnx(key, 1)
  155. if not is_lock:
  156. return response.json(5)
  157. redisObj.CONN.expire(key, 60)
  158. # 判断序列号是否已和企业关联
  159. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  160. if not company_serial_qs.exists():
  161. return response.json(173)
  162. company_serial = company_serial_qs[0]
  163. if company_serial.status == 0: # 该序列号未绑定企业
  164. return response.json(173)
  165. elif company_serial.status == 1: # 绑定uid
  166. # is_verify: '1',跳过查询扫码记录
  167. if is_verify == '1':
  168. region_country = 0
  169. else:
  170. region_country = app_scanned_serial_qs[0]['region_country']
  171. # 获取并判断region_id
  172. region_id = CommonService.confirm_region_id(region_country)
  173. if region_id not in REGION_ID_LIST:
  174. return response.json(444, {'invalid region_id': region_id})
  175. # 获取p2p类型
  176. p2p_type = request_dict.get('p2ptype', None)
  177. if serial_number[9:10]:
  178. p2p_type = serial_number[9:10]
  179. elif not p2p_type:
  180. return response.json(444, {'param': 'p2ptype'})
  181. p2p_type = int(p2p_type)
  182. with transaction.atomic():
  183. count = 0
  184. while count < 3:
  185. # 查询是否存在未绑定序列号的uid
  186. uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id,
  187. vpg__region_id=region_id, status=0, p2p_type=p2p_type). \
  188. order_by('update_time')
  189. if not uid_qs.exists():
  190. return response.json(375)
  191. uid = uid_qs[0]
  192. # 判断uid是否已绑定过序列号
  193. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(uid_id=uid.id)
  194. if uid_company_serial_qs.exists():
  195. return response.json(377)
  196. result = UIDModel.objects.filter(id=uid.id, status=0).update(status=2, update_time=now_time)
  197. if int(result) <= 0: # 更新失败
  198. count += 1
  199. continue
  200. # 判断序列号是否已绑定过uid
  201. company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id)
  202. if company_serial_qs.exists():
  203. return response.json(380)
  204. # UID关联【企业关联序列号】表创建数据
  205. UIDCompanySerialModel.objects.create(uid_id=uid.id, company_serial_id=company_serial.id,
  206. add_time=now_time, update_time=now_time)
  207. company_serial.status = 2
  208. company_serial.update_time = now_time
  209. company_serial.save()
  210. full_uid_code = uid.full_uid_code
  211. if uid.platform in CRCKey.keys():
  212. full_uid_code += ':' + CRCKey[uid.platform]
  213. res = {
  214. 'full_uid_code': CommonService.encode_data(full_uid_code),
  215. 'uid': CommonService.encode_data(uid.uid),
  216. 'extra': uid.uid_extra,
  217. 'platform': uid.platform,
  218. 'initString': uid.init_string,
  219. 'initStringApp': uid.init_string_app,
  220. }
  221. # 记录操作日志
  222. ip = CommonService.get_ip_address(request)
  223. content = json.loads(json.dumps(request_dict))
  224. log = {
  225. 'ip': ip,
  226. 'user_id': 1,
  227. 'status': 200,
  228. 'time': int(time.time()),
  229. 'content': json.dumps(content),
  230. 'url': 'serialNumber/attachUID',
  231. 'operation': '序列号{}绑定uid: {}'.format(serial, uid.uid),
  232. }
  233. LogModel.objects.create(**log)
  234. redisObj.del_data(key=key)
  235. # 处理序列号状态和计算剩余uid数量线程
  236. thread = threading.Thread(target=self.rpush_serial_and_count_uid, args=(serial, p2p_type,
  237. redisObj))
  238. thread.start()
  239. return response.json(0, res)
  240. return response.json(5)
  241. elif company_serial.status == 2: # 返回uid
  242. res = self.get_uid_info_by_serial(company_serial.id)
  243. # 记录操作日志
  244. ip = CommonService.get_ip_address(request)
  245. content = json.loads(json.dumps(request_dict))
  246. log = {
  247. 'ip': ip,
  248. 'user_id': 1,
  249. 'status': 200,
  250. 'time': now_time,
  251. 'content': json.dumps(content),
  252. 'url': 'serialNumber/attachUID',
  253. 'operation': '序列号{}获取uid: {}'.format(serial, CommonService.decode_data(res['uid'])),
  254. }
  255. LogModel.objects.create(**log)
  256. redisObj.del_data(key=key)
  257. return response.json(0, res)
  258. elif company_serial.status == 3: # 已占用
  259. redisObj.del_data(key=key)
  260. sync_success = self.sync_serial_data_and_log(request, company_serial.id, serial_number, now_time)
  261. if not sync_success:
  262. return response.json(10042)
  263. return response.json(0, self.get_uid_info_by_serial(company_serial.id))
  264. except Exception as e:
  265. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  266. @classmethod
  267. def get_uid_info_by_serial(cls, company_serial_id):
  268. """
  269. 根据企业关联序列号ID返回UID信息
  270. """
  271. uid_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial_id)
  272. if not uid_qs.exists():
  273. return {}
  274. uid = uid_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__full_uid_code',
  275. 'uid__platform', 'uid__init_string', 'uid__init_string_app')[0]
  276. full_uid_code = uid['uid__full_uid_code']
  277. if uid['uid__platform'] in CRCKey.keys():
  278. full_uid_code += ':' + CRCKey[uid['uid__platform']]
  279. res = {
  280. 'full_uid_code': CommonService.encode_data(full_uid_code),
  281. 'uid': CommonService.encode_data(uid['uid__uid']),
  282. 'extra': uid['uid__uid_extra'],
  283. 'platform': uid['uid__platform'],
  284. 'initString': uid['uid__init_string'],
  285. 'initStringApp': uid['uid__init_string_app'],
  286. }
  287. return res
  288. @classmethod
  289. def check_serial_status(cls, request_dict, response):
  290. serial_number = request_dict.get('serial_number', None)
  291. if not serial_number:
  292. return response.json(444)
  293. serial = serial_number[0:6]
  294. company_identity = serial_number[6:9]
  295. # 根据企业标识确认企业秘钥
  296. company_secret = ''
  297. if company_identity == '11A':
  298. company_secret = 'MTEyMTNB'
  299. elif company_identity == '11L':
  300. company_secret = 'VmXEWnBR'
  301. elif company_identity == '11Z':
  302. company_secret = 'ZsKWcxdD'
  303. try:
  304. # 判断序列号是否已和企业关联
  305. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  306. if not company_serial_qs.exists():
  307. return response.json(173)
  308. company_serial = company_serial_qs[0]
  309. # 获取企业序列号是否绑定UID
  310. uid_company_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id) \
  311. .values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__status', 'uid__area', 'uid__vpg_id',
  312. 'uid__p2p_type', 'uid__full_uid_code', 'uid__platform',
  313. 'uid__init_string', 'uid__init_string_app')
  314. uid_info = {}
  315. if uid_company_qs.exists():
  316. # 更新被同步数据的uid的状态为3(数据被同步)
  317. uid = uid_company_qs[0]['uid__uid']
  318. UIDModel.objects.filter(uid=uid).update(status=3)
  319. uid_info['uid'] = uid
  320. uid_info['mac'] = uid_company_qs[0]['uid__mac']
  321. uid_info['uid_extra'] = uid_company_qs[0]['uid__uid_extra']
  322. uid_info['status'] = uid_company_qs[0]['uid__status']
  323. uid_info['area'] = uid_company_qs[0]['uid__area']
  324. uid_info['vpg_id'] = uid_company_qs[0]['uid__vpg_id']
  325. uid_info['p2p_type'] = uid_company_qs[0]['uid__p2p_type']
  326. uid_info['full_uid_code'] = uid_company_qs[0]['uid__full_uid_code']
  327. uid_info['platform'] = uid_company_qs[0]['uid__platform']
  328. uid_info['init_string'] = uid_company_qs[0]['uid__init_string']
  329. uid_info['init_string_app'] = uid_company_qs[0]['uid__init_string_app']
  330. results = {'serial': company_serial.serial_number, 'status': company_serial.status,
  331. 'uidInfo': uid_info}
  332. return response.json(0, results)
  333. except Exception as e:
  334. LOGGER.info('查询序列号异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  335. return response.json(176, str(e))
  336. @staticmethod
  337. def rpush_serial_and_count_uid(serial, p2p_type, redis_obj):
  338. """
  339. 处理序列号状态和计算剩余uid数量线程
  340. @param serial: 序列号
  341. @param p2p_type: p2p类型
  342. @param redis_obj: redis对象
  343. @return:
  344. """
  345. # 写入已使用序列号redis列表
  346. redis_obj.rpush(USED_SERIAL_REDIS_LIST, serial)
  347. p2p_type = int(p2p_type)
  348. platform = '尚云' if p2p_type == 1 else 'tutk'
  349. redis_key = 'uid_count_warning_time_limit_' + platform
  350. redis_obj = RedisObject()
  351. time_limit = redis_obj.get_data(redis_key)
  352. if not time_limit:
  353. vpg_id = 1
  354. if CONFIG_INFO == CONFIG_US:
  355. vpg_id = 3
  356. elif CONFIG_INFO == CONFIG_EUR:
  357. vpg_id = 4
  358. try:
  359. # 尚云剩余uid数量少于1000,尚云剩余uid数量少于5000,发送邮件提醒
  360. unused_uid_count = UIDModel.objects.filter(vpg_id=vpg_id, p2p_type=p2p_type, status=0).count()
  361. warning_count = 1000 if p2p_type == 1 else 5000
  362. if unused_uid_count < warning_count:
  363. # 限制一天提醒一次
  364. redis_obj.set_data(redis_key, 1, 60 * 60 * 24)
  365. email_content = '{}服{}的uid数量少于{}个,剩余数量:{},请及时处理'.format(
  366. CONFIG_INFO, platform, warning_count, unused_uid_count)
  367. S3Email().faEmail(email_content, 'servers@ansjer.com')
  368. except Exception as e:
  369. LOGGER.info('发送提醒邮件异常: error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  370. try:
  371. # 异步调用客户代理平台同步序列号绑定UID
  372. serial_number = serial + '11A'
  373. agent_thread = threading.Thread(target=AgentDeviceView.device_binding_or_unbinding,
  374. args=(serial_number, 1))
  375. agent_thread.start()
  376. except Exception as e:
  377. LOGGER.error('异步更新定制客户序列号状态一次: error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno,
  378. repr(e)))
  379. @staticmethod
  380. def sync_serial_data_and_log(request, company_serial_id, serial, now_time):
  381. """
  382. 同步序列号数据和记录日志
  383. @param company_serial_id: 企业关联序列号 ID
  384. @param request: 请求
  385. @param serial: 序列号
  386. @param now_time: 当前时间
  387. @return : bool
  388. """
  389. redis = RedisObject()
  390. key = f'BIND:UID:LIMIT:{serial}'
  391. serial_obj = redis.get_data(key)
  392. # 序列号已占用一天写一次日志记录
  393. if serial_obj:
  394. return False
  395. ip = CommonService.get_ip_address(request)
  396. operation = '{}序列号占用,APP扫码已停用同步UID'.format(serial)
  397. log = {
  398. 'ip': ip,
  399. 'user_id': 1,
  400. 'status': 200,
  401. 'time': now_time,
  402. 'url': 'serialNumber/attachUID',
  403. 'operation': operation
  404. }
  405. LogModel.objects.create(**log)
  406. redis.set_data(key, '1', 86400)
  407. return False
  408. # sync_result = False
  409. # # 测试服和国内服不同步
  410. # if CONFIG_INFO == 'test' or CONFIG_INFO == 'cn':
  411. # return sync_result
  412. # try:
  413. # # 判断当前序列号是否绑定UID
  414. # uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial_id)
  415. # if uid_serial_qs.exists():
  416. # operation += ',已绑定UID,不同步数据'
  417. # log['operation'] = operation
  418. # LogModel.objects.create(**log)
  419. # return sync_result
  420. #
  421. # region = 'us'
  422. # # 欧洲服同步美洲服,美洲服同步国内服数据
  423. # if CONFIG_INFO == 'eur':
  424. # domain_name = 'https://www.dvema.com/'
  425. # else:
  426. # region = 'cn'
  427. # domain_name = 'https://www.zositechc.cn/'
  428. #
  429. # url = domain_name + 'serialNumber/get-status'
  430. # response = requests.get(url=url, params={'serial_number': serial}, timeout=15)
  431. #
  432. # if response.status_code != 200:
  433. # operation += '查询{}服UID数据响应状态码异常:{}'.format(region, response.status_code)
  434. # log['operation'] = operation
  435. # LogModel.objects.create(**log)
  436. # return sync_result
  437. #
  438. # results = json.loads(response.text)
  439. # if results['result_code'] != 0:
  440. # operation += '查询{}服UID数据result_code异常:{}'.format(region, results['result_code'])
  441. # log['operation'] = operation
  442. # LogModel.objects.create(**log)
  443. # return sync_result
  444. #
  445. # # 其它服没有绑定uid
  446. # uid_info = results['result']['uidInfo']
  447. # if not uid_info:
  448. # operation += '{}服没有绑定UID'.format(region)
  449. # log['operation'] = operation
  450. # LogModel.objects.create(**log)
  451. # return sync_result
  452. # # 同步uid数据
  453. # if uid_info['p2p_type'] == 1:
  454. # operation += '尚云UID不同步数据'
  455. # else:
  456. # uid_qs = UIDModel.objects.filter(uid=uid_info['uid'])
  457. # if not uid_qs.exists():
  458. # uid_info['add_time'] = now_time
  459. # uid_info['update_time'] = now_time
  460. # uid_id = UIDModel.objects.create(**uid_info).id
  461. # else:
  462. # if uid_qs.first().status == 2: # 判断uid是否被使用
  463. # operation += 'uid{}已被使用'.format(uid_info['uid'])
  464. # log['operation'] = operation
  465. # LogModel.objects.create(**log)
  466. # return sync_result
  467. # else:
  468. # uid_qs.update(status=2, update_time=now_time)
  469. # uid_id = uid_qs.first().id
  470. #
  471. # # 企业序列号关联 uid
  472. # UIDCompanySerialModel.objects.create(
  473. # uid_id=uid_id, company_serial_id=company_serial_id, add_time=now_time, update_time=now_time)
  474. # # 修改企业序列号状态为2(绑定uid)
  475. # CompanySerialModel.objects.filter(id=company_serial_id) \
  476. # .update(status=2, update_time=now_time)
  477. # sync_iot_result = SerialNumberView.sync_iot_core_data(domain_name, serial)
  478. #
  479. # operation += '同步{}服uid数据成功,同步iot数据结果:{}'.format(region, sync_iot_result)
  480. # sync_result = True
  481. #
  482. # # 记录日志
  483. # log['operation'] = operation
  484. # LogModel.objects.create(**log)
  485. # return sync_result
  486. #
  487. # except Exception as e:
  488. # operation += '同步数据异常,error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))
  489. # log['operation'] = operation
  490. # LogModel.objects.create(**log)
  491. # return sync_result
  492. def do_get_uid(self, request_dict, response):
  493. serial_number = request_dict.get('serial_number', None)
  494. token = request_dict.get('token', None)
  495. time_stamp = request_dict.get('time_stamp', None)
  496. if token and time_stamp and serial_number:
  497. # 时间戳token校验
  498. if not CommonService.check_time_stamp_token(token, time_stamp):
  499. return response.json(13)
  500. mark = serial_number[6:9]
  501. serial = serial_number[0:6]
  502. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__company__mark=mark,
  503. company_serial__serial_number__serial_number=serial)
  504. if uid_company_serial_qs.exists():
  505. uid = uid_company_serial_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra')[0]
  506. res = {
  507. 'uid': CommonService.encode_data(uid['uid__uid']),
  508. 'mac': CommonService.encode_data(uid['uid__mac']),
  509. 'extra': uid['uid__uid_extra']
  510. }
  511. return response.json(0, res)
  512. else:
  513. return response.json(173)
  514. else:
  515. return response.json(444)
  516. @staticmethod
  517. def do_detach_uid(request, request_dict, response):
  518. token = request_dict.get('token', None)
  519. time_stamp = request_dict.get('time_stamp', None)
  520. serial_number = request_dict.get('serial_number', None)
  521. if not all([token, time_stamp, serial_number]):
  522. return response.json(444)
  523. # 时间戳token校验
  524. if not CommonService.check_time_stamp_token(token, time_stamp):
  525. return response.json(13)
  526. now_time = int(time.time())
  527. # 记录操作日志
  528. ip = CommonService.get_ip_address(request)
  529. content = json.loads(json.dumps(request_dict))
  530. serial = serial_number[0:6]
  531. company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial).values('status')
  532. if not company_serial_qs.exists():
  533. return response.json(379)
  534. status = company_serial_qs[0]['status']
  535. if status == 1:
  536. return response.json(0, {'success': '序列号未绑定uid'})
  537. elif status == 3:
  538. return response.json(10043)
  539. uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial)
  540. if not uid_serial_qs.exists():
  541. return response.json(173)
  542. uid_serial = uid_serial_qs[0]
  543. # 判断序列号是否刚绑定uid,刚绑定需要过1分钟才能解绑
  544. redisObj = RedisObject()
  545. used_serial_redis_list = redisObj.lrange(USED_SERIAL_REDIS_LIST, 0, -1)
  546. used_serial_redis_list = [str(i, 'utf-8') for i in used_serial_redis_list]
  547. if serial in used_serial_redis_list:
  548. return response.json(5)
  549. # 判断序列号是否未清除uid数据
  550. serial_unbind_uid_qs = SerialUnbindUID.objects.filter(serial=serial, status=0)
  551. if serial_unbind_uid_qs.exists():
  552. return response.json(5)
  553. try:
  554. uid = uid_serial.uid.uid
  555. # 写入序列号解绑uid表
  556. SerialUnbindUID.objects.create(serial=serial, uid=uid, created_time=now_time, updated_time=now_time)
  557. end_time = int(time.time())
  558. # 记录操作日志
  559. log = {
  560. 'ip': ip,
  561. 'user_id': 1,
  562. 'status': 200,
  563. 'time': now_time,
  564. 'content': json.dumps(content),
  565. 'url': 'serialNumber/detachUID',
  566. 'operation': '序列号{}加入解绑队列uid:{}:{}秒'.format(serial, uid, end_time-now_time),
  567. }
  568. LogModel.objects.create(**log)
  569. return response.json(0)
  570. except Exception as e:
  571. log = {
  572. 'ip': ip,
  573. 'user_id': 1,
  574. 'status': 200,
  575. 'time': now_time,
  576. 'content': json.dumps(content) + '异常:{}'.format(repr(e)),
  577. 'url': 'serialNumber/detachUID',
  578. 'operation': '序列号{}解绑uid异常'.format(serial),
  579. }
  580. LogModel.objects.create(**log)
  581. return response.json(176, str(e))
  582. def get_uid(self, request_dict, response, request, user_id):
  583. """
  584. app获取序列号
  585. @param request_dict:
  586. @param response:
  587. @param request:
  588. @param user_id:
  589. @return:
  590. """
  591. token = request_dict.get('token', None)
  592. time_stamp = request_dict.get('time_stamp', None)
  593. company_secret = request_dict.get('company_id', None)
  594. serial_number = request_dict.get('serial_number', None)
  595. if not all([token, time_stamp, company_secret, serial_number]):
  596. return response.json(444)
  597. # 时间戳token校验
  598. if not CommonService.check_time_stamp_token(token, time_stamp):
  599. return response.json(13)
  600. now_time = int(time.time())
  601. serial = serial_number[0:6]
  602. # 判断序列号是否已和企业关联
  603. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  604. if not company_serial_qs.exists():
  605. return response.json(173)
  606. company_serial = company_serial_qs[0]
  607. try:
  608. # 添加或更新扫码记录
  609. ip = CommonService.get_ip_address(request)
  610. LOGGER.info('请求获取UID{},userId:{},ip:{}'.format(serial_number, user_id, ip))
  611. # 查询用户国家id
  612. region_country = 0
  613. # ios请求头没传token,user_id为None
  614. if user_id:
  615. device_user_qs = Device_User.objects.filter(userID=user_id).values('region_country')
  616. if device_user_qs.exists():
  617. region_country = device_user_qs[0]['region_country']
  618. data = {
  619. 'ip': ip,
  620. 'update_time': now_time,
  621. 'region_country': region_country
  622. }
  623. app_scanned_serial_qs = AppScannedSerial.objects.filter(serial=serial)
  624. if app_scanned_serial_qs.exists():
  625. app_scanned_serial_qs.update(**data)
  626. else:
  627. data['serial'] = serial
  628. data['add_time'] = now_time
  629. AppScannedSerial.objects.create(**data)
  630. # 扫码后删除缓存
  631. redis_obj = RedisObject()
  632. scanned_serial_key = serial + 'scanned_serial'
  633. redis_obj.del_data(scanned_serial_key)
  634. if company_serial.status == 0 or company_serial.status == 1: # 未使用
  635. UnicomComboView().is_4g_device(serial_number, request_dict, request)
  636. return response.json(173)
  637. elif company_serial.status == 2: # 返回uid
  638. res = self.get_uid_info_by_serial(company_serial.id)
  639. return response.json(0, res)
  640. elif company_serial.status == 3: # 已占用
  641. sync_success = self.sync_serial_data_and_log(request, company_serial.id, serial_number, now_time)
  642. if not sync_success:
  643. return response.json(20001)
  644. return response.json(0, self.get_uid_info_by_serial(company_serial.id))
  645. except Exception as e:
  646. error_logger = logging.getLogger('django')
  647. error_logger.exception(repr(e))
  648. return response.json(176, str(e))
  649. @staticmethod
  650. def get_region_info(request_dict, response):
  651. """
  652. 根据序列号状态确认uid地区
  653. @param request_dict: 请求参数
  654. @param response: 响应对象
  655. @request_dict serial_number: 序列号
  656. @return: response
  657. """
  658. serial_number = request_dict.get('serial_number', None)
  659. if not serial_number:
  660. return response(444)
  661. company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial_number[:6]).values('status')
  662. if not company_serial_qs.exists():
  663. return response.json(173)
  664. status = company_serial_qs[0]['status']
  665. if status == 2:
  666. if CONFIG_INFO == CONFIG_CN:
  667. return response.json(0, {'region': 1})
  668. elif CONFIG_INFO == CONFIG_US:
  669. return response.json(0, {'region': 3})
  670. elif status == 3:
  671. if CONFIG_INFO == CONFIG_CN:
  672. return response.json(0, {'region': 3})
  673. elif CONFIG_INFO == CONFIG_US:
  674. return response.json(0, {'region': 1})
  675. return response.json(0)
  676. @staticmethod
  677. def save_region(request, request_dict, response):
  678. """
  679. 保存设备地区信息
  680. @param request: 请求体
  681. @param request_dict: 请求参数
  682. @param response: 响应对象
  683. @request_dict token: 令牌
  684. @request_dict time_stamp: 时间戳
  685. @return: response
  686. """
  687. token = request_dict.get('token', None)
  688. serial_number = request_dict.get('serial_number', None)
  689. if not all([serial_number, token]):
  690. return response(444)
  691. try:
  692. serial_number = serial_number[:6]
  693. # 测试和国内服不保存区域信息
  694. if CONFIG_INFO == CONFIG_CN or CONFIG_INFO == CONFIG_TEST:
  695. return response.json(0)
  696. # 不是美洲服,请求美洲域名保存数据
  697. if CONFIG_INFO != CONFIG_US:
  698. # token认证
  699. token_obj = TokenObject(token)
  700. if token_obj.code != 0:
  701. return response.json(token_obj.code)
  702. response.lang = token_obj.lang
  703. url = SERVER_DOMAIN_US + 'serialNumber/saveRegion'
  704. data = request_dict.dict()
  705. data['ip'] = CommonService.get_ip_address(request)
  706. data['region_id'] = CommonService.confirm_region_id()
  707. try:
  708. r = requests.post(url=url, data=data, timeout=10)
  709. assert r.status_code == 200
  710. res = r.json()
  711. assert res['result_code'] == 0
  712. except Exception as e:
  713. pass
  714. # 美洲服,处理请求和保存数据
  715. else:
  716. data = {}
  717. # 处理其他服务器发起请求的情况
  718. region_id = request_dict.get('region_id', None)
  719. if region_id is not None:
  720. region_id = int(region_id)
  721. data['region_id'] = region_id
  722. data['ip'] = request_dict.get('ip', '')
  723. else:
  724. # token认证
  725. token_obj = TokenObject(token)
  726. if token_obj.code != 0:
  727. return response.json(token_obj.code)
  728. response.lang = token_obj.lang
  729. region_id = CommonService.confirm_region_id()
  730. data['region_id'] = region_id
  731. data['ip'] = CommonService.get_ip_address(request)
  732. # 写入数据
  733. device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number). \
  734. values('region_id')
  735. if not device_domain_region_qs.exists():
  736. data['serial_number'] = serial_number
  737. DeviceDomainRegionModel.objects.create(**data)
  738. else:
  739. # 设备解绑过uid,更新region_id
  740. if device_domain_region_qs[0]['region_id'] == 0:
  741. device_domain_region_qs.update(**data)
  742. return response.json(0)
  743. except Exception as e:
  744. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  745. @staticmethod
  746. def get_domain(request_dict, response):
  747. """
  748. 设备获取域名
  749. @param request_dict: 请求参数
  750. @param response: 响应对象
  751. @request_dict serial_number: 序列号
  752. @request_dict time_stamp_token: 时间戳token
  753. @request_dict time_stamp: 时间戳
  754. @return: response
  755. """
  756. serial_number = request_dict.get('serial_number', None)
  757. time_stamp_token = request_dict.get('time_stamp_token', None)
  758. time_stamp = request_dict.get('time_stamp', None)
  759. if not all([serial_number, time_stamp_token, time_stamp]):
  760. return response.json(444)
  761. # 时间戳token校验
  762. if not CommonService.check_time_stamp_token(time_stamp_token, time_stamp):
  763. return response.json(13)
  764. try:
  765. serial_number = serial_number[:6]
  766. device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number).values(
  767. 'region_id')
  768. if not device_domain_region_qs.exists():
  769. return response.json(173)
  770. region_id = device_domain_region_qs[0]['region_id']
  771. region_qs = RegionModel.objects.filter(id=region_id).values('api', 'push_api')
  772. if not region_qs.exists():
  773. return response.json(173)
  774. # 国内和测试的推送存储地区为国内
  775. push_region = 2 if region_id in [1, 5] else 1
  776. res = {
  777. 'api': region_qs[0]['api'],
  778. 'push_api': region_qs[0]['push_api'],
  779. 'push_region': push_region
  780. }
  781. return response.json(0, res)
  782. except Exception as e:
  783. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  784. @staticmethod
  785. def reset_region_id(request_dict, response):
  786. """
  787. 重置地区id
  788. @param request_dict: 请求参数
  789. @param response: 响应对象
  790. @request_dict serial_number: 序列号
  791. @return: response
  792. """
  793. serial_number = request_dict.get('serial_number', None)
  794. if not serial_number:
  795. return response(444)
  796. try:
  797. serial_number = serial_number[:6]
  798. DeviceDomainRegionModel.objects.filter(serial_number=serial_number).update(region_id=0)
  799. return response.json(0)
  800. except Exception as e:
  801. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  802. @staticmethod
  803. def get_uid_region(request_dict, response):
  804. """
  805. 根据序列号获取uid地区
  806. @param request_dict: 请求参数
  807. @param response: 响应对象
  808. @request_dict serial_number: 序列号
  809. @return: response
  810. """
  811. serial_number = request_dict.get('serial_number', None)
  812. if not serial_number:
  813. return response(444)
  814. try:
  815. serial_number = serial_number[:6]
  816. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(
  817. company_serial__serial_number=serial_number).values('uid__uid')
  818. res = []
  819. for item in uid_company_serial_qs:
  820. res.append({'uid': item['uid__uid']})
  821. return response.json(0, res)
  822. except Exception as e:
  823. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  824. @staticmethod
  825. def get_global_uid_region(request_dict, response):
  826. """
  827. 获取序列号在全球服绑定uid的地区
  828. @param request_dict: 请求参数
  829. @param response: 响应对象
  830. @request_dict serial_number: 序列号
  831. @return: response
  832. """
  833. orders_domain_name_list = SERVER_DOMAIN_LIST
  834. if SERVER_DOMAIN_TEST in orders_domain_name_list:
  835. orders_domain_name_list.remove(SERVER_DOMAIN_TEST)
  836. uid_list = []
  837. try:
  838. for orders_domain_name in orders_domain_name_list:
  839. url = orders_domain_name + 'serialNumber/getUidRegion'
  840. res = requests.post(url=url, data=request_dict)
  841. result = res.json()
  842. if result['result_code'] != 0:
  843. return response.json(result['result_code'])
  844. if orders_domain_name == SERVER_DOMAIN_CN:
  845. for item in result['result']:
  846. item['region'] = 1
  847. uid_list.append(item)
  848. elif orders_domain_name == SERVER_DOMAIN_US:
  849. for item in result['result']:
  850. item['region'] = 3
  851. uid_list.append(item)
  852. elif orders_domain_name == SERVER_DOMAIN_EUR:
  853. for item in result['result']:
  854. item['region'] = 4
  855. uid_list.append(item)
  856. return response.json(0, uid_list)
  857. except Exception as e:
  858. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  859. @classmethod
  860. def get_iot_core_by_serial_number(cls, request_dict, response):
  861. """
  862. 根据序列号查询iot core
  863. """
  864. try:
  865. serial_number = request_dict.get('serialNumber', None)
  866. if not serial_number:
  867. return response.json(444)
  868. serial = serial_number[0:6]
  869. LOGGER.info('根据序列号查询IoTC:{}'.format(serial_number))
  870. device_iot_qs = iotdeviceInfoModel.objects.filter(serial_number=serial)
  871. if not device_iot_qs.exists():
  872. return response.json(173)
  873. iot_vo = device_iot_qs.first()
  874. iot_dto = {
  875. 'serial_number': iot_vo.serial_number,
  876. 'uid': iot_vo.uid,
  877. 'certificate_id': iot_vo.certificate_id,
  878. 'certificate_pem': iot_vo.certificate_pem,
  879. 'public_key': iot_vo.public_key,
  880. 'private_key': iot_vo.private_key,
  881. 'thing_name': iot_vo.thing_name,
  882. 'thing_groups': iot_vo.thing_groups,
  883. 'endpoint': iot_vo.endpoint,
  884. 'token_iot_number': iot_vo.token_iot_number,
  885. 'add_time': iot_vo.add_time.strftime("%Y-%m-%d %H:%M:%S"),
  886. 'update_time': iot_vo.update_time.strftime("%Y-%m-%d %H:%M:%S")
  887. }
  888. return response.json(0, {'iotInfo': iot_dto})
  889. except Exception as e:
  890. LOGGER.info('查询序列号异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  891. return response.json(176, str(e))
  892. @staticmethod
  893. def sync_iot_core_data(domain_name, serial_number):
  894. """
  895. 同步iot core 数据
  896. @param domain_name: 域名
  897. @param serial_number: 序列号
  898. """
  899. try:
  900. serial = serial_number[0:6]
  901. device_iot_qs = iotdeviceInfoModel.objects.filter(serial_number=serial)
  902. if device_iot_qs.exists():
  903. return False
  904. url = domain_name + 'serialNumber/getIoTCoreBySerialNumber'
  905. response = requests.get(url=url, params={'serialNumber': serial_number}, timeout=15)
  906. if response.status_code != 200:
  907. return False
  908. results = json.loads(response.text)
  909. if results['result_code'] != 0:
  910. return False
  911. iot_vo = results['result']['iotInfo']
  912. iot_vo['add_time'] = datetime.strptime(iot_vo['add_time'], "%Y-%m-%d %H:%M:%S")
  913. iot_vo['update_time'] = datetime.strptime(iot_vo['update_time'], "%Y-%m-%d %H:%M:%S")
  914. iotdeviceInfoModel.objects.create(**iot_vo)
  915. return True
  916. except Exception as e:
  917. LOGGER.info('{}同步iot异常,errLine:{}, errMsg:{}'.format(serial_number, e.__traceback__.tb_lineno, repr(e)))
  918. return False
  919. @classmethod
  920. def save_user_net_info(cls, request_dict, response):
  921. """
  922. 保存用户网络信息
  923. @return:
  924. """
  925. serial = request_dict.get('serial', None)
  926. username = request_dict.get('username', None)
  927. wifi_name = request_dict.get('wifi_name', None)
  928. wifi_password = request_dict.get('wifi_password', None)
  929. time_stamp = request_dict.get('time_stamp', None)
  930. token = request_dict.get('time_stamp_token', None)
  931. if not all([serial, username, wifi_name, wifi_password, time_stamp, token]):
  932. return response.json(444)
  933. if len(serial) < 14:
  934. return response.json(444, '序列号长度小于14')
  935. # 根据序列号获取p2p类型,设备类型信息
  936. serial_number = serial[:9]
  937. p2p_type = serial[9:10]
  938. device_type = int(serial[10:14], 16)
  939. # 请求绑定uid或查询uid
  940. data = {
  941. 'serial_number': serial_number,
  942. 'p2ptype': p2p_type,
  943. 'time_stamp': time_stamp,
  944. 'token': token,
  945. 'is_verify': '1'
  946. }
  947. url = SERVER_DOMAIN + 'serialNumber/attachUID'
  948. try:
  949. r = requests.post(url=url, data=data, timeout=30)
  950. assert r.status_code == 200
  951. r = r.json()
  952. if r['result_code'] != 0:
  953. return response.json(r['result_code'])
  954. uid = CommonService.decode_data(r['result']['uid'])
  955. # 查询用户是否存在,不存在则创建
  956. device_user_qs = Device_User.objects.filter(username=username).values('userID')
  957. if device_user_qs.exists():
  958. user_id = device_user_qs[0]['userID']
  959. # 判断设备是否已被其他账号添加
  960. device_info_qs = Device_Info.objects.filter(~Q(userID_id=user_id), UID=uid).values('id')
  961. if device_info_qs.exists():
  962. return response.json(174)
  963. # 已保存过,更新网络信息
  964. device_info_qs = Device_Info.objects.filter(userID_id=user_id, UID=uid).values('id')
  965. if device_info_qs.exists():
  966. device_id = device_info_qs[0]['id']
  967. device_net_info_qs = DeviceNetInfo.objects.filter(device_id=device_id)
  968. if device_net_info_qs.exists():
  969. device_net_info_qs.update(wifi_name=wifi_name, wifi_password=wifi_password)
  970. else:
  971. # 创建用户设备和设备网络数据
  972. cls.creat_device_data(user_id, serial, uid, device_type, username, wifi_name, wifi_password)
  973. else:
  974. # 判断设备是否已被其他账号添加
  975. device_info_qs = Device_Info.objects.filter(UID=uid).values('id')
  976. if device_info_qs.exists():
  977. return response.json(174)
  978. password = ''
  979. user_id = CommonService.getUserID(μs=False, setOTAID=True)
  980. user_data = {
  981. 'userID': user_id,
  982. 'username': username,
  983. 'NickName': username,
  984. 'password': password,
  985. 'is_active': True,
  986. 'user_isValid': True
  987. }
  988. # 判断用户名是手机号还是邮箱
  989. if DataValid().mobile_validate(username):
  990. user_data['phone'] = username
  991. elif DataValid().email_validate(username):
  992. user_data['userEmail'] = username
  993. else:
  994. return response.json(444)
  995. Device_User.objects.create(**user_data)
  996. # 创建用户设备和设备网络数据
  997. cls.creat_device_data(user_id, serial, uid, device_type, username, wifi_name, wifi_password)
  998. # 生成或更新扫码记录
  999. serial = serial[:6]
  1000. now_time = int(time.time())
  1001. app_scanned_serial_qs = AppScannedSerial.objects.filter(serial=serial)
  1002. if app_scanned_serial_qs.exists():
  1003. app_scanned_serial_qs.update(update_time=now_time)
  1004. else:
  1005. AppScannedSerial.objects.create(serial=serial, add_time=now_time, update_time=now_time)
  1006. return response.json(0)
  1007. except Exception as e:
  1008. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1009. @staticmethod
  1010. def creat_device_data(user_id, serial, uid, device_type, username, wifi_name, wifi_password):
  1011. """
  1012. @param user_id:
  1013. @param serial:
  1014. @param uid:
  1015. @param device_type:
  1016. @param username:
  1017. @param wifi_name:
  1018. @param wifi_password:
  1019. @return:
  1020. """
  1021. nickname = serial[:6]
  1022. device_id = CommonService.getUserID(getUser=False)
  1023. Device_Info.objects.create(
  1024. id=device_id, userID_id=user_id, serial_number=serial[:9], UID=uid, NickName=nickname,
  1025. Type=device_type, View_Account='admin', View_Password='admin', vodPrimaryMaster=username,
  1026. vodPrimaryUserID=user_id
  1027. )
  1028. DeviceNetInfo.objects.create(
  1029. device_id=device_id, wifi_name=wifi_name, wifi_password=wifi_password
  1030. )
  1031. # 创建或更新设备影子昵称
  1032. uid_set_qs = UidSetModel.objects.filter(uid=uid)
  1033. if uid_set_qs.exists():
  1034. uid_set_qs.update(nickname=nickname)
  1035. else:
  1036. UidSetModel.objects.create(uid=uid, nickname=nickname)
  1037. @staticmethod
  1038. def get_baidu_big_model_license_url(request_dict, response):
  1039. """
  1040. 获取百度大模型许可证下载链接
  1041. @param request_dict: 请求参数
  1042. @param response: 响应对象
  1043. @request_dict serial_number: 序列号
  1044. @return: response
  1045. """
  1046. serial = request_dict.get('serial', None)
  1047. if not serial:
  1048. return response.json(444)
  1049. try:
  1050. # 同个序列号返回相同license
  1051. baidu_big_model_license_qs = BaiduBigModelLicense.objects.filter(serial=serial).values('license_name')
  1052. if baidu_big_model_license_qs.exists():
  1053. license_name = baidu_big_model_license_qs[0]['license_name']
  1054. else:
  1055. # 查询未被使用的license,使用事务和行锁避免并发问题
  1056. with transaction.atomic():
  1057. baidu_big_model_license_qs = BaiduBigModelLicense.objects.filter(
  1058. serial='', use_status=0
  1059. ).select_for_update().order_by('id').first()
  1060. if not baidu_big_model_license_qs:
  1061. return response.json(173)
  1062. license_name = baidu_big_model_license_qs.license_name
  1063. # 更新数据为已使用
  1064. now_time = int(time.time())
  1065. baidu_big_model_license_qs.serial = serial
  1066. baidu_big_model_license_qs.use_status = 1
  1067. baidu_big_model_license_qs.updated_time = now_time
  1068. baidu_big_model_license_qs.save()
  1069. # 生成华为云OBS临时下载链接
  1070. from obs import ObsClient
  1071. obs_client = ObsClient(
  1072. access_key_id=HUAWEICLOUD_AK,
  1073. secret_access_key=HUAWEICLOUD_SK,
  1074. server=HUAWEICLOUD_OBS_SERVER
  1075. )
  1076. download_url = obs_client.createSignedUrl(
  1077. method='GET',
  1078. bucketName=HUAWEICLOUD_BAIDU_BIG_MODEL_LICENSE_BUKET,
  1079. objectKey=license_name,
  1080. expires=3600 # 有效期1小时
  1081. )
  1082. res = {
  1083. 'license_url': download_url.signedUrl
  1084. }
  1085. return response.json(0, res)
  1086. except Exception as e:
  1087. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1088. @staticmethod
  1089. def get_instavision(request_dict, response, request):
  1090. """
  1091. 获取instavision数据
  1092. @param request_dict: 请求参数
  1093. @param response: 响应对象
  1094. @request_dict mac: 设备mac地址
  1095. @return: response
  1096. """
  1097. mac = request_dict.get('mac', None)
  1098. if not mac:
  1099. return response.json(444)
  1100. try:
  1101. scheme_code = request_dict.get('scheme_code', 'INST01350WA')
  1102. ip = CommonService.get_ip_address(request)
  1103. # 查询mac是否已存在数据
  1104. instavision_qs = Instavision.objects.filter(mac=mac, scheme_code=scheme_code, use_status=1).values('device_id', 'access_key')
  1105. if instavision_qs.exists():
  1106. res = {
  1107. 'device_id': instavision_qs[0]['device_id'],
  1108. 'access_key': instavision_qs[0]['access_key'],
  1109. }
  1110. LOGGER.info('{}获取instavision,ip:{}'.format(mac, ip))
  1111. return response.json(0, res)
  1112. else:
  1113. # 使用事务和select_for_update来处理并发问题
  1114. with transaction.atomic():
  1115. # 使用select_for_update加锁,防止并发时多个请求获取到同一条记录
  1116. instavision_qs = Instavision.objects.select_for_update().filter(use_status=0, scheme_code=scheme_code).first()
  1117. if not instavision_qs:
  1118. return response.json(444, '没有可用的即时视觉数据')
  1119. device_id = instavision_qs.device_id
  1120. access_key = instavision_qs.access_key
  1121. # 更新该条数据的mac、use_status和updated_time
  1122. instavision_qs.mac = mac
  1123. instavision_qs.use_status = 1 # 标记为已使用
  1124. instavision_qs.updated_time = int(time.time())
  1125. instavision_qs.save()
  1126. res = {
  1127. 'device_id': device_id,
  1128. 'access_key': access_key,
  1129. }
  1130. LOGGER.info('{}绑定instavision,ip:{}'.format(mac, ip))
  1131. return response.json(0, res)
  1132. except Exception as e:
  1133. LOGGER.error('获取DID error:{},mac:{}'.format(repr(e), mac))
  1134. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  1135. @staticmethod
  1136. def get_insta_vision_v2(request_dict, response, request):
  1137. """
  1138. 获取insta_vision数据
  1139. @param request_dict: 请求参数
  1140. @param response: 响应对象
  1141. @request_dict mac: 设备mac地址
  1142. @request_dict code: 设备code
  1143. @request_dict scheme_code: 设备scheme_code
  1144. @request_dict time_stamp: 时间戳
  1145. @request_dict token: token
  1146. @return: response
  1147. """
  1148. mac = request_dict.get('mac', None)
  1149. token = request_dict.get('token', None)
  1150. time_stamp = request_dict.get('time_stamp', None)
  1151. scheme_code = request_dict.get('scheme_code', None)
  1152. try:
  1153. if not all([mac, token, time_stamp, scheme_code]):
  1154. LOGGER.error(f'ins获取DID参数缺失,mac:{mac}')
  1155. return response.json(444)
  1156. # 时间戳token校验
  1157. if not CommonService.check_time_stamp_token(token, time_stamp):
  1158. LOGGER.error(f'ins获取DID{scheme_code}时间戳校验失败time:{time_stamp},token:{token}')
  1159. return response.json(13)
  1160. ip = CommonService.get_ip_address(request)
  1161. content = json.loads(json.dumps(request_dict))
  1162. # 查询mac是否已存在数据
  1163. ins_qs = (Instavision.objects.filter(mac=mac, scheme_code=scheme_code, use_status=1)
  1164. .values('device_id', 'access_key'))
  1165. log = {
  1166. 'ip': ip,
  1167. 'user_id': 1,
  1168. 'status': 200,
  1169. 'time': int(time.time()),
  1170. 'content': json.dumps(content),
  1171. 'url': 'serialNumber/getInstaVisionV2',
  1172. }
  1173. if ins_qs.exists():
  1174. res = {
  1175. 'device_id': ins_qs[0]['device_id'],
  1176. 'access_key': ins_qs[0]['access_key'],
  1177. }
  1178. did = ins_qs[0]['device_id']
  1179. log['operation'] = f'MAC:{mac}获取uid: {did}'
  1180. LogModel.objects.create(**log)
  1181. return response.json(0, res)
  1182. else:
  1183. # 使用事务和select_for_update来处理并发问题
  1184. with (transaction.atomic()):
  1185. # 使用select_for_update加锁,防止并发时多个请求获取到同一条记录
  1186. ins_qs = Instavision.objects.select_for_update(
  1187. ).filter(use_status=0, scheme_code=scheme_code).first()
  1188. if not ins_qs:
  1189. LOGGER.error(f'ins获取DID{mac}没有可用的即时视觉数据,code:{scheme_code}')
  1190. return response.json(444, '没有可用的即时视觉数据')
  1191. device_id = ins_qs.device_id
  1192. access_key = ins_qs.access_key
  1193. # 更新该条数据的mac、use_status和updated_time
  1194. ins_qs.mac = mac
  1195. ins_qs.use_status = 1 # 标记为已使用
  1196. ins_qs.updated_time = int(time.time())
  1197. ins_qs.save()
  1198. res = {
  1199. 'device_id': device_id,
  1200. 'access_key': access_key,
  1201. }
  1202. log['operation'] = f'MAC:{mac}绑定uid: {device_id}'
  1203. LogModel.objects.create(**log)
  1204. return response.json(0, res)
  1205. except Exception as e:
  1206. LOGGER.error('ins获取DID,error:{},mac:{}'.format(repr(e), mac))
  1207. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))