SerialNumberController.py 20 KB

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