views.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import time
  6. import simplejson as json
  7. from django.conf import settings
  8. from django.http import HttpResponse
  9. from pymongo.errors import DuplicateKeyError
  10. from typing import TYPE_CHECKING
  11. from apilib.utils_datetime import get_zero_time, get_tomorrow_zero_time, \
  12. to_datetime
  13. from apilib.utils_json import JsonResponse
  14. from apps.web.common.models import OperatorLog
  15. from apps.web.constant import Const, DeviceCmdCode
  16. from apps.web.core import ROLE
  17. from apps.web.core.helpers import ActionDeviceBuilder
  18. from apps.web.core.adapter.base import fill_2_hexByte
  19. from apps.web.core.exceptions import ServiceException, TestError
  20. from apps.web.exceptions import UserServerException
  21. from apps.web.core.networking import MessageSender
  22. from apps.web.core.utils import JsonErrorResponse, JsonOkResponse
  23. from apps.web.device.define import DeviceChannelType
  24. from apps.web.device.models import Device, CheckDevice
  25. from apps.web.device.models import DeviceDict
  26. from apps.web.helpers import get_wx_config
  27. from apps.web.services.bluetooth.service import ActionBtDeviceBuilder
  28. from apps.web.test.models import TestRecord, TestStats
  29. from apps.web.utils import trace_call, error_tolerate, tester_login, permission_required, \
  30. LimitAttemptsManager
  31. if TYPE_CHECKING:
  32. from django.core.handlers.wsgi import WSGIRequest
  33. from apps.web.test.models import Tester
  34. logger = logging.getLogger(__name__)
  35. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'入库失败,请重试'}))
  36. @trace_call(logger = logger)
  37. @permission_required(ROLE.tester)
  38. def bindCode(request):
  39. curr_user = request.user
  40. if not curr_user.has_privilage('bind'):
  41. return JsonResponse({'result': 0, 'description': u'您无权限绑定设备', 'payload': {}})
  42. logicalCode = str(request.GET.get('logicalCode'))
  43. imei = str(request.GET.get('imei'))
  44. logger.debug('logicalCode = %s; devNo = %s' % (logicalCode, imei))
  45. if not logicalCode:
  46. return JsonResponse({'result': 0, 'description': u'设备编号为空', 'payload': {}})
  47. if not imei:
  48. return JsonResponse({'result': 0, 'description': u'设备IMEI为空', 'payload': {}})
  49. logicalCode = logicalCode.strip()
  50. if 'DATA_MATRIX' in imei:
  51. imei = imei.split(',')[1].split(';')[0].strip()
  52. elif 'MAC:' in imei:
  53. imei = imei.split(',')[0].split(':')[1].strip()
  54. elif ';' in imei:
  55. imei = imei.split(';')[0].strip()
  56. if len(imei) > 15:
  57. return JsonResponse({'result': 0, 'description': u'错误的IMEI: {}'.format(imei), 'payload': {}})
  58. dev = Device.get_collection().find_one(
  59. {'$or': [{'logicalCode': logicalCode}, {'devNo': imei, 'logicalCode': {'$nin': [None, '']}}]})
  60. if dev:
  61. return JsonResponse({'result': 0, 'description': u'已经绑定(L=%s, IMEI=%s)' % (logicalCode, imei), 'payload': {}})
  62. try:
  63. Device.bind(imei, logicalCode, curr_user)
  64. except DuplicateKeyError:
  65. return JsonResponse({
  66. 'result': 0,
  67. 'description': u'已经绑定(L=%s, IMEI=%s)' % (logicalCode, imei),
  68. 'payload': {}})
  69. except UserServerException as e:
  70. return JsonErrorResponse(description = e.message)
  71. return JsonResponse({'result': 1, 'description': u'绑定成功', 'payload': {}})
  72. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'入库失败,请重试'}))
  73. @trace_call(logger = logger)
  74. @permission_required(ROLE.tester)
  75. def unbindCode(request):
  76. curr_user = request.user # type: Tester
  77. if not curr_user.has_privilage('unbind'):
  78. return JsonResponse({'result': 0, 'description': u'您没有权限解解绑定设备', 'payload': {}})
  79. imei = str(request.GET.get('imei'))
  80. logger.debug('devNo = %s' % imei)
  81. if not imei:
  82. return JsonResponse({'result': 0, 'description': u'设备IMEI为空', 'payload': {}})
  83. if 'DATA_MATRIX' in imei:
  84. imei = imei.split(',')[1].split(';')[0].strip()
  85. elif 'MAC:' in imei:
  86. imei = imei.split(',')[0].split(':')[1].strip()
  87. try:
  88. dev = Device.get_dev(imei) # type: DeviceDict
  89. if not dev:
  90. return JsonResponse({'result': 0, 'description': u'该设备不存在', 'payload': {}})
  91. if curr_user.has_privilage('forceUnbind'):
  92. Device.unbind(dev = dev)
  93. else:
  94. Device.unbind(dev = dev, operator = curr_user)
  95. OperatorLog.log(user = request.user,
  96. level = OperatorLog.LogLevel.CRITICAL,
  97. operator_name = u'强制解除绑定',
  98. content = {
  99. 'logicalCode': dev.logicalCode,
  100. 'devNo': dev.devNo,
  101. 'iccid': dev.iccid,
  102. 'imsi': dev.imsi,
  103. 'simExpireDate': dev.get('simExpireDate', None),
  104. 'expireDate': dev.get('expireDate', None),
  105. 'location': dev.get('location'),
  106. 'softVer': dev.softVer,
  107. 'server': dev.server,
  108. 'coreVer': dev.coreVer
  109. })
  110. return JsonResponse({'result': 1, 'description': u'解绑成功', 'payload': {}})
  111. except UserServerException as e:
  112. return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
  113. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'解注册失败,请重试'}))
  114. @trace_call(logger = logger)
  115. @permission_required(ROLE.tester)
  116. def unregisterCode(request):
  117. curr_user = request.user # type: Tester
  118. if not curr_user.has_privilage('unregister'):
  119. return JsonResponse({'result': 0, 'description': u'您没有权限解注册设备', 'payload': {}})
  120. imei = str(request.GET.get('imei'))
  121. logger.debug('devNo = %s' % imei)
  122. if not imei:
  123. return JsonResponse({'result': 0, 'description': u'设备IMEI为空', 'payload': {}})
  124. try:
  125. device = Device.get_dev(imei) # type: DeviceDict
  126. if not device:
  127. return JsonResponse({'result': 0, 'description': u'该设备不存在', 'payload': {}})
  128. if not device.is_registered:
  129. return JsonResponse({'result': 0, 'description': u'该设备没有注册,不需要解绑', 'payload': {}})
  130. Device.un_register(device, force = True, operator = request.user.human_id)
  131. return JsonResponse({'result': 1, 'description': u'解注册成功', 'payload': {}})
  132. except Exception as e:
  133. return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
  134. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  135. @trace_call(logger = logger)
  136. @permission_required(ROLE.tester)
  137. def accountInfo(request):
  138. # type: (WSGIRequest)->JsonResponse
  139. return JsonResponse({"result": 1, "description": None, 'payload': request.user.to_dict()})
  140. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  141. @trace_call(logger = logger)
  142. def login(request):
  143. # type: (WSGIRequest)->JsonResponse
  144. try:
  145. payload = json.loads(request.body)
  146. username, password = payload['username'], payload['password']
  147. return tester_login(request, logger, username, password)
  148. except Exception as e:
  149. logger.exception('super manager login error = %s' % e)
  150. return JsonResponse({'result': 0, 'description': u'登录异常', 'payload': {}})
  151. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  152. @trace_call(logger = logger)
  153. @permission_required(ROLE.tester)
  154. def confirmTestResult(request):
  155. pass
  156. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  157. @trace_call(logger = logger)
  158. @permission_required(ROLE.tester)
  159. def getDeviceInfo(request):
  160. devNo = Device.get_dev_no_from_request(request)
  161. if devNo:
  162. dev = Device.get_dev(devNo) # type: DeviceDict
  163. if not dev:
  164. return JsonResponse({'result': 0, 'description': u'设备不存在,请首先绑定'})
  165. if not dev.get('devNo'):
  166. return JsonResponse({'result': 0, 'description': u'设备无对应IMEI绑定,请首先绑定'})
  167. device = Device.objects(devNo = devNo).first()
  168. if device is None:
  169. return JsonResponse({'result': 0, 'description': u'设备不存在数据库中,请首先绑定'})
  170. payload = {
  171. 'devNo': dev.devNo,
  172. 'logicalCode': dev.logicalCode,
  173. 'softVer': dev.get('softVer', ''),
  174. 'hwVer': dev.get('hwVer', ''),
  175. 'mf': dev.get('mf', ''),
  176. 'registered': dev.is_registered
  177. }
  178. if dev.channelType == DeviceChannelType.Channel_BT:
  179. return JsonResponse(
  180. {
  181. '_comment_': 1,
  182. 'result': 1,
  183. 'description': None,
  184. 'payload': payload
  185. })
  186. elif device.driverCode == Const.DEVICE_TYPE_CODE_CAR_NENGPAI:
  187. return JsonResponse(
  188. {
  189. '_comment_': 1,
  190. 'result': 1,
  191. 'description': None,
  192. 'payload': payload
  193. })
  194. else:
  195. device_info = MessageSender.send(device = dev,
  196. cmd = DeviceCmdCode.GET_DEVINFO,
  197. payload = {
  198. 'IMEI': dev['devNo']
  199. },
  200. timeout = 15,
  201. retry = 3)
  202. if device_info['rst'] == 0:
  203. payload.update({
  204. 'driverCode': device_info.get('driverCode', u'不支持该属性'),
  205. 'driverVersion': device_info.get('driverVersion', u'不支持该属性'),
  206. 'coreVer': device_info.get('core_ver', u'不支持该属性'),
  207. 'boardValid': device_info.get('board_valid', u'不支持该属性'),
  208. 'pw_cut_memory': device_info.get('pw_cut_memory', u'不支持该属性'),
  209. 'bindTime': device.dateTimeBinded.strftime(
  210. '%Y-%m-%d %H:%M:%S') if device.dateTimeBinded is not None else u'未知',
  211. 'testTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  212. })
  213. return JsonResponse(
  214. {
  215. '_comment_': 1,
  216. 'result': 1,
  217. 'description': None,
  218. 'payload': payload
  219. })
  220. else:
  221. return JsonResponse({'result': 0, 'description': u'获取模块信息超时,请检查模块是否上线,必要时重启模块'})
  222. return JsonResponse({'result': 0, 'description': u'设备不存在'})
  223. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  224. @trace_call(logger = logger)
  225. @permission_required(ROLE.tester)
  226. def getTestResultList(request):
  227. results = CheckDevice.objects()
  228. return JsonResponse(
  229. {
  230. 'result': 1,
  231. 'description': None,
  232. 'payload': {'total': 0, 'items': []}
  233. })
  234. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  235. @trace_call(logger = logger)
  236. @permission_required(ROLE.tester)
  237. def onPoints(request):
  238. """
  239. 远程上分, 代理商通过上分测试机器系统流程正确。
  240. :param request:
  241. :return:
  242. """
  243. logicalCode = str(request.POST.get('value', None))
  244. devNo = Device.get_devNo_by_logicalCode(logicalCode)
  245. logger.info('l=%s,devNo=%s' % (logicalCode, devNo))
  246. if not devNo:
  247. return JsonResponse({'result': 0, 'description': u'设备不存在'})
  248. score = int(request.POST.get('coins', '1'))
  249. intfType = request.POST.get('type', 'pulse')
  250. # 通知设备,付款
  251. dev = Device.get_dev(devNo) # type:DeviceDict
  252. if dev.is_registered:
  253. return JsonResponse({'result': 0, 'description': u'该设备已注册,不支持测试,如需测试,请首先解除绑定!'})
  254. # 到设备上获取驱动编码信息
  255. if 'driverCode' in dev and dev['driverCode'] == Const.DEVICE_TYPE_CODE_CAR_NENGPAI:
  256. try:
  257. device_adapter = ActionDeviceBuilder.create_action_device(dev, typeCode = Const.DEVICE_TYPE_CODE_CAR_NENGPAI)
  258. result = device_adapter.test(coins = score)
  259. if result['rst'] == -1:
  260. return JsonResponse({'result': 0, 'description': u'下发命令超时, 请检查设备是否快闪上线'})
  261. elif result['rst'] == 1:
  262. return JsonResponse({'result': 0, 'description': u'串口命令超时,请检查设备和模块之间的串口连线'})
  263. elif result['rst'] != 0:
  264. if not result.has_key('desc'):
  265. return JsonResponse({'result': 0, 'description': u'未知错误({}),请联系平台客服'.format(result['rst'])})
  266. else:
  267. return JsonResponse({'result': 0, 'description': u'错误:({}),请联系平台客服'.format(result['desc'])})
  268. except ServiceException, e:
  269. return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
  270. return JsonResponse({'result': 1, 'description': u'success'})
  271. devInfo = MessageSender.send(dev, DeviceCmdCode.GET_DEVINFO, {'IMEI': dev['devNo']})
  272. if 'rst' in devInfo and devInfo['rst'] != 0:
  273. if devInfo['rst'] == -1:
  274. return JsonResponse({'result': 0, 'description': u'下发命令超时, 请检查设备是否快闪上线'})
  275. elif devInfo['rst'] == 1:
  276. return JsonResponse({'result': 0, 'description': u'串口命令超时,请检查设备和模块之间的串口连线'})
  277. else:
  278. return JsonResponse({'result': 0, 'description': u'未知错误({}),请联系平台客服'})
  279. if 'driverCode' in devInfo and intfType == 'uart':
  280. type_code = devInfo['driverCode']
  281. elif intfType == 'pulse':
  282. type_code = Const.DEVICE_TYPE_CODE_PULSE
  283. elif 'soft_ver' in devInfo:
  284. version = devInfo['soft_ver'].split('.')[0].upper()
  285. if version >= 'V7':
  286. type_code = Const.DEVICE_TYPE_CODE_CHANGING_WEIFULE
  287. if 'V7.1' in version:
  288. type_code = Const.DEVICE_TYPE_CODE_CHANGING_WEIFULE2
  289. else:
  290. return JsonResponse({'result': 0, 'description': u'不支持该设备类型的设备测试'})
  291. try:
  292. device_adapter = ActionDeviceBuilder.create_action_device(dev, typeCode = type_code)
  293. result = device_adapter.test(coins = score)
  294. if result['rst'] == -1:
  295. return JsonResponse({'result': 0, 'description': u'下发命令超时, 请检查设备是否快闪上线'})
  296. elif result['rst'] == 1:
  297. return JsonResponse({'result': 0, 'description': u'串口命令超时,请检查设备和模块之间的串口连线'})
  298. elif result['rst'] != 0:
  299. if not result.has_key('desc'):
  300. return JsonResponse({'result': 0, 'description': u'未知错误({}),请联系平台客服'.format(result['rst'])})
  301. else:
  302. return JsonResponse({'result': 0, 'description': u'错误:({}),请联系平台客服'.format(result['desc'])})
  303. except ServiceException, e:
  304. return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
  305. return JsonResponse({'result': 1, 'description': u'success'})
  306. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  307. @trace_call(logger = logger)
  308. @permission_required(ROLE.tester)
  309. def onBtPoints(request):
  310. payload = json.loads(request.body)
  311. logicalCode = payload.get('logicalCode')
  312. major = int(payload.get('major', 0x1))
  313. minor = int(payload.get('minor', 0x1))
  314. dev = Device.get_dev_by_logicalCode(logicalCode) # type: DeviceDict
  315. if not dev:
  316. return JsonResponse({'result': 0, 'description': u'设备不存在'})
  317. if dev.is_registered:
  318. return JsonResponse({'result': 0, 'description': u'该设备已注册,不支持测试,如需测试,请首先解除绑定!'})
  319. dev['major'] = major
  320. dev['minor'] = minor
  321. actionBox = ActionBtDeviceBuilder.create(Const.BT_DEVICE_TYPE_CODE_MAP[int(payload.get('code', 1))], dev)
  322. return JsonResponse({'result': 1, 'description': '',
  323. 'payload': {
  324. 'command': actionBox.encode_cmd(
  325. cmdId = 1,
  326. **{
  327. 'attachParas':
  328. {
  329. 'package': {
  330. 'coins': int(payload.get('coins', 1))
  331. }
  332. },
  333. 'seqNo': int(time.time())})}})
  334. @trace_call(logger = logger)
  335. @permission_required(ROLE.tester)
  336. def labelDevice(request):
  337. """
  338. 标记坏的设备,便于我们记录错误信息
  339. :param request:
  340. :return:
  341. """
  342. payload = json.loads(request.body)
  343. logicalCode = payload.get('logicalCode', None)
  344. devNo = Device.get_devNo_by_logicalCode(logicalCode)
  345. label = payload.get('label', '')
  346. if not devNo:
  347. return JsonResponse({'result': 0, 'description': u'设备不存在'})
  348. try:
  349. CheckDevice.get_collection().update_one({'imei': devNo}, {'$set': {'label': label}},
  350. upsert = False)
  351. except Exception, e:
  352. logger.exception('[label_device]update checkdevice error = %s' % e)
  353. return JsonResponse({'result': 0, 'description': 'update checkdevice error=%s' % e})
  354. return JsonResponse({'result': 1, 'description': u'success'})
  355. @trace_call(logger = logger)
  356. @permission_required(ROLE.tester)
  357. def getDeviceLabel(request):
  358. """
  359. 标记坏的设备,便于我们记录错误信息
  360. :param request:
  361. :return:
  362. """
  363. logicalCode = request.POST.get('value', None)
  364. devNo = Device.get_devNo_by_logicalCode(logicalCode)
  365. if not devNo:
  366. return JsonResponse({'result': 0, 'description': u'设备不存在'})
  367. try:
  368. results = CheckDevice.get_collection().find({'imei': devNo})
  369. except Exception, e:
  370. logger.info('update check device error = %s' % e)
  371. return JsonResponse({'result': 0, 'description': 'update check device error=%s' % e})
  372. if len(results) == 0:
  373. return JsonResponse({'result': 0, 'description': u'没有找到设备的标记信息'})
  374. result = {}
  375. result['devNo'] = results[0]['devNo']
  376. result['logicalCode'] = results[0]['logicalCode']
  377. result['testTime'] = results[0]['testTime']
  378. result['testResult'] = results[0]['testResult']
  379. result['testResultDesc'] = results[0]['testResultDesc']
  380. result['bindTime'] = results[0]['bindTime']
  381. result['devNo'] = results[0]['devNo']
  382. result['label'] = results[0]['label']
  383. return JsonResponse({'result': 1, 'description': u'success', 'payload': result})
  384. @trace_call(logger = logger)
  385. def wxconfig(request):
  386. url = request.GET.get('href')
  387. if not url:
  388. return JsonResponse({'result': 0, 'description': u'参数错误', 'payload': {}})
  389. value = get_wx_config(None, url)
  390. return JsonOkResponse(payload = {'wxconfig': value})
  391. @permission_required(ROLE.tester)
  392. def setComDriver(request):
  393. driverName = request.POST.get("driverName")
  394. logicalCode = request.POST.get("logicalCode")
  395. dev = Device.get_dev_by_logicalCode(logicalCode)
  396. result = MessageSender.send(dev, DeviceCmdCode.SET_DEVINFO, {
  397. 'IMEI': dev['devNo'],
  398. 'driver_set': {
  399. 'driver_url': 'http://www.washpayer.com/uploaded/' + driverName + '.driver'
  400. }
  401. })
  402. if result['rst'] != 0:
  403. return JsonResponse({'result': 0, 'description': u'安装驱动失败', 'payload': {}})
  404. return JsonResponse({'result': 1, 'description': None, 'payload': {}})
  405. @permission_required(ROLE.tester)
  406. def getComDriver(request):
  407. logicalCode = request.GET.get("logicalCode")
  408. dev = Device.get_dev_by_logicalCode(logicalCode)
  409. devInfo = MessageSender.send(dev, DeviceCmdCode.GET_DEVINFO, {
  410. 'IMEI': dev['devNo']
  411. })
  412. if devInfo['rst'] != 0:
  413. return JsonResponse({'result': 0, 'description': u'查询驱动失败', 'payload': {}})
  414. return JsonResponse({'result': 1, 'description': None, 'payload': {
  415. 'driverCode': devInfo['driverCode'], 'driverVersion': 'driverVersion'}})
  416. @error_tolerate(logger = logger, nil = JsonResponse({'result': 0, 'description': u'系统错误'}))
  417. @permission_required(ROLE.tester)
  418. def checkLogicalBindingByRange(request):
  419. # type: (WSGIRequest)->JsonResponse
  420. """
  421. 检测逻辑码在某一个范围是否都绑定了
  422. :param request:
  423. :return:
  424. """
  425. payload = json.loads(request.body)
  426. # todo 这个不用了,后续写在Validation类里面
  427. # try:
  428. # logicalCodeRange(payload)
  429. # except MultipleInvalid:
  430. # return JsonErrorResponse(description=u'编号只能输入数字')
  431. start = payload.get('start')
  432. end = payload.get('end')
  433. strStart = str(start)
  434. strEnd = str(end)
  435. if 'G' in strStart and 'G' in strEnd:
  436. title = 'G'
  437. start = strStart[1:]
  438. end = strEnd[1:]
  439. elif 'R' in strStart and 'R' in strEnd:
  440. title = 'R'
  441. start = strStart[1:]
  442. end = strEnd[1:]
  443. elif 'N' in strStart and 'N' in strEnd:
  444. title = 'N'
  445. start = strStart[1:]
  446. end = strEnd[1:]
  447. elif 'B' in strStart and 'B' in strEnd:
  448. title = 'B'
  449. start = strStart[1:]
  450. end = strEnd[1:]
  451. else:
  452. title = ''
  453. spec = [title + str(_) for _ in xrange(int(start), int(end) + 1)]
  454. match = [_['logicalCode'] for _ in Device.get_collection().find({'logicalCode': {'$in': spec}})]
  455. diff = set(spec) - set(match)
  456. unbind_count = len(diff)
  457. description = u'测试结果: 一共检查了%d条数据。\n' % (len(spec),)
  458. description += u'全部已经绑定' if not bool(unbind_count) else u'有未绑定逻辑码(%s)条,它们为 %s' % (unbind_count, ', '.join(diff))
  459. return JsonResponse({'result': 1, 'description': description, 'payload': {}})
  460. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'更新错误'))
  461. @permission_required(ROLE.tester)
  462. def resetPassword(request):
  463. # type: (WSGIRequest)->JsonResponse
  464. tester = request.user
  465. oldPassword = request.POST.get('oldPassword', "")
  466. if not oldPassword:
  467. return JsonResponse({"result": 0, "description": u"请输入旧密码", 'payload': {}})
  468. limitManager = LimitAttemptsManager('resetPassword', oldPassword)
  469. if limitManager.is_exceeded_limit():
  470. return JsonResponse({'result': 0, 'description': u'超出输入错误次数限制,请明日再试', 'payload': {}})
  471. if tester.check_password(oldPassword):
  472. password = request.POST.get('password', "")
  473. if password == "":
  474. return JsonResponse({"result": 0, "description": u"请输入密码", 'payload': {}})
  475. try:
  476. tester.set_password(password)
  477. limitManager.clear()
  478. return JsonResponse({"result": 1, "description": None, 'payload': {}})
  479. except Exception, e:
  480. logger.exception('update Dealer password some error=%s' % e)
  481. limitManager.incr()
  482. return JsonResponse({
  483. 'result': 0,
  484. 'description': u'旧密码输入错误,您还可输入%s次' % limitManager.times_left(),
  485. 'payload': {}
  486. })
  487. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'获取特性错误'))
  488. @permission_required(ROLE.tester)
  489. def getFeatureList(request):
  490. features = request.user.features
  491. resultDict = {}
  492. for f in features:
  493. resultDict[f] = True
  494. return JsonOkResponse(payload = resultDict)
  495. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'测试错误'))
  496. @permission_required(ROLE.tester)
  497. def dlxTest(request):
  498. payload = json.loads(request.body)
  499. ports = payload['ports']
  500. logicalCode = payload['logicalCode']
  501. # 首先检查驱动是否正确
  502. dev = Device.get_dev_by_l(logicalCode)
  503. if dev.get('ownerId'):
  504. return JsonResponse({'result': 0, 'description': u'该设备已注册,不支持测试,如需测试,请首先解除绑定!'})
  505. try:
  506. devInfo = MessageSender.send(dev, DeviceCmdCode.GET_DEVINFO, {'IMEI': dev['devNo']})
  507. except Exception, e:
  508. return JsonResponse({'result': 1, 'description': u'检测失败,网络通讯失败。'})
  509. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  510. if devInfo['rst'] == -1:
  511. return JsonResponse({'result': 0, 'description': u'检测失败,设备网络通讯超时。'})
  512. elif devInfo['rst'] == 1:
  513. return JsonResponse({'result': 0, 'description': u'检测失败,模块之间的串口通讯超时, 设备的串口接线可能有问题。'})
  514. if devInfo['driverCode'] != Const.DEVICE_TYPE_CODE_CHARGING_DIANCHUAN:
  515. return JsonResponse({'result': 0, 'description': u'检测失败,设备驱动错误。'})
  516. for port in ports:
  517. try:
  518. hexPort = fill_2_hexByte(hex(int(port)), 2)
  519. hexTime = fill_2_hexByte(hex(1))
  520. devInfo = MessageSender.send(dev, DeviceCmdCode.OPERATE_DEV_SYNC,
  521. {'IMEI': dev['devNo'], "funCode": '02', 'data': hexPort + '0000' + hexTime})
  522. except Exception, e:
  523. return JsonResponse({'result': 0, 'description': u'检测失败,启动多个端口的时候失败,可能是因为您的网络不好,请重试。'})
  524. return JsonOkResponse()
  525. @error_tolerate(logger = logger, nil = JsonErrorResponse(u"测试出现异常,请稍后重试"))
  526. @permission_required(ROLE.tester)
  527. def serialTest(request):
  528. """
  529. 串口测试 这个地方或做成类似 设备参数设置函数一样的
  530. 此函数只负责 测试串口 结果 测试是否通过由测试人员决定
  531. :param request:
  532. :return:
  533. """
  534. payload = json.loads(request.body)
  535. logicalCode = payload.get("logicalCode", "")
  536. if not logicalCode:
  537. return JsonErrorResponse(u"请先扫码获取设备逻辑码")
  538. device = Device.objects.filter(logicalCode = logicalCode).first()
  539. if not device:
  540. return JsonErrorResponse(u"设备尚未绑定入库")
  541. driverCode = device.driverCode
  542. dev = Device.get_dev_by_logicalCode(logicalCode)
  543. # TODO 德力西的先兼容 后续搞到serialTest上去
  544. if driverCode in ["100210", "100205"]:
  545. return dlxTest(request)
  546. box = ActionDeviceBuilder.create_action_device(dev, typeCode = driverCode)
  547. try:
  548. result = box.serial_test(payload)
  549. except NotImplementedError:
  550. return JsonErrorResponse(description = u"该设备尚不支持串口测试")
  551. except TestError as e:
  552. # 这个地方主要会有三种错误,一是串口不通 二是网络超时 三是设备明确表示串口失败
  553. return JsonErrorResponse(description = str(e))
  554. return JsonOkResponse(result.get("description", ""))
  555. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'记录结果错误'))
  556. @permission_required(ROLE.tester)
  557. def recordTestResult(request):
  558. payload = json.loads(request.body)
  559. logicalCode = payload.get('logicalCode')
  560. result = payload.get('result')
  561. desc = payload.get('desc')
  562. username = request.user.username
  563. nickname = request.user.nickname
  564. nowTime = datetime.datetime.now()
  565. sTime = get_zero_time(nowTime)
  566. eTime = get_tomorrow_zero_time(nowTime)
  567. # 先把今天的这台测试记录删除掉
  568. TestRecord.objects.filter(testerName = username, logicalCode = logicalCode, dateTimeAdded__gte = sTime,
  569. dateTimeAdded__lte = eTime).delete()
  570. # 增加进来
  571. if result == 'success':
  572. desc = u'扫码测试通过'
  573. TestRecord(testerName = username, nickname = nickname, logicalCode = logicalCode, result = result, desc = desc,
  574. dateTimeAdded = nowTime).save()
  575. rcds = TestRecord.objects.filter(testerName = username, dateTimeAdded__gte = sTime, dateTimeAdded__lte = eTime)
  576. allCount, success, failed = 0, 0, 0
  577. for rcd in rcds:
  578. if rcd.result == 'failed':
  579. failed += 1
  580. elif rcd.result == 'success':
  581. success += 1
  582. else:
  583. pass
  584. allCount += 1
  585. okScale = int(success * 100.0 / allCount)
  586. today = nowTime.strftime(Const.DATE_FMT)
  587. TestStats.get_collection().update({'date': today, 'testerName': username},
  588. {'$set': {
  589. 'testerName': username,
  590. 'nickname': nickname,
  591. 'date': today,
  592. 'all': allCount,
  593. 'success': success,
  594. 'failed': failed,
  595. 'okScale': okScale
  596. }}, upsert = True)
  597. return JsonOkResponse()
  598. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'获取统计错误'))
  599. @permission_required(ROLE.tester)
  600. def getTestStatsByDay(request):
  601. # payload = json.loads(request.body)
  602. startDay = request.GET.get('startDay')
  603. endDay = request.GET.get('endDay')
  604. pageIndex = int(request.GET.get('pageIndex'))
  605. pageSize = int(request.GET.get('pageSize'))
  606. rcds = TestStats.objects.filter(date__gte = startDay, date__lte = endDay, testerName = request.user.username)
  607. showRcds = rcds.paginate(pageIndex = pageIndex, pageSize = pageSize)
  608. dataList = [{'count': rcd.all, 'successCount': rcd.success, 'failCount': rcd.failed, 'date': rcd.date} for rcd in
  609. showRcds]
  610. return JsonOkResponse(payload = {'total': rcds.count(), 'dataList': dataList})
  611. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'获取统计错误'))
  612. @permission_required(ROLE.tester)
  613. def queryTestRcds(request):
  614. pageIndex = int(request.GET.get('pageIndex'))
  615. pageSize = int(request.GET.get('pageSize'))
  616. searchKey = str(request.GET.get('searchKey', ''))
  617. date = request.GET.get('date', None)
  618. if date is not None:
  619. today = to_datetime(date + ' 00:00:00')
  620. sTime = get_zero_time(today)
  621. eTime = get_tomorrow_zero_time(today)
  622. rcds = TestRecord.objects(testerName = request.user.username, dateTimeAdded__gte = sTime,
  623. dateTimeAdded__lte = eTime).search(searchKey).order_by('-dateTimeAdded')
  624. else:
  625. rcds = TestRecord.objects(testerName = request.user.username).search(searchKey).order_by('-dateTimeAdded')
  626. dataList = []
  627. for rcd in rcds.paginate(pageIndex = pageIndex, pageSize = pageSize):
  628. dataList.append({
  629. 'logicalCode': rcd.logicalCode,
  630. 'result': rcd.result,
  631. 'desc': rcd.desc,
  632. 'dateTimeAdded': rcd.dateTimeAdded.strftime(Const.DATETIME_FMT)
  633. })
  634. return JsonOkResponse(payload = {'total': rcds.count(), 'dataList': dataList})
  635. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'获取统计错误'))
  636. @permission_required(ROLE.tester)
  637. def queryDeviceTestDetail(request):
  638. logicalCode = request.GET.get('logicalCode')
  639. devs = Device.get_collection().find({'logicalCode': logicalCode})
  640. if devs.count < 0:
  641. return JsonErrorResponse(description = u'查询失败,没有找到设备')
  642. devDict = devs[0]
  643. dataList = []
  644. if devDict.has_key('dateTimeBinded') and devDict['dateTimeBinded']:
  645. dataList.insert(0, {'time': devDict['dateTimeBinded'].strftime(Const.DATETIME_FMT), 'desc': u'绑定二维码成功',
  646. 'name': u'维码器生产商'})
  647. if devDict.has_key('simActiveFirstTime') and devDict['simActiveFirstTime']:
  648. dataList.insert(0, {'time': devDict['simActiveFirstTime'].strftime(Const.DATETIME_FMT), 'desc': u'设备首次上线成功',
  649. 'name': u'模块生产商'})
  650. rcds = TestRecord.objects.filter(logicalCode = logicalCode).order_by('dateTimeAdded')
  651. for rcd in rcds:
  652. dataList.insert(0, {'time': rcd.dateTimeAdded.strftime(Const.DATETIME_FMT), 'desc': rcd.desc,
  653. 'name': rcd.nickname})
  654. return JsonOkResponse(payload = {'dataList': dataList})
  655. def getCookies(request):
  656. response = HttpResponse()
  657. if settings.DEBUG:
  658. from urllib import unquote
  659. session = ''
  660. for key in request.session.keys():
  661. session += '<h2>{} -- {}</h2>'.format(key, request.session.get(key))
  662. cookies = ''
  663. for key in request.COOKIES.keys():
  664. cookies += '<h2>{} -- {}</h2>'.format(key, unquote(request.COOKIES.get(key)))
  665. response.content = '<h1>SESSION</h1>{}<hr><h1>COOKIES</h1>{}'.format(session, cookies)
  666. return response
  667. def setCookies(request):
  668. key = request.GET.get('k', 'jump')
  669. value = request.GET.get('v', '')
  670. if not value:
  671. resp = HttpResponse(
  672. '<h1>设置失败 {}--{}</h1>'.format(key, value)
  673. )
  674. else:
  675. resp = HttpResponse(
  676. '<h1>设置成功 {}--{}</h1>'.format(key, value)
  677. )
  678. resp.set_cookie(key = key, value = value, max_age = 24 * 3600 * 30, domain = settings.COOKIE_DOMAIN)
  679. return resp
  680. def clearCookies(request):
  681. response = HttpResponse('清理成功')
  682. if settings.DEBUG:
  683. session = ''
  684. for key in request.session.keys():
  685. session += '<h2>{} -- {}</h2>'.format(key, request.session.get(key))
  686. from urllib import unquote
  687. cookies = ''
  688. for key in request.COOKIES.keys():
  689. cookies += '<h2>{} -- {}</h2>'.format(key, unquote(request.COOKIES.get(key)))
  690. response.content = '<h1>清理成功</h1><h1>SESSION</h1>{}<hr><h1>COOKIES</h1>{}'.format(session, cookies)
  691. # session清除
  692. request.session.clear()
  693. # cookie清除
  694. for key in request.COOKIES.keys():
  695. response.delete_cookie(key, domain = settings.COOKIE_DOMAIN)
  696. return response
  697. def bindParentNode(request):
  698. logicalCode = request.GET.get('childLogicalCode')
  699. gateImei = request.GET.get('parentLogicalCode')
  700. devObj = Device.objects(logicalCode = logicalCode).first()
  701. if devObj is None:
  702. return JsonErrorResponse(description = u"没有找到该设备")
  703. if not gateImei:
  704. return JsonErrorResponse(description = u"网关的IMEI没有传入")
  705. Device.get_collection().update({'logicalCode': logicalCode}, {'$set': {'gateImei': gateImei}})
  706. return JsonOkResponse()
  707. def unbindParentNode(request):
  708. logicalCode = request.POST['logicalCode']
  709. devObj = Device.objects(logicalCode = logicalCode).first()
  710. if devObj:
  711. Device.get_collection().update({'logicalCode': logicalCode}, {'$set': {'gateImei': ''}})
  712. return JsonOkResponse()
  713. else:
  714. return JsonErrorResponse(description = u"没有找到该设备")