SerialNumberController.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  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.views import View
  9. from Ansjer.config import CRCKey, CONFIG_INFO, CONFIG_US, CONFIG_EUR, \
  10. CONFIG_CN, USED_SERIAL_REDIS_LIST, UNUSED_SERIAL_REDIS_LIST, SERVER_DOMAIN_US, REGION_ID_LIST, SERVER_DOMAIN_TEST, \
  11. SERVER_DOMAIN_LIST, SERVER_DOMAIN_CN, SERVER_DOMAIN_EUR, RESET_REGION_ID_SERIAL_REDIS_LIST, LOGGER
  12. from Controller.UnicomCombo.UnicomComboController import UnicomComboView
  13. from Model.models import SerialNumberModel, CompanySerialModel, UIDCompanySerialModel, UIDModel, Device_Info, \
  14. iotdeviceInfoModel, LogModel, UidSetModel, UID_Bucket, \
  15. Unused_Uid_Meal, Order_Model, StsCrdModel, VodHlsModel, ExperienceContextModel, UidUserModel, ExperienceAiModel, \
  16. AiService, DeviceDomainRegionModel, RegionModel, UidPushModel, UnicomDeviceInfo
  17. from Object.AWS.S3Email import S3Email
  18. from Object.RedisObject import RedisObject
  19. from Object.TokenObject import TokenObject
  20. from Object.UnicomObject import UnicomObjeect
  21. from Object.uidManageResponseObject import uidManageResponseObject
  22. from Service.AlgorithmService import AlgorithmBaseOn35
  23. from Service.CommonService import CommonService
  24. from Service.EquipmentInfoService import EquipmentInfoService
  25. from Service.VodHlsService import SplitVodHlsObject
  26. class SerialNumberView(View):
  27. def get(self, request, *args, **kwargs):
  28. request.encoding = 'utf-8'
  29. operation = kwargs.get('operation', None)
  30. request_dict = request.GET
  31. return self.validate(request_dict, operation, request)
  32. def post(self, request, *args, **kwargs):
  33. request.encoding = 'utf-8'
  34. operation = kwargs.get('operation', None)
  35. request_dict = request.POST
  36. return self.validate(request_dict, operation, request)
  37. def validate(self, request_dict, operation, request):
  38. response = uidManageResponseObject()
  39. if operation == 'attachUID': # 绑定uid
  40. return self.do_attach_uid(request_dict, response, request)
  41. elif operation == 'detachUID': # 解绑uid
  42. return self.do_detach_uid(request, request_dict, response)
  43. elif operation == 'get-uid': # app获取uid
  44. return self.get_uid(request_dict, response, request)
  45. elif operation == 'create': # 创建序列号
  46. return self.do_create(request_dict, response)
  47. elif operation == 'getUID': # 根据序列号获取uid
  48. return self.do_get_uid(request_dict, response)
  49. elif operation == 'getRegionInfo': # 根据序列号状态确认uid地区(PC工具使用)
  50. return self.get_region_info(request_dict, response)
  51. elif operation == 'saveRegion': # 保存设备地区信息(app使用)
  52. return self.save_region(request, request_dict, response)
  53. elif operation == 'getDomain': # 获取域名(设备使用)
  54. return self.get_domain(request_dict, response)
  55. elif operation == 'resetRegionId': # 重置地区id
  56. return self.reset_region_id(request_dict, response)
  57. elif operation == 'get-status': # 获取序列号绑定信息
  58. return self.check_serial_status(request_dict, response)
  59. elif operation == 'getUidRegion': # 根据序列号获取uid地区
  60. return self.get_uid_region(request_dict, response)
  61. elif operation == 'getGlobalUidRegion': # 获取序列号在全球服绑定uid的地区
  62. return self.get_global_uid_region(request_dict, response)
  63. elif operation == 'getIoTCoreBySerialNumber': # 根据序列号获取iot core
  64. return self.get_iot_core_by_serial_number(request_dict, response)
  65. else:
  66. return response.json(414)
  67. @staticmethod
  68. def do_create(request_dict, response):
  69. quantity = int(request_dict.get('quantity', 0))
  70. if not quantity:
  71. return response.json(444)
  72. try:
  73. try:
  74. number = SerialNumberModel.objects.last().id
  75. except:
  76. number = 0
  77. serial_number_bulk = []
  78. now_time = int(time.time())
  79. algorithm = AlgorithmBaseOn35()
  80. for i in range(quantity):
  81. serial_number = algorithm.getLetter(number)
  82. number += 1 # sum每次递增1
  83. # 前面补0至六位
  84. serial_number = (6 - len(serial_number)) * '0' + serial_number
  85. serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time))
  86. # 开启事务写入
  87. with transaction.atomic():
  88. SerialNumberModel.objects.bulk_create(serial_number_bulk)
  89. return response.json(0)
  90. except Exception as e:
  91. print(e)
  92. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  93. def do_attach_uid(self, request_dict, response, request):
  94. serial_number = request_dict.get('serial_number', None)
  95. token = request_dict.get('token', None)
  96. time_stamp = request_dict.get('time_stamp', None)
  97. if not all([serial_number, token, time_stamp]):
  98. return response.json(444)
  99. # 时间戳token校验
  100. if not CommonService.check_time_stamp_token(token, time_stamp):
  101. return response.json(13)
  102. now_time = int(time.time())
  103. serial = serial_number[0:6]
  104. company_identity = serial_number[6:9]
  105. full_serial = serial_number[0:9]
  106. # 根据企业标识确认企业秘钥
  107. company_secret = ''
  108. if company_identity == '11A':
  109. company_secret = 'MTEyMTNB'
  110. elif company_identity == '11L':
  111. company_secret = 'VmXEWnBR'
  112. elif company_identity == '11Z':
  113. company_secret = 'ZsKWcxdD'
  114. try:
  115. # 判断序列号是否刚解绑,刚解绑1分钟内不能进行绑定
  116. redisObj = RedisObject()
  117. unused_serial_redis_list = redisObj.lrange(UNUSED_SERIAL_REDIS_LIST, 0, -1)
  118. unused_serial_redis_list = [str(i, 'utf-8') for i in unused_serial_redis_list]
  119. if serial in unused_serial_redis_list:
  120. return response.json(5)
  121. # 判断序列号是否已和企业关联
  122. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  123. if not company_serial_qs.exists():
  124. return response.json(173)
  125. company_serial = company_serial_qs[0]
  126. if company_serial.status == 0: # 该序列号未绑定企业
  127. return response.json(173)
  128. elif company_serial.status == 1: # 绑定uid
  129. # redis加锁,防止同一个序列号重复绑定
  130. key = serial + 'do_attach_uid'
  131. isLock = redisObj.CONN.setnx(key, 1)
  132. redisObj.CONN.expire(key, 60)
  133. if not isLock:
  134. return response.json(5)
  135. # 获取并判断region_id
  136. region_id = CommonService.confirm_region_id()
  137. if region_id not in REGION_ID_LIST:
  138. return response.json(444, {'invalid region_id': region_id})
  139. # 获取p2p类型
  140. p2p_type = request_dict.get('p2ptype', None)
  141. if serial_number[9:10]:
  142. p2p_type = serial_number[9:10]
  143. elif not p2p_type:
  144. return response.json(444, {'param': 'p2ptype'})
  145. p2p_type = int(p2p_type)
  146. with transaction.atomic():
  147. count = 0
  148. while count < 3:
  149. # 查询是否存在未绑定序列号的uid
  150. uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id,
  151. vpg__region_id=region_id, status=0, p2p_type=p2p_type). \
  152. order_by('update_time')
  153. if not uid_qs.exists():
  154. return response.json(375)
  155. uid = uid_qs[0]
  156. # 判断uid是否已绑定过序列号
  157. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(uid_id=uid.id)
  158. if uid_company_serial_qs.exists():
  159. return response.json(377)
  160. result = UIDModel.objects.filter(id=uid.id, status=0).update(status=2, update_time=now_time)
  161. if int(result) <= 0: # 更新失败
  162. count += 1
  163. continue
  164. # UID关联【企业关联序列号】表创建数据
  165. UIDCompanySerialModel.objects.create(uid_id=uid.id, company_serial_id=company_serial.id,
  166. add_time=now_time, update_time=now_time)
  167. company_serial.status = 2
  168. company_serial.update_time = now_time
  169. company_serial.save()
  170. dev = Device_Info.objects.filter(UID=uid.uid)
  171. if dev.exists():
  172. dev.update(serial_number=full_serial)
  173. full_uid_code = uid.full_uid_code
  174. if uid.platform in CRCKey.keys():
  175. full_uid_code += ':' + CRCKey[uid.platform]
  176. res = {
  177. 'full_uid_code': CommonService.encode_data(full_uid_code),
  178. 'uid': CommonService.encode_data(uid.uid),
  179. 'extra': uid.uid_extra,
  180. 'platform': uid.platform,
  181. 'initString': uid.init_string,
  182. 'initStringApp': uid.init_string_app,
  183. }
  184. # 记录操作日志
  185. ip = CommonService.get_ip_address(request)
  186. content = json.loads(json.dumps(request_dict))
  187. log = {
  188. 'ip': ip,
  189. 'user_id': 1,
  190. 'status': 200,
  191. 'time': now_time,
  192. 'content': json.dumps(content),
  193. 'url': 'serialNumber/attachUID',
  194. 'operation': '序列号{}绑定uid: {}'.format(serial, uid.uid),
  195. }
  196. LogModel.objects.create(**log)
  197. redisObj.del_data(key=key)
  198. # 处理序列号状态和计算剩余uid数量线程
  199. thread = threading.Thread(target=self.rpush_serial_and_count_uid, args=(serial, p2p_type,
  200. redisObj))
  201. thread.start()
  202. return response.json(0, res)
  203. return response.json(5)
  204. elif company_serial.status == 2: # 返回uid
  205. res = self.get_uid_info_by_serial(company_serial.id)
  206. return response.json(0, res)
  207. elif company_serial.status == 3: # 已占用
  208. res = self.log_and_send_email(request, company_serial.id, serial_number, now_time)
  209. if not res:
  210. return response.json(10042)
  211. return response.json(0, self.get_uid_info_by_serial(company_serial.id))
  212. except Exception as e:
  213. djangoLogger = logging.getLogger('django')
  214. djangoLogger.exception(repr(e))
  215. return response.json(176, str(e))
  216. @classmethod
  217. def get_uid_info_by_serial(cls, company_serial_id):
  218. """
  219. 根据企业关联序列号ID返回UID信息
  220. """
  221. uid_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial_id)
  222. if not uid_qs.exists():
  223. return {}
  224. uid = uid_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__full_uid_code',
  225. 'uid__platform', 'uid__init_string', 'uid__init_string_app')[0]
  226. full_uid_code = uid['uid__full_uid_code']
  227. if uid['uid__platform'] in CRCKey.keys():
  228. full_uid_code += ':' + CRCKey[uid['uid__platform']]
  229. res = {
  230. 'full_uid_code': CommonService.encode_data(full_uid_code),
  231. 'uid': CommonService.encode_data(uid['uid__uid']),
  232. 'extra': uid['uid__uid_extra'],
  233. 'platform': uid['uid__platform'],
  234. 'initString': uid['uid__init_string'],
  235. 'initStringApp': uid['uid__init_string_app'],
  236. }
  237. return res
  238. @classmethod
  239. def check_serial_status(cls, request_dict, response):
  240. serial_number = request_dict.get('serial_number', None)
  241. if not serial_number:
  242. return response.json(444)
  243. serial = serial_number[0:6]
  244. company_identity = serial_number[6:9]
  245. # 根据企业标识确认企业秘钥
  246. company_secret = ''
  247. if company_identity == '11A':
  248. company_secret = 'MTEyMTNB'
  249. elif company_identity == '11L':
  250. company_secret = 'VmXEWnBR'
  251. elif company_identity == '11Z':
  252. company_secret = 'ZsKWcxdD'
  253. try:
  254. # 判断序列号是否已和企业关联
  255. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  256. if not company_serial_qs.exists():
  257. return response.json(173)
  258. company_serial = company_serial_qs[0]
  259. # 获取企业序列号是否绑定UID
  260. uid_company_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id) \
  261. .values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__status', 'uid__area', 'uid__vpg_id',
  262. 'uid__p2p_type', 'uid__full_uid_code', 'uid__platform',
  263. 'uid__init_string', 'uid__init_string_app')
  264. uid_info = {}
  265. if uid_company_qs.exists():
  266. uid_info['uid'] = uid_company_qs[0]['uid__uid']
  267. uid_info['mac'] = uid_company_qs[0]['uid__mac']
  268. uid_info['uid_extra'] = uid_company_qs[0]['uid__uid_extra']
  269. uid_info['status'] = uid_company_qs[0]['uid__status']
  270. uid_info['area'] = uid_company_qs[0]['uid__area']
  271. uid_info['vpg_id'] = uid_company_qs[0]['uid__vpg_id']
  272. uid_info['p2p_type'] = uid_company_qs[0]['uid__p2p_type']
  273. uid_info['full_uid_code'] = uid_company_qs[0]['uid__full_uid_code']
  274. uid_info['platform'] = uid_company_qs[0]['uid__platform']
  275. uid_info['init_string'] = uid_company_qs[0]['uid__init_string']
  276. uid_info['init_string_app'] = uid_company_qs[0]['uid__init_string_app']
  277. results = {'serial': company_serial.serial_number, 'status': company_serial.status,
  278. 'uidInfo': uid_info}
  279. return response.json(0, results)
  280. except Exception as e:
  281. LOGGER.info('查询序列号异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  282. return response.json(176, str(e))
  283. @staticmethod
  284. def rpush_serial_and_count_uid(serial, p2p_type, redis_obj):
  285. """
  286. 处理序列号状态和计算剩余uid数量线程
  287. @param serial: 序列号
  288. @param p2p_type: p2p类型
  289. @param redis_obj: redis对象
  290. @return:
  291. """
  292. # 写入已使用序列号redis列表
  293. redis_obj.rpush(USED_SERIAL_REDIS_LIST, serial)
  294. redis_obj = RedisObject()
  295. time_limit = redis_obj.get_data('uid_count_warning_time_limit')
  296. if not time_limit:
  297. vpg_id = 1
  298. if CONFIG_INFO == CONFIG_US:
  299. vpg_id = 3
  300. elif CONFIG_INFO == CONFIG_EUR:
  301. vpg_id = 4
  302. p2p_type = int(p2p_type)
  303. try:
  304. # 剩余uid数量少于2000邮件提醒
  305. unused_uid_count = UIDModel.objects.filter(vpg_id=vpg_id, p2p_type=p2p_type, status=0).count()
  306. LOGGER.info('uid剩余数量:{}'.format(unused_uid_count))
  307. warning_count = 2000
  308. if unused_uid_count < warning_count:
  309. # 限制一天提醒一次
  310. redis_obj.set_data('uid_count_warning_time_limit', 1, 60 * 60 * 24)
  311. platform = '尚云' if p2p_type == 1 else 'tutk'
  312. email_content = '{}服{}的uid数量少于{}个,请及时处理'.format(CONFIG_INFO, platform, warning_count)
  313. S3Email().faEmail(email_content, 'servers@ansjer.com')
  314. except Exception as e:
  315. LOGGER.info('发送提醒邮件异常: error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  316. @staticmethod
  317. def log_and_send_email(request, company_serial_id, serial, now_time):
  318. """
  319. 记录序列号占用操作日志及发送邮件通知,(美服、欧服已占用序列号将执行数据同步)
  320. @param company_serial_id: 企业关联序列号 ID
  321. @param request: 请求
  322. @param serial: 序列号
  323. @param now_time: 当前时间
  324. """
  325. send_email = S3Email()
  326. try:
  327. if CONFIG_INFO == 'cn' or CONFIG_INFO == 'test':
  328. return {}
  329. # 判断当前序列号是否绑定UID
  330. uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial_id)
  331. if uid_serial_qs.exists():
  332. email_content = '{}序列号已占用当前数据库已绑定UID: {}'.format(CONFIG_INFO, serial)
  333. send_email.faEmail(email_content, 'servers@ansjer.com')
  334. return {}
  335. if CONFIG_INFO == 'eur': # 查美服
  336. response = requests.get("https://www.dvema.com/serialNumber/get-status",
  337. params={'serial_number': serial}, timeout=3)
  338. else: # 查国服
  339. response = requests.get("https://www.zositechc.cn/serialNumber/get-status",
  340. params={'serial_number': serial}, timeout=3)
  341. ip = CommonService.get_ip_address(request)
  342. operation = '{}序列号占用:{}'.format(CONFIG_INFO, serial)
  343. log = {
  344. 'ip': ip,
  345. 'user_id': 1,
  346. 'status': 200,
  347. 'time': now_time,
  348. 'operation': operation,
  349. 'url': 'serialNumber/attachUID',
  350. }
  351. if not response.status_code == 200:
  352. operation += '查询其它服UID数据异常响应状态:{}'.format(response.status_code)
  353. log['operation'] = operation
  354. LogModel.objects.create(**log)
  355. return {}
  356. results = json.loads(response.text)
  357. if not results['result_code'] == 0:
  358. operation += '其它服绑定UID数据result_code: {}'.format(results['result_code'])
  359. log['operation'] = operation
  360. LogModel.objects.create(**log)
  361. return {}
  362. # 解析从其它服获取的UID数据
  363. uid_info = results['result']['uidInfo']
  364. if uid_info:
  365. if uid_info['p2p_type'] == 1: # 尚云UID不进行同步只进行 邮寄警报
  366. # 邮件通知
  367. email_content = '国内uid同步国外服类型为尚云不操作: {}'.format(serial)
  368. send_email.faEmail(email_content, 'servers@ansjer.com')
  369. else:
  370. # 同步UID数据
  371. uid_id = ''
  372. uid_qs = UIDModel.objects.filter(uid=uid_info['uid'])
  373. if uid_qs.exists():
  374. if uid_qs.first().status == 2: # 判断uid是否被使用
  375. email_content = '{}序列号已占用且{}已被使用:{}'.format(CONFIG_INFO, uid_info['uid'], serial)
  376. send_email.faEmail(email_content, 'servers@ansjer.com')
  377. return {}
  378. else:
  379. uid_qs.update(status=2, update_time=now_time)
  380. uid_id = uid_qs.first().id
  381. if not uid_id:
  382. uid_id = UIDModel.objects.create(**uid_info).id
  383. # 企业序列号关联 uid
  384. UIDCompanySerialModel.objects.create(uid_id=uid_id, company_serial_id=company_serial_id,
  385. add_time=now_time, update_time=now_time)
  386. # 成功后 修改企业序列号状态为2(已分配)
  387. CompanySerialModel.objects.filter(id=company_serial_id) \
  388. .update(status=2, update_time=now_time)
  389. SerialNumberView.sync_iot_core_data(serial)
  390. email_content = '{}序列号已占用已将其它服UID数据同步完成: {}'.format(CONFIG_INFO, serial)
  391. send_email.faEmail(email_content, 'servers@ansjer.com')
  392. operation += '同步成功'
  393. log['operation'] = operation
  394. LogModel.objects.create(**log)
  395. return 'success'
  396. email_content = '{}序列号已占用其它服没有绑定UID: {}'.format(CONFIG_INFO, serial)
  397. send_email.faEmail(email_content, 'servers@ansjer.com')
  398. return {}
  399. except Exception as e:
  400. email_content = '序列号占用同步数据异常: {},errLine:{}, errMsg:{}' \
  401. .format(serial, e.__traceback__.tb_lineno, repr(e))
  402. send_email.faEmail(email_content, 'servers@ansjer.com')
  403. send_email.faEmail(email_content, 'antony@ansjer.com')
  404. return {}
  405. def do_get_uid(self, request_dict, response):
  406. serial_number = request_dict.get('serial_number', None)
  407. token = request_dict.get('token', None)
  408. time_stamp = request_dict.get('time_stamp', None)
  409. if token and time_stamp and serial_number:
  410. # 时间戳token校验
  411. if not CommonService.check_time_stamp_token(token, time_stamp):
  412. return response.json(13)
  413. mark = serial_number[6:9]
  414. serial = serial_number[0:6]
  415. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__company__mark=mark,
  416. company_serial__serial_number__serial_number=serial)
  417. if uid_company_serial_qs.exists():
  418. uid = uid_company_serial_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra')[0]
  419. res = {
  420. 'uid': CommonService.encode_data(uid['uid__uid']),
  421. 'mac': CommonService.encode_data(uid['uid__mac']),
  422. 'extra': uid['uid__uid_extra']
  423. }
  424. return response.json(0, res)
  425. else:
  426. return response.json(173)
  427. else:
  428. return response.json(444)
  429. @staticmethod
  430. def do_detach_uid(request, request_dict, response):
  431. token = request_dict.get('token', None)
  432. time_stamp = request_dict.get('time_stamp', None)
  433. serial_number = request_dict.get('serial_number', None)
  434. if not all([token, time_stamp, serial_number]):
  435. return response.json(444)
  436. # 时间戳token校验
  437. if not CommonService.check_time_stamp_token(token, time_stamp):
  438. return response.json(13)
  439. now_time = int(time.time())
  440. serial = serial_number[0:6]
  441. company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial).values('status')
  442. if not company_serial_qs.exists():
  443. return response.json(379)
  444. status = company_serial_qs[0]['status']
  445. if status == 1:
  446. return response.json(0, {'success': '序列号未绑定uid'})
  447. elif status == 3:
  448. return response.json(10043)
  449. uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial)
  450. if not uid_serial_qs.exists():
  451. return response.json(173)
  452. uid_serial = uid_serial_qs[0]
  453. # 判断序列号是否刚绑定uid,刚绑定需要过1分钟才能解绑
  454. redisObj = RedisObject()
  455. used_serial_redis_list = redisObj.lrange(USED_SERIAL_REDIS_LIST, 0, -1)
  456. used_serial_redis_list = [str(i, 'utf-8') for i in used_serial_redis_list]
  457. if serial in used_serial_redis_list:
  458. return response.json(5)
  459. try:
  460. with transaction.atomic():
  461. uid = uid_serial.uid.uid
  462. # 更新序列号状态
  463. company_serial_qs.update(status=1, update_time=now_time)
  464. # 删除设备相关数据,参考后台的设备重置删除的数据
  465. Device_Info.objects.filter(UID=uid).delete()
  466. UidSetModel.objects.filter(uid=uid).delete()
  467. UidUserModel.objects.filter(UID=uid).delete()
  468. UidPushModel.objects.filter(uid_set__uid=uid).delete()
  469. iotdeviceInfoModel.objects.filter(serial_number=serial).delete()
  470. # 删除推送消息
  471. for val in range(1, 8):
  472. EquipmentInfoService.get_equipment_info_model('', val).filter(device_uid=uid).delete()
  473. # 重置设备云存
  474. UID_Bucket.objects.filter(uid=uid).delete()
  475. Unused_Uid_Meal.objects.filter(uid=uid).delete()
  476. Order_Model.objects.filter(UID=uid).delete()
  477. StsCrdModel.objects.filter(uid=uid).delete()
  478. VodHlsModel.objects.filter(uid=uid).delete()
  479. # 删除vod_hls分表数据
  480. split_vod_hls_obj = SplitVodHlsObject()
  481. split_vod_hls_obj.del_vod_hls_data(uid=uid)
  482. ExperienceContextModel.objects.filter(uid=uid).delete()
  483. # 重置AI
  484. ExperienceAiModel.objects.filter(uid=uid).delete()
  485. AiService.objects.filter(uid=uid).delete()
  486. # 写入未使用序列号redis列表
  487. redisObj.rpush(UNUSED_SERIAL_REDIS_LIST, serial)
  488. # 重置region_id,不为美洲服,则写入redis列表
  489. if CONFIG_INFO == CONFIG_US:
  490. DeviceDomainRegionModel.objects.filter(serial_number=serial).update(region_id=0)
  491. else:
  492. redisObj.rpush(RESET_REGION_ID_SERIAL_REDIS_LIST, serial)
  493. # 重置uid的使用状态为未使用,更新时间
  494. UIDModel.objects.filter(uid=uid).update(status=0, mac='', update_time=now_time)
  495. uid_serial.delete()
  496. # 记录操作日志
  497. ip = CommonService.get_ip_address(request)
  498. content = json.loads(json.dumps(request_dict))
  499. log = {
  500. 'ip': ip,
  501. 'user_id': 1,
  502. 'status': 200,
  503. 'time': now_time,
  504. 'content': json.dumps(content),
  505. 'url': 'serialNumber/detachUID',
  506. 'operation': '序列号{}解绑uid: {}'.format(serial, uid),
  507. }
  508. LogModel.objects.create(**log)
  509. return response.json(0)
  510. except Exception as e:
  511. # 记录操作日志
  512. ip = CommonService.get_ip_address(request)
  513. content = json.loads(json.dumps(request_dict))
  514. log = {
  515. 'ip': ip,
  516. 'user_id': 1,
  517. 'status': 200,
  518. 'time': now_time,
  519. 'content': json.dumps(content) + '异常:{}'.format(repr(e)),
  520. 'url': 'serialNumber/detachUID',
  521. 'operation': '序列号{}解绑uid{}异常'.format(serial, uid),
  522. }
  523. LogModel.objects.create(**log)
  524. return response.json(176, str(e))
  525. def get_uid(self, request_dict, response, request):
  526. """
  527. app获取序列号
  528. @param request_dict:
  529. @param response:
  530. @param request:
  531. @return:
  532. """
  533. token = request_dict.get('token', None)
  534. time_stamp = request_dict.get('time_stamp', None)
  535. company_secret = request_dict.get('company_id', None)
  536. serial_number = request_dict.get('serial_number', None)
  537. if not all([token, time_stamp, company_secret, serial_number]):
  538. return response.json(444)
  539. # 时间戳token校验
  540. if not CommonService.check_time_stamp_token(token, time_stamp):
  541. return response.json(13)
  542. now_time = int(time.time())
  543. serial = serial_number[0:6]
  544. # 判断序列号是否已和企业关联
  545. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  546. if not company_serial_qs.exists():
  547. return response.json(173)
  548. company_serial = company_serial_qs[0]
  549. try:
  550. if company_serial.status == 0 or company_serial.status == 1: # 未使用
  551. self.is_4g_device(serial_number, request_dict, request)
  552. return response.json(173)
  553. elif company_serial.status == 2: # 返回uid
  554. res = self.get_uid_info_by_serial(company_serial.id)
  555. return response.json(0, res)
  556. elif company_serial.status == 3: # 已占用
  557. res = self.log_and_send_email(request, company_serial.id, serial_number, now_time)
  558. if not res:
  559. return response.json(10042)
  560. return response.json(0, self.get_uid_info_by_serial(company_serial.id))
  561. except Exception as e:
  562. error_logger = logging.getLogger('django')
  563. error_logger.exception(repr(e))
  564. return response.json(176, str(e))
  565. @staticmethod
  566. def get_region_info(request_dict, response):
  567. """
  568. 根据序列号状态确认uid地区
  569. @param request_dict: 请求参数
  570. @param response: 响应对象
  571. @request_dict serial_number: 序列号
  572. @return: response
  573. """
  574. serial_number = request_dict.get('serial_number', None)
  575. if not serial_number:
  576. return response(444)
  577. company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial_number[:6]).values('status')
  578. if not company_serial_qs.exists():
  579. return response.json(173)
  580. status = company_serial_qs[0]['status']
  581. if status == 2:
  582. if CONFIG_INFO == CONFIG_CN:
  583. return response.json(0, {'region': 1})
  584. elif CONFIG_INFO == CONFIG_US:
  585. return response.json(0, {'region': 3})
  586. elif status == 3:
  587. if CONFIG_INFO == CONFIG_CN:
  588. return response.json(0, {'region': 3})
  589. elif CONFIG_INFO == CONFIG_US:
  590. return response.json(0, {'region': 1})
  591. return response.json(0)
  592. @staticmethod
  593. def save_region(request, request_dict, response):
  594. """
  595. 保存设备地区信息
  596. @param request: 请求体
  597. @param request_dict: 请求参数
  598. @param response: 响应对象
  599. @request_dict token: 令牌
  600. @request_dict time_stamp: 时间戳
  601. @return: response
  602. """
  603. token = request_dict.get('token', None)
  604. serial_number = request_dict.get('serial_number', None)
  605. if not all([serial_number, token]):
  606. return response(444)
  607. try:
  608. serial_number = serial_number[:6]
  609. # 不是美洲服,请求美洲域名保存数据
  610. if CONFIG_INFO != CONFIG_US:
  611. # token认证
  612. token_obj = TokenObject(token)
  613. if token_obj.code != 0:
  614. return response.json(token_obj.code)
  615. response.lang = token_obj.lang
  616. url = SERVER_DOMAIN_US + 'serialNumber/saveRegion'
  617. data = request_dict.dict()
  618. data['ip'] = CommonService.get_ip_address(request)
  619. data['region_id'] = CommonService.confirm_region_id()
  620. try:
  621. r = requests.post(url=url, data=data, timeout=3)
  622. assert r.status_code == 200
  623. res = r.json()
  624. assert res['result_code'] == 0
  625. except (TimeoutError, AssertionError):
  626. return response.json(5)
  627. # 美洲服,处理请求和保存数据
  628. else:
  629. data = {}
  630. # 处理其他服务器发起请求的情况
  631. region_id = request_dict.get('region_id', None)
  632. if region_id is not None:
  633. region_id = int(region_id)
  634. data['region_id'] = region_id
  635. data['ip'] = request_dict.get('ip', '')
  636. else:
  637. # token认证
  638. token_obj = TokenObject(token)
  639. if token_obj.code != 0:
  640. return response.json(token_obj.code)
  641. response.lang = token_obj.lang
  642. region_id = CommonService.confirm_region_id()
  643. data['region_id'] = region_id
  644. data['ip'] = CommonService.get_ip_address(request)
  645. # 写入数据
  646. device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number). \
  647. values('region_id')
  648. if not device_domain_region_qs.exists():
  649. data['serial_number'] = serial_number
  650. DeviceDomainRegionModel.objects.create(**data)
  651. else:
  652. # 设备解绑过uid,更新region_id
  653. if device_domain_region_qs[0]['region_id'] == 0:
  654. device_domain_region_qs.update(**data)
  655. return response.json(0)
  656. except Exception as e:
  657. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  658. @staticmethod
  659. def get_domain(request_dict, response):
  660. """
  661. 设备获取域名
  662. @param request_dict: 请求参数
  663. @param response: 响应对象
  664. @request_dict serial_number: 序列号
  665. @request_dict time_stamp_token: 时间戳token
  666. @request_dict time_stamp: 时间戳
  667. @return: response
  668. """
  669. serial_number = request_dict.get('serial_number', None)
  670. time_stamp_token = request_dict.get('time_stamp_token', None)
  671. time_stamp = request_dict.get('time_stamp', None)
  672. if not all([serial_number, time_stamp_token, time_stamp]):
  673. return response.json(444)
  674. # 时间戳token校验
  675. if not CommonService.check_time_stamp_token(time_stamp_token, time_stamp):
  676. return response.json(13)
  677. try:
  678. serial_number = serial_number[:6]
  679. device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number).values(
  680. 'region_id')
  681. if not device_domain_region_qs.exists():
  682. return response.json(173)
  683. region_id = device_domain_region_qs[0]['region_id']
  684. region_qs = RegionModel.objects.filter(id=region_id).values('api', 'push_api')
  685. if not region_qs.exists():
  686. return response.json(173)
  687. res = {
  688. 'api': region_qs[0]['api'],
  689. 'push_api': region_qs[0]['push_api']
  690. }
  691. return response.json(0, res)
  692. except Exception as e:
  693. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  694. @staticmethod
  695. def reset_region_id(request_dict, response):
  696. """
  697. 重置地区id
  698. @param request_dict: 请求参数
  699. @param response: 响应对象
  700. @request_dict serial_number: 序列号
  701. @return: response
  702. """
  703. serial_number = request_dict.get('serial_number', None)
  704. if not serial_number:
  705. return response(444)
  706. try:
  707. serial_number = serial_number[:6]
  708. DeviceDomainRegionModel.objects.filter(serial_number=serial_number).update(region_id=0)
  709. return response.json(0)
  710. except Exception as e:
  711. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  712. @staticmethod
  713. def get_uid_region(request_dict, response):
  714. """
  715. 根据序列号获取uid地区
  716. @param request_dict: 请求参数
  717. @param response: 响应对象
  718. @request_dict serial_number: 序列号
  719. @return: response
  720. """
  721. serial_number = request_dict.get('serial_number', None)
  722. if not serial_number:
  723. return response(444)
  724. try:
  725. serial_number = serial_number[:6]
  726. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(
  727. company_serial__serial_number=serial_number).values('uid__uid')
  728. res = []
  729. for item in uid_company_serial_qs:
  730. res.append({'uid': item['uid__uid']})
  731. return response.json(0, res)
  732. except Exception as e:
  733. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  734. @staticmethod
  735. def get_global_uid_region(request_dict, response):
  736. """
  737. 获取序列号在全球服绑定uid的地区
  738. @param request_dict: 请求参数
  739. @param response: 响应对象
  740. @request_dict serial_number: 序列号
  741. @return: response
  742. """
  743. orders_domain_name_list = SERVER_DOMAIN_LIST
  744. if SERVER_DOMAIN_TEST in orders_domain_name_list:
  745. orders_domain_name_list.remove(SERVER_DOMAIN_TEST)
  746. uid_list = []
  747. try:
  748. for orders_domain_name in orders_domain_name_list:
  749. url = orders_domain_name + 'serialNumber/getUidRegion'
  750. res = requests.post(url=url, data=request_dict)
  751. result = res.json()
  752. if result['result_code'] != 0:
  753. return response.json(result['result_code'])
  754. if orders_domain_name == SERVER_DOMAIN_CN:
  755. for item in result['result']:
  756. item['region'] = 1
  757. uid_list.append(item)
  758. elif orders_domain_name == SERVER_DOMAIN_US:
  759. for item in result['result']:
  760. item['region'] = 3
  761. uid_list.append(item)
  762. elif orders_domain_name == SERVER_DOMAIN_EUR:
  763. for item in result['result']:
  764. item['region'] = 4
  765. uid_list.append(item)
  766. return response.json(0, uid_list)
  767. except Exception as e:
  768. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  769. @classmethod
  770. def get_iot_core_by_serial_number(cls, request_dict, response):
  771. """
  772. 根据序列号查询iot core
  773. """
  774. try:
  775. serial_number = request_dict.get('serialNumber', None)
  776. if not serial_number:
  777. return response.json(444)
  778. serial = serial_number[0:6]
  779. LOGGER.info('根据序列号查询IoTC:{}'.format(serial_number))
  780. device_iot_qs = iotdeviceInfoModel.objects.filter(serial_number=serial)
  781. if not device_iot_qs.exists():
  782. return response.json(173)
  783. iot_vo = device_iot_qs.first()
  784. iot_dto = {
  785. 'serial_number': iot_vo.serial_number,
  786. 'uid': iot_vo.uid,
  787. 'certificate_id': iot_vo.certificate_id,
  788. 'certificate_pem': iot_vo.certificate_pem,
  789. 'public_key': iot_vo.public_key,
  790. 'private_key': iot_vo.private_key,
  791. 'thing_name': iot_vo.thing_name,
  792. 'thing_groups': iot_vo.thing_groups,
  793. 'endpoint': iot_vo.endpoint,
  794. 'token_iot_number': iot_vo.token_iot_number,
  795. 'add_time': iot_vo.add_time.strftime("%Y-%m-%d %H:%M:%S"),
  796. 'update_time': iot_vo.update_time.strftime("%Y-%m-%d %H:%M:%S")
  797. }
  798. return response.json(0, {'iotInfo': iot_dto})
  799. except Exception as e:
  800. LOGGER.info('查询序列号异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  801. return response.json(176, str(e))
  802. @staticmethod
  803. def sync_iot_core_data(serial_number):
  804. """
  805. 同步iot core 数据,目前只同步美服到欧服
  806. @param serial_number: 序列号
  807. """
  808. try:
  809. if not CONFIG_INFO == 'eur':
  810. return False
  811. response = requests.get("https://www.dvema.com/serialNumber/getIoTCoreBySerialNumber",
  812. params={'serialNumber': serial_number}, timeout=3)
  813. if response.status_code != 200:
  814. return False
  815. results = json.loads(response.text)
  816. if results['result_code'] != 0:
  817. return False
  818. iot_vo = results['result']['iotInfo']
  819. iot_vo['add_time'] = datetime.strptime(iot_vo['add_time'], "%Y-%m-%d %H:%M:%S")
  820. iot_vo['update_time'] = datetime.strptime(iot_vo['update_time'], "%Y-%m-%d %H:%M:%S")
  821. iotdeviceInfoModel.objects.create(**iot_vo)
  822. return True
  823. except Exception as e:
  824. LOGGER.info('{}同步iot异常,errLine:{}, errMsg:{}'.format(serial_number, e.__traceback__.tb_lineno, repr(e)))
  825. return False
  826. @staticmethod
  827. def is_4g_device(serial_number, request_dict, request):
  828. """
  829. 判断是否4G设备
  830. """
  831. try:
  832. serial_no = serial_number[0:9]
  833. key = f'ASJ:UNICOM:CARD:ACTIVATE:{serial_no}'
  834. redis = RedisObject()
  835. if redis.get_data(key):
  836. return True
  837. # 根据序列号查询联通iccid
  838. unicom_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no, status=1, card_type=0) \
  839. .values('iccid', 'status')
  840. if not unicom_qs.exists():
  841. return False
  842. unicom_qs = unicom_qs.first()
  843. unicom_api = UnicomObjeect()
  844. unicom_api.change_device_to_activate(unicom_qs['iccid'])
  845. redis.CONN.setnx(key, str(unicom_qs['iccid']))
  846. redis.CONN.expire(key, 7200) # 已调用过激活两个小时内不可调用
  847. ip = CommonService.get_ip_address(request)
  848. describe = '{}获取uid请求激活4G卡,{}'.format(serial_no, unicom_qs['iccid'])
  849. UnicomComboView().create_operation_log('serialNumber/get-uid', ip, request_dict, describe)
  850. return True
  851. except Exception as e:
  852. LOGGER.info('{}判断是否4G设备异常,errLine:{}, errMsg:{}'.format(serial_number, e.__traceback__.tb_lineno, repr(e)))
  853. return False