weifuleCar.py 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import re
  6. import threading
  7. import time
  8. from decimal import Decimal
  9. from django.core.cache import cache
  10. from apilib.monetary import RMB
  11. from apilib.utils_AES import EncryptDate
  12. from apps import serviceCache
  13. from apps.web.common.proxy import ClientConsumeModelProxy
  14. from apps.web.constant import DeviceCmdCode, ErrorCode, Const, MQTT_TIMEOUT
  15. from apps.web.core.adapter.base import SmartBox
  16. from apps.web.core.exceptions import ServiceException, DeviceNetworkTimeoutError, StartDeviceError, UartTimeoutError
  17. from apps.web.core.networking import MessageSender
  18. from apps.web.device.models import Device, DeviceType
  19. from apps.web.user.models import ServiceProgress, Card, MyUser, ConsumeRecord
  20. cardKey = 'FR4e1OFCnDdrYA7u'
  21. logger = logging.getLogger(__name__)
  22. class ChargingWeiFuLeCarBox(SmartBox):
  23. def __init__(self, device):
  24. super(ChargingWeiFuLeCarBox, self).__init__(device)
  25. self.PORT = '1'
  26. def analyze_event_data(self, device_data):
  27. uart_data = device_data.get('data')
  28. if not uart_data:
  29. return
  30. fun_code = uart_data.get('fun_code')
  31. if not fun_code:
  32. return
  33. billingType = 'elec'
  34. cmd = fun_code
  35. if cmd == '32':
  36. return uart_data.get('order')
  37. def disable_app_device(self, switch=True):
  38. # type:(bool) -> None
  39. otherConf = self.device.get('otherConf', {})
  40. otherConf['disableDevice'] = switch
  41. Device.objects.filter(devNo=self.device['devNo']).update(otherConf=otherConf)
  42. Device.invalid_device_cache(self.device['devNo'])
  43. @staticmethod
  44. def check_params_range(params, minData=None, maxData=None, desc=''):
  45. # type:(str,float,float,str) -> str
  46. """
  47. 检查参数,返回字符串参数
  48. """
  49. if params is None:
  50. raise ServiceException({'result': 2, 'description': u'参数错误.'})
  51. if not isinstance(params, Decimal):
  52. params = Decimal(params)
  53. if not minData and maxData:
  54. if not isinstance(maxData, Decimal):
  55. maxData = Decimal(maxData)
  56. if params <= maxData:
  57. return '%g' % params
  58. else:
  59. raise ServiceException({'result': 2, 'description': u'%s超出可选范围,可选最大值为%g' % (desc, maxData)})
  60. if not maxData and minData:
  61. if not isinstance(minData, Decimal):
  62. minData = Decimal(minData)
  63. if minData <= params:
  64. return '%g' % params
  65. else:
  66. raise ServiceException({'result': 2, 'description': u'%s超出可选范围,可选最小值为%g' % (desc, minData)})
  67. if not minData and not maxData:
  68. return '%g' % params
  69. else:
  70. if not isinstance(minData, Decimal):
  71. minData = Decimal(minData)
  72. if not isinstance(maxData, Decimal):
  73. maxData = Decimal(maxData)
  74. if minData <= params <= maxData:
  75. return '%g' % params
  76. else:
  77. raise ServiceException(
  78. {'result': 2, 'description': u'%s参数超出可选范围,可取范围为%g-%g' % (desc, minData, maxData)})
  79. def send_mqtt(self, data=None, cmd=DeviceCmdCode.OPERATE_DEV_SYNC, otherData=None):
  80. """
  81. 发送mqtt 指令默认210 返回data
  82. """
  83. if data:
  84. payload = {'data': data}
  85. else:
  86. payload = otherData
  87. result = MessageSender.send(self.device, cmd,
  88. payload)
  89. if 'rst' in result and result['rst'] != 0:
  90. if result['rst'] == -1:
  91. raise ServiceException(
  92. {'result': 2, 'description': u'该设备正在玩命找网络,请您稍候再试', 'rst': -1})
  93. elif result['rst'] == 1:
  94. raise ServiceException(
  95. {'result': 2, 'description': u'该设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能', 'rst': 1})
  96. else:
  97. if cmd in [DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE]:
  98. return
  99. if result.get('data') == '00':
  100. raise ServiceException({'result': 2, 'description': u'设备操作失败.请重试'})
  101. else:
  102. return result.get('data', 'ok')
  103. def _get_all_info(self):
  104. data = {
  105. 'funCode': 2,
  106. 'all': True
  107. }
  108. data = self.send_mqtt(data)
  109. return data
  110. def _do_update_configs(self, updateDict):
  111. dev = Device.objects.get(devNo=self.device.devNo)
  112. deviceConfigs = dev.otherConf.get('deviceConfigs', {})
  113. deviceConfigs.update(updateDict)
  114. dev.otherConf['deviceConfigs'] = deviceConfigs
  115. dev.save()
  116. Device.invalid_device_cache(self.device.devNo)
  117. def _get_device_configs(self):
  118. return Device.objects.get(devNo=self.device.devNo).otherConf.get('deviceConfigs', {})
  119. def _start(self, money, order_id):
  120. amount = int(float(money) * 100)
  121. data = {
  122. 'fun_code': 7,
  123. 'amount': amount,
  124. 'order_id': order_id
  125. }
  126. payload = {'data': data}
  127. return MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, payload,
  128. timeout=MQTT_TIMEOUT.START_DEVICE)
  129. def do_ack_order_32(self, order_id):
  130. data = {
  131. 'fun_code': 32,
  132. 'order_id': order_id
  133. }
  134. self.send_mqtt(data)
  135. def do_ack_remove_order_from_device_34(self, order_id):
  136. data = {
  137. 'fun_code': 34,
  138. 'order_id': order_id
  139. }
  140. self.send_mqtt(data)
  141. def _check_dev_status(self):
  142. data = {
  143. 'fun_code': 2,
  144. 'status': True,
  145. 'exec_orders': True,
  146. 'wait_orders': True,
  147. }
  148. data = self.send_mqtt(data)
  149. exec_orders = data.get('exec_orders') or []
  150. wait_orders = data.get('wait_orders') or []
  151. order_list = []
  152. if exec_orders:
  153. order_list.append(exec_orders[0]['id'])
  154. if wait_orders:
  155. order_list += list(map(lambda x: x['id'], wait_orders))
  156. result = False
  157. status = data.get('status')
  158. if status == 'fault':
  159. raise ServiceException({'result': 2, 'description': u'该充电桩出现故障,请使用其他充电桩'})
  160. elif status == 'idle':
  161. raise ServiceException({'result': 2, 'description': u'请先连接充电枪'})
  162. elif status == 'link':
  163. result = True
  164. elif status == 'estop':
  165. raise ServiceException({'result': 2, 'description': u'该充电桩处于 紧急停止 状态,请确认充电桩安全状态后,再次扫码使用或选择其他充电桩'})
  166. elif status == 'ready':
  167. result = True
  168. elif status == 'busy':
  169. result = True
  170. else:
  171. pass
  172. return {'result': result, 'order_list': order_list}
  173. def _check_package(self, package):
  174. """
  175. 获取设备启动的发送数据 根据设备的当前模式以及套餐获取
  176. :param package:
  177. :return:
  178. """
  179. unit = package.get('unit')
  180. _time = package.get('time')
  181. billingType = 'elec'
  182. if unit != u'度':
  183. raise ServiceException({'result': 2, 'description': u'套餐单位错误,应选取单位(度),请联系经销商'})
  184. else:
  185. _time = _time
  186. return _time, unit, billingType
  187. def _transform_prices(self, prices, mode='send'):
  188. if mode == 'send':
  189. send_list = []
  190. default_price = round(float(prices.get('default_price', 0)), 2)
  191. item = ['default', default_price]
  192. send_list.append(item)
  193. if all([prices.get('time1_start_m'), prices.get('time1_start_h'), prices.get('time1_end_m'),
  194. prices.get('time1_end_h'), prices.get('price1')]):
  195. time1_start_m = '{0:0>2}'.format(prices.get('time1_start_m'))
  196. time1_start_h = '{0:0>2}'.format(prices.get('time1_start_h'))
  197. time1_end_m = '{0:0>2}'.format(prices.get('time1_end_m'))
  198. time1_end_h = '{0:0>2}'.format(prices.get('time1_end_h'))
  199. price1 = round(float(prices.get('price1', 0)), 2)
  200. if time1_end_h + ':' + time1_end_m <= time1_start_h + ':' + time1_start_m:
  201. raise ServiceException({'result': 2, 'description': u'时段1结束时间必须大于起始时间'})
  202. str = time1_start_h + ':' + time1_start_m + '-' + time1_end_h + ':' + time1_end_m
  203. item = [str, price1]
  204. send_list.append(item)
  205. else:
  206. raise ServiceException({'result': 2, 'description': u'时段1参数不完整'})
  207. if all([prices.get('time2_start_m'), prices.get('time2_start_h'), prices.get('time2_end_m'),
  208. prices.get('time2_end_h'), prices.get('price2')]):
  209. time2_start_m = '{0:0>2}'.format(prices.get('time2_start_m'))
  210. time2_start_h = '{0:0>2}'.format(prices.get('time2_start_h'))
  211. time2_end_m = '{0:0>2}'.format(prices.get('time2_end_m'))
  212. time2_end_h = '{0:0>2}'.format(prices.get('time2_end_h'))
  213. price2 = round(float(prices.get('price2', 0)), 2)
  214. if time2_end_h + ':' + time2_end_m <= time2_start_h + ':' + time2_start_m:
  215. raise ServiceException({'result': 2, 'description': u'时段2结束时间必须大于起始时间'})
  216. str = time2_start_h + ':' + time2_start_m + '-' + time2_end_h + ':' + time2_end_m
  217. item = [str, price2]
  218. send_list.append(item)
  219. else:
  220. raise ServiceException({'result': 2, 'description': u'时段2参数不完整'})
  221. if all([prices.get('time3_start_m'), prices.get('time3_start_h'), prices.get('time3_end_m'),
  222. prices.get('time3_end_h'), prices.get('price3')]):
  223. time3_start_m = '{0:0>2}'.format(prices.get('time3_start_m'))
  224. time3_start_h = '{0:0>2}'.format(prices.get('time3_start_h'))
  225. time3_end_m = '{0:0>2}'.format(prices.get('time3_end_m'))
  226. time3_end_h = '{0:0>2}'.format(prices.get('time3_end_h'))
  227. price3 = round(float(prices.get('price3', 0)), 2)
  228. if time3_end_h + ':' + time3_end_m <= time3_start_h + ':' + time3_start_m:
  229. raise ServiceException({'result': 2, 'description': u'时段3结束时间必须大于起始时间'})
  230. str = time3_start_h + ':' + time3_start_m + '-' + time3_end_h + ':' + time3_end_m
  231. item = [str, price3]
  232. send_list.append(item)
  233. else:
  234. raise ServiceException({'result': 2, 'description': u'时段3参数不完整'})
  235. if not (time3_start_h + ':' + time3_start_m >= time2_end_h + ':' + time2_end_m and time2_start_h + ':' + time2_start_m >= time1_end_h + ':' + time1_end_m):
  236. raise ServiceException({'result': 2, 'description': u'时段的其实时间不能小于上一个时段的结束时间'})
  237. return send_list
  238. else:
  239. price_dict = {}
  240. index = 1
  241. for price in prices:
  242. if price[0] == 'default':
  243. price_dict.update({'default_price': price[1]})
  244. else:
  245. time1_start, time1_end = price[0].split('-')
  246. price_dict.update({
  247. 'time{}_start_h'.format(index): time1_start.split(':')[0],
  248. 'time{}_start_m'.format(index): time1_start.split(':')[1],
  249. 'time{}_end_h'.format(index): time1_end.split(':')[0],
  250. 'time{}_end_m'.format(index): time1_end.split(':')[1],
  251. 'price{}'.format(index): price[1]
  252. })
  253. index += 1
  254. return price_dict
  255. def _reboot_device(self):
  256. data = {
  257. 'fun_code': 11,
  258. 'reset_mcu': True,
  259. }
  260. self.send_mqtt(data)
  261. def _restart_device(self):
  262. data = {
  263. 'restart': True,
  264. }
  265. self.send_mqtt(otherData=data, cmd=DeviceCmdCode.SET_DEVINFO)
  266. def _factory_set_device(self):
  267. data = {
  268. 'factory_set': True,
  269. }
  270. self.send_mqtt(otherData=data, cmd=DeviceCmdCode.SET_DEVINFO)
  271. def _get_current_order(self):
  272. data = {
  273. 'fun_code': 2,
  274. 'exec_orders': True,
  275. }
  276. data = self.send_mqtt(data)
  277. return data.get('exec_orders', [])
  278. def _get_total_card(self):
  279. data = {
  280. 'fun_code': 8
  281. }
  282. data = self.send_mqtt(data)
  283. return {'total_card': int(data.get('total_card', 0)) / 100.0}
  284. def _reset_total_card(self):
  285. data = {
  286. 'fun_code': 9
  287. }
  288. self.send_mqtt(data)
  289. def is_port_can_use(self, port, canAdd=False):
  290. return True, ''
  291. # data = {
  292. # 'fun_code': 2,
  293. # 'status': True,
  294. # 'exec_orders': True,
  295. # 'wait_orders': True,
  296. # }
  297. # data = self.send_mqtt(data)
  298. # exec_orders = data.get('exec_orders')
  299. # wait_orders = data.get('wait_orders')
  300. #
  301. # order_list = []
  302. # if exec_orders:
  303. # order_list.append(exec_orders[0]['id'])
  304. # if wait_orders:
  305. # order_list += list(map(lambda x: x['id'], wait_orders))
  306. #
  307. # status = data.get('status')
  308. # if status == 'fault':
  309. # return False, '该充电桩出现故障,请使用其他充电桩'
  310. # elif status == 'idle':
  311. # return False, '请先连接充电枪'
  312. # elif status == 'link':
  313. # return True, ''
  314. # elif status == 'estop':
  315. # raise False, '该充电桩处于 紧急停止 状态,请确认充电桩安全状态后,再次扫码使用或选择其他充电桩'
  316. # elif status == 'ready':
  317. # return True, ''
  318. # elif status == 'busy':
  319. # return True, ''
  320. # else:
  321. # return False, '该充电桩出现故障,请使用其他充电桩'
  322. def check_dev_status(self, attachParas=None):
  323. if attachParas.get('isTempPackage') == True:
  324. washConfig = self.device.get('tempWashConfig', {})
  325. else:
  326. washConfig = self.device.get('washConfig', {})
  327. packageId = attachParas.get('packageId', '1')
  328. package = washConfig.get(packageId)
  329. # self._check_package(package)
  330. data = self._check_dev_status()
  331. openId = attachParas.get('openId')
  332. order_list = data.get('order_list')
  333. result = data.get('result')
  334. if not order_list:
  335. return result
  336. else:
  337. consumeRcd = ConsumeRecord.objects.filter(devNo=self.device.devNo, orderNo=order_list[0]).first()
  338. if not consumeRcd: # 没有找到订单 证明是刷卡启动的 或则经销商远程上分
  339. raise ServiceException({'result': 2, 'description': u'当前设备已经有其他人启动充电,请不要操作设备或充电枪, 小心触电!'})
  340. else:
  341. if consumeRcd.openId != openId:
  342. raise ServiceException({'result': 2, 'description': u'当前设备已有人在使用,请您选择空闲的设备进行操作'})
  343. else:
  344. return result
  345. def get_port_status(self, force=False):
  346. if force:
  347. self._get_port_status()
  348. ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
  349. if not ctrInfo.get(self.PORT, {}).get('status'):
  350. self._get_port_status()
  351. ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
  352. result = {}
  353. for port, info in ctrInfo.items():
  354. if port.isdigit():
  355. result[port] = info
  356. return result
  357. def async_update_portinfo_from_dev(self):
  358. class Sender(threading.Thread):
  359. def __init__(self, smartBox):
  360. super(Sender, self).__init__()
  361. self._smartBox = smartBox
  362. def run(self):
  363. try:
  364. self._smartBox._get_port_status()
  365. except Exception as e:
  366. logger.info('get port stats from dev,e=%s' % e)
  367. sender = Sender(self)
  368. sender.start()
  369. def start_device(self, package, openId, attachParas):
  370. if attachParas is None:
  371. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  372. if not attachParas.has_key('chargeIndex'):
  373. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  374. onPoints = attachParas.get('onPoints')
  375. if onPoints: # 远程上分
  376. self._check_dev_status()
  377. orderNo = ConsumeRecord.make_no()
  378. logger.info('dealer onPoints package<{}> order<{}>'.format(package, orderNo))
  379. else:
  380. orderNo = str(attachParas.get('orderNo'))
  381. coins = package.get('coins')
  382. result = self._start(coins, orderNo)
  383. if result['rst'] == 0:
  384. consumeOrder = {
  385. 'orderNo': orderNo,
  386. 'coin': package.get('coins'),
  387. 'consumeType': 'coin',
  388. }
  389. self.register_service_progress(openId, orderNo, consumeOrder, attachParas)
  390. elif result['rst'] == -1: # 网络丢失
  391. raise DeviceNetworkTimeoutError()
  392. elif result['rst'] == 1: # 充电桩已被禁用(模块没有单)
  393. raise StartDeviceError('充电桩已被禁用')
  394. elif result['rst'] == 2: # 计量器故障(模块没有单)
  395. raise StartDeviceError('计量器故障')
  396. elif result['rst'] == 3: # 串口超时(模块没有单)
  397. raise UartTimeoutError()
  398. elif result['rst'] == 4: # 充电桩故障, 请联系服务商(模块没有单)
  399. raise StartDeviceError('充电桩故障, 请联系服务商')
  400. elif result['rst'] == 5: # 未连接充电枪(模块没有单)
  401. raise StartDeviceError('未连接充电枪')
  402. elif result['rst'] == 6: # 设备急停状态(模块没有单)
  403. raise StartDeviceError('设备急停状态')
  404. elif result['rst'] == 7: # 充电启动失败(模块没有单)
  405. raise StartDeviceError('充电启动失败')
  406. elif result['rst'] == 9: # 充电启动失败(车辆侧充电器开关未闭合)
  407. raise StartDeviceError('车辆侧充电器开关未闭合')
  408. event_info = {
  409. 'cmd': 100,
  410. 'data': {
  411. 'fun_code': 32,
  412. 'order': {
  413. 'order_type': 'apps_start',
  414. 'id': orderNo,
  415. 'status': 'running',
  416. 'adapter': True
  417. }
  418. },
  419. 'IMEI': '862167056713559',
  420. 'rst': 0
  421. }
  422. return event_info
  423. def register_service_progress(self, openId, weifuleOrderNo, consumeOrder=None, attachParas=None):
  424. return ServiceProgress.objects.create(
  425. open_id=openId,
  426. device_imei=self.device.devNo,
  427. devTypeCode='100257',
  428. port=1,
  429. attachParas=attachParas if attachParas else {},
  430. start_time=int(time.time()),
  431. finished_time=int(time.time() + 24 * 60 * 60),
  432. consumeOrder=consumeOrder if consumeOrder else {},
  433. weifuleOrderNo=weifuleOrderNo,
  434. expireAt = datetime.datetime.now() + datetime.timedelta(days = 91)
  435. ).id
  436. def get_port_info(self, port):
  437. if not port or port not in [1, '1']:
  438. return {}
  439. else:
  440. data = cache.get('port_info_{}'.format(self.device.devNo))
  441. if data:
  442. return data
  443. else:
  444. data = {
  445. 'fun_code': 2,
  446. 'all': True
  447. }
  448. data = self.send_mqtt(data)
  449. exec_orders = data.get('exec_orders')
  450. ctrInfo = Device.get_dev_control_cache(self.device.devNo)
  451. lineInfo = ctrInfo.get(port, {})
  452. if exec_orders and lineInfo.get('order_id') == exec_orders[0]['id']:
  453. elec = sum(map(lambda x: x['elec'], exec_orders))
  454. data = {
  455. 'power': '%.2f' % (data.get('watt', 0)),
  456. 'voltage': '%.2f' % (data.get('volt', 0)),
  457. 'elec': '%.4f' % (elec / 1000000.0),
  458. 'ampere': '%.2f' % (data.get('ampr', 0) / 1000.0),
  459. }
  460. cache.set('port_info_{}'.format(self.device.devNo), data, 5)
  461. return data
  462. else:
  463. return {}
  464. def recharge_card(self, cardNo, money, orderNo=None):
  465. data = {
  466. 'card_no': cardNo,
  467. 'fun_code': 37,
  468. 'result': 1,
  469. 'charge': int(money * 100),
  470. 'order_id': orderNo
  471. }
  472. self.send_mqtt(data)
  473. card = Card.objects.filter(cardNo=cardNo, dealerId=self.device.ownerId).first()
  474. balance = card.balance + money
  475. return {
  476. 'result': ErrorCode.SUCCESS,
  477. 'description': ''
  478. }, balance
  479. def set_device_function(self, request, lastSetConf):
  480. update_dict = {'fun_code': 11}
  481. if request.POST.get('pile_disable') == True or request.POST.get('pile_disable') == False:
  482. update_dict.update({'pile_disable': request.POST.get('pile_disable')})
  483. self.disable_app_device(request.POST.get('pile_disable'))
  484. if request.POST.get('card_disable') == True or request.POST.get('card_disable') == False:
  485. update_dict.update({'card_disable': request.POST.get('card_disable')})
  486. if request.POST.get('scan_disable') == True or request.POST.get('scan_disable') == False:
  487. update_dict.update({'scan_disable': request.POST.get('scan_disable')})
  488. if request.POST.get('sys_pwd') == True or request.POST.get('sys_pwd') == False:
  489. update_dict.update({'sys_pwd': request.POST.get('sys_pwd')})
  490. if request.POST.get('card_refund') == True or request.POST.get('card_refund') == False:
  491. update_dict.update({'card_refund': request.POST.get('card_refund')})
  492. if request.POST.get('reboot') == True:
  493. self._reboot_device()
  494. return
  495. if request.POST.get('restart') == True:
  496. self._restart_device()
  497. return
  498. if request.POST.get('factory_set') == True:
  499. self._factory_set_device()
  500. return
  501. if request.POST.get('czskze') == True:
  502. self._reset_total_card()
  503. return
  504. self.send_mqtt(update_dict)
  505. def set_device_function_param(self, request, lastSetConf):
  506. update_dict = {'fun_code': 11}
  507. if request.POST.get('volume'):
  508. self.check_params_range(request.POST.get('volume'), minData=0, maxData=7, desc='音量')
  509. update_dict.update({'volume': int(request.POST.get('volume'))})
  510. if request.POST.get('one_card'):
  511. update_dict.update({'one_card': int(float(request.POST.get('one_card')) * 100)})
  512. if request.POST.get('max_watt'):
  513. update_dict.update({'max_watt': int(request.POST.get('max_watt'))})
  514. if request.POST.get('max_volt'):
  515. update_dict.update({'max_volt': int(request.POST.get('max_volt'))})
  516. if request.POST.get('max_ampr'):
  517. update_dict.update({'max_ampr': int(request.POST.get('max_ampr'))})
  518. if request.POST.get('card_timeout'):
  519. update_dict.update({'card_timeout': int(request.POST.get('card_timeout'))})
  520. if request.POST.get('max_time'):
  521. update_dict.update({'max_time': int(request.POST.get('max_time'))})
  522. if request.POST.get('price1'):
  523. prices = self._transform_prices(request.POST)
  524. update_dict.update({'prices': prices})
  525. if request.POST.get('sys_old_pwd'):
  526. password = serviceCache.get(self.cache_key())
  527. if not password:
  528. raise ServiceException({'result': 2, 'description': u'当前页面已过期,请刷新后重试'})
  529. enObj = EncryptDate(cardKey)
  530. password = enObj.decrypt(password)
  531. sys_old_pwd = request.POST.get('sys_old_pwd')
  532. sys_pwd = request.POST.get('sys_pwd')
  533. sys_pwd2 = request.POST.get('sys_pwd2')
  534. if sys_pwd != sys_pwd2:
  535. raise ServiceException({'result': 2, 'description': u'两次新密码输入不一致'})
  536. if not sys_pwd:
  537. raise ServiceException({'result': 2, 'description': u'请输入新密码'})
  538. if sys_old_pwd == sys_pwd:
  539. raise ServiceException({'result': 2, 'description': u'新旧密码不能为一致'})
  540. if password != sys_old_pwd:
  541. raise ServiceException({'result': 2, 'description': u'旧密码输入错误'})
  542. result = re.findall(r'[a-zA-Z0-9]{6,10}', sys_pwd)
  543. if not result or len(result[0]) != len(sys_pwd) or len(result[0]) < 6 or len(result[0]) > 10:
  544. raise ServiceException({'result': 2, 'description': u'新密码只能是6-10位,由字母或者数字'})
  545. update_dict.update({'sys_pwd': enObj.encrypt(sys_pwd)})
  546. self.send_mqtt(update_dict)
  547. serviceCache.set(self.cache_key(), enObj.encrypt(sys_pwd), 600)
  548. if request.POST.get('card_dft_pwd'):
  549. card_dft_pwd = str(request.POST.get('card_dft_pwd'))
  550. result = re.findall(r'[a-zA-Z0-9]{6}', card_dft_pwd)
  551. if not result or len(result[0]) != len(card_dft_pwd):
  552. raise ServiceException({'result': 2, 'description': u'卡片密码只能是6位,由字母或者数字组成'})
  553. update_dict.update({'card_dft_pwd': card_dft_pwd})
  554. if request.POST.get('card_dft_mny'):
  555. update_dict.update({'card_dft_mny': int(float(request.POST.get('card_dft_mny')) * 100)})
  556. if request.POST.get('card_token'):
  557. card_token = str(request.POST.get('card_token'))
  558. result = re.findall(r'[a-zA-Z0-9]{6}', card_token)
  559. if not result or len(result[0]) != len(card_token):
  560. raise ServiceException({'result': 2, 'description': u'设备刷卡标签只能是6位,由字母或者数字组成'})
  561. update_dict.update({'card_token': card_token})
  562. if request.POST.get('temp_threshold'):
  563. update_dict.update({'temp_threshold': int(request.POST.get('temp_threshold'))})
  564. if len(update_dict) > 1:
  565. self.send_mqtt(update_dict)
  566. if request.POST.get('csh_tel', None) != None:
  567. data = {
  568. 'csh_tel': request.POST.get('csh_tel')
  569. }
  570. self.send_mqtt(otherData=data, cmd=DeviceCmdCode.SET_DEVINFO)
  571. self._do_update_configs({'csh_tel': request.POST.get('csh_tel')})
  572. def get_dev_setting(self):
  573. data = {
  574. 'fun_code': 12,
  575. 'all': True,
  576. }
  577. data = self.send_mqtt(data)
  578. data['one_card'] = data.get('one_card', 0) / 100.0
  579. data['card_dft_mny'] = data.get('card_dft_mny', 0) / 100.0
  580. price = data.pop('prices')
  581. price_dict = self._transform_prices(price, 'get')
  582. sys_pwd = data.pop('sys_pwd')
  583. serviceCache.set(self.cache_key(), sys_pwd, 600)
  584. data.update(price_dict)
  585. total_card = self._get_total_card()
  586. data.update(total_card)
  587. deviceConfigs = self._get_device_configs()
  588. if deviceConfigs:
  589. data.update(deviceConfigs)
  590. return data
  591. def get_port_status_from_dev(self):
  592. data = {
  593. 'fun_code': 2,
  594. 'all': True
  595. }
  596. data = self.send_mqtt(data)
  597. exec_orders = data.get('exec_orders') or []
  598. wait_orders = data.get('wait_orders') or []
  599. status = data.get('status')
  600. item = {
  601. 'index': 1,
  602. 'power': '%.2f' % (data.get('watt', 0)),
  603. 'voltage': '%.2f' % (data.get('volt', 0)),
  604. 'ampere': '%.2f' % (data.get('ampr', 0) / 1000.0),
  605. 'status': 'fault',
  606. 'devTemp': '%.2f' % data.get('temp', 0),
  607. }
  608. if status == 'busy' or status == 'ready':
  609. item.update({'status': status})
  610. exec_order = exec_orders[0]
  611. start_time = exec_order.get('create_time')
  612. elec = exec_order.get('elec', 0)
  613. time = exec_order.get('time', 0)
  614. start_time = datetime.datetime.fromtimestamp(start_time)
  615. order_id = exec_order.get('id')
  616. consumeOrder = ConsumeRecord.objects.filter(devNo=self.device.devNo, orderNo=order_id).first()
  617. order_type = exec_order.get('order_type', 'apps_start')
  618. if order_type == 'apps_start':
  619. _info = {
  620. 'consumeType': 'mobile',
  621. 'coins': '{}{}'.format(str(RMB.fen_to_yuan(exec_order.get('amount', 0))), self.show_pay_unit),
  622. 'leftMoney': '{}{}'.format(str(RMB.fen_to_yuan(exec_order.get('left_money', 0))),
  623. self.show_pay_unit),
  624. 'consumeMoney': '{}{}'.format(str(RMB.fen_to_yuan(exec_order.get('amount', 0)) - RMB.fen_to_yuan(
  625. exec_order.get('left_money', 0))), self.show_pay_unit),
  626. 'startTime': start_time.strftime('%m-%d %H:%M:%S'),
  627. 'elec': '%.4f' % (elec / 1000000.0),
  628. 'usedTime': '%.2f' % (time / 60.0),
  629. }
  630. # 远程上分没有订单号
  631. if not consumeOrder:
  632. people = MyUser(nickname='经销商远程上分')
  633. else:
  634. people = MyUser.objects.filter(openId=consumeOrder.openId, groupId=self.device['groupId']).first()
  635. #后付费
  636. payAfterUse = consumeOrder.attachParas.get('payAfterUse')
  637. if payAfterUse:
  638. _info['consumeType'] = 'postpaid'
  639. _info.pop('leftMoney', None)
  640. _info.pop('coins', None)
  641. _info['nickName'] = people.nickname
  642. if wait_orders:
  643. waittingOrder = []
  644. for _this in wait_orders:
  645. one = {}
  646. if _this['order_type'] == 'apps_start':
  647. one['consumeType'] = 'mobile'
  648. try:
  649. consumeOne = ConsumeRecord.objects.filter(orderNo=order_id).first()
  650. if consumeOne.attachParas.get('payAfterUse'):
  651. one['consumeType'] = 'postpaid'
  652. except:
  653. pass
  654. elif _this['order_type'] == 'card_start':
  655. one['consumeType'] = 'card'
  656. one['cardNo'] = _this.get('card_no')
  657. one['cardBalance'] = '{}{}'.format(str(RMB.fen_to_yuan(_this.get('balance', 0))),
  658. self.show_pay_unit)
  659. one['coins'] = '{}{}'.format(str(RMB.fen_to_yuan(_this.get('amount', 0))), self.show_pay_unit)
  660. createTime = datetime.datetime.fromtimestamp(_this['create_time'])
  661. one['createTime'] = createTime.strftime('%m-%d %H:%M:%S')
  662. waittingOrder.append(one)
  663. _info['waittingOrder'] = waittingOrder
  664. elif order_type == 'card_start':
  665. card_no = exec_order.get('card_no')
  666. _info = {
  667. 'consumeType': 'card',
  668. 'cardNo': card_no,
  669. 'coins': '{}{}'.format(str(RMB.fen_to_yuan(exec_order.get('amount', 0))), self.show_pay_unit),
  670. 'cardLeftMoney': '{}{}'.format(str(RMB.fen_to_yuan(exec_order.get('left_money', 0))),
  671. self.show_pay_unit),
  672. 'cardBalance': '{}{}'.format(str(RMB.fen_to_yuan(exec_order.get('balance', 0))),
  673. self.show_pay_unit),
  674. 'cardConsumeMoney': '{}{}'.format(
  675. str(RMB.fen_to_yuan(exec_order.get('amount', 0)) - RMB.fen_to_yuan(
  676. exec_order.get('left_money', 0))), self.show_pay_unit),
  677. 'startTime': start_time.strftime('%m-%d %H:%M:%S'),
  678. 'elec': '%.4f' % (elec / 1000000.0),
  679. }
  680. card = Card.objects.filter(cardNo=card_no, dealerId=self.device.ownerId).first()
  681. if card:
  682. _info.update({'nickName': card.nickName})
  683. else:
  684. _info.update({'nickName': '匿名用户'})
  685. if wait_orders:
  686. waittingOrder = []
  687. for _this in wait_orders:
  688. one = {}
  689. if _this['order_type'] == 'apps_start':
  690. one['consumeType'] = 'mobile'
  691. elif _this['order_type'] == 'card_start':
  692. one['consumeType'] = 'card'
  693. one['cardNo'] = _this.get('card_no')
  694. one['cardBalance'] = '{}{}'.format(str(RMB.fen_to_yuan(_this.get('balance', 0))),
  695. self.show_pay_unit)
  696. one['coins'] = '{}{}'.format(str(RMB.fen_to_yuan(_this.get('amount', 0))), self.show_pay_unit)
  697. createTime = datetime.datetime.fromtimestamp(_this['create_time'])
  698. one['createTime'] = createTime.strftime('%m-%d %H:%M:%S')
  699. waittingOrder.append(one)
  700. _info['waittingOrder'] = waittingOrder
  701. else:
  702. _info = {}
  703. item.update(_info)
  704. elif status == 'fault':
  705. item.update({'status': status})
  706. elif status == 'estop':
  707. item.update({'status': status})
  708. elif status == 'idle':
  709. item.update({'status': status})
  710. elif status == 'link':
  711. item.update({'status': 'connected'})
  712. return [item, ]
  713. def stop(self, port=None):
  714. data = {
  715. 'fun_code': 6,
  716. 'operator': 'dealer'
  717. }
  718. self.send_mqtt(data)
  719. def active_deactive_port(self, port, active):
  720. if active == False:
  721. self.stop()
  722. def stop_by_order(self, port=None, orderNo=''):
  723. order = ConsumeRecord.objects.filter(orderNo=orderNo, isNormal=True).first()
  724. if not order:
  725. logger.info('no this order <{}>'.format(orderNo))
  726. return
  727. people = MyUser.objects.filter(openId=order.openId, groupId=self.device['groupId']).first()
  728. data = {
  729. 'fun_code': 4,
  730. 'operator': 'user',
  731. 'operator_id': str(people.id),
  732. 'order_id': orderNo
  733. }
  734. data = self.send_mqtt(data)
  735. reback_order_id = data.get('order_id')
  736. if reback_order_id and reback_order_id == orderNo:
  737. return
  738. else:
  739. # 数据库中有但是没有结束的异常单
  740. try:
  741. order.update(isNormal=False,
  742. errorDesc='异常结束,设备丢失此订单code:3,',
  743. finishedTime=datetime.datetime.now())
  744. ServiceProgress.objects.filter(device_imei = self.device.devNo,
  745. weifuleOrderNo = order.orderNo).update(
  746. isFinished = True,
  747. finished_time = int(time.time()),
  748. expireAt = datetime.datetime.now())
  749. except Exception:
  750. pass
  751. @property
  752. def isHaveStopEvent(self):
  753. return True
  754. def cache_key(self):
  755. return 'sys_pwd_{}'.format(self.device.devNo)
  756. def _get_port_status(self):
  757. data = {
  758. 'fun_code': 2,
  759. 'status': True
  760. }
  761. data = self.send_mqtt(data)
  762. status = data.get('status')
  763. if status == 'fault':
  764. res = {'status': Const.DEV_WORK_STATUS_FAULT, 'port': self.PORT}
  765. elif status == 'idle':
  766. res = {'status': Const.DEV_WORK_STATUS_IDLE, 'port': self.PORT}
  767. elif status == 'link':
  768. res = {'status': Const.DEV_WORK_STATUS_CONNECTED, 'port': self.PORT}
  769. elif status == 'estop':
  770. res = {'status': Const.DEV_WORK_STATUS_ESTOP, 'port': self.PORT}
  771. elif status == 'ready':
  772. res = {'status': Const.DEV_WORK_STATUS_READY, 'port': self.PORT}
  773. elif status == 'busy':
  774. res = {'status': Const.DEV_WORK_STATUS_WORKING, 'port': self.PORT}
  775. else:
  776. res = {'status': Const.DEV_WORK_STATUS_FAULT, 'port': self.PORT}
  777. Device.update_port_control_cache(self.device['devNo'], res)
  778. def get_current_use(self, **kw):
  779. base_data = kw.get('base_data')
  780. spDict = kw.get('spDict')
  781. # sp = ServiceProgress.objects.filter(device_imei=self.device.devNo, weifuleOrderNo=spDict.get('weifuleOrderNo')).first()
  782. portInfo = serviceCache.get('_all_orders_{}'.format(self.device.devNo))
  783. if not portInfo:
  784. data = {'fun_code': 2, 'all': True}
  785. portInfo = self.send_mqtt(data)
  786. serviceCache.set('_all_orders_{}'.format(self.device.devNo), portInfo, 5)
  787. exec_orders = portInfo.get('exec_orders') or []
  788. wait_orders = portInfo.get('wait_orders') or []
  789. all_orders = exec_orders + wait_orders
  790. unit = self.show_pay_unit
  791. result_list = [] # 数据整理返回
  792. for order in all_orders:
  793. if order['id'] != spDict['weifuleOrderNo']:
  794. continue
  795. item = {}
  796. item.update(base_data)
  797. item['orderNo'] = order['id']
  798. if order['status'] == 'running':
  799. item['voltage'] = round(portInfo.get('volt', 0), 2)
  800. item['power'] = round(portInfo.get('watt', 0), 2)
  801. item['ampere'] = round((portInfo.get('ampr', 0) * 0.001), 2)
  802. item['elec'] = round(order.get('elec', 0) * 0.000001, 4)
  803. item['usedTime'] = round(order.get('time', 0) / 60.0, 2)
  804. consumeType = 'card' if 'card_no' in order else 'mobile'
  805. item['consumeMoney'] = '{}{}'.format(round(order.get('money', 0) * 0.01, 2), unit)
  806. item['leftMoney'] = '{}{}'.format(round(order.get('left_money', 0) * 0.01, 2), unit)
  807. item['order'] = {
  808. 'orderNo': order['id'], # 停止按钮传订单停单用
  809. 'coin': '{}{}'.format(round(order.get('amount', 0) * 0.01, 2), unit),
  810. 'consumeType': consumeType,
  811. }
  812. if 'card_no' in order:
  813. item['cardNo'] = order['card_no']
  814. elif order['status'] == 'waiting':
  815. item['desc'] = '此订单已经下发到设备上,上一单运行完毕就会自动运行此订单'
  816. consumeType = 'card' if 'card_no' in order else 'mobile'
  817. item['order'] = {
  818. 'orderNo': order['id'], # 停止按钮传订单停单用
  819. 'coin': '{}{}'.format(round(order.get('amount', 0) * 0.01, 2), unit),
  820. 'consumeType': consumeType,
  821. }
  822. if 'cardNo' in order:
  823. item['cardNo'] = order['card_no']
  824. try:
  825. consumeRcd = ConsumeRecord.objects.filter(orderNo=order['id']).first()
  826. # 问题单兼容
  827. payAfterUse = consumeRcd.attachParas.get('payAfterUse')
  828. if payAfterUse:
  829. item['order'] = {
  830. 'orderNo': order['id'], # 停止按钮传订单停单用
  831. 'coin': '{}{}'.format(0, unit),
  832. 'consumeType': 'postpaid',
  833. }
  834. item.pop('leftMoney', None)
  835. except:
  836. pass
  837. item.update(DeviceType.get_services_button(self.device['devType']['id']))
  838. result_list.append(item)
  839. break
  840. if not result_list:
  841. ServiceProgress.objects.filter(device_imei=self.device.devNo,
  842. weifuleOrderNo=spDict.get('weifuleOrderNo')).update(
  843. isFinished=True,
  844. expireAt = datetime.datetime.now())
  845. ConsumeRecord.objects.filter(devNo=self.device.devNo, isNormal=True,
  846. orderNo=spDict.get('weifuleOrderNo')).update(isNormal=False,
  847. errorDesc='异常结束,设备订单丢失 code:4',
  848. finishedTime=datetime.datetime.now())
  849. return result_list
  850. @property
  851. def show_pay_unit(self):
  852. """
  853. 前台显示付费的时候,目前有不同的客户希望 显示不同的单位 有的显示金币 有的显示元, 这个地方处理下
  854. :return:
  855. """
  856. if self.device['otherConf'].get('pay_unit'):
  857. return self.device['otherConf'].get('pay_unit')
  858. return u'币'
  859. def dealer_get_port_status(self):
  860. """
  861. 远程上分的时候获取端口状态
  862. :return:
  863. """
  864. return self.get_port_status(force=True)
  865. def check_order_state(self, openId):
  866. dealerId = self.device.ownerId
  867. return ClientConsumeModelProxy.get_not_finished_record(ownerId=dealerId, openId=openId,
  868. devTypeCode=self._device['devType']['code'],
  869. attachParas__payAfterUse=True)
  870. def force_stop_order(self,order, **kwargs):
  871. if not order.attachParas.get('payAfterUse'):
  872. pass
  873. else:
  874. errorDesc = order.errorDesc + '经销商手动强制关单<{}>'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  875. order.update(status='finished', errorDesc=errorDesc, isNormal=False)
  876. def get_policy_infos(self):
  877. data = {
  878. 'fun_code': 12,
  879. 'all': True,
  880. }
  881. data = self.send_mqtt(data)
  882. price = data.pop('prices')
  883. price_dict = self._transform_prices(price, 'get')
  884. return price_dict
  885. def set_policy_infos(self,payload):
  886. update_dict = {'fun_code': 11}
  887. if payload.get('price1'):
  888. prices = self._transform_prices(payload)
  889. update_dict.update({'prices': prices})
  890. return self.send_mqtt(update_dict)
  891. def get_policy_for_user(self):
  892. data = {
  893. 'fun_code': 12,
  894. 'all': True,
  895. }
  896. data = self.send_mqtt(data)
  897. prices = data.get('prices')
  898. # 用默认时间填满缝隙
  899. defaultPrice = 1.5
  900. priceList = []
  901. for price in prices:
  902. if price[0] == 'default':
  903. defaultPrice = price[1]
  904. else:
  905. priceList.append(price)
  906. fillList = []
  907. for ii in range(len(priceList)-1):
  908. price = priceList[ii]
  909. if price[0] == 'default':
  910. continue
  911. endTime= price[0].split('-')[1]
  912. nextPrice = priceList[ii+1]
  913. nextStartTime = nextPrice[0].split('-')[0]
  914. if nextStartTime>endTime:
  915. fillList.append(('%s-%s' % (endTime,nextStartTime),defaultPrice))
  916. # 头尾加上时间
  917. firstTime = priceList[0][0].split('-')[0]
  918. if firstTime != '00:00':
  919. priceList.insert(0, ('00:00-%s'% firstTime,defaultPrice))
  920. tailTime = priceList[-1][0].split('-')[1]
  921. if tailTime != '24:00':
  922. priceList.append(('%s-24:00'% tailTime,defaultPrice))
  923. # 合并价格一样的时间区间
  924. startTime = priceList[0][0].split('-')[0]
  925. elecPrice = priceList[0][1]
  926. resultList = [{'startTime':startTime,'elecPrice':elecPrice}]
  927. for ii in range(len(priceList)-1):
  928. nextPrice = priceList[ii+1]
  929. if nextPrice[1] == resultList[-1]['elecPrice']:
  930. continue
  931. resultList.append({'startTime':nextPrice[0].split('-')[0],'elecPrice':nextPrice[1],'sevicePrice':0})
  932. return resultList
  933. def get_customize_score_unit(self):
  934. return u'元'
  935. def start_customize_point(self,pointNum,openId,port):
  936. package = {'name':'customizePoint','price':pointNum,'coins':pointNum,'unit':u'次','time':1}
  937. attachParas = {'chargeIndex':port,'onPoints':True}
  938. return self.start_device(package, openId, attachParas)