KVSController.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Author : Rocky
  4. @Time : 2022/10/18 9:48
  5. @File :KVSController.py
  6. """
  7. import hashlib
  8. import time
  9. import uuid
  10. import datetime
  11. from django.http import HttpResponse, StreamingHttpResponse, FileResponse
  12. from wsgiref.util import FileWrapper
  13. from django.views import View
  14. from Model.models import KVS, Device_User, Device_Info
  15. from Object.AWS.AmazonKinesisVideoUtil import AmazonKinesisVideoObject, AmazonKVAMObject
  16. from Object.RedisObject import RedisObject
  17. from Object.ResponseObject import ResponseObject
  18. from Ansjer.config import ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME, SERVER_DOMAIN
  19. from Object.TokenObject import TokenObject
  20. class UserRelatedView(View):
  21. def get(self, request, *args, **kwargs):
  22. request.encoding = 'utf-8'
  23. operation = kwargs.get('operation')
  24. return self.validation(request.GET, operation, request)
  25. def post(self, request, *args, **kwargs):
  26. request.encoding = 'utf-8'
  27. operation = kwargs.get('operation')
  28. return self.validation(request.POST, operation, request)
  29. def validation(self, request_dict, operation, request):
  30. response = ResponseObject()
  31. if operation == 'generate-qr-code': # 网页生成二维码
  32. return self.generate_qr_code(response)
  33. elif operation == 'web-login': # 网页登录
  34. return self.web_login(request_dict, response)
  35. elif operation == 'confirm-login': # app确认登录
  36. return self.confirm_login(request_dict, response)
  37. else:
  38. tko = TokenObject(
  39. request.META.get('HTTP_AUTHORIZATION'),
  40. returntpye='pc')
  41. if tko.code != 0:
  42. return response.json(tko.code)
  43. response.lang = tko.lang
  44. user_id = tko.userID
  45. if operation == 'get-device': # 获取设备列表
  46. return self.get_device(response, user_id)
  47. else:
  48. return response.json(404)
  49. @staticmethod
  50. def generate_qr_code(response):
  51. """
  52. 网页生成二维码
  53. @param request_dict: 请求参数
  54. @param response: 响应对象
  55. @return: response
  56. """
  57. nwo_time = time.time()
  58. redis_obj = RedisObject()
  59. try:
  60. uuid_number = hashlib.md5((str(uuid.uuid1()) + str(nwo_time)).encode('utf-8')).hexdigest()
  61. flag = redis_obj.set_ex_data(uuid_number, 0, 300)
  62. res = {'type': 'autologin', 'id': uuid_number}
  63. if flag:
  64. return response.json(0, res)
  65. else:
  66. return response.json(119)
  67. except Exception as e:
  68. print(e)
  69. return response.json(500)
  70. @staticmethod
  71. def web_login(request_dict, response):
  72. """
  73. 网页登录
  74. @param request_dict: 请求参数
  75. @request_dict serial_number: 序列号
  76. @param response: 响应对象
  77. @return: response
  78. """
  79. uuid_number = request_dict.get('uuid', None)
  80. if not uuid_number:
  81. return response.json(444, {'error param': 'uuid'})
  82. try:
  83. redis_obj = RedisObject()
  84. status = redis_obj.get_data(uuid_number)
  85. if status == '0':
  86. return response.json(18)
  87. elif status is False:
  88. return response.json(119)
  89. redis_obj.del_data(uuid_number)
  90. tko = TokenObject(status, returntpye='pc')
  91. response.lang = tko.lang
  92. if tko.code != 0:
  93. return response.json(tko.code)
  94. user_id = tko.userID
  95. device_user_qs = Device_User.objects.filter(userID=user_id).values('NickName', 'userIconPath',
  96. 'userIconUrl')
  97. if not device_user_qs.exists():
  98. user_icon_url = ''
  99. nick_name = ''
  100. else:
  101. users = device_user_qs.first()
  102. nick_name = users['NickName']
  103. user_icon_path = str(users['userIconPath'])
  104. if user_icon_path:
  105. user_icon_path = user_icon_path.replace('static/', '').replace('\\', '/')
  106. user_icon_url = SERVER_DOMAIN + 'account/getAvatar/' + user_icon_path
  107. else:
  108. user_icon_url = ''
  109. return response.json(0, {'token': status, 'userIconUrl': user_icon_url, 'nickName': nick_name})
  110. except Exception as e:
  111. print(e)
  112. return response.json(500)
  113. @staticmethod
  114. def confirm_login(request_dict, response):
  115. """
  116. app确认登录
  117. @param request_dict: 请求参数
  118. @request_dict serial_number: 序列号
  119. @param response: 响应对象
  120. @return: response
  121. """
  122. uuid_number = request_dict.get('uuid', None)
  123. token = request_dict.get('token', None)
  124. if not all([uuid_number, token]):
  125. return response.json(444, {'error param': 'uuid or token'})
  126. redis_obj = RedisObject()
  127. try:
  128. status = redis_obj.get_data(uuid_number)
  129. if status is False:
  130. return response.json(119)
  131. flag = redis_obj.set_ex_data(uuid_number, token, 300)
  132. if flag is False:
  133. return response.json(309)
  134. return response.json(0)
  135. except Exception as e:
  136. print(e)
  137. return response.json(500)
  138. @staticmethod
  139. def get_device(response, user_id):
  140. """
  141. 获取设备列表
  142. @param response: 响应对象
  143. @param user_id: 用户id
  144. @return: response
  145. """
  146. try:
  147. device_qs = Device_Info.objects.filter(userID=user_id).values('serial_number', 'NickName')
  148. return response.json(0, list(device_qs))
  149. except Exception as e:
  150. print(e)
  151. return response.json(500)
  152. class KVSView(View):
  153. def get(self, request, *args, **kwargs):
  154. request.encoding = 'utf-8'
  155. operation = kwargs.get('operation')
  156. return self.validation(request.GET, request, operation)
  157. def post(self, request, *args, **kwargs):
  158. request.encoding = 'utf-8'
  159. operation = kwargs.get('operation')
  160. return self.validation(request.POST, request, operation)
  161. def validation(self, request_dict, request, operation):
  162. response = ResponseObject()
  163. if operation == 'create-media': # 创建视频流
  164. return self.create_media(request_dict, response)
  165. elif operation == 'update-data-retention': # 修改视频流数据保留时间
  166. return self.update_data_retention(request_dict, response)
  167. else:
  168. # tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
  169. # if tko.code != 0:
  170. # return response.json(tko.code)
  171. # response.lang = tko.lang
  172. # user_id = tko.userID
  173. if operation == 'get-device-midea-list': # 获取设备列表
  174. return self.get_device_midea_list(request_dict, response)
  175. elif operation == 'get-hls-midea': # 获取视频播放地址
  176. return self.get_hls_midea_url(request_dict, response)
  177. elif operation == 'download-clip': # 获取视频播放地址
  178. return self.download_clip(request_dict, response)
  179. else:
  180. return response.json(404)
  181. @staticmethod
  182. def create_media(request_dict, response):
  183. """
  184. 创建视频流
  185. @param request_dict: 请求参数
  186. @request_dict serial_number: 序列号
  187. @param response: 响应对象
  188. @return: response
  189. """
  190. serial_number = request_dict.get('serial_number', None)
  191. try:
  192. kvs_qs = KVS.objects.filter(stream_name=serial_number)
  193. if kvs_qs.exists():
  194. return response.json(174)
  195. kinesis_video_obj = AmazonKinesisVideoObject(
  196. aws_access_key_id=ACCESS_KEY_ID,
  197. secret_access_key=SECRET_ACCESS_KEY,
  198. region_name=REGION_NAME
  199. )
  200. stream_arn = kinesis_video_obj.create_stream(stream_name=serial_number)
  201. if stream_arn:
  202. now_time = int(time.time())
  203. KVS.objects.create(stream_name=serial_number, stream_arn=stream_arn, created_time=now_time,
  204. updated_time=now_time)
  205. return response.json(0)
  206. else:
  207. return response.json(178)
  208. except Exception as e:
  209. print(e)
  210. return response.json(500)
  211. @staticmethod
  212. def update_data_retention(request_dict, response):
  213. """
  214. 修改视频流数据保留时间
  215. @param request_dict: 请求参数
  216. @request_dict serial_number: 序列号
  217. @request_dict operation: 操作,增加/减少
  218. @request_dict data_retention_change_in_hours: 修改的时间
  219. @param response: 响应对象
  220. @return: response
  221. """
  222. serial_number = request_dict.get('serial_number', None)
  223. operation = request_dict.get('operation', None)
  224. data_retention_change_in_hours = request_dict.get('data_retention_change_in_hours', None)
  225. try:
  226. kvs_qs = KVS.objects.filter(stream_name=serial_number)
  227. if not kvs_qs.exists():
  228. return response.json(174)
  229. kinesis_video_obj = AmazonKinesisVideoObject(
  230. aws_access_key_id=ACCESS_KEY_ID,
  231. secret_access_key=SECRET_ACCESS_KEY,
  232. region_name=REGION_NAME
  233. )
  234. now_time = int(time.time())
  235. data_retention_change_in_hours = int(data_retention_change_in_hours)
  236. kinesis_video_obj.update_data_retention(stream_name=serial_number, operation=operation,
  237. data_retention_change_in_hours=data_retention_change_in_hours)
  238. kvs_qs.update(data_retention_in_hours=data_retention_change_in_hours, updated_time=now_time)
  239. return response.json(0)
  240. except Exception as e:
  241. print(e)
  242. return response.json(500)
  243. @staticmethod
  244. def get_hls_midea_url(request_dict, response):
  245. """
  246. 获取视频播放地址
  247. @param request_dict: 请求参数
  248. @request_dict serial_number: 序列号
  249. @request_dict startTime: 开始时间
  250. @request_dict endTime: 结束时间
  251. @request_dict playMode: 播放模式
  252. @param response: 响应对象
  253. @return: response
  254. """
  255. serial_number = request_dict.get('serial_number', None)
  256. start_time = request_dict.get('startTime', None)
  257. end_time = request_dict.get('endTime', None)
  258. play_mode = request_dict.get('playMode', None)
  259. if not all([serial_number, start_time, end_time, play_mode]):
  260. return response.json(444)
  261. start_time = datetime.datetime.fromtimestamp(int(start_time)) - datetime.timedelta(hours=8)
  262. end_time = datetime.datetime.fromtimestamp(int(end_time)) - datetime.timedelta(hours=8)
  263. play_mode = int(play_mode)
  264. play_mode = 'ON_DEMAND' if play_mode == 0 else 'LIVE_REPLAY'
  265. try:
  266. # kvs_qs = KVS.objects.filter(stream_name=serial_number)
  267. # if not kvs_qs.exists():
  268. # return response.json(174)
  269. kinesis_video_obj = AmazonKVAMObject(
  270. aws_access_key_id='AKIA2E67UIMD45Y3HL53',
  271. secret_access_key='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',
  272. region_name='us-east-1',
  273. stream_name=serial_number,
  274. api_name='GET_HLS_STREAMING_SESSION_URL'
  275. )
  276. hls_streaming_session_url = kinesis_video_obj.get_hls_streaming_session_url(serial_number, start_time,
  277. end_time, play_mode)
  278. return response.json(0, {"HlsStreamingSessionUrl": hls_streaming_session_url})
  279. except Exception as e:
  280. print(e)
  281. return response.json(500, repr(e))
  282. @staticmethod
  283. def get_device_midea_list(request_dict, response):
  284. """
  285. 获取视频播放列表
  286. @param request_dict: 请求参数
  287. @request_dict serial_number: 序列号
  288. @request_dict startTime: 开始时间
  289. @request_dict endTime: 结束时间
  290. @param response: 响应对象
  291. @return: response
  292. """
  293. serial_number = request_dict.get('serial_number', None)
  294. start_time = request_dict.get('startTime', None)
  295. end_time = request_dict.get('endTime', None)
  296. page = request_dict.get('page', None)
  297. size = request_dict.get('size', None)
  298. if not all([serial_number, start_time, end_time, page, size]):
  299. return response.json(444)
  300. page = int(page)
  301. size = int(size)
  302. start_time = datetime.datetime.fromtimestamp(int(start_time)) - datetime.timedelta(hours=8)
  303. end_time = datetime.datetime.fromtimestamp(int(end_time)) - datetime.timedelta(hours=8)
  304. try:
  305. # kvs_qs = KVS.objects.filter(stream_name=serial_number)
  306. # if not kvs_qs.exists():
  307. # return response.json(174)
  308. kinesis_fragments_obj = AmazonKVAMObject(
  309. aws_access_key_id='AKIA2E67UIMD45Y3HL53',
  310. secret_access_key='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',
  311. region_name='us-east-1',
  312. stream_name=serial_number,
  313. api_name='LIST_FRAGMENTS'
  314. )
  315. kinesis_images_obj = AmazonKVAMObject(
  316. aws_access_key_id='AKIA2E67UIMD45Y3HL53',
  317. secret_access_key='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',
  318. region_name='us-east-1',
  319. stream_name=serial_number,
  320. api_name='GET_IMAGES'
  321. )
  322. stream_list = kinesis_fragments_obj.get_list_fragments(serial_number, start_time, end_time)[
  323. (page - 1) * size:page * size]
  324. for item in stream_list:
  325. temp_start_time = (item['startTime'] - datetime.timedelta(hours=8)).replace(tzinfo=datetime.timezone.utc)
  326. temp_end_time = temp_start_time + datetime.timedelta(seconds=300)
  327. item['image'] = kinesis_images_obj.get_images(serial_number, temp_start_time, temp_end_time)
  328. item['startTime'] = int(item['startTime'].timestamp())
  329. item['endTime'] = int(item['endTime'].timestamp())
  330. return response.json(0, stream_list)
  331. except Exception as e:
  332. print(e)
  333. return response.json(500, repr(e))
  334. @staticmethod
  335. def download_clip(request_dict, response):
  336. """
  337. 获取视频播放地址
  338. @param request_dict: 请求参数
  339. @request_dict serial_number: 序列号
  340. @request_dict startTime: 开始时间
  341. @request_dict endTime: 结束时间
  342. @param response: 响应对象
  343. @return: response
  344. """
  345. serial_number = request_dict.get('serial_number', None)
  346. start_time = request_dict.get('startTime', None)
  347. end_time = request_dict.get('endTime', None)
  348. if not all([serial_number, start_time, end_time]):
  349. return response.json(444)
  350. start_time = datetime.datetime.fromtimestamp(int(start_time)) - datetime.timedelta(hours=8)
  351. end_time = datetime.datetime.fromtimestamp(int(end_time)) - datetime.timedelta(hours=8)
  352. try:
  353. # kvs_qs = KVS.objects.filter(stream_name=serial_number)
  354. # if not kvs_qs.exists():
  355. # return response.json(174)
  356. kinesis_video_obj = AmazonKVAMObject(
  357. aws_access_key_id='AKIA2E67UIMD45Y3HL53',
  358. secret_access_key='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',
  359. region_name='us-east-1',
  360. stream_name=serial_number,
  361. api_name='GET_CLIP'
  362. )
  363. clip_obj, clip_size = kinesis_video_obj.get_clip(serial_number, start_time, end_time)
  364. res = HttpResponse(clip_obj.read())
  365. res["content_type"] = "video/mp4"
  366. res["Content-Disposition"] = "attachment;filename=video.mp4"
  367. res['Content-Length'] = str(clip_size)
  368. return res
  369. except Exception as e:
  370. print(e)
  371. return response.json(500, repr(e))