SerialNumberController.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. import json
  2. import logging
  3. import time
  4. import requests
  5. from django.db import transaction
  6. from django.views import View
  7. from Ansjer.config import CRCKey, CONFIG_INFO, CONFIG_TEST, CONFIG_US, \
  8. CONFIG_CN, USED_SERIAL_REDIS_LIST, UNUSED_SERIAL_REDIS_LIST, SERVER_DOMAIN_US, REGION_ID_LIST
  9. from Model.models import SerialNumberModel, CompanySerialModel, UIDCompanySerialModel, UIDModel, Device_Info, \
  10. iotdeviceInfoModel, LogModel, UidSetModel, UID_Bucket, \
  11. Unused_Uid_Meal, Order_Model, StsCrdModel, VodHlsModel, ExperienceContextModel, UidUserModel, ExperienceAiModel, \
  12. AiService, DeviceDomainRegionModel, RegionModel
  13. from Object.RedisObject import RedisObject
  14. from Object.TokenObject import TokenObject
  15. from Object.uidManageResponseObject import uidManageResponseObject
  16. from Service.AlgorithmService import AlgorithmBaseOn35
  17. from Service.CommonService import CommonService
  18. from Service.EquipmentInfoService import EquipmentInfoService
  19. class SerialNumberView(View):
  20. def get(self, request, *args, **kwargs):
  21. request.encoding = 'utf-8'
  22. operation = kwargs.get('operation', None)
  23. request_dict = request.GET
  24. return self.validate(request_dict, operation, request)
  25. def post(self, request, *args, **kwargs):
  26. request.encoding = 'utf-8'
  27. operation = kwargs.get('operation', None)
  28. request_dict = request.POST
  29. return self.validate(request_dict, operation, request)
  30. def validate(self, request_dict, operation, request):
  31. response = uidManageResponseObject()
  32. if operation == 'attachUID': # 绑定uid
  33. return self.do_attach_uid(request_dict, response, request)
  34. elif operation == 'detachUID': # 解绑uid
  35. return self.do_detach_uid(request, request_dict, response)
  36. elif operation == 'create': # 创建序列号
  37. return self.do_create(request_dict, response)
  38. elif operation == 'getUID': # 根据序列号获取uid
  39. return self.do_get_uid(request_dict, response)
  40. elif operation == 'getRegionInfo': # 根据序列号状态确认uid地区(PC工具使用)
  41. return self.get_region_info(request_dict, response)
  42. elif operation == 'saveRegion': # 保存设备地区信息(app使用)
  43. return self.save_region(request, request_dict, response)
  44. elif operation == 'getDomain': # 获取域名(设备使用)
  45. return self.get_domain(request_dict, response)
  46. elif operation == 'resetRegionId': # 重置地区id
  47. return self.reset_region_id(request_dict, response)
  48. else:
  49. return response.json(414)
  50. @staticmethod
  51. def do_create(request_dict, response):
  52. quantity = int(request_dict.get('quantity', 0))
  53. if not quantity:
  54. return response.json(444)
  55. try:
  56. try:
  57. number = SerialNumberModel.objects.last().id
  58. except:
  59. number = 0
  60. serial_number_bulk = []
  61. now_time = int(time.time())
  62. algorithm = AlgorithmBaseOn35()
  63. for i in range(quantity):
  64. serial_number = algorithm.getLetter(number)
  65. number += 1 # sum每次递增1
  66. # 前面补0至六位
  67. serial_number = (6 - len(serial_number)) * '0' + serial_number
  68. serial_number_bulk.append(SerialNumberModel(serial_number=serial_number, add_time=now_time))
  69. # 开启事务写入
  70. with transaction.atomic():
  71. SerialNumberModel.objects.bulk_create(serial_number_bulk)
  72. return response.json(0)
  73. except Exception as e:
  74. print(e)
  75. return response.json(500, repr(e))
  76. def do_attach_uid(self, request_dict, response, request):
  77. serial_number = request_dict.get('serial_number', None)
  78. token = request_dict.get('token', None)
  79. time_stamp = request_dict.get('time_stamp', None)
  80. if not all([serial_number, token, time_stamp]):
  81. return response.json(444)
  82. # 时间戳token校验
  83. if not CommonService.check_time_stamp_token(token, time_stamp):
  84. return response.json(13)
  85. now_time = int(time.time())
  86. serial = serial_number[0:6]
  87. company_identity = serial_number[6:9]
  88. full_serial = serial_number[0:9]
  89. # 根据企业标识确认企业秘钥
  90. company_secret = ''
  91. if company_identity == '11A':
  92. company_secret = 'MTEyMTNB'
  93. elif company_identity == '11L':
  94. company_secret = 'VmXEWnBR'
  95. elif company_identity == '11Z':
  96. company_secret = 'ZsKWcxdD'
  97. try:
  98. # 判断序列号是否已和企业关联
  99. company_serial_qs = CompanySerialModel.objects.filter(company__secret=company_secret, serial_number=serial)
  100. if not company_serial_qs.exists():
  101. return response.json(173)
  102. company_serial = company_serial_qs[0]
  103. if company_serial.status == 0: # 该序列号未绑定企业
  104. return response.json(173)
  105. elif company_serial.status == 1: # 绑定uid
  106. # redis加锁,防止同一个序列号重复绑定
  107. key = serial + 'do_attach_uid'
  108. redisObj = RedisObject()
  109. isLock = redisObj.CONN.setnx(key, 1)
  110. redisObj.CONN.expire(key, 60)
  111. if not isLock:
  112. return response.json(5)
  113. # 获取并判断region_id
  114. region_id = CommonService.confirm_region_id()
  115. if region_id not in REGION_ID_LIST:
  116. return response.json(444, {'invalid region_id': region_id})
  117. p2p_type = request_dict.get('p2ptype', 1)
  118. if serial_number[9:10]:
  119. p2p_type = serial_number[9:10]
  120. p2p_type = int(p2p_type)
  121. with transaction.atomic():
  122. count = 0
  123. while count < 3:
  124. # 查询是否存在未绑定序列号的uid
  125. uid_qs = UIDModel.objects.filter(vpg__company_id=company_serial.company.id,
  126. vpg__region_id=region_id, status=0, p2p_type=p2p_type). \
  127. order_by('id')
  128. if not uid_qs.exists():
  129. return response.json(375)
  130. uid = uid_qs[0]
  131. # 判断uid是否已绑定过序列号
  132. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(uid_id=uid.id)
  133. if uid_company_serial_qs.exists():
  134. return response.json(377)
  135. result = UIDModel.objects.filter(id=uid.id, status=0).update(status=2, update_time=now_time)
  136. if int(result) <= 0: # 更新失败
  137. count += 1
  138. continue
  139. # UID关联【企业关联序列号】表创建数据
  140. UIDCompanySerialModel.objects.create(uid_id=uid.id, company_serial_id=company_serial.id,
  141. add_time=now_time, update_time=now_time)
  142. company_serial.status = 2
  143. company_serial.save()
  144. dev = Device_Info.objects.filter(UID=uid.uid)
  145. if dev.exists():
  146. dev.update(serial_number=full_serial)
  147. full_uid_code = uid.full_uid_code
  148. if uid.platform in CRCKey.keys():
  149. full_uid_code += ':' + CRCKey[uid.platform]
  150. res = {
  151. 'full_uid_code': CommonService.encode_data(full_uid_code),
  152. 'uid': CommonService.encode_data(uid.uid),
  153. 'extra': uid.uid_extra,
  154. 'platform': uid.platform,
  155. 'initString': uid.init_string,
  156. 'initStringApp': uid.init_string_app,
  157. }
  158. # 记录操作日志
  159. ip = CommonService.get_ip_address(request)
  160. content = json.loads(json.dumps(request_dict))
  161. log = {
  162. 'ip': ip,
  163. 'user_id': 1,
  164. 'status': 200,
  165. 'time': now_time,
  166. 'content': json.dumps(content),
  167. 'url': 'serialNumber/attachUID',
  168. 'operation': '序列号{}绑定uid: {}'.format(serial, uid.uid),
  169. }
  170. LogModel.objects.create(**log)
  171. if CONFIG_INFO != CONFIG_TEST: # 不为测试服,则序列号写入redis列表
  172. redisObj.rpush(USED_SERIAL_REDIS_LIST, serial)
  173. redisObj.del_data(key=key)
  174. return response.json(0, res)
  175. return response.json(5)
  176. elif company_serial.status == 2: # 返回uid
  177. uid_qs = UIDCompanySerialModel.objects.filter(company_serial_id=company_serial.id)
  178. if not uid_qs.exists():
  179. return response.json(173)
  180. uid = uid_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra', 'uid__full_uid_code',
  181. 'uid__platform', 'uid__init_string', 'uid__init_string_app')[0]
  182. full_uid_code = uid['uid__full_uid_code']
  183. if uid['uid__platform'] in CRCKey.keys():
  184. full_uid_code += ':' + CRCKey[uid['uid__platform']]
  185. res = {
  186. 'full_uid_code': CommonService.encode_data(full_uid_code),
  187. 'uid': CommonService.encode_data(uid['uid__uid']),
  188. 'extra': uid['uid__uid_extra'],
  189. 'platform': uid['uid__platform'],
  190. 'initString': uid['uid__init_string'],
  191. 'initStringApp': uid['uid__init_string_app'],
  192. }
  193. return response.json(0, res)
  194. elif company_serial.status == 3:
  195. return response.json(10042)
  196. except Exception as e:
  197. djangoLogger = logging.getLogger('django')
  198. djangoLogger.exception(repr(e))
  199. return response.json(176, str(e))
  200. def do_get_uid(self, request_dict, response):
  201. serial_number = request_dict.get('serial_number', None)
  202. token = request_dict.get('token', None)
  203. time_stamp = request_dict.get('time_stamp', None)
  204. if token and time_stamp and serial_number:
  205. # 时间戳token校验
  206. if not CommonService.check_time_stamp_token(token, time_stamp):
  207. return response.json(13)
  208. mark = serial_number[6:9]
  209. serial = serial_number[0:6]
  210. uid_company_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__company__mark=mark,
  211. company_serial__serial_number__serial_number=serial)
  212. if uid_company_serial_qs.exists():
  213. uid = uid_company_serial_qs.values('uid__uid', 'uid__mac', 'uid__uid_extra')[0]
  214. res = {
  215. 'uid': CommonService.encode_data(uid['uid__uid']),
  216. 'mac': CommonService.encode_data(uid['uid__mac']),
  217. 'extra': uid['uid__uid_extra']
  218. }
  219. return response.json(0, res)
  220. else:
  221. return response.json(173)
  222. else:
  223. return response.json(444)
  224. def do_detach_uid(self, request, request_dict, response):
  225. token = request_dict.get('token', None)
  226. time_stamp = request_dict.get('time_stamp', None)
  227. serial_number = request_dict.get('serial_number', None)
  228. if not all([token, time_stamp, serial_number]):
  229. return response.json(444)
  230. # 时间戳token校验
  231. if not CommonService.check_time_stamp_token(token, time_stamp):
  232. return response.json(13)
  233. now_time = int(time.time())
  234. serial = serial_number[0:6]
  235. company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial).values('status')
  236. if not company_serial_qs.exists():
  237. return response.json(379)
  238. status = company_serial_qs[0]['status']
  239. if status == 1:
  240. return response.json(0, {'success': '序列号未绑定uid'})
  241. elif status == 3:
  242. return response.json(10043)
  243. uid_serial_qs = UIDCompanySerialModel.objects.filter(company_serial__serial_number=serial)
  244. if not uid_serial_qs.exists():
  245. return response.json(173)
  246. uid_serial = uid_serial_qs[0]
  247. redisObj = RedisObject()
  248. try:
  249. with transaction.atomic():
  250. uid = uid_serial.uid.uid
  251. company_serial_qs.update(status=1) # 更新序列号状态
  252. # 删除设备相关数据,参考后台的设备重置删除的数据
  253. Device_Info.objects.filter(UID=uid).delete()
  254. UidSetModel.objects.filter(uid=uid).delete()
  255. UidUserModel.objects.filter(UID=uid).delete()
  256. iotdeviceInfoModel.objects.filter(serial_number=serial).delete()
  257. # 删除推送消息
  258. for val in range(1, 8):
  259. EquipmentInfoService.get_equipment_info_model('', val).filter(device_uid=uid).delete()
  260. # 重置设备云存
  261. UID_Bucket.objects.filter(uid=uid).delete()
  262. Unused_Uid_Meal.objects.filter(uid=uid).delete()
  263. Order_Model.objects.filter(UID=uid).delete()
  264. StsCrdModel.objects.filter(uid=uid).delete()
  265. VodHlsModel.objects.filter(uid=uid).delete()
  266. ExperienceContextModel.objects.filter(uid=uid).delete()
  267. # 重置AI
  268. ExperienceAiModel.objects.filter(uid=uid).delete()
  269. AiService.objects.filter(uid=uid).delete()
  270. if CONFIG_INFO != CONFIG_TEST: # 不为测试服,则序列号写入redis列表
  271. redisObj.rpush(UNUSED_SERIAL_REDIS_LIST, serial)
  272. UIDModel.objects.filter(uid=uid).update(status=0, mac='') # 重置uid的使用状态为未使用
  273. uid_serial.delete()
  274. # 重置region_id
  275. if CONFIG_INFO == CONFIG_US:
  276. DeviceDomainRegionModel.objects.filter(serial_number=serial).update(region_id=0)
  277. else:
  278. try:
  279. url = SERVER_DOMAIN_US + 'serialNumber/resetRegionId'
  280. data = {'serial_number': serial}
  281. r = requests.post(url, data, timeout=3)
  282. assert r.status_code == 200
  283. res = r.json()
  284. assert res['result_code'] == 0
  285. except (TimeoutError, AssertionError):
  286. return response.json(5)
  287. # 记录操作日志
  288. ip = CommonService.get_ip_address(request)
  289. content = json.loads(json.dumps(request_dict))
  290. log = {
  291. 'ip': ip,
  292. 'user_id': 1,
  293. 'status': 200,
  294. 'time': now_time,
  295. 'content': json.dumps(content),
  296. 'url': 'serialNumber/detachUID',
  297. 'operation': '序列号{}解绑uid: {}'.format(serial, uid),
  298. }
  299. LogModel.objects.create(**log)
  300. return response.json(0)
  301. except Exception as e:
  302. djangoLogger = logging.getLogger('django')
  303. djangoLogger.exception(repr(e))
  304. return response.json(176, str(e))
  305. @staticmethod
  306. def get_region_info(request_dict, response):
  307. """
  308. 根据序列号状态确认uid地区
  309. @param request_dict: 请求参数
  310. @param response: 响应对象
  311. @request_dict serial_number: 序列号
  312. @return: response
  313. """
  314. serial_number = request_dict.get('serial_number', None)
  315. if not serial_number:
  316. return response(444)
  317. company_serial_qs = CompanySerialModel.objects.filter(serial_number=serial_number[:6]).values('status')
  318. if not company_serial_qs.exists():
  319. return response.json(173)
  320. status = company_serial_qs[0]['status']
  321. if status == 2:
  322. if CONFIG_INFO == CONFIG_CN:
  323. return response.json(0, {'region': 1})
  324. elif CONFIG_INFO == CONFIG_US:
  325. return response.json(0, {'region': 3})
  326. elif status == 3:
  327. if CONFIG_INFO == CONFIG_CN:
  328. return response.json(0, {'region': 3})
  329. elif CONFIG_INFO == CONFIG_US:
  330. return response.json(0, {'region': 1})
  331. return response.json(0)
  332. @staticmethod
  333. def save_region(request, request_dict, response):
  334. """
  335. 保存设备地区信息
  336. @param request: 请求体
  337. @param request_dict: 请求参数
  338. @param response: 响应对象
  339. @request_dict token: 令牌
  340. @request_dict time_stamp: 时间戳
  341. @return: response
  342. """
  343. token = request_dict.get('token', None)
  344. serial_number = request_dict.get('serial_number', None)
  345. if not all([serial_number, token]):
  346. return response(444)
  347. try:
  348. serial_number = serial_number[:6]
  349. # 不是美洲服,请求美洲域名保存数据
  350. if CONFIG_INFO != CONFIG_US:
  351. # token认证
  352. token_obj = TokenObject(token)
  353. if token_obj.code != 0:
  354. return response.json(token_obj.code)
  355. response.lang = token_obj.lang
  356. url = SERVER_DOMAIN_US + 'serialNumber/saveRegion'
  357. data = request_dict.dict()
  358. data['ip'] = CommonService.get_ip_address(request)
  359. data['region_id'] = CommonService.confirm_region_id()
  360. try:
  361. r = requests.post(url=url, data=data, timeout=3)
  362. assert r.status_code == 200
  363. res = r.json()
  364. assert res['result_code'] == 0
  365. except (TimeoutError, AssertionError):
  366. return response.json(5)
  367. # 美洲服,处理请求和保存数据
  368. else:
  369. data = {}
  370. # 处理其他服务器发起请求的情况
  371. region_id = request_dict.get('region_id', None)
  372. if region_id is not None:
  373. region_id = int(region_id)
  374. data['region_id'] = region_id
  375. data['ip'] = request_dict.get('ip', '')
  376. else:
  377. # token认证
  378. token_obj = TokenObject(token)
  379. if token_obj.code != 0:
  380. return response.json(token_obj.code)
  381. response.lang = token_obj.lang
  382. region_id = CommonService.confirm_region_id()
  383. data['region_id'] = region_id
  384. data['ip'] = CommonService.get_ip_address(request)
  385. # 写入数据
  386. device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number).\
  387. values('region_id')
  388. if not device_domain_region_qs.exists():
  389. data['serial_number'] = serial_number
  390. DeviceDomainRegionModel.objects.create(**data)
  391. else:
  392. # 设备解绑过uid,更新region_id
  393. if device_domain_region_qs[0]['region_id'] == 0:
  394. device_domain_region_qs.update(**data)
  395. return response.json(0)
  396. except Exception as e:
  397. return response.json(500, repr(e))
  398. @staticmethod
  399. def get_domain(request_dict, response):
  400. """
  401. 获取域名
  402. @param request_dict: 请求参数
  403. @param response: 响应对象
  404. @request_dict serial_number: 序列号
  405. @request_dict time_stamp_token: 时间戳token
  406. @request_dict time_stamp: 时间戳
  407. @return: response
  408. """
  409. serial_number = request_dict.get('serial_number', None)
  410. time_stamp_token = request_dict.get('time_stamp_token', None)
  411. time_stamp = request_dict.get('time_stamp', None)
  412. if not all([serial_number, time_stamp_token, time_stamp]):
  413. return response(444)
  414. # 时间戳token校验
  415. if not CommonService.check_time_stamp_token(time_stamp_token, time_stamp):
  416. return response.json(13)
  417. try:
  418. serial_number = serial_number[:6]
  419. device_domain_region_qs = DeviceDomainRegionModel.objects.filter(serial_number=serial_number).values(
  420. 'region_id')
  421. if not device_domain_region_qs.exists():
  422. return response.json(173)
  423. region_id = device_domain_region_qs[0]['region_id']
  424. region_qs = RegionModel.objects.filter(id=region_id).values('api')
  425. res = {
  426. 'api': region_qs[0]['api']
  427. }
  428. return response.json(0, res)
  429. except Exception as e:
  430. return response.json(500, repr(e))
  431. @staticmethod
  432. def reset_region_id(request_dict, response):
  433. """
  434. 重置地区id
  435. @param request_dict: 请求参数
  436. @param response: 响应对象
  437. @request_dict serial_number: 序列号
  438. @return: response
  439. """
  440. serial_number = request_dict.get('serial_number', None)
  441. if not serial_number:
  442. return response(444)
  443. try:
  444. serial_number = serial_number[:6]
  445. DeviceDomainRegionModel.objects.filter(serial_number=serial_number).update(region_id=0)
  446. return response.json(0)
  447. except Exception as e:
  448. return response.json(500, repr(e))