SerialNumberController.py 20 KB

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