OTAEquipment.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. import hashlib
  2. import os
  3. import simplejson as json
  4. import time
  5. import traceback
  6. import logging
  7. from wsgiref.util import FileWrapper
  8. from zlib import crc32
  9. from django.http import HttpResponse
  10. from django.utils.decorators import method_decorator
  11. from django.views.decorators.csrf import csrf_exempt
  12. from django.views.generic import TemplateView
  13. from Ansjer.config import BASE_DIR
  14. from Ansjer.config import SERVER_DOMAIN
  15. from Ansjer.config import SERVER_TYPE
  16. from Model.models import Device_User, EquipmentVersionLimitModel, CountryIPModel, DeviceOTAUpgradeRecord
  17. from Model.models import Equipment_Version
  18. from Object.RedisObject import RedisObject
  19. from Object.ResponseObject import ResponseObject
  20. from Object.TokenObject import TokenObject
  21. from Object.UrlTokenObject import UrlTokenObject
  22. from Service.CommonService import CommonService
  23. from Service.ModelService import ModelService
  24. def downloadUrl(fileType, fileCode, fileVersion, fileName):
  25. fullPath = os.path.join(BASE_DIR, "static/Upgrade").replace('\\', '/')
  26. if fileType == 'IPC':
  27. Path = '/'.join((fullPath, 'IPC', fileCode, fileVersion, fileName)).replace('\\', '/')
  28. elif fileType == 'DVR':
  29. Path = '/'.join((fullPath, 'DVR', fileCode, fileVersion, fileName)).replace('\\', '/')
  30. elif fileType == 'NVR':
  31. Path = '/'.join((fullPath, 'NVR', fileCode, fileVersion, fileName)).replace('\\', '/')
  32. elif fileType == 'XVR':
  33. Path = '/'.join((fullPath, 'IPC', fileCode, fileVersion, fileName)).replace('\\', '/')
  34. else:
  35. if fileType == 'CHM':
  36. Path = fileName
  37. else:
  38. Path = '/'.join((fullPath, 'Other', fileName)).replace('\\', '/')
  39. if os.path.isfile(Path):
  40. try:
  41. JSON = json.dumps(
  42. {
  43. "result_code": 0,
  44. "reason": 'Success',
  45. "result": {},
  46. "error_code": 0,
  47. }, ensure_ascii=False
  48. )
  49. wrapper = FileWrapper(open(Path, 'rb'))
  50. response = HttpResponse(wrapper, content_type="application/octet-stream")
  51. response['Content-Length'] = os.path.getsize(Path)
  52. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(Path)
  53. response['Content-MD5'] = getMD5orSHA265(Path)
  54. response['Content-SHA265'] = getMD5orSHA265(Path, 'SHA265')
  55. response['Content-CRC32'] = getMD5orSHA265(Path, 'CRC32')
  56. response['Content-Error'] = JSON
  57. return response
  58. except Exception as e:
  59. res = ResponseObject()
  60. errorJSON = res.formal(906, {'details': repr(e)})
  61. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  62. response['Content-Error'] = errorJSON
  63. return response
  64. else:
  65. res = ResponseObject()
  66. errorJSON = res.formal(907)
  67. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  68. response['Content-Error'] = errorJSON
  69. return response
  70. def getMD5orSHA265(fileName, encryptionType='MD5'):
  71. """
  72. :param filePath:
  73. :param encryptionType:
  74. :return:
  75. """
  76. if not os.path.isfile(fileName):
  77. return ''
  78. else:
  79. if encryptionType == 'MD5':
  80. encryption = hashlib.md5()
  81. elif encryptionType == 'SHA265':
  82. encryption = hashlib.sha256()
  83. elif encryptionType == 'CRC32':
  84. f = open(fileName, 'rb')
  85. chunk = f.read()
  86. return crc32(chunk)
  87. f = open(fileName, 'rb')
  88. block_size = 8192 # why is 8192 | 8192 is fast than 2048
  89. while True:
  90. chunk = f.read(block_size)
  91. if not chunk:
  92. break
  93. encryption.update(chunk)
  94. f.close()
  95. return encryption.hexdigest()
  96. @csrf_exempt
  97. def downloadUpdataFileUrl(request):
  98. response = ResponseObject()
  99. if request.method == 'GET':
  100. request_dict = request.GET
  101. elif request.method == 'POST':
  102. request_dict = request.POST
  103. else:
  104. errorJSON = response.formal(444)
  105. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  106. response['Content-Error'] = errorJSON
  107. return response
  108. fileType = request_dict.get('fileType', None)
  109. fileCode = request_dict.get('fileCode', None)
  110. fileVersion = request_dict.get('fileVersion', None)
  111. fileName = request_dict.get('fileName', None)
  112. if fileType != None and fileCode != None and fileVersion != \
  113. None and fileName != None:
  114. return downloadUrl(fileType, fileCode, fileVersion, fileName, response)
  115. else:
  116. errorJSON = response.formal(444)
  117. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  118. response['Content-Error'] = errorJSON
  119. return response
  120. @csrf_exempt
  121. def getEquipmentVersionInterface(request):
  122. response = ResponseObject()
  123. if request.method == "POST":
  124. request.encoding = 'utf-8'
  125. request_dict = request.POST
  126. elif request.method == "GET":
  127. request.encoding = 'gb2312'
  128. request_dict = request.GET
  129. else:
  130. return response.json(444)
  131. code = request_dict.get('code', None)
  132. ov = request_dict.get('ov', None)
  133. if not code:
  134. return response.json(444, 'code')
  135. eqs = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
  136. if not eqs.exists():
  137. return response.json(900)
  138. if ov is not None:
  139. # 判断大小
  140. nv = eqs[0].softwareVersion
  141. if ov > nv:
  142. return response.json(0, {'softwareVersion': ov})
  143. equipment = eqs[0]
  144. return response.json(0, {'softwareVersion': equipment.softwareVersion})
  145. @csrf_exempt
  146. def getUpdataFileUrlInterface(request):
  147. response = ResponseObject()
  148. request.encoding = 'utf-8'
  149. if request.method == "POST":
  150. code = request.POST.get('code', None)
  151. elif request.method == "GET":
  152. code = request.GET.get('code', None)
  153. else:
  154. return response.json(444)
  155. if not code:
  156. return response.json(444, 'code')
  157. eq = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
  158. # 判断是否有版本存在
  159. if not eq.exists():
  160. return response.json(902)
  161. file_path = eq[0].filePath
  162. urls = []
  163. if file_path:
  164. if file_path.find('static/Upgrade/') != -1:
  165. path = file_path.replace('static/Upgrade/', '').replace('\\', '/')
  166. url = SERVER_DOMAIN + 'OTA/downloads/' + path + '?time=' + str(time.time())
  167. urls.append(url)
  168. if file_path.find('static/otapack') != -1:
  169. url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path + '?time=' + str(time.time())
  170. urls.append(url)
  171. if len(urls) > 0:
  172. res = {
  173. "urlCount": len(urls),
  174. "url": urls,
  175. "fileSize": eq[0].fileSize,
  176. "Description": eq[0].Description,
  177. }
  178. return response.json(0, res)
  179. else:
  180. return response.json(901)
  181. @csrf_exempt
  182. def downloadUpdataFileUrlInterface(request, fileType, fileName,
  183. *callback_args, **callback_kwargs):
  184. res = ResponseObject()
  185. if fileType is not None and fileName is not None:
  186. fullPath = os.path.join(BASE_DIR, "static/Upgrade/").replace('\\', '/')
  187. if fileType == 'IPC':
  188. fullPath += 'IPC/' + fileName
  189. elif fileType == 'DVR':
  190. fullPath += 'DVR/' + fileName
  191. elif fileType == 'NVR':
  192. fullPath += 'NVR/' + fileName
  193. elif fileType == 'XVR':
  194. fullPath += 'XVR/' + fileName
  195. elif fileType == 'User':
  196. fullPath = os.path.join(BASE_DIR, "static/").replace('\\', '/')
  197. fullPath += 'User/' + fileName
  198. elif fileType == 'ADCloud':
  199. fullPath = os.path.join(BASE_DIR, "static/APK/").replace('\\', '/')
  200. fullPath += 'ADCloud/' + fileName
  201. elif fileType == 'ACCloud':
  202. fullPath = os.path.join(BASE_DIR, "static/APK/").replace('\\', '/')
  203. fullPath += 'ACCloud/' + fileName
  204. else:
  205. fullPath += 'Other/' + fileName
  206. print(fullPath)
  207. if os.path.isfile(fullPath):
  208. try:
  209. JSON = res.formal(0)
  210. if fileType != 'User':
  211. wrapper = FileWrapper(open(fullPath, 'rb'))
  212. response = HttpResponse(wrapper, content_type="application/octet-stream")
  213. response['Content-Length'] = os.path.getsize(fullPath)
  214. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(fullPath)
  215. response['Content-MD5'] = getMD5orSHA265(fullPath)
  216. # 校验文件md5值
  217. response['Content-SHA265'] = getMD5orSHA265(fullPath, 'SHA265')
  218. response['Content-CRC32'] = getMD5orSHA265(fullPath, 'CRC32')
  219. response['Content-Error'] = JSON
  220. return response
  221. else:
  222. Imagedata = open(fullPath, 'rb').read()
  223. response = HttpResponse(Imagedata, content_type="image/jpeg")
  224. return response
  225. except Exception as e:
  226. errorJSON = res.formal(906)
  227. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  228. response['Content-Error'] = errorJSON
  229. return response
  230. else:
  231. errorJSON = res.formal(907)
  232. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  233. response['Content-Error'] = errorJSON
  234. return response
  235. else:
  236. errorJSON = res.formal(444)
  237. response = HttpResponse(errorJSON, content_type='text/plain', charset='utf-8')
  238. response['Content-Error'] = errorJSON
  239. return response
  240. class getUploadFiletoDirView(TemplateView):
  241. @method_decorator(csrf_exempt)
  242. def dispatch(self, *args, **kwargs):
  243. return super(getUploadFiletoDirView, self).dispatch(*args, **kwargs)
  244. def post(self, request, *args, **kwargs):
  245. request.encoding = 'utf-8'
  246. request_dict = request.POST
  247. fileName = request.FILES.get('fileName', None)
  248. return self.ValidationError(request_dict, fileName)
  249. def get(self, request, *args, **kwargs):
  250. request.encoding = 'gb2312'
  251. request_dict = request.GET
  252. fileName = request.FILES.get('fileName', None)
  253. return self.ValidationError(request_dict, fileName)
  254. def ValidationError(self, request_dict, fileName):
  255. response = ResponseObject()
  256. token = request_dict.get('token', None)
  257. fileType = request_dict.get('fileType', None)
  258. fileCode = request_dict.get('fileCode', None)
  259. fileVersion = request_dict.get('fileVersion', None)
  260. if not fileName or not fileType:
  261. return response.json(444, 'fileName,fileType')
  262. tko = TokenObject(token)
  263. response.lang = tko.lang
  264. if tko.code != 0:
  265. return response.json(tko.code)
  266. userID = tko.userID
  267. if not userID:
  268. return response.json(104)
  269. own_perm = ModelService.check_perm(userID=userID, permID=210)
  270. if not own_perm:
  271. return response.json(404)
  272. if fileVersion != None and fileCode != None:
  273. return self.getUploadFiletoDir(userID, fileType, fileName, response, fileCode,
  274. fileVersion=fileVersion)
  275. else:
  276. return self.getUploadFiletoDir(userID, fileType, fileName, response)
  277. def getUploadFiletoDir(self, userID, fileType, fileName, response, *args, **kwargs):
  278. """
  279. 将上传的文件写入服务器对应目录下
  280. :param Type: equipment type
  281. :param fileName: File name of upgrade file.
  282. :return: filePath
  283. """
  284. User = Device_User.objects.filter(userID=userID)
  285. if not User:
  286. return response.json(104)
  287. own_perm = ModelService.check_perm(userID, permID=210)
  288. if own_perm is not True:
  289. return response.json(404)
  290. updataFile = fileName.name
  291. updataFile = updataFile.replace(' ', '+')
  292. versionIndex = updataFile.find('.', updataFile.find('.', updataFile.find('.') + 1) + 1)
  293. codeIndex = versionIndex + 12
  294. if codeIndex != -1 and versionIndex != -1:
  295. fileVersion = len(updataFile[1: versionIndex]) > 0 and updataFile[1: versionIndex] or None
  296. fileCode = len(updataFile[versionIndex + 1: codeIndex]) > 0 and \
  297. updataFile[versionIndex + 1: codeIndex] or None
  298. if fileCode is not None and fileVersion is not None:
  299. return self.getDir(fileType, fileName, fileCode, fileVersion, response)
  300. else:
  301. fileCode = kwargs.get('fileCode', None)
  302. fileVersion = kwargs.get('fileVersion', None)
  303. print(fileCode, fileVersion)
  304. if fileCode != None and fileVersion != None:
  305. return self.getDir(fileType, fileName, fileCode, fileVersion)
  306. else:
  307. return response.json(903)
  308. else:
  309. fileCode = kwargs.get('fileCode', None)
  310. fileVersion = kwargs.get('fileVersion', None)
  311. if fileCode != None and fileVersion != None:
  312. return self.getDir(fileType, fileName, fileCode, fileVersion, response)
  313. else:
  314. return response.json(903)
  315. def getDir(self, fileType, fileName, fileCode, fileVersion, response):
  316. try:
  317. if fileCode != None and fileVersion != None:
  318. path = '/'.join((BASE_DIR, 'static/Upgrade', fileType, fileCode, fileVersion)).replace('\\', '/') + '/'
  319. else:
  320. if fileType != 'IPC' and fileType != 'DVR' and fileType != 'NVR' and fileType != 'XVR':
  321. path = '/'.join((BASE_DIR, "static/Upgrade", 'Other')).replace('\\', '/') + '/'
  322. if not os.path.exists(path):
  323. os.makedirs(path)
  324. file_name = path + str(fileName)
  325. if os.path.exists(file_name):
  326. os.remove(file_name)
  327. destination = open(file_name, 'wb+')
  328. for chunk in fileName.chunks():
  329. destination.write(chunk)
  330. destination.close()
  331. else:
  332. file_name = path + str(fileName)
  333. if os.path.exists(file_name):
  334. os.remove(file_name)
  335. destination = open(file_name, 'wb+')
  336. for chunk in fileName.chunks():
  337. destination.write(chunk)
  338. destination.close()
  339. except Exception as e:
  340. errorInfo = traceback.format_exc()
  341. print('上传文件错误: %s' % errorInfo)
  342. return response.json(700, {'details': repr(e)})
  343. else:
  344. index = file_name.find('static/')
  345. filePath = file_name[index:]
  346. return response.json(0, {'filePath': filePath})
  347. @csrf_exempt
  348. def addNewEquipmentVersionInterface(request):
  349. request.encoding = 'utf-8'
  350. response = ResponseObject()
  351. if request.method == "POST":
  352. request_dict = request.POST
  353. elif request.method == "GET":
  354. request_dict = request.GET
  355. else:
  356. return response.json(444)
  357. deviceContent = request_dict.get('content', None).encode('utf-8')
  358. token = request_dict.get('token', None)
  359. file_s = request.FILES.get('file', None)
  360. deviceContent = str(deviceContent, encoding='utf-8')
  361. deviceContent = deviceContent.replace(' ', ' ').replace('\'', '\"')
  362. if deviceContent is None:
  363. return response.json(444, 'content')
  364. tko = TokenObject(token)
  365. response.lang = tko.lang
  366. if tko.code != 0:
  367. return response.json(tko.code)
  368. userID = tko.userID
  369. own_perm = ModelService.check_perm(userID=userID, permID=220)
  370. if own_perm is False:
  371. return response.json(404)
  372. try:
  373. deviceData = json.loads(deviceContent)
  374. version = deviceData.get('version', None)
  375. filePath = deviceData.get('filePath', None)
  376. code = deviceData.get('code', None)
  377. lang = deviceData.get('lang', None)
  378. if code and lang:
  379. try:
  380. Equipment_Version.objects.filter(code=code, lang=lang).delete()
  381. except Exception as e:
  382. pass
  383. if version is None or filePath is None:
  384. return response.json(444, 'content')
  385. deviceData['filePath'] = ','.join(filePath)
  386. paths = 'static/versions/image'
  387. if not os.path.exists(paths):
  388. os.makedirs(paths) # makedirs 创建文件时如果路径不存在会创建这个路径
  389. # print ('该文件不存在')
  390. else:
  391. print('该文件存在')
  392. print(file_s)
  393. if file_s is None:
  394. deviceData['img'] = ''
  395. else:
  396. rv_path = 'static/versions/image/' + code + '.png'
  397. try:
  398. as_path = os.path.join(BASE_DIR, rv_path)
  399. if os.path.exists(as_path):
  400. os.remove(as_path)
  401. with open(as_path, 'wb+') as destination:
  402. for chunk in file_s.chunks():
  403. destination.write(chunk)
  404. except Exception as e:
  405. pass
  406. else:
  407. deviceData['img'] = SERVER_DOMAIN + 'sysfile/' + rv_path
  408. ev_qs = Equipment_Version(
  409. eid=CommonService.getUserID(getUser=False, setOTAID=True),
  410. **deviceData)
  411. ev_qs.save()
  412. except Exception as e:
  413. return response.json(444, repr(e))
  414. else:
  415. res = CommonService.qs_to_dict([ev_qs])
  416. return response.json(0, res)
  417. def showAllEquipmentVersion(userID, response):
  418. userValid = Device_User.objects.filter(userID=userID).order_by('-data_joined')
  419. if not userValid.exists():
  420. return response.json(104)
  421. own_perm = ModelService.check_perm(userID=userID, permID=240)
  422. if not own_perm:
  423. return response.json(404)
  424. qs = Equipment_Version.objects.all()
  425. res = CommonService.qs_to_dict(qs)
  426. return response.json(0, res)
  427. # 检测ota更新包
  428. @csrf_exempt
  429. def getNewVerInterface(request):
  430. response = ResponseObject()
  431. if request.method == "POST":
  432. request_dict = request.POST
  433. elif request.method == "GET":
  434. request_dict = request.GET
  435. else:
  436. return response.json(404)
  437. code = request_dict.get('code', None)
  438. token = request_dict.get('token', None)
  439. lang = request_dict.get('lang', None)
  440. now_ver = request_dict.get('ver', None)
  441. uid = request_dict.get('uid', 'null')
  442. serial_number = request_dict.get('serial_number', 'null')
  443. if not code or not now_ver:
  444. return response.json(902, {'param': 'code,ver'})
  445. # return response.json(444, 'code,ver')
  446. tko = TokenObject(token)
  447. response.lang = tko.lang
  448. if tko.code != 0:
  449. return response.json(tko.code)
  450. if lang == 'zh-Hans' or lang == 'cn':
  451. equipmentValid = Equipment_Version.objects.filter(code=code, status=1, lang='zh-Hans').order_by(
  452. '-data_joined')
  453. else:
  454. equipmentValid = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by(
  455. '-data_joined')
  456. if equipmentValid.exists():
  457. equipment = equipmentValid[0]
  458. redisObject = RedisObject()
  459. key = 'limit_{eid}'.format(eid=equipment.eid)
  460. evl_qs = redisObject.get_data(key=key)
  461. if evl_qs:
  462. evl_qs = json.loads(evl_qs)
  463. else:
  464. evl_qs = EquipmentVersionLimitModel.objects.filter(equipment_version_id=equipment.eid, status=1).values()
  465. if evl_qs.exists():
  466. redisObject.set_data(key=key, val=json.dumps(list(evl_qs.values())), expire=600)
  467. if evl_qs and len(evl_qs) > 0:
  468. evl = evl_qs[0]
  469. if evl['type'] == 1: # uid限制
  470. uids = json.loads(evl['content'])
  471. if not uids.__contains__(uid):
  472. return response.json(902)
  473. elif evl['type'] == 2: # user限制
  474. users = json.loads(evl['content'])
  475. if not users.__contains__(tko.userID):
  476. return response.json(902)
  477. elif evl['type'] == 3: # 国家地区限制
  478. countries = json.loads(evl['content'])
  479. country_ip_qs = CountryIPModel.objects.filter(user_ex__userID=tko.userID)
  480. if country_ip_qs.exists():
  481. country = country_ip_qs[0].country
  482. else:
  483. country = CommonService.getAddr(CommonService.get_ip_address(request))
  484. if not countries.__contains__(country):
  485. return response.json(902)
  486. file_path = equipment.filePath
  487. version = equipment.version
  488. mci = equipment.mci
  489. ver = equipment.softwareVersion
  490. max_ver = equipment.max_ver
  491. print(now_ver <= max_ver)
  492. if now_ver <= max_ver:
  493. # 创建url的token
  494. url_tko = UrlTokenObject()
  495. file_path = url_tko.generate(
  496. data={'Url': "ansjer/" + CommonService.RandomStr(6) + "/" + file_path, 'user_id': tko.userID,
  497. 'uid': uid, 'serial_number': serial_number, 'old_version': now_ver,'new_version': version, 'mci': mci})
  498. url = SERVER_DOMAIN + 'dlotapack/' + file_path
  499. print(url)
  500. # if SERVER_TYPE == 'Ansjer.formal_settings':
  501. # url = SERVER_DOMAIN + 'dlotapack/' + file_path
  502. # else:
  503. # 这里调用国内服务器进行下载,防止下载bug
  504. # if code == '18E201200CA' or code == '18E201200CZ':
  505. # url = 'http://www.zositech.xyz/dlotapack/' + file_path
  506. # else:
  507. # url = SERVER_DOMAIN + 'dlotapack/' + file_path
  508. return response.json(0, {
  509. 'ver': ver,
  510. 'url': url,
  511. "Description": equipment.Description,
  512. })
  513. else:
  514. return response.json(902)
  515. else:
  516. return response.json(902)
  517. # ota包上传
  518. class uploadOTAInterfaceView(TemplateView):
  519. @method_decorator(csrf_exempt)
  520. def dispatch(self, *args, **kwargs):
  521. return super(uploadOTAInterfaceView, self).dispatch(*args, **kwargs)
  522. def post(self, request, *args, **kwargs):
  523. request.encoding = 'utf-8'
  524. token = request.POST.get('token', None)
  525. fileName = request.FILES.get('fileName', None)
  526. fileType = request.POST.get('fileType', None)
  527. language = request.POST.get('language', None)
  528. return self.validate(token, fileName, fileType, language)
  529. def get(self, request, *args, **kwargs):
  530. request.encoding = 'gb2312'
  531. token = request.GET.get('token', None)
  532. fileName = request.FILES.get('fileName', None)
  533. fileType = request.GET.get('fileType', None)
  534. language = request.GET.get('language', None)
  535. return self.validate(token, fileName, fileType, language)
  536. def validate(self, token, fileName, fileType, language):
  537. response = ResponseObject()
  538. if not fileName or not fileType:
  539. return response.json(444, 'fileName,fileType')
  540. tko = TokenObject(token)
  541. response.lang = tko.lang
  542. if tko.code != 0:
  543. return response.json(tko.code)
  544. userID = tko.userID
  545. if not userID:
  546. return response.json(104)
  547. own_permission = ModelService.check_perm(userID=userID, permID=210)
  548. if own_permission is not True:
  549. return response.json(404)
  550. return self.upload_ota_file(fileName, response, fileType, language)
  551. def upload_ota_file(self, fileName, response, fileType, language):
  552. try:
  553. if not language:
  554. language = 0
  555. path = '/'.join((BASE_DIR, 'static/otapack', fileType, str(language))).replace('\\', '/') + '/'
  556. if not os.path.exists(path):
  557. os.makedirs(path)
  558. file_name = path + str(fileName)
  559. if os.path.exists(file_name):
  560. os.remove(file_name)
  561. destination = open(file_name, 'wb+')
  562. for chunk in fileName.chunks():
  563. destination.write(chunk)
  564. destination.close()
  565. else:
  566. file_name = path + str(fileName)
  567. if os.path.exists(file_name):
  568. os.remove(file_name)
  569. destination = open(file_name, 'wb+')
  570. for chunk in fileName.chunks():
  571. destination.write(chunk)
  572. destination.close()
  573. except Exception as e:
  574. errorInfo = traceback.format_exc()
  575. print('上传文件错误: %s' % errorInfo)
  576. return response.json(700, {'details': repr(e)})
  577. else:
  578. index = file_name.find('static/')
  579. filePath = file_name[index:]
  580. return response.json(0, {'filePath': filePath})
  581. # ota包下载
  582. @csrf_exempt
  583. def downloadOTAInterface(request, fullPath, *callback_args, **callback_kwargs):
  584. res = ResponseObject()
  585. print('fullPath:')
  586. print(fullPath)
  587. if fullPath:
  588. if os.path.isfile(fullPath):
  589. try:
  590. wrapper = FileWrapper(open(fullPath, 'rb'))
  591. response = HttpResponse(wrapper, content_type="application/octet-stream")
  592. response['Content-Length'] = os.path.getsize(fullPath)
  593. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(fullPath)
  594. response['Content-MD5'] = getMD5orSHA265(fullPath)
  595. # 校验文件md5值
  596. response['Content-SHA265'] = getMD5orSHA265(fullPath, 'SHA265')
  597. response['Content-CRC32'] = getMD5orSHA265(fullPath, 'CRC32')
  598. response['Content-Error'] = res.formal(0)
  599. return response
  600. except Exception as e:
  601. return res.json(906, repr(e))
  602. else:
  603. return res.json(907)
  604. else:
  605. return res.json(444, 'fullPath')
  606. # ota包下载
  607. @csrf_exempt
  608. def downloadOTAInterfaceV2(request, fullPath, *callback_args, **callback_kwargs):
  609. res = ResponseObject()
  610. # print('fullPath:%s' % fullPath)
  611. # 解密url的token
  612. url_token = UrlTokenObject(fullPath)
  613. fp = url_token.Url
  614. serial_number = url_token.serial_number
  615. uid = url_token.uid
  616. user_id = url_token.user_id
  617. mci = url_token.mci
  618. old_version = url_token.old_version
  619. new_version = url_token.new_version
  620. logger = logging.getLogger('info')
  621. if '' == fp:
  622. # print('过期了')
  623. logger.info('过期了%s' % fp)
  624. return res.json(907)
  625. else:
  626. print('URL参数%s-%s-%s-%s-%s-', (url_token.Url,url_token.serial_number,url_token.uid,url_token.user_id,url_token.eid))
  627. fullPath = fp[14:]
  628. if fullPath:
  629. if os.path.isfile(fullPath):
  630. try:
  631. wrapper = FileWrapper(open(fullPath, 'rb'))
  632. response = HttpResponse(wrapper, content_type="application/octet-stream")
  633. response['Content-Length'] = os.path.getsize(fullPath)
  634. response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(fullPath)
  635. response['Content-MD5'] = getMD5orSHA265(fullPath)
  636. # 校验文件md5值
  637. response['Content-SHA265'] = getMD5orSHA265(fullPath, 'SHA265')
  638. response['Content-CRC32'] = getMD5orSHA265(fullPath, 'CRC32')
  639. response['Content-Error'] = res.formal(0)
  640. #设备下载OTA包,记录数据库
  641. # 记录设备OTA升级
  642. createdTime = int(time.time())
  643. DeviceOTAUpgradeRecord.objects.create(
  644. created_time=createdTime,
  645. old_version=old_version,
  646. new_version=new_version,
  647. user_id=user_id,
  648. serial_number=serial_number,
  649. uid=uid,
  650. mci=mci,
  651. )
  652. logger.info('记录成功')
  653. return response
  654. except Exception as e:
  655. logger.info('下载中断')
  656. return res.json(906, repr(e))
  657. else:
  658. logger.info('过期了--2')
  659. return res.json(907)
  660. else:
  661. return res.json(444, 'fullPath')
  662. @csrf_exempt
  663. def getDownLoadOTApackUrl(request):
  664. # QT获取升级文件的下载链接
  665. response = ResponseObject()
  666. if request.method == "POST":
  667. request_dict = request.POST
  668. elif request.method == "GET":
  669. request_dict = request.GET
  670. else:
  671. return response.json(444)
  672. deviceType = request_dict.get('deviceType', None)
  673. version = request_dict.get('version', None)
  674. if not deviceType or not version:
  675. return response.json(444, 'deviceType or version')
  676. equipmentVersion = Equipment_Version.objects.filter(mci=deviceType, version=version)
  677. # 判断是否有该版本存在
  678. if not equipmentVersion.exists():
  679. return response.json(907)
  680. file_path = equipmentVersion[0].filePath
  681. if file_path:
  682. if file_path.find('static/otapack') != -1: # 只下载otapack路径下的文件
  683. url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path # 复用app下载ota包的方式
  684. # SERVER_DOMAIN = 'https://test.dvema.com/'
  685. # url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path
  686. res = {
  687. "url": url,
  688. }
  689. return response.json(0, res)
  690. else:
  691. return response.json(901)
  692. else:
  693. return response.json(901)
  694. @csrf_exempt
  695. def checkMaxVersion(request):
  696. # QT检查ota设备软件版本是否需要更新
  697. response = ResponseObject()
  698. if request.method == "POST":
  699. request_dict = request.POST
  700. elif request.method == "GET":
  701. request_dict = request.GET
  702. else:
  703. return response.json(444)
  704. deviceType = request_dict.get('deviceType', None)
  705. version = request_dict.get('version', None) # 设备版本:当前版本+设备规格代码
  706. lang = request_dict.get('lang', None) # 'zh-Hans','en'
  707. if not deviceType or not version:
  708. return response.json(444, 'deviceType or version')
  709. now_version = version[1:version.rindex('.')] # 去掉V
  710. code = version[version.rindex('.') + 1:]
  711. equipmentVersion = Equipment_Version.objects.filter(mci=deviceType, code=code, lang=lang,
  712. status=1) # order by data_joined
  713. # 判断是否有该版本存在
  714. if not equipmentVersion.exists():
  715. return response.json(907)
  716. filePath = equipmentVersion[0].filePath
  717. softwareVersion = equipmentVersion[0].softwareVersion # 可用最新版本的版本号
  718. maxVersion = equipmentVersion[0].max_ver
  719. if now_version >= softwareVersion:
  720. # 当前版本大于等于最新版本,不需要更新
  721. return response.json(902)
  722. url = SERVER_DOMAIN + 'OTA/downloadsPack/' + filePath # 复用app下载ota包的方式
  723. res = {
  724. 'url': url,
  725. }
  726. return response.json(0, res)