DeviceDataController.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : UserDataController.py
  4. @Time : 2022/8/16 10:44
  5. @Author : peng
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import datetime
  10. import requests
  11. from django.db.models import Count, Q
  12. from django.views.generic.base import View
  13. from Model.models import Device_Info, CountryModel, UidSetModel, DeviceTypeModel, VideoPlaybackTimeModel
  14. from Service.CommonService import CommonService
  15. # 设备数据
  16. class DeviceDataView(View):
  17. def get(self, request, *args, **kwargs):
  18. request.encoding = 'utf-8'
  19. operation = kwargs.get('operation')
  20. return self.validation(request.GET, request, operation)
  21. def post(self, request, *args, **kwargs):
  22. request.encoding = 'utf-8'
  23. operation = kwargs.get('operation')
  24. return self.validation(request.POST, request, operation)
  25. def validation(self, request_dict, request, operation):
  26. token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
  27. if token_code != 0:
  28. return response.json(token_code)
  29. if operation == 'type': # 统计设备类型
  30. return self.type_statistics(response)
  31. if operation == 'regional': # 设备地区分布
  32. return self.regional_statistics(response)
  33. if operation == 'addDevice': # 查询设备增长数据(数据有些许差异)
  34. return self.add_device(request_dict, response)
  35. if operation == 'active': # 设备活跃数据
  36. return self.device_active(request_dict, response)
  37. if operation == 'global/regional': # 全球设备分布
  38. return self.global_regional(request, request_dict, response)
  39. if operation == 'global/type': # 全球设备类型
  40. return self.golbal_type(request, request_dict, response)
  41. if operation == 'global/active': # 全球设备活跃分布
  42. return self.golbal_active(request, request_dict, response)
  43. if operation == 'global/addDevice': # 全球新增设备数据
  44. return self.golbal_add_device(request, request_dict, response)
  45. # if operation == 'ip/country': #
  46. # return self.ip_country(response)
  47. # else:
  48. # return response.json(414)
  49. #
  50. # @staticmethod
  51. # def ip_country(response):
  52. # uid_set_qs = UidSetModel.objects.filter(~Q(ip='') & Q(tb_country=0)).values('ip')
  53. # for uid_set in uid_set_qs:
  54. # ip = uid_set['ip']
  55. # ipInfo = CommonService.getIpIpInfo(ip, 'CN')
  56. # country_qs = CountryModel.objects.filter(country_code=ipInfo['country_code']).values('id')
  57. # if country_qs.exists():
  58. # country = country_qs[0]['id']
  59. # uid_set_qs.filter(ip=ip).update(tb_country=country)
  60. # return response.json(0)
  61. @classmethod
  62. def golbal_add_device(cls, request, request_dict, response):
  63. """
  64. 全球新增设备数据
  65. @param request:请求
  66. @param request_dict:请求参数
  67. @param response: 响应对象
  68. """
  69. url_list = CommonService.get_domain_name()
  70. try:
  71. headers = {
  72. 'Authorization': request.META.get('HTTP_AUTHORIZATION')
  73. }
  74. device_list = []
  75. device_count = 0
  76. type_list = []
  77. type_count = 0
  78. region_list = []
  79. region_count = 0
  80. order_list = []
  81. order_count = 0
  82. for url in url_list:
  83. url = url + request.path.replace('global/', '')
  84. res = requests.get(url=url, params=request_dict, headers=headers)
  85. result = res.json()
  86. if result['result_code'] == 0:
  87. for item in result['result']['addDevice']:
  88. flag = 0
  89. for each in device_list:
  90. if item['startTime'] == each['startTime'] and item['endTime'] == each['endTime']:
  91. each['count'] += item['count']
  92. device_count += item['count']
  93. flag = 1
  94. break
  95. if flag == 0:
  96. device_list.append(item)
  97. device_count += item['count']
  98. for item in device_list:
  99. item['rate'] = round(item['count'] / device_count * 100, 2)
  100. for item in result['result']['region']:
  101. flag = 0
  102. for each in region_list:
  103. if item['countryName'] == each['countryName']:
  104. each['count'] += item['count']
  105. region_count += item['count']
  106. flag = 1
  107. break
  108. if flag == 0:
  109. region_list.append(item)
  110. region_count += item['count']
  111. for item in region_list:
  112. item['rate'] = round(item['count'] / region_count * 100, 2)
  113. for item in result['result']['type']:
  114. flag = 0
  115. for each in type_list:
  116. if item['type'] == each['type']:
  117. each['count'] += item['count']
  118. type_count += item['count']
  119. flag = 1
  120. break
  121. if flag == 0:
  122. type_list.append(item)
  123. type_count += item['count']
  124. for item in type_list:
  125. item['rate'] = round(item['count'] / type_count * 100, 2)
  126. for item in result['result']['version']:
  127. flag = 0
  128. for each in order_list:
  129. if item['type'] == each['type']:
  130. each['count'] += item['count']
  131. order_count += item['count']
  132. flag = 1
  133. break
  134. if flag == 0:
  135. order_list.append(item)
  136. order_count += item['count']
  137. for item in order_list:
  138. item['rate'] = round(item['count'] / order_count * 100, 2)
  139. else:
  140. return response.json(result['result_code'])
  141. res = {
  142. 'device': device_list,
  143. 'type': type_list,
  144. 'region': CommonService.list_sort(region_list),
  145. 'version': order_list
  146. }
  147. return response.json(0, res)
  148. except Exception as e:
  149. print(e)
  150. return response.json(500, repr(e))
  151. @classmethod
  152. def golbal_active(cls, request, request_dict, response):
  153. """
  154. 全球设备活跃分布
  155. @param request:请求
  156. @param request_dict:请求参数
  157. @param response: 响应对象
  158. """
  159. url_list = CommonService.get_domain_name()
  160. try:
  161. headers = {
  162. 'Authorization': request.META.get('HTTP_AUTHORIZATION')
  163. }
  164. type_list = []
  165. type_count = 0
  166. region_list = []
  167. region_count = 0
  168. for url in url_list:
  169. url = url + request.path.replace('global/', '')
  170. res = requests.get(url=url, params=request_dict, headers=headers)
  171. result = res.json()
  172. if result['result_code'] == 0:
  173. for item in result['result']['vodHls']:
  174. flag = 0
  175. for each in type_list:
  176. if item['startTime'] == each['startTime'] and item['endTime'] == each['endTime']:
  177. each['count'] += item['count']
  178. type_count += item['count']
  179. flag = 1
  180. break
  181. if flag == 0:
  182. type_list.append(item)
  183. type_count += item['count']
  184. for item in type_list:
  185. item['rate'] = round(item['count'] / type_count * 100, 2)
  186. for item in result['result']['region']:
  187. flag = 0
  188. for each in region_list:
  189. if item['countryName'] == each['countryName']:
  190. each['count'] += item['count']
  191. region_count += item['count']
  192. flag = 1
  193. break
  194. if flag == 0:
  195. region_list.append(item)
  196. region_count += item['count']
  197. for item in region_list:
  198. item['rate'] = round(item['count'] / region_count * 100, 2)
  199. else:
  200. return response.json(result['result_code'])
  201. res = {
  202. 'device': type_list,
  203. 'region': CommonService.list_sort(region_list)
  204. }
  205. return response.json(0, res)
  206. except Exception as e:
  207. print(e)
  208. return response.json(500, repr(e))
  209. @classmethod
  210. def golbal_type(cls, request, request_dict, response):
  211. """
  212. 全球设备类型分布
  213. @param request:请求
  214. @param request_dict:请求参数
  215. @param response: 响应对象
  216. """
  217. url_list = CommonService.get_domain_name()
  218. try:
  219. headers = {
  220. 'Authorization': request.META.get('HTTP_AUTHORIZATION')
  221. }
  222. type_list = []
  223. type_count = 0
  224. for url in url_list:
  225. url = url + request.path.replace('global/', '')
  226. res = requests.get(url=url, params=request_dict, headers=headers)
  227. result = res.json()
  228. if result['result_code'] == 0:
  229. for item in result['result']['type']:
  230. flag = 0
  231. for each in type_list:
  232. if item['type'] == each['type']:
  233. each['count'] += item['count']
  234. type_count += item['count']
  235. flag = 1
  236. break
  237. if flag == 0:
  238. type_list.append(item)
  239. type_count += item['count']
  240. for item in type_list:
  241. item['rate'] = round(item['count'] / type_count * 100, 2)
  242. else:
  243. return response.json(result['result_code'])
  244. res = {
  245. 'type': CommonService.list_sort(type_list)
  246. }
  247. return response.json(0, res)
  248. except Exception as e:
  249. print(e)
  250. return response.json(500)
  251. @classmethod
  252. def global_regional(cls, request, request_dict, response):
  253. """
  254. 全球设备分布
  255. @param request:请求
  256. @param request_dict:请求参数
  257. @param response:响应对象
  258. @return:
  259. """
  260. url_list = CommonService.get_domain_name()
  261. try:
  262. headers = {
  263. 'Authorization': request.META.get('HTTP_AUTHORIZATION')
  264. }
  265. device_list = []
  266. device_count = 0
  267. region_list = []
  268. region_count = 0
  269. for url in url_list:
  270. url = url + request.path.replace('global/', '')
  271. res = requests.get(url=url, params=request_dict, headers=headers)
  272. result = res.json()
  273. if result['result_code'] == 0:
  274. # 处理地区
  275. for item in result['result']['countries']:
  276. flag = 0
  277. for each in device_list:
  278. if each['countryName'] == item['countryName']:
  279. each['count'] += int(item['count'])
  280. device_count += int(item['count'])
  281. flag = 1
  282. break
  283. if flag == 0:
  284. device_list.append(item)
  285. device_count += int(item['count'])
  286. for item in device_list:
  287. rate = round(item['count'] / device_count * 100, 2)
  288. item['rate'] = rate
  289. for item in result['result']['continent']:
  290. flag = 0
  291. for each in region_list:
  292. if each['continentName'] == item['continentName']:
  293. each['count'] += item['count']
  294. region_count += item['count']
  295. flag = 1
  296. break
  297. if flag == 0:
  298. region_list.append(item)
  299. region_count += item['count']
  300. for item in region_list:
  301. item['rate'] = round(item['count'] / region_count * 100, 2)
  302. else:
  303. return response.json(result['result_code'])
  304. res = {
  305. 'countries': CommonService.list_sort(device_list[:20]),
  306. 'continent': region_list
  307. }
  308. return response.json(0, res)
  309. except Exception as e:
  310. return response.json(500, repr(e))
  311. @classmethod
  312. def device_active(cls, request_dict, response):
  313. """
  314. 设备活跃数据
  315. @param request_dict:请求参数
  316. @request_dict starTime:开始时间
  317. @request_dict endTime:结束时间
  318. @param response:响应对象
  319. """
  320. start_time = request_dict.get('startTime', None) # 时间戳
  321. end_time = request_dict.get('endTime', None)
  322. unit_time = request_dict.get('timeUnit', None)
  323. if not all([start_time, end_time, unit_time]):
  324. return response.json(444, {'error param': 'startTime or endTime or timeUnit'})
  325. s_time = datetime.datetime.fromtimestamp(int(start_time))
  326. e_time = datetime.datetime.fromtimestamp(int(end_time))
  327. time_list = CommonService.cutting_time(s_time, e_time, unit_time)
  328. try:
  329. video_playback_time_qs = VideoPlaybackTimeModel.objects.filter(startTime__range=(start_time, end_time))
  330. null_list = []
  331. if not video_playback_time_qs.exists():
  332. return response.json(0, null_list)
  333. video_playback_uid_qs = video_playback_time_qs.values('uid').order_by('uid').distinct()
  334. res = {}
  335. video_list = []
  336. region_list = []
  337. for item in time_list:
  338. video_playback_qs = video_playback_time_qs.filter(startTime__range=(item[0], item[1]))
  339. uid_qs = video_playback_qs.values('uid').order_by('uid').distinct()
  340. rate = round(uid_qs.count() / video_playback_uid_qs.count() * 100, 2)
  341. vod_dict = {
  342. 'count': uid_qs.count(),
  343. 'rate': rate,
  344. 'startTime': item[0],
  345. 'endTime': item[1]
  346. }
  347. video_list.append(vod_dict)
  348. res['vodHls'] = video_list
  349. type_country_qs = UidSetModel.objects.filter(uid__in=video_playback_uid_qs.values('uid')).values(
  350. 'tb_country').annotate(count=Count('tb_country')).order_by('-count')
  351. for type_country in type_country_qs:
  352. country_id = type_country['tb_country']
  353. country_name_qs = CountryModel.objects.filter(id=country_id).values('country_name')
  354. country_name = country_name_qs[0]['country_name'] if country_name_qs.exists() else '未知区域'
  355. rate = round(type_country['count'] / video_playback_uid_qs.count() * 100, 2)
  356. country_dict = {
  357. 'countryName': country_name,
  358. 'count': type_country['count'],
  359. 'rate': rate
  360. }
  361. region_list.append(country_dict)
  362. res['region'] = region_list
  363. return response.json(0, res)
  364. except Exception as e:
  365. print(e)
  366. return response.json(500)
  367. @classmethod
  368. def add_device(cls, request_dict, response):
  369. """
  370. 查询设备增长数据
  371. @param request_dict:请求参数
  372. @request_dict starTime:开始时间
  373. @request_dict endTime:结束时间
  374. @param response:响应对象
  375. """
  376. start_time = request_dict.get('startTime', None) # 时间戳
  377. end_time = request_dict.get('endTime', None)
  378. unit_time = request_dict.get('timeUnit', None)
  379. if not all([start_time, end_time, unit_time]):
  380. return response.json(444, {'error param': 'startTime or endTime or timeUnit'})
  381. try:
  382. uid_set_qs = UidSetModel.objects.filter(addTime__range=(start_time, end_time))
  383. null_list = []
  384. if not uid_set_qs.exists():
  385. return response.json(0, null_list)
  386. uid_qs = uid_set_qs.values('uid')
  387. count_all = uid_set_qs.count()
  388. # 统计该时间段的设备数量(已去重)
  389. res = {
  390. 'addDevice': '',
  391. 'region': '',
  392. 'type': '',
  393. 'version': '',
  394. }
  395. info_list = []
  396. region_list = []
  397. type_list = []
  398. version_list = []
  399. start_time = datetime.datetime.fromtimestamp(int(start_time))
  400. end_time = datetime.datetime.fromtimestamp(int(end_time))
  401. time_list = CommonService.cutting_time(start_time, end_time, unit_time)
  402. for item in time_list:
  403. deivce_uid_qs = uid_set_qs.filter(addTime__range=(item[0], item[1]))
  404. count_part = deivce_uid_qs.count()
  405. rate = round(count_part / count_all * 100, 2)
  406. info_dict = {
  407. 'startTime': item[0],
  408. 'endTime': item[1],
  409. 'count': count_part,
  410. 'rate': rate
  411. }
  412. info_list.append(info_dict)
  413. # 统计地区设备数量
  414. device_info_country_qs = uid_set_qs.values('tb_country').annotate(
  415. count=Count('tb_country')).order_by(
  416. '-count')
  417. for item in device_info_country_qs:
  418. country_id = item['tb_country']
  419. country_qs = CountryModel.objects.filter(id=country_id).values('country_name', 'id')
  420. country_name = country_qs[0]['country_name'] if country_qs.exists() else '未知区域'
  421. country_qs = uid_set_qs.values('tb_country')
  422. total_list = [item[key] for item in country_qs for key in item]
  423. country_count = total_list.count(country_id)
  424. rate = round(country_count / count_all * 100, 2)
  425. country_dict = {
  426. 'countryName': country_name,
  427. 'count': country_count,
  428. 'rate': rate
  429. }
  430. region_list.append(country_dict)
  431. # 统计设备类型数量
  432. device_info_type_qs = Device_Info.objects.filter(UID__in=uid_qs.values('uid'))
  433. device_type_qs = device_info_type_qs.values('Type').annotate(
  434. count=Count('Type', distinct=True)).order_by('-count').distinct()
  435. name = '未知类型'
  436. count_remain = count_all - device_info_type_qs.count()
  437. rate = round(count_remain / count_all * 100, 2)
  438. type_list.append({
  439. 'type': name,
  440. 'count': count_remain,
  441. 'rate': rate
  442. })
  443. for device_type in device_type_qs:
  444. Type = device_type['Type']
  445. device_type_name_qs = DeviceTypeModel.objects.filter(type=Type).values('name')
  446. name = device_type_name_qs[0]['name'] if device_type_name_qs.exists() else '未知类型'
  447. type_qs = device_info_type_qs.values('Type')
  448. test_list = [item[key] for item in type_qs for key in item]
  449. type_count = test_list.count(Type)
  450. rate = round(type_count / count_all * 100, 2)
  451. type_list.append({
  452. 'type': name,
  453. 'count': type_count,
  454. 'rate': rate
  455. })
  456. # 云存版本数量
  457. uid_cloud_qs = uid_set_qs.exclude(cloud_vod=2).values('uid')
  458. device_info_type_qs = Device_Info.objects.filter(UID__in=uid_cloud_qs.values('uid')).distinct()
  459. cloud_type_qs = device_info_type_qs.values('Type').annotate(
  460. count=Count('Type', distinct=True)).order_by('-count').distinct()
  461. type_qs = device_info_type_qs.values('Type')
  462. test_list = [item[key] for item in type_qs for key in item]
  463. count = uid_cloud_qs.count() - device_info_type_qs.count()
  464. name = '未知类型'
  465. rate = round(count / count_all * 100, 2)
  466. version_list.append({
  467. 'type': name,
  468. 'count': count,
  469. 'rate': rate
  470. })
  471. for cloud_type in cloud_type_qs:
  472. Type = cloud_type['Type']
  473. device_type_qs = DeviceTypeModel.objects.filter(type=Type).values('name')
  474. name = device_type_qs[0]['name'] if device_type_qs.exists() else '未知类型'
  475. type_count = test_list.count(Type)
  476. rate = round(type_count / count_all * 100, 2)
  477. version_list.append({
  478. 'type': name,
  479. 'count': type_count,
  480. 'rate': rate
  481. })
  482. res['addDevice'] = info_list
  483. res['region'] = CommonService.list_sort(region_list)
  484. res['type'] = CommonService.list_sort(type_list)
  485. res['version'] = CommonService.list_sort(version_list)
  486. return response.json(0, res)
  487. except Exception as e:
  488. print(e)
  489. return response.json(500, repr(e))
  490. @classmethod
  491. def regional_statistics(cls, response):
  492. """
  493. 统计地区设备数量
  494. @param response:响应对象
  495. """
  496. uid_set_qs = UidSetModel.objects.all()
  497. if not uid_set_qs.exists():
  498. return response.json(444)
  499. tb_country_qs = uid_set_qs.values('tb_country').annotate(
  500. count=Count('tb_country')).order_by('-count')
  501. res = {}
  502. try:
  503. device_country_list = []
  504. continent_list = []
  505. for device_country in tb_country_qs:
  506. country_id = device_country['tb_country']
  507. country_qs = CountryModel.objects.filter(id=country_id).values('country_name', 'region__name')
  508. if country_qs.exists():
  509. name = country_qs[0]['country_name']
  510. else:
  511. name = '未知地区'
  512. count = uid_set_qs.filter(
  513. tb_country=device_country['tb_country']).values('uid').annotate(
  514. count=Count('uid', distinct=True)).order_by('-count').count()
  515. device_country_list.append({
  516. 'countryName': name,
  517. 'count': count
  518. })
  519. if country_qs.exists():
  520. flag = 0
  521. for each in continent_list:
  522. if country_qs[0]['region__name'] == each['continentName']:
  523. each['count'] += count
  524. flag = 1
  525. break
  526. if flag == 0:
  527. continent_list.append({
  528. 'continentName': country_qs[0]['region__name'],
  529. 'count': count
  530. })
  531. for item in continent_list:
  532. item['rate'] = round(item['count'] / uid_set_qs.count() * 100, 2)
  533. res['countries'] = CommonService.list_sort(device_country_list)
  534. res['continent'] = CommonService.list_sort(continent_list)
  535. return response.json(0, res)
  536. except Exception as e:
  537. print(e)
  538. return response.json(500)
  539. @classmethod
  540. def type_statistics(cls, response):
  541. """
  542. 统计设备类型
  543. @param response:响应对象
  544. @return:
  545. """
  546. uid_set_qs = UidSetModel.objects.values('uid').order_by('uid')
  547. count_all = uid_set_qs.count()
  548. device_info_qs = Device_Info.objects.filter(UID__in=uid_set_qs.values('uid'))
  549. device_info_count = device_info_qs.count()
  550. device_info_type_qs = device_info_qs.values('Type').annotate(count=Count('Type')).order_by('-count')
  551. # 查询不到(类型)的设备数量
  552. if not device_info_qs.exists():
  553. return response.json(444)
  554. res = {}
  555. try:
  556. device_info_list = []
  557. count = count_all - device_info_count
  558. name = '未知类型'
  559. rate = round(count / count_all * 100, 2)
  560. device_info_list.append({
  561. 'type': name,
  562. 'count': count,
  563. 'rate': rate
  564. })
  565. for device_info in device_info_type_qs:
  566. Type = device_info['Type']
  567. device_type_qs = DeviceTypeModel.objects.filter(type=Type).values('name')
  568. name = device_type_qs[0]['name'] if device_type_qs.exists() else '未知类型'
  569. count = device_info['count']
  570. rate = round(count / count_all * 100, 2)
  571. device_info_list.append({
  572. 'type': name,
  573. 'count': count,
  574. 'rate': rate
  575. })
  576. res['type'] = device_info_list
  577. return response.json(0, res)
  578. except Exception as e:
  579. print(e)
  580. return response.json(500)