OTAEquipment.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. from zlib import crc32
  2. from django.core import serializers
  3. from wsgiref.util import FileWrapper
  4. import traceback, hashlib
  5. from Ansjer.config import SERVER_DOMAIN
  6. from django.views.decorators.csrf import csrf_exempt
  7. from django.views.generic import TemplateView
  8. from django.utils.decorators import method_decorator
  9. from Model.models import Equipment_Version
  10. from Model.models import Device_User
  11. from Service.ModelService import ModelService
  12. from Service.CommonService import CommonService
  13. import time, os, simplejson as json
  14. from Object.ResponseObject import ResponseObject
  15. from Object.TokenObject import TokenObject
  16. from django.http import HttpResponse
  17. from Ansjer.config import BASE_DIR
  18. def addNewEquipmentVersion(deviceContent, token, response):
  19. """
  20. :param deviceContent:
  21. :return:
  22. """
  23. if token is not None:
  24. tko = TokenObject(token)
  25. # 设置语言
  26. response.lang = tko.lang
  27. if tko.code == 0:
  28. userID = tko.userID
  29. own_permission = ModelService.check_perm(userID=userID, permID=220)
  30. if own_permission is True:
  31. try:
  32. print(deviceContent)
  33. print(type(deviceContent))
  34. deviceData = json.loads(deviceContent)
  35. except Exception as e:
  36. return response.json(444, repr(e))
  37. else:
  38. version = deviceData.get('version', None)
  39. if version is not None:
  40. filePath = deviceData.get('filePath', None)
  41. if filePath is not None:
  42. try:
  43. deviceData['filePath'] = ','.join(filePath)
  44. equipmentVersion = Equipment_Version(
  45. eid=CommonService.getUserID(getUser=False, setOTAID=True),
  46. **deviceData)
  47. equipmentVersion.save()
  48. except Exception as e:
  49. errorInfo = traceback.format_exc()
  50. print('添加设备错误: %s ' % errorInfo)
  51. return response.json(444, repr(e))
  52. else:
  53. res = CommonService.qs_to_dict([equipmentVersion])
  54. return response.json(0, res)
  55. else:
  56. return response.json(806)
  57. else:
  58. return response.json(806)
  59. else:
  60. return response.json(404)
  61. else:
  62. return response.json(309)
  63. def downloadUrl(fileType, fileCode, fileVersion, fileName):
  64. fullPath = os.path.join(BASE_DIR, "static/Upgrade").replace('\\', '/')
  65. if fileType == 'IPC':
  66. Path = '/'.join((fullPath, 'IPC', fileCode, fileVersion, fileName)).replace('\\', '/')
  67. elif fileType == 'DVR':
  68. Path = '/'.join((fullPath, 'DVR', fileCode, fileVersion, fileName)).replace('\\', '/')
  69. elif fileType == 'NVR':
  70. Path = '/'.join((fullPath, 'NVR', fileCode, fileVersion, fileName)).replace('\\', '/')
  71. elif fileType == 'XVR':
  72. Path = '/'.join((fullPath, 'IPC', fileCode, fileVersion, fileName)).replace('\\', '/')
  73. else:
  74. if fileType == 'CHM':
  75. Path = fileName
  76. else:
  77. Path = '/'.join((fullPath, 'Other', fileName)).replace('\\', '/')
  78. if os.path.isfile(Path):
  79. try:
  80. JSON = json.dumps(
  81. {
  82. "result_code": 0,
  83. "reason": 'Success',
  84. "result": {},
  85. "error_code": 0,
  86. }, ensure_ascii=False
  87. )
  88. wrapper = FileWrapper(open(Path, 'rb'))
  89. response = HttpResponse(wrapper, content_type="application/octet-stream")
  90. response['Content-Length'] = os.path.getsize(Path)
  91. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(Path)
  92. response['Content-MD5'] = getMD5orSHA265(Path)
  93. response['Content-SHA265'] = getMD5orSHA265(Path, 'SHA265')
  94. response['Content-CRC32'] = getMD5orSHA265(Path, 'CRC32')
  95. response['Content-Error'] = JSON
  96. return response
  97. except Exception as e:
  98. res = ResponseObject()
  99. errorJSON = res.formal(906, {'details': repr(e)})
  100. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  101. response['Content-Error'] = errorJSON
  102. return response
  103. else:
  104. res = ResponseObject()
  105. errorJSON = res.formal(907)
  106. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  107. response['Content-Error'] = errorJSON
  108. return response
  109. def getMD5orSHA265(fileName, encryptionType='MD5'):
  110. """
  111. :param filePath:
  112. :param encryptionType:
  113. :return:
  114. """
  115. if not os.path.isfile(fileName):
  116. return ''
  117. else:
  118. if encryptionType == 'MD5':
  119. encryption = hashlib.md5()
  120. elif encryptionType == 'SHA265':
  121. encryption = hashlib.sha256()
  122. elif encryptionType == 'CRC32':
  123. f = open(fileName, 'rb')
  124. chunk = f.read()
  125. return crc32(chunk)
  126. f = open(fileName, 'rb')
  127. block_size = 8192 # why is 8192 | 8192 is fast than 2048
  128. while True:
  129. chunk = f.read(block_size)
  130. if not chunk:
  131. break
  132. encryption.update(chunk)
  133. f.close()
  134. return encryption.hexdigest()
  135. @csrf_exempt
  136. def downloadUpdataFileUrl(request):
  137. response = ResponseObject()
  138. if request.method == 'GET':
  139. request_dict = request.GET
  140. elif request.method == 'POST':
  141. request_dict = request.POST
  142. else:
  143. errorJSON = response.formal(444)
  144. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  145. response['Content-Error'] = errorJSON
  146. return response
  147. fileType = request_dict.get('fileType', None)
  148. fileCode = request_dict.get('fileCode', None)
  149. fileVersion = request_dict.get('fileVersion', None)
  150. fileName = request_dict.get('fileName', None)
  151. if fileType != None and fileCode != None and fileVersion != \
  152. None and fileName != None:
  153. return downloadUrl(fileType, fileCode, fileVersion, fileName, response)
  154. else:
  155. errorJSON = response.formal(444)
  156. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  157. response['Content-Error'] = errorJSON
  158. return response
  159. '''
  160. http://192.168.136.40:8077/OTA/getEquipmentVersion?31AX162001A
  161. '''
  162. @csrf_exempt
  163. def getEquipmentVersionInterface(request):
  164. response = ResponseObject()
  165. if request.method == "POST":
  166. request.encoding = 'utf-8'
  167. request_dict = request.POST
  168. elif request.method == "GET":
  169. request.encoding = 'gb2312'
  170. request_dict = request.GET
  171. else:
  172. return response.json(444)
  173. code = request_dict.get('code', None)
  174. ov = request_dict.get('ov', None)
  175. if not code:
  176. return response.json(444, 'code')
  177. eqs = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
  178. if not eqs.exists():
  179. return response.json(900)
  180. if ov is not None:
  181. # 判断大小
  182. nv = eqs[0].softwareVersion
  183. if ov > nv:
  184. return response.json(900)
  185. equipment = eqs[0]
  186. return response.json(0, {'softwareVersion': equipment.softwareVersion})
  187. @csrf_exempt
  188. def getUpdataFileUrlInterface(request):
  189. response = ResponseObject()
  190. if request.method == "POST":
  191. request.encoding = 'utf-8'
  192. code = request.POST.get('code', None)
  193. elif request.method == "GET":
  194. request.encoding = 'utf-8'
  195. code = request.GET.get('code', None)
  196. else:
  197. return response.json(444)
  198. if not code:
  199. return response.json(444, 'code')
  200. eq = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
  201. # 判断是否有版本存在
  202. if not eq.exists():
  203. return response.json(902)
  204. file_path = eq[0].filePath
  205. urls = []
  206. if file_path:
  207. if file_path.find('static/Upgrade/') != -1:
  208. path = file_path.replace('static/Upgrade/', '').replace('\\', '/')
  209. url = SERVER_DOMAIN + 'OTA/downloads/' + path + '?time=' + str(time.time())
  210. urls.append(url)
  211. if file_path.find('static/otapack') != -1:
  212. url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path + '?time=' + str(time.time())
  213. urls.append(url)
  214. if len(urls) > 0:
  215. res = {
  216. "urlCount": len(urls),
  217. "url": urls,
  218. "fileSize": eq[0].fileSize,
  219. "Description": eq[0].Description,
  220. }
  221. return response.json(0, res)
  222. else:
  223. return response.json(901)
  224. @csrf_exempt
  225. def downloadUpdataFileUrlInterface(request, fileType, fileName,
  226. *callback_args, **callback_kwargs):
  227. res = ResponseObject()
  228. if fileType is not None and fileName is not None:
  229. fullPath = os.path.join(BASE_DIR, "static/Upgrade/").replace('\\', '/')
  230. if fileType == 'IPC':
  231. fullPath += 'IPC/' + fileName
  232. elif fileType == 'DVR':
  233. fullPath += 'DVR/' + fileName
  234. elif fileType == 'NVR':
  235. fullPath += 'NVR/' + fileName
  236. elif fileType == 'XVR':
  237. fullPath += 'XVR/' + fileName
  238. elif fileType == 'User':
  239. fullPath = os.path.join(BASE_DIR, "static/").replace('\\', '/')
  240. fullPath += 'User/' + fileName
  241. elif fileType == 'ADCloud':
  242. fullPath = os.path.join(BASE_DIR, "static/APK/").replace('\\', '/')
  243. fullPath += 'ADCloud/' + fileName
  244. elif fileType == 'ACCloud':
  245. fullPath = os.path.join(BASE_DIR, "static/APK/").replace('\\', '/')
  246. fullPath += 'ACCloud/' + fileName
  247. else:
  248. fullPath += 'Other/' + fileName
  249. print(fullPath)
  250. if os.path.isfile(fullPath):
  251. try:
  252. JSON = res.formal(0)
  253. if fileType != 'User':
  254. wrapper = FileWrapper(open(fullPath, 'rb'))
  255. response = HttpResponse(wrapper, content_type="application/octet-stream")
  256. response['Content-Length'] = os.path.getsize(fullPath)
  257. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(fullPath)
  258. response['Content-MD5'] = getMD5orSHA265(fullPath)
  259. # 校验文件md5值
  260. response['Content-SHA265'] = getMD5orSHA265(fullPath, 'SHA265')
  261. response['Content-CRC32'] = getMD5orSHA265(fullPath, 'CRC32')
  262. response['Content-Error'] = JSON
  263. return response
  264. else:
  265. Imagedata = open(fullPath, 'rb').read()
  266. response = HttpResponse(Imagedata, content_type="image/jpeg")
  267. return response
  268. except Exception as e:
  269. errorJSON = res.formal(906)
  270. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  271. response['Content-Error'] = errorJSON
  272. return response
  273. else:
  274. errorJSON = res.formal(907)
  275. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  276. response['Content-Error'] = errorJSON
  277. return response
  278. else:
  279. errorJSON = res.formal(444)
  280. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  281. response['Content-Error'] = errorJSON
  282. return response
  283. class getUploadFiletoDirView(TemplateView):
  284. @method_decorator(csrf_exempt)
  285. def dispatch(self, *args, **kwargs):
  286. return super(getUploadFiletoDirView, self).dispatch(*args, **kwargs)
  287. def post(self, request, *args, **kwargs):
  288. request.encoding = 'utf-8'
  289. request_dict = request.POST
  290. fileName = request.FILES.get('fileName', None)
  291. return self.ValidationError(request_dict, fileName)
  292. def get(self, request, *args, **kwargs):
  293. request.encoding = 'gb2312'
  294. request_dict = request.GET
  295. fileName = request.FILES.get('fileName', None)
  296. return self.ValidationError(request_dict, fileName)
  297. def ValidationError(self, request_dict, fileName):
  298. response = ResponseObject()
  299. token = request_dict.get('token', None)
  300. fileType = request_dict.get('fileType', None)
  301. fileCode = request_dict.get('fileCode', None)
  302. fileVersion = request_dict.get('fileVersion', None)
  303. if not fileName or not fileType:
  304. return response.json(444, 'fileName,fileType')
  305. tko = TokenObject(token)
  306. response.lang = tko.lang
  307. if tko.code != 0:
  308. return response.json(tko.code)
  309. userID = tko.userID
  310. if not userID:
  311. return response.json(104)
  312. own_perm = ModelService.check_perm(userID=userID, permID=210)
  313. if not own_perm:
  314. return response.json(404)
  315. if fileVersion != None and fileCode != None:
  316. return self.getUploadFiletoDir(userID, fileType, fileName, response, fileCode,
  317. fileVersion=fileVersion)
  318. else:
  319. return self.getUploadFiletoDir(userID, fileType, fileName, response)
  320. def getUploadFiletoDir(self, userID, fileType, fileName, response, *args, **kwargs):
  321. """
  322. 将上传的文件写入服务器对应目录下
  323. :param Type: equipment type
  324. :param fileName: File name of upgrade file.
  325. :return: filePath
  326. """
  327. User = Device_User.objects.filter(userID=userID)
  328. if not User:
  329. return response.json(104)
  330. own_perm = ModelService.check_perm(userID, permID=210)
  331. if own_perm is not True:
  332. return response.json(404)
  333. updataFile = fileName.name
  334. updataFile = updataFile.replace(' ', '+')
  335. versionIndex = updataFile.find('.', updataFile.find('.', updataFile.find('.') + 1) + 1)
  336. codeIndex = versionIndex + 12
  337. if codeIndex != -1 and versionIndex != -1:
  338. fileVersion = len(updataFile[1: versionIndex]) > 0 and updataFile[1: versionIndex] or None
  339. fileCode = len(updataFile[versionIndex + 1: codeIndex]) > 0 and \
  340. updataFile[versionIndex + 1: codeIndex] or None
  341. if fileCode is not None and fileVersion is not None:
  342. return self.getDir(fileType, fileName, fileCode, fileVersion, response)
  343. else:
  344. fileCode = kwargs.get('fileCode', None)
  345. fileVersion = kwargs.get('fileVersion', None)
  346. print(fileCode, fileVersion)
  347. if fileCode != None and fileVersion != None:
  348. return self.getDir(fileType, fileName, fileCode, fileVersion)
  349. else:
  350. return response.json(903)
  351. else:
  352. fileCode = kwargs.get('fileCode', None)
  353. fileVersion = kwargs.get('fileVersion', None)
  354. if fileCode != None and fileVersion != None:
  355. return self.getDir(fileType, fileName, fileCode, fileVersion, response)
  356. else:
  357. return response.json(903)
  358. def getDir(self, fileType, fileName, fileCode, fileVersion, response):
  359. try:
  360. if fileCode != None and fileVersion != None:
  361. path = '/'.join((BASE_DIR, 'static/Upgrade', fileType, fileCode, fileVersion)).replace('\\', '/') + '/'
  362. else:
  363. if fileType != 'IPC' and fileType != 'DVR' and fileType != 'NVR' and fileType != 'XVR':
  364. path = '/'.join((BASE_DIR, "static/Upgrade", 'Other')).replace('\\', '/') + '/'
  365. if not os.path.exists(path):
  366. os.makedirs(path)
  367. file_name = path + str(fileName)
  368. if os.path.exists(file_name):
  369. os.remove(file_name)
  370. destination = open(file_name, 'wb+')
  371. for chunk in fileName.chunks():
  372. destination.write(chunk)
  373. destination.close()
  374. else:
  375. file_name = path + str(fileName)
  376. if os.path.exists(file_name):
  377. os.remove(file_name)
  378. destination = open(file_name, 'wb+')
  379. for chunk in fileName.chunks():
  380. destination.write(chunk)
  381. destination.close()
  382. except Exception as e:
  383. errorInfo = traceback.format_exc()
  384. print('上传文件错误: %s' % errorInfo)
  385. return response.json(700, {'details': repr(e)})
  386. else:
  387. index = file_name.find('static/')
  388. filePath = file_name[index:]
  389. return response.json(0, {'filePath': filePath})
  390. @csrf_exempt
  391. def addNewEquipmentVersionInterface(request):
  392. request.encoding = 'utf-8'
  393. response = ResponseObject()
  394. if request.method == "POST":
  395. request_dict = request.POST
  396. elif request.method == "GET":
  397. request_dict = request.GET
  398. else:
  399. return response.json(444)
  400. deviceContent = request_dict.get('content', None).encode('utf-8')
  401. token = request_dict.get('token', None)
  402. deviceContent = str(deviceContent, encoding='utf-8')
  403. deviceContent = deviceContent.replace(' ', ' ').replace('\'', '\"')
  404. if deviceContent is not None:
  405. return addNewEquipmentVersion(deviceContent, token, response)
  406. else:
  407. return response.json(800)
  408. def showAllEquipmentVersion(userID, response):
  409. userValid = Device_User.objects.filter(userID=userID).order_by('-data_joined')
  410. if not userValid.exists():
  411. return response.json(104)
  412. own_perm = ModelService.check_perm(userID=userID, permID=240)
  413. if not own_perm:
  414. return response.json(404)
  415. qs = Equipment_Version.objects.all()
  416. res = CommonService.qs_to_dict(qs)
  417. return response.json(0, res)
  418. # 检测ota更新包
  419. @csrf_exempt
  420. def getNewVerInterface(request):
  421. response = ResponseObject()
  422. if request.method == "POST":
  423. request.encoding = 'utf-8'
  424. request_dict = request.POST
  425. elif request.method == "GET":
  426. request.encoding = 'utf-8'
  427. request_dict = request.GET
  428. code = request_dict.get('code', None)
  429. token = request_dict.get('token', None)
  430. lang = request_dict.get('lang', None)
  431. if not code:
  432. return response.json(444,'code')
  433. tko = TokenObject(token)
  434. response.lang = tko.lang
  435. if tko.code != 0:
  436. return response.json(tko.code)
  437. if lang == 'zh-Hans':
  438. equipmentValid = Equipment_Version.objects.filter(code=code, status=1, lang=lang).order_by(
  439. '-data_joined')
  440. else:
  441. equipmentValid = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by(
  442. '-data_joined')
  443. if equipmentValid.exists():
  444. ver = equipmentValid[0].softwareVersion
  445. equipment = equipmentValid[0]
  446. file_path = equipment.filePath
  447. # 检测ip进行替换
  448. client_ip = CommonService.get_ip_address(request)
  449. url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path + '?time=' + str(time.time())
  450. return response.json(0, {
  451. 'ver': ver,
  452. 'url': url,
  453. "Description": equipment.Description,
  454. })
  455. else:
  456. return response.json(902)
  457. # ota包上传
  458. class uploadOTAInterfaceView(TemplateView):
  459. @method_decorator(csrf_exempt)
  460. def dispatch(self, *args, **kwargs):
  461. return super(uploadOTAInterfaceView, self).dispatch(*args, **kwargs)
  462. def post(self, request, *args, **kwargs):
  463. request.encoding = 'utf-8'
  464. token = request.POST.get('token', None)
  465. fileName = request.FILES.get('fileName', None)
  466. fileType = request.POST.get('fileType', None)
  467. language = request.POST.get('language', None)
  468. return self.validate(token, fileName, fileType, language)
  469. def get(self, request, *args, **kwargs):
  470. request.encoding = 'gb2312'
  471. token = request.GET.get('token', None)
  472. fileName = request.FILES.get('fileName', None)
  473. fileType = request.GET.get('fileType', None)
  474. language = request.GET.get('language', None)
  475. return self.validate(token, fileName, fileType, language)
  476. def validate(self, token, fileName, fileType, language):
  477. response = ResponseObject()
  478. if not fileName or not fileType:
  479. return response.json(444,'fileName,fileType')
  480. tko = TokenObject(token)
  481. response.lang = tko.lang
  482. if tko.code != 0:
  483. return response.json(tko.code)
  484. userID = tko.userID
  485. if not userID:
  486. return response.json(104)
  487. own_permission = ModelService.check_perm(userID=userID, permID=210)
  488. if own_permission is not True:
  489. return response.json(404)
  490. return self.upload_ota_file(fileName, response, fileType, language)
  491. def upload_ota_file(self, fileName, response, fileType, language):
  492. try:
  493. if not language:
  494. language = 0
  495. path = '/'.join((BASE_DIR, 'static/otapack', fileType, str(language))).replace('\\', '/') + '/'
  496. if not os.path.exists(path):
  497. os.makedirs(path)
  498. file_name = path + str(fileName)
  499. if os.path.exists(file_name):
  500. os.remove(file_name)
  501. destination = open(file_name, 'wb+')
  502. for chunk in fileName.chunks():
  503. destination.write(chunk)
  504. destination.close()
  505. else:
  506. file_name = path + str(fileName)
  507. if os.path.exists(file_name):
  508. os.remove(file_name)
  509. destination = open(file_name, 'wb+')
  510. for chunk in fileName.chunks():
  511. destination.write(chunk)
  512. destination.close()
  513. except Exception as e:
  514. errorInfo = traceback.format_exc()
  515. print('上传文件错误: %s' % errorInfo)
  516. return response.json(700, {'details': repr(e)})
  517. else:
  518. index = file_name.find('static/')
  519. filePath = file_name[index:]
  520. return response.json(0, {'filePath': filePath})
  521. # ota包下载
  522. # class downloadOTAInterfaceView(TemplateView):
  523. @csrf_exempt
  524. def downloadOTAInterface(request, fullPath, *callback_args, **callback_kwargs):
  525. res = ResponseObject()
  526. print('fullPath:')
  527. print(fullPath)
  528. if fullPath:
  529. if os.path.isfile(fullPath):
  530. try:
  531. wrapper = FileWrapper(open(fullPath, 'rb'))
  532. response = HttpResponse(wrapper, content_type="application/octet-stream")
  533. response['Content-Length'] = os.path.getsize(fullPath)
  534. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(fullPath)
  535. response['Content-MD5'] = getMD5orSHA265(fullPath)
  536. # 校验文件md5值
  537. response['Content-SHA265'] = getMD5orSHA265(fullPath, 'SHA265')
  538. response['Content-CRC32'] = getMD5orSHA265(fullPath, 'CRC32')
  539. response['Content-Error'] = res.formal(0)
  540. return response
  541. except Exception as e:
  542. return res.json(906, repr(e))
  543. else:
  544. return res.json(907)
  545. else:
  546. return res.json(444,'fullPath')