yuze5.py 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import time
  6. from decimal import Decimal
  7. from apilib.monetary import RMB
  8. from apps.web.constant import DeviceCmdCode, Const, ErrorCode, MQTT_TIMEOUT, DeviceErrorCodeDesc
  9. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, make_six_bytes_session_id
  10. from apps.web.core.exceptions import ServiceException
  11. from apps.web.core.networking import MessageSender
  12. from apps.web.device.models import Device, GroupDict
  13. logger = logging.getLogger(__name__)
  14. class YuZe5Box(SmartBox):
  15. def __init__(self, device):
  16. super(YuZe5Box, self).__init__(device)
  17. def _check_package(self, package):
  18. """
  19. 获取设备启动的发送数据 根据设备的当前模式以及套餐获取
  20. :param package:
  21. :return:
  22. """
  23. consumeMode = self._device.get("otherConf", dict()).get("consumeMode")
  24. if not consumeMode:
  25. tempDict = self.get_all_dev_settings()
  26. consumeMode = tempDict.get('consumeMode')
  27. Device.get_collection().update_one({'devNo': self._device['devNo']}, {
  28. '$set': {'otherConf.consumeMode': int(consumeMode)}})
  29. Device.invalid_device_cache(self._device['devNo'])
  30. unit = package.get("unit", u"分钟")
  31. _time = float(package.get("time", 0))
  32. # 按时间计费 或者线下免费模式
  33. if consumeMode == 0 or consumeMode == 2:
  34. billingType = "time"
  35. if unit == u"小时":
  36. _time = _time * 60
  37. elif unit == u"天":
  38. _time = _time * 24 * 60
  39. elif unit == u"秒":
  40. _time = _time / 60
  41. elif unit == u"分钟":
  42. _time = _time
  43. else:
  44. raise ServiceException({"result": 2, "description": u"套餐单位错误,请联系经销商"})
  45. # 按电量计费
  46. else:
  47. billingType = "elec"
  48. if unit != u"度":
  49. raise ServiceException({"result": 2, "description": u"套餐单位错误,请联系经销商"})
  50. else:
  51. _time = _time * 100
  52. return _time, unit, billingType
  53. def translate_funcode(self, funCode):
  54. funCodeDict = {
  55. '01': u'获取端口数量',
  56. '02': u'移动支付',
  57. '0C': u'获取设备设置',
  58. '08': u'设置设备参数',
  59. '06': u'获取设备端口详情',
  60. '07': u'获取刷卡投币统计数据',
  61. '09': u'设置刷卡投币使能',
  62. '0A': u'端口使能',
  63. '0B': u'端口关闭',
  64. '16': u'设置设备参数',
  65. '20': u'设备重启',
  66. '13': u'设置卡充满退费',
  67. '15': u'获取功率费率配置',
  68. '14': u'设置功率费率配置',
  69. '12': u'充值',
  70. '22': u'回复卡充值',
  71. }
  72. return funCodeDict.get(funCode, '')
  73. def translate_event_cmdcode(self, cmdCode):
  74. cmdDict = {
  75. '03': u'投币上报',
  76. '04': u'刷卡上报',
  77. '05': u'充电结束',
  78. '16': u'充电结束',
  79. '10': u'刷卡上报',
  80. '0D': u'故障',
  81. '20': u'启动设备',
  82. '11': u'刷卡使用',
  83. '12': u'卡充值',
  84. '22': u'ID卡扣费',
  85. '23': u'ID卡扣费状态',
  86. '17': u'IC卡回收余额成功',
  87. '30': u'电流上报',
  88. '31': u'温度上报',
  89. '32': u'烟感上报',
  90. }
  91. return cmdDict.get(cmdCode, '')
  92. def is_port_can_use(self, port, canAdd = False):
  93. # 电川的在启动的时候去判断是否需要续充
  94. return True, ''
  95. def check_dev_status(self, attachParas = None):
  96. """
  97. 如果超过两个心跳周期没有报心跳,并且最后一次更新时间在2个小时内,需要从设备获取状态
  98. 否则以缓存状态为准。
  99. :param attachParas:
  100. :return:
  101. """
  102. if attachParas is None:
  103. raise ServiceException({'result': 0, 'description': u'请您选择合适的充电端口、电池类型信息'})
  104. if not attachParas.has_key('chargeIndex'):
  105. raise ServiceException({'result': 0, 'description': u'请您选择合适的充电端口'})
  106. if not self.device.need_fetch_online:
  107. raise ServiceException(
  108. {'result': 2, 'description': DeviceErrorCodeDesc.get(ErrorCode.DEVICE_CONN_CHECK_FAIL)})
  109. self.get_port_status_from_dev()
  110. group = self.device.group # type: GroupDict
  111. if group.is_free:
  112. logger.debug('{} is free. no need to check continue pay.'.format(repr(self.device)))
  113. return
  114. # 处理是否能够续充
  115. portDict = self.get_port_status()
  116. port = str(attachParas['chargeIndex'])
  117. if port in portDict:
  118. isCanAdd = self.device['devType'].get('payableWhileBusy', False)
  119. if portDict[port]['status'] == Const.DEV_WORK_STATUS_IDLE:
  120. return
  121. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_FAULT:
  122. raise ServiceException({'result': 0, 'description': u'该端口故障,暂时不能使用'})
  123. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_WORKING:
  124. if isCanAdd:
  125. return
  126. else:
  127. raise ServiceException({'result': 0, 'description': u'该端口正在工作不能使用,请您使用其他端口'})
  128. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_FORBIDDEN:
  129. raise ServiceException({'result': 0, 'description': u'该端口已被禁止使用,请您使用其他端口'})
  130. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_CONNECTED:
  131. return
  132. else:
  133. raise ServiceException({'result': 0, 'description': u'端口状态未知,暂时不能使用'})
  134. else:
  135. raise ServiceException({'result': 0, 'description': u'未知端口,暂时不能使用'})
  136. def test(self, coins):
  137. hexPort = fill_2_hexByte(hex(int(1)), 2)
  138. hexTime = fill_2_hexByte(hex(5))
  139. devInfo = MessageSender.send(device = self.device,
  140. cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  141. payload = {
  142. 'IMEI': self._device['devNo'],
  143. "funCode": '02',
  144. 'data': hexPort + '0000' + hexTime
  145. },
  146. timeout = MQTT_TIMEOUT.SHORT)
  147. return devInfo
  148. def port_is_busy(self, port_dict):
  149. if not port_dict:
  150. return False
  151. if 'billingType' not in port_dict:
  152. return False
  153. if 'status' not in port_dict:
  154. return False
  155. if 'coins' not in port_dict:
  156. return False
  157. if 'price' not in port_dict:
  158. return False
  159. if port_dict['billingType'] not in ['time', 'elec']:
  160. return False
  161. if port_dict['billingType'] == 'time':
  162. if 'needTime' not in port_dict:
  163. return False
  164. else:
  165. if 'needElec' not in port_dict:
  166. return False
  167. if port_dict['status'] == Const.DEV_WORK_STATUS_WORKING:
  168. return True
  169. else:
  170. return False
  171. def start_device(self, package, openId, attachParas):
  172. if attachParas is None:
  173. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  174. if not attachParas.has_key('chargeIndex'):
  175. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  176. price = float(package['price'])
  177. dev = Device.objects.get(devNo = self._device['devNo'])
  178. refundProtection = dev.otherConf.get('refundProtection', 0)
  179. refundProtectionTime = dev.otherConf.get('refundProtectionTime', 5)
  180. port = hex(int(attachParas['chargeIndex']))
  181. hexPort = fill_2_hexByte(port, 2)
  182. _time, unit, billingType = self._check_package(package)
  183. coins = float(package['coins'])
  184. hexTime = fill_2_hexByte(hex(int(_time)))
  185. devInfo = MessageSender.send(
  186. device = self.device,
  187. cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  188. payload = {
  189. 'IMEI': self._device['devNo'],
  190. "funCode": '02',
  191. 'data': 'EE0D02{}'.format(make_six_bytes_session_id()) + hexPort + '0000' + hexTime
  192. }, timeout = MQTT_TIMEOUT.START_DEVICE)
  193. usePort = int(attachParas['chargeIndex'])
  194. if 'rst' not in devInfo:
  195. raise ServiceException(
  196. {
  197. 'result': 2,
  198. 'description': u'启动设备失败,您的支付金额已经退还,请重新扫码设备试试(1001)'
  199. })
  200. if devInfo['rst'] != 0:
  201. if devInfo['rst'] == -1:
  202. raise ServiceException(
  203. {
  204. 'result': 2,
  205. 'description': u'充电桩正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'
  206. })
  207. elif devInfo['rst'] == 1:
  208. self.check_serial_port_for_startcmd(attachParas['chargeIndex'])
  209. else:
  210. raise ServiceException(
  211. {
  212. 'result': 2,
  213. 'description': u'启动设备失败,您的支付金额已经退回,请重新扫码设备({})'.format(devInfo['rst'])
  214. })
  215. else:
  216. if 'data' not in devInfo:
  217. logger.warning('no data in success response. result = {}'.format(str(devInfo)))
  218. raise ServiceException(
  219. {
  220. 'result': 2,
  221. 'description': u'启动设备失败,您的支付金额已经退还,请重试'
  222. })
  223. else:
  224. data = devInfo['data'][18::]
  225. result = data[2:4]
  226. if result == '01': # 成功
  227. pass
  228. elif result == '02':
  229. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
  230. Device.update_dev_control_cache(self._device['devNo'], newValue)
  231. raise ServiceException({'result': 2, 'description': u'充电站故障'})
  232. elif result == '03':
  233. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_WORKING, 'statusInfo': u''}}
  234. Device.update_dev_control_cache(self._device['devNo'], newValue)
  235. raise ServiceException({'result': 2, 'description': u'该端口正在使用中'})
  236. else:
  237. raise ServiceException({
  238. 'result': 2,
  239. 'description': u'启动设备失败({}),您的支付金额已经退回,请重新扫码设备'.format(result)
  240. })
  241. portDict = {
  242. 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  243. 'status': Const.DEV_WORK_STATUS_WORKING,
  244. 'coins': coins,
  245. 'price': price,
  246. 'billingType': billingType,
  247. 'isStart': True,
  248. 'openId': openId,
  249. 'refunded': False,
  250. 'vCardId': self._vcard_id,
  251. 'refundProtection': refundProtection,
  252. 'refundProtectionTime': refundProtectionTime
  253. }
  254. ctrInfo = Device.get_dev_control_cache(self._device.devNo)
  255. lastPortInfo = ctrInfo.get(str(usePort), None)
  256. if self.port_is_busy(lastPortInfo) and \
  257. lastPortInfo.get('billingType') == billingType and \
  258. lastPortInfo.get('openId') == openId:
  259. is_continus = True
  260. portDict['coins'] = float(coins) + lastPortInfo['coins']
  261. portDict['price'] = float(price) + lastPortInfo['price']
  262. else:
  263. is_continus = False
  264. portDict['coins'] = float(coins)
  265. portDict['price'] = float(price)
  266. if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
  267. if is_continus:
  268. payInfo = lastPortInfo.get("payInfo", list())
  269. if not payInfo:
  270. logger.warning("miss payInfo! {}-{}".format(self._device["devNo"], usePort))
  271. else:
  272. payInfo = list()
  273. payInfo.append({'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])})
  274. portDict['payInfo'] = payInfo
  275. if billingType == 'time':
  276. if is_continus:
  277. portDict['needTime'] = _time + lastPortInfo['needTime']
  278. else:
  279. portDict['needTime'] = _time
  280. finishedTime = int(time.time()) + int(portDict['needTime'] * 60)
  281. else:
  282. if is_continus:
  283. portDict['needElec'] = _time / 100.0 + lastPortInfo['needElec']
  284. else:
  285. portDict['needElec'] = _time / 100.0
  286. finishedTime = int(time.time()) + 60 * 60 * 12
  287. portDict.update({'finishedTime': finishedTime})
  288. if 'orderNo' in attachParas:
  289. portDict.update({'orderNo': attachParas['orderNo']})
  290. Device.update_dev_control_cache(
  291. self._device['devNo'],
  292. {
  293. str(usePort): portDict
  294. })
  295. devInfo['finishedTime'] = finishedTime
  296. return devInfo
  297. def analyze_event_data(self, data):
  298. cmdCode = data[4:6]
  299. if cmdCode == '05':
  300. port = int(data[18:20], 16)
  301. leftTime = int(data[20:24], 16)
  302. reason = data[24:26]
  303. if reason == '00':
  304. desc = u'购买的充电时间或者电量已经用完'
  305. elif reason == '01':
  306. desc = u'系统判断为异常断电(插头被拔或者松动,或者电瓶已经充满),电瓶车充电器种类繁多,可能存在误差'
  307. elif reason == '02':
  308. desc = u'电池已经充满'
  309. elif reason == '03':
  310. desc = u'设备或者端口故障。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电'
  311. elif reason == '04':
  312. desc = u'警告!您的电池功率超过本机最大限制。为了公共安全,不建议您在该充电桩充电'
  313. elif reason == '05':
  314. desc = u'刷卡退费结束'
  315. elif reason == '06':
  316. desc = u'可能是插头被拔掉或者未连接充电器。如果不是自己操作,建议您到现场检查是否有人误操作'
  317. elif reason == '07':
  318. desc = u'远程方式停止充电。如果不是自己操作,建议到现场尽快恢复充电'
  319. else:
  320. desc = u''
  321. # 刷卡充电的结束
  322. if len(data) > 34:
  323. cardNo = str(int(data[26:34], 16))
  324. backMoney = int(data[34:36], 16) / 10.0
  325. cardType = 'ID' if data[36:40] == 'AA33' else 'IC'
  326. if cardNo != str(0):
  327. return {'status': Const.DEV_WORK_STATUS_IDLE, 'cmdCode': cmdCode, 'port': port,
  328. 'leftTime': leftTime, 'reason': desc, 'isStart': False, 'cardNo': cardNo,
  329. 'backMoney': backMoney, 'cardType': cardType, 'endType': reason,
  330. 'reasonCode': reason, 'uartData': data}
  331. else:
  332. return {'status': Const.DEV_WORK_STATUS_IDLE, 'cmdCode': cmdCode, 'port': port,
  333. 'leftTime': leftTime, 'reason': desc, 'isStart': False, 'endType': reason,
  334. 'reasonCode': reason, 'uartData': data}
  335. # 非刷卡充电的结束
  336. else:
  337. return {'status': Const.DEV_WORK_STATUS_IDLE, 'cmdCode': cmdCode, 'port': port,
  338. 'leftTime': leftTime, 'reason': desc, 'isStart': False, 'endType': reason,
  339. 'reasonCode': reason, 'uartData': data}
  340. elif cmdCode == '0D':
  341. port = int(data[16:18], 16)
  342. errCode = data[18:20]
  343. if errCode == '01':
  344. return {'statusInfo': u'端口输出故障', 'cmdCode': cmdCode, 'port': port, 'FaultCode': errCode, "uart": data}
  345. elif errCode == '02':
  346. return {'statusInfo': u'机器整体充电功率过大', 'cmdCode': cmdCode, 'port': port, 'FaultCode': errCode,
  347. "uart": data}
  348. elif errCode == '03':
  349. return {'statusInfo': u'电源故障', 'cmdCode': cmdCode, 'port': port, 'FaultCode': errCode, "uart": data}
  350. elif cmdCode == '03': # 投币上报
  351. coin = int(data[18:20], 16)
  352. try:
  353. port = int(data[20:22], 16)
  354. except:
  355. port = None
  356. return {'cmdCode': cmdCode, 'coins': coin, 'port': port}
  357. elif cmdCode == '11': # 刷卡后,按下端口,上报的报文
  358. # cardNo = str(int(''.join(re.findall(r'..', data[18:26])[::-1]), 16))
  359. cardNo = int(data[18:26], 16)
  360. cardNo = str(cardNo)
  361. fee = int(data[26:28], 16) / 10.0
  362. balance = int(data[28:32], 16) / 10.0
  363. cardType = 'ID' if data[32:36] == 'AA33' else 'IC'
  364. port = int(data[36:38], 16)
  365. status = data[38:40]
  366. return {'cardNo': cardNo, 'fee': fee, 'balance': balance, 'cardType': cardType, 'port': port,
  367. 'status': status, 'cmdCode': cmdCode}
  368. elif cmdCode == '12':
  369. cardNo = data[18:26]
  370. cardNo = str(int(cardNo, 16))
  371. balance = int(data[26:30], 16) / 10.0
  372. cardType = 'ID' if data[30:34] == 'AA33' else 'IC'
  373. return {'cmdCode': cmdCode, 'balance': balance, 'cardType': cardType, 'cardNo': cardNo}
  374. elif cmdCode == '04': # 旧版本的刷卡报文
  375. money = int(data[18:20], 16)
  376. return {'cmdCode': cmdCode, 'money': money}
  377. elif cmdCode == '30': # 宇泽家的,主动上报电流
  378. portData = data[18:48]
  379. port1 = int(portData[2:4])
  380. port2 = int(portData[4:6])
  381. port3 = int(portData[6:8])
  382. port4 = int(portData[8:10])
  383. port5 = int(portData[10:12])
  384. port6 = int(portData[12:14])
  385. port7 = int(portData[14:16])
  386. port8 = int(portData[16:18])
  387. port9 = int(portData[18:20])
  388. port10 = int(portData[20:22])
  389. device = int(portData[22:24])
  390. return {
  391. 'cmdCode': cmdCode,
  392. 'port1': port1,
  393. 'port2': port2,
  394. 'port3': port3,
  395. 'port4': port4,
  396. 'port5': port5,
  397. 'port6': port6,
  398. 'port7': port7,
  399. 'port8': port8,
  400. 'port9': port9,
  401. 'port10': port10,
  402. 'device': device,
  403. }
  404. elif cmdCode == '31': # 宇泽家的,主动上报温度
  405. portData = data[18:48]
  406. port1 = int(portData[2:4])
  407. port2 = int(portData[4:6])
  408. port3 = int(portData[6:8])
  409. port4 = int(portData[8:10])
  410. port5 = int(portData[10:12])
  411. port6 = int(portData[12:14])
  412. port7 = int(portData[14:16])
  413. port8 = int(portData[16:18])
  414. port9 = int(portData[18:20])
  415. port10 = int(portData[20:22])
  416. device = int(portData[22:24])
  417. return {
  418. 'cmdCode': cmdCode,
  419. 'port1': port1,
  420. 'port2': port2,
  421. 'port3': port3,
  422. 'port4': port4,
  423. 'port5': port5,
  424. 'port6': port6,
  425. 'port7': port7,
  426. 'port8': port8,
  427. 'port9': port9,
  428. 'port10': port10,
  429. 'device': device,
  430. }
  431. elif cmdCode == '32': # 宇泽家的,主动上报温度
  432. if data[18:20] == '01':
  433. return {'isYangan': True, 'cmdCode': cmdCode}
  434. else:
  435. return {'isYangan': False, 'cmdCode': cmdCode}
  436. elif cmdCode == '17':
  437. """
  438. IC卡回收余额成功,上报回收的数目
  439. 样例 660F170048614800052DDA5A0D000001DD
  440. """
  441. cardNo = int(data[18:26], 16)
  442. cardNo = str(cardNo)
  443. backMoney = int(data[26:30], 16) / 10.0
  444. return {'cmdCode': cmdCode, 'cardNo': cardNo, 'backMoney': backMoney}
  445. elif cmdCode == '22': # ID卡,上报上来扣费
  446. cardNo = int(data[18:26], 16)
  447. cardNo = str(cardNo)
  448. fee = int(data[26:28], 16) / 10.0
  449. cardType = 'ID' if data[28:32] == 'AA33' else 'IC'
  450. return {'cmdCode': cmdCode, 'cardNo': cardNo, 'fee': fee, 'cardType': cardType}
  451. elif cmdCode == '23': # ID卡,上报上来扣费
  452. cardNo = int(data[18:26], 16)
  453. cardNo = str(cardNo)
  454. status = data[26:28]
  455. return {'cmdCode': cmdCode, 'cardNo': cardNo, 'status': status}
  456. elif cmdCode == '35':
  457. temperature = int(data[18:20], 16)
  458. smoke = int(data[20:22], 16)
  459. voltage = int(data[22:26], 16)
  460. return {'cmdCode': cmdCode, 'temperature': temperature, 'smokeWarning': (smoke == 0x01), 'voltage': voltage}
  461. elif cmdCode == '41':
  462. return {'cmdCode': cmdCode, 'smokeWarning': True}
  463. def get_dev_consume_count(self):
  464. """
  465. crc校验错
  466. :return:
  467. """
  468. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  469. {'IMEI': self._device['devNo'], "funCode": '07', 'data': '00'})
  470. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  471. if devInfo['rst'] == -1:
  472. raise ServiceException(
  473. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  474. elif devInfo['rst'] == 1:
  475. raise ServiceException(
  476. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  477. data = devInfo['data'][16::]
  478. cardFee = int(data[2:6], 16) / 10.0 # 以角为单位
  479. coinFee = int(data[6:10], 16) # 以元为单位
  480. return {'cardFee': cardFee, 'coinFee': coinFee}
  481. def get_port_info(self, line):
  482. data = fill_2_hexByte(hex(int(line)), 2)
  483. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  484. {'IMEI': self._device['devNo'], "funCode": '06', 'data': data})
  485. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  486. if devInfo['rst'] == -1:
  487. raise ServiceException(
  488. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  489. elif devInfo['rst'] == 1:
  490. raise ServiceException(
  491. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  492. data = devInfo['data'][16::]
  493. leftTime = int(data[4:8], 16)
  494. if data[8:12] == 'FFFF':
  495. power = 0
  496. else:
  497. power = int(data[8:12], 16) / 10.0
  498. data = {"port": line, "power": power}
  499. # 电量计费模式
  500. if not self._device.get("otherConf", dict()).get("consumeMode", 0):
  501. data.update({"leftTime": leftTime})
  502. else:
  503. data.update({"leftElec": leftTime / 100.0})
  504. return data
  505. def get_port_status_from_dev(self):
  506. """
  507. 访问设备,获取设备端口信息
  508. :return:
  509. """
  510. devInfo = MessageSender.send(device = self.device,
  511. cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  512. payload = {
  513. 'IMEI': self._device['devNo'],
  514. 'funCode': '01',
  515. 'data': 'EE0901{}'.format(make_six_bytes_session_id()) + '00'
  516. })
  517. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  518. if devInfo['rst'] == -1:
  519. raise ServiceException(
  520. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试', 'rst': -1})
  521. elif devInfo['rst'] == 1:
  522. raise ServiceException(
  523. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能', 'rst': 1})
  524. data = devInfo['data'][16::]
  525. result = {}
  526. portNum = int(data[2:4], 16)
  527. portData = data[4::]
  528. ii = 0
  529. while ii < portNum:
  530. statusTemp = portData[ii * 2:ii * 2 + 2]
  531. if statusTemp == '01':
  532. status = {'status': Const.DEV_WORK_STATUS_IDLE}
  533. elif statusTemp == '02':
  534. status = {'status': Const.DEV_WORK_STATUS_WORKING}
  535. elif statusTemp == '03':
  536. status = {'status': Const.DEV_WORK_STATUS_FORBIDDEN}
  537. elif statusTemp == '04':
  538. status = {'status': Const.DEV_WORK_STATUS_FAULT}
  539. # 不再上述状态之列的 统一为故障状态
  540. else:
  541. status = {'status': Const.DEV_WORK_STATUS_FAULT}
  542. ii += 1
  543. result[str(ii)] = status
  544. allPorts, usedPorts, usePorts = self.get_port_static_info(result)
  545. # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
  546. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  547. for strPort, info in result.items():
  548. if ctrInfo.has_key(strPort):
  549. ctrInfo[strPort].update({'status': info['status']})
  550. else:
  551. ctrInfo[strPort] = info
  552. ctrInfo.update({
  553. 'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts
  554. })
  555. Device.update_dev_control_cache(self.device.devNo, ctrInfo)
  556. return result
  557. def get_default_port_nums(self):
  558. default_num = 10
  559. return default_num
  560. def get_port_status(self, force = False):
  561. if force:
  562. return self.get_port_status_from_dev()
  563. ctrInfo = Device.get_dev_control_cache(self.device.devNo)
  564. if 'allPorts' in ctrInfo and ctrInfo['allPorts'] > 0:
  565. allPorts = ctrInfo['allPorts']
  566. else:
  567. allPorts = self.get_default_port_nums()
  568. statusDict = {}
  569. for ii in range(allPorts):
  570. tempDict = ctrInfo.get(str(ii + 1), {})
  571. if tempDict.has_key('status'):
  572. statusDict[str(ii + 1)] = {'status': tempDict.get('status')}
  573. elif tempDict.has_key('isStart'):
  574. if tempDict['isStart']:
  575. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
  576. else:
  577. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  578. else:
  579. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  580. return statusDict
  581. def lock_unlock_port(self, port, lock = True):
  582. lockStr = '00' if lock else '01'
  583. portStr = fill_2_hexByte(hex(int(port)), 2)
  584. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  585. payload = {'IMEI': self._device['devNo'], "funCode": '0A',
  586. 'data': portStr + lockStr}, timeout = MQTT_TIMEOUT.SHORT)
  587. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  588. if devInfo['rst'] == -1:
  589. raise ServiceException(
  590. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  591. elif devInfo['rst'] == 1:
  592. raise ServiceException(
  593. {'result': 2, 'description': u'端口禁用功能只有带保险丝版本的才有。可能是您的设备版本过低,暂时不支持此功能,也可能是设备繁忙无响应。'})
  594. data = devInfo['data'][18::]
  595. if data[0:2] == '01': # 表示成功
  596. pass
  597. else:
  598. raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
  599. if lock:
  600. Device.update_dev_control_cache(self._device['devNo'],
  601. {str(port): {'status': Const.DEV_WORK_STATUS_FORBIDDEN}})
  602. else:
  603. Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
  604. def active_deactive_port(self, port, active):
  605. if active:
  606. raise ServiceException({'result': 2, 'description': u'该设备不支持直接打开端口'})
  607. self.stop_charging_port(port)
  608. devInfo = Device.get_dev_control_cache(self._device['devNo'])
  609. portCtrInfo = devInfo.get(str(port), {})
  610. portCtrInfo.update({'isStart': False, 'status': Const.DEV_WORK_STATUS_IDLE, 'needTime': 0, 'leftTime': 0,
  611. 'endTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  612. newValue = {str(port): portCtrInfo}
  613. Device.update_dev_control_cache(self._device['devNo'], newValue)
  614. def stop_charging_port(self, port):
  615. portStr = fill_2_hexByte(hex(int(port)), 2)
  616. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  617. payload = {'IMEI': self._device['devNo'], "funCode": '0B', 'data': portStr},
  618. timeout = MQTT_TIMEOUT.SHORT)
  619. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  620. if devInfo['rst'] == -1:
  621. raise ServiceException(
  622. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  623. elif devInfo['rst'] == 1:
  624. raise ServiceException(
  625. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  626. data = devInfo['data'][16::]
  627. port = int(data[2:4], 16)
  628. leftTime = int(data[4:8], 16)
  629. data = {"port": port}
  630. # 电量计费模式
  631. if not self._device.get("otherConf", dict()).get("consumeMode", 0):
  632. data.update({"remainder_time": leftTime})
  633. else:
  634. data.update({"remainder_time": leftTime / 100.0})
  635. return data
  636. def stop(self, port = None):
  637. return self.stop_charging_port(port)
  638. @property
  639. def isHaveStopEvent(self):
  640. return True
  641. def set_IC_coin_power_config(self, infoDict):
  642. data = ''
  643. data += fill_2_hexByte(hex(int(infoDict['maxPower'])), 4)
  644. data += fill_2_hexByte(hex(int(infoDict['icMoney'])), 2)
  645. data += fill_2_hexByte(hex(int(infoDict['time1'])), 4)
  646. data += fill_2_hexByte(hex(int(infoDict['time2'])), 4)
  647. data += fill_2_hexByte(hex(int(infoDict['time3'])), 4)
  648. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  649. payload = {'IMEI': self._device['devNo'], "funCode": '08', 'data': data},
  650. timeout = MQTT_TIMEOUT.SHORT)
  651. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  652. if devInfo['rst'] == -1:
  653. raise ServiceException(
  654. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  655. elif devInfo['rst'] == 1:
  656. raise ServiceException(
  657. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  658. def get_coin_card_enable(self):
  659. putCoins = self.device['otherConf'].get('putCoins', False)
  660. icCard = self.device['otherConf'].get('icCard', False)
  661. return {'putCoins': putCoins, 'icCard': icCard}
  662. def set_coin_card_enable(self, infoDict):
  663. data = ''
  664. if infoDict['putCoins']:
  665. data += '01'
  666. else:
  667. data += '00'
  668. if infoDict['icCard']:
  669. data += '01'
  670. else:
  671. data += '00'
  672. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  673. payload = {'IMEI': self._device['devNo'], "funCode": '09', 'data': data},
  674. timeout = MQTT_TIMEOUT.SHORT)
  675. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  676. if devInfo['rst'] == -1:
  677. raise ServiceException(
  678. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  679. elif devInfo['rst'] == 1:
  680. raise ServiceException(
  681. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  682. else:
  683. Device.get_collection().update_one({'devNo': self._device['devNo']},
  684. {'$set': {
  685. 'otherConf.putCoins': infoDict['putCoins'],
  686. 'otherConf.icCard': infoDict['icCard'],
  687. }})
  688. Device.invalid_device_cache(self.device.devNo)
  689. def get_dev_setting(self):
  690. # 发送指令查询
  691. resultDict = {}
  692. try:
  693. tempDict = self.get_fullstop_cardrefund()
  694. resultDict.update(tempDict)
  695. except:
  696. pass
  697. # try:
  698. # tempDict = self.get_gear_conf()
  699. # resultDict.update(tempDict)
  700. # except:
  701. # pass
  702. try:
  703. tempDict = self.get_all_dev_settings()
  704. resultDict.update(tempDict)
  705. except:
  706. pass
  707. try:
  708. tempDict = self.get_consume_mode_volume_andsoon_config()
  709. resultDict.update(tempDict)
  710. except:
  711. pass
  712. try:
  713. # 设置后保存到设备的参数
  714. tempDict = self.get_coin_card_enable()
  715. resultDict.update(tempDict)
  716. except:
  717. pass
  718. try:
  719. tempDict = self.get_elec_rule()
  720. resultDict.update(tempDict)
  721. except:
  722. pass
  723. return resultDict
  724. def get_fullstop_cardrefund(self):
  725. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  726. payload = {'IMEI': self._device['devNo'], "funCode": '0C', 'data': '00'},
  727. timeout = MQTT_TIMEOUT.SHORT)
  728. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  729. if devInfo['rst'] == -1:
  730. raise ServiceException(
  731. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  732. elif devInfo['rst'] == 1:
  733. raise ServiceException(
  734. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  735. confData = devInfo['data'][18::]
  736. maxPower = int(confData[0:4], 16)
  737. icMoney = int(confData[4:6], 16)
  738. if len(confData) > 6:
  739. time1 = int(confData[6:10], 16)
  740. time2 = int(confData[10:14], 16)
  741. time3 = int(confData[14:18], 16)
  742. else:
  743. time1, time2, time3 = 0, 0, 0
  744. autoStop = True if confData[20:22] == u'01' else False
  745. cardRefund = True if confData[18:20] == u'01' else False
  746. return {'maxPower': maxPower}
  747. def set_fullstop_cardrefund(self, infoDict):
  748. data = ''
  749. if infoDict['autoStop']:
  750. data += '01'
  751. else:
  752. data += '00'
  753. if infoDict['cardRefund']:
  754. data += '01'
  755. else:
  756. data += '00'
  757. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  758. payload = {'IMEI': self._device['devNo'], "funCode": '13', 'data': data},
  759. timeout = MQTT_TIMEOUT.SHORT)
  760. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  761. if devInfo['rst'] == -1:
  762. raise ServiceException(
  763. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  764. elif devInfo['rst'] == 1:
  765. raise ServiceException(
  766. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  767. def get_gear_conf(self):
  768. resultDict = {'power1': 0, 'power1ratio': 0, 'power2': 0,
  769. 'power2ratio': 0, 'power3': 0, 'power3ratio': 0}
  770. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  771. payload = {'IMEI': self._device['devNo'], "funCode": '15', 'data': '00'},
  772. timeout = MQTT_TIMEOUT.SHORT)
  773. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  774. if devInfo['rst'] == -1:
  775. raise ServiceException(
  776. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  777. elif devInfo['rst'] == 1:
  778. return resultDict
  779. confData = devInfo['data'][18::]
  780. power1 = int(confData[0:4], 16)
  781. power1ratio = int(confData[4:6], 16)
  782. power2 = int(confData[6:10], 16)
  783. power2ratio = int(confData[10:12], 16)
  784. power3 = int(confData[12:16], 16)
  785. power3ratio = int(confData[16:18], 16)
  786. result = {
  787. 'power1': power1, 'power1ratio': power1ratio, 'power2': power2,
  788. 'power2ratio': power2ratio, 'power3': power3, 'power3ratio': power3ratio
  789. }
  790. if len(confData) > 31:
  791. power4 = int(confData[18:22], 16)
  792. power4ratio = int(confData[22:24], 16)
  793. power5 = int(confData[24:28], 16)
  794. power5ratio = int(confData[28:30], 16)
  795. result.update({'power4': power4, 'power4ratio': power4ratio,
  796. 'power5': power5, 'power5ratio': power5ratio})
  797. return result
  798. def set_gear_conf(self, infoDict):
  799. data = ''
  800. data += fill_2_hexByte(hex(infoDict['power1']), 4)
  801. data += fill_2_hexByte(hex(infoDict['power1ratio']), 2)
  802. data += fill_2_hexByte(hex(infoDict['power2']), 4)
  803. data += fill_2_hexByte(hex(infoDict['power2ratio']), 2)
  804. data += fill_2_hexByte(hex(infoDict['power3']), 4)
  805. data += fill_2_hexByte(hex(infoDict['power3ratio']), 2)
  806. if infoDict.has_key('power4'):
  807. data += fill_2_hexByte(hex(int(infoDict['power4'])), 4)
  808. data += fill_2_hexByte(hex(int(infoDict['power4ratio'])), 2)
  809. data += fill_2_hexByte(hex(int(infoDict['power5'])), 4)
  810. data += fill_2_hexByte(hex(int(infoDict['power5ratio'])), 2)
  811. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  812. payload = {'IMEI': self._device['devNo'], "funCode": '14', 'data': data},
  813. timeout = MQTT_TIMEOUT.SHORT)
  814. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  815. if devInfo['rst'] == -1:
  816. raise ServiceException(
  817. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  818. elif devInfo['rst'] == 1:
  819. raise ServiceException(
  820. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  821. def recharge_card(self, cardNo, money, orderNo = None):
  822. try:
  823. data = 'EE1012{}'.format(make_six_bytes_session_id())
  824. cardNo = fill_2_hexByte(hex(int(cardNo)), 8)
  825. data += cardNo + fill_2_hexByte(hex(int(money * 10)), 4) + '0001'
  826. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  827. payload = {'IMEI': self._device['devNo'], 'data': data, 'funCode': '12'},
  828. timeout = MQTT_TIMEOUT.LONGEST)
  829. if devInfo['rst'] != 0:
  830. if devInfo['rst'] == ErrorCode.DEVICE_CONN_FAIL:
  831. # 离线无法判断是否成功, 认为充值成功, 走售后解决
  832. return {
  833. 'result': ErrorCode.DEVICE_CONN_FAIL,
  834. 'description': u'当前充电桩正在玩命找网络,请您稍候再试'
  835. }, None
  836. elif devInfo['rst'] == ErrorCode.BOARD_UART_TIMEOUT:
  837. return {
  838. 'result': ErrorCode.BOARD_UART_TIMEOUT,
  839. 'description': u'当前充电桩忙,无响应,请您稍候再试'
  840. }, None
  841. else:
  842. return {
  843. 'result': devInfo['rst'],
  844. 'description': u'系统异常'
  845. }, None
  846. resultData = devInfo['data']
  847. if resultData[4:6] != '16':
  848. return {
  849. 'result': ErrorCode.PARAMETER_ERROR_TO_BOX,
  850. 'description': u'充值返回报文命令码不为16'
  851. }, None
  852. balance = RMB(int(resultData[26:30], 16)) * Decimal('0.1')
  853. result = True if resultData[34:36] == '01' else False
  854. if result:
  855. return {
  856. 'result': ErrorCode.SUCCESS,
  857. 'description': ''
  858. }, balance
  859. else:
  860. return {
  861. 'result': ErrorCode.IC_RECHARGE_FAIL,
  862. 'description': u'充值失败'
  863. }, balance
  864. except Exception as e:
  865. logger.exception(e)
  866. return {
  867. 'result': ErrorCode.EXCEPTION,
  868. 'description': e.message
  869. }, None
  870. def get_consume_mode_volume_andsoon_config(self):
  871. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  872. payload = {'IMEI': self._device['devNo'], "funCode": '2A', 'data': '00'},
  873. timeout = MQTT_TIMEOUT.SHORT)
  874. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  875. if devInfo['rst'] == -1:
  876. raise ServiceException(
  877. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  878. elif devInfo['rst'] == 1:
  879. raise ServiceException(
  880. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  881. confData = devInfo['data'][18::]
  882. card1Time = int(confData[0:4], 16)
  883. card2Time = int(confData[4:8], 16)
  884. card3Time = int(confData[8:12], 16)
  885. consumeMode = int(confData[12:14])
  886. volume = int(confData[14:16], 16)
  887. fuchongPower = int(confData[16:20], 16) * 0.1
  888. fuchongTime = int(confData[20:24], 16)
  889. return { 'volume': volume, }
  890. def set_consume_mode_volume_config(self, infoDict):
  891. data = fill_2_hexByte(hex(int(infoDict.get('consumeMode', 5))), 2)
  892. data += fill_2_hexByte(hex(int(infoDict.get('volume', 5))), 2)
  893. devInfo = MessageSender.send(device = self.device, cmd = self.make_random_cmdcode(),
  894. payload = {'IMEI': self._device['devNo'], "funCode": '27', 'data': data},
  895. timeout = MQTT_TIMEOUT.SHORT)
  896. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  897. if devInfo['rst'] == -1:
  898. raise ServiceException(
  899. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  900. elif devInfo['rst'] == 1:
  901. raise ServiceException(
  902. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  903. def set_fuchong_config(self, infoDict):
  904. """
  905. 已弃用 替代指令 37
  906. :param infoDict:
  907. :return:
  908. """
  909. data = fill_2_hexByte(hex(int(infoDict['fuchongPower']) * 10), 4)
  910. data += fill_2_hexByte(hex(int(infoDict['fuchongTime'])), 4)
  911. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  912. payload = {'IMEI': self._device['devNo'], "funCode": '28', 'data': data},
  913. timeout = MQTT_TIMEOUT.SHORT)
  914. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  915. if devInfo['rst'] == -1:
  916. raise ServiceException(
  917. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  918. elif devInfo['rst'] == 1:
  919. raise ServiceException(
  920. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  921. def set_card_time_config(self, infoDict):
  922. data = fill_2_hexByte(hex(int(infoDict['card1Time'])), 4)
  923. data += fill_2_hexByte(hex(int(infoDict['card2Time'])), 4)
  924. data += fill_2_hexByte(hex(int(infoDict['card3Time'])), 4)
  925. devInfo = MessageSender.send(device = self.device, cmd = self.make_random_cmdcode(),
  926. payload = {'IMEI': self._device['devNo'], "funCode": '29', 'data': data},
  927. timeout = MQTT_TIMEOUT.SHORT)
  928. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  929. if devInfo['rst'] == -1:
  930. raise ServiceException(
  931. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  932. elif devInfo['rst'] == 1:
  933. raise ServiceException(
  934. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  935. def set_fuchong_config_new(self, infoDict):
  936. data = fill_2_hexByte(hex(int(infoDict['fuchongPower']) * 10), 4)
  937. data += fill_2_hexByte(hex(int(infoDict['fuchongTime'])), 4)
  938. data += fill_2_hexByte(hex(int(infoDict['noloadTime'])), 4)
  939. devInfo = MessageSender.send(device=self.device, cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  940. payload={'IMEI': self._device['devNo'], "funCode": '37', 'data': data},
  941. timeout=MQTT_TIMEOUT.SHORT)
  942. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  943. if devInfo['rst'] == -1:
  944. raise ServiceException(
  945. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  946. elif devInfo['rst'] == 1:
  947. raise ServiceException(
  948. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  949. else:
  950. Device.get_collection().update_one({'devNo': self.device.devNo},
  951. {'$set': {
  952. 'otherConf.fuchongPower': int(infoDict['fuchongPower']),
  953. 'otherConf.fuchongTime': int(infoDict['fuchongTime']),
  954. 'otherConf.noloadTime': int(infoDict['noloadTime']),
  955. }})
  956. Device.invalid_device_cache(self.device.devNo)
  957. def set_elec_rule(self, infoDict):
  958. coinElec = int(infoDict['coinElec'])
  959. cardElec = int(infoDict['cardElec'])
  960. data = fill_2_hexByte(hex(coinElec), 4)
  961. data += fill_2_hexByte(hex(cardElec), 4)
  962. devInfo = MessageSender.send(device=self.device, cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  963. payload={'IMEI': self._device['devNo'], "funCode": '42', 'data': data},
  964. timeout=MQTT_TIMEOUT.SHORT)
  965. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  966. if devInfo['rst'] == -1:
  967. raise ServiceException(
  968. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  969. elif devInfo['rst'] == 1:
  970. raise ServiceException(
  971. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  972. # else:
  973. # Device.get_collection().update_one({'devNo': self.device.devNo},
  974. # {'$set': {
  975. # 'otherConf.coinElec': coinElec,
  976. # 'otherConf.cardElec': cardElec
  977. # }})
  978. # Device.invalid_device_cache(self.device.devNo)
  979. def get_elec_rule(self):
  980. # coinElec = self.device['otherConf'].get('coinElec', 0)
  981. # cardElec = self.device['otherConf'].get('coinElec', 0)
  982. devInfo = MessageSender.send(device=self.device, cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  983. payload={'IMEI': self._device['devNo'], "funCode": '47', 'data': '00'},
  984. timeout=MQTT_TIMEOUT.SHORT)
  985. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  986. if devInfo['rst'] == -1:
  987. raise ServiceException(
  988. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  989. elif devInfo['rst'] == 1:
  990. raise ServiceException(
  991. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  992. confData = devInfo['data'][18::]
  993. coinElec = int(confData[:4], 16)
  994. cardElec = int(confData[4:8], 16)
  995. return {'coinElec': coinElec, 'cardElec': cardElec}
  996. def set_device_function(self, request, lastSetConf):
  997. if request.POST.has_key('putCoins'):
  998. # putCoins = True if request.POST.get('putCoins') == 'true' else False
  999. putCoins = request.POST.get("putCoins", False)
  1000. lastSetConf.update({'putCoins': putCoins})
  1001. self.set_coin_card_enable(lastSetConf)
  1002. if request.POST.has_key('icCard'):
  1003. # icCard = True if request.POST.get('icCard') == 'true' else False
  1004. icCard = request.POST.get("icCard", False)
  1005. lastSetConf.update({'icCard': icCard})
  1006. self.set_coin_card_enable(lastSetConf)
  1007. if request.POST.has_key('autoStop'):
  1008. # autoStop = True if request.POST.get('autoStop') == 'true' else False
  1009. autoStop = request.POST.get("autoStop", False)
  1010. lastSetConf.update({'autoStop': autoStop})
  1011. self.set_fullstop_cardrefund(lastSetConf)
  1012. if request.POST.has_key('cardRefund'):
  1013. # cardRefund = True if request.POST.get('cardRefund') == 'true' else False
  1014. cardRefund = request.POST.get("cardRefund", False)
  1015. lastSetConf.update({'cardRefund': cardRefund})
  1016. self.set_fullstop_cardrefund(lastSetConf)
  1017. if request.POST.has_key('consumeMode'):
  1018. consumeMode = request.POST.get("consumeMode", False)
  1019. lastSetConf.update({'consumeMode': consumeMode})
  1020. self.set_consume_mode_volume_config(lastSetConf)
  1021. def set_device_function_param(self, request, lastSetConf):
  1022. # 和 主板厂家沟通 目前已经不会存在 有maxPower这个控制选项 maxPower 就是分档功率中的最高档功率
  1023. if 'icMoney' in request.POST:
  1024. lastSetConf.update({'icMoney': int(request.POST.get('icMoney', 0))})
  1025. lastSetConf.update({'maxPower': int(request.POST.get('maxPower', 0))})
  1026. self.set_IC_coin_power_config(lastSetConf)
  1027. if 'time1' in request.POST and 'time2' in request.POST and 'time3' in request.POST:
  1028. lastSetConf.update({'time1': int(request.POST.get('time1', 0))})
  1029. lastSetConf.update({'time2': int(request.POST.get('time2', 0))})
  1030. lastSetConf.update({'time3': int(request.POST.get('time3', 0))})
  1031. self.set_IC_coin_power_config(lastSetConf)
  1032. if 'power1' in request.POST and 'power1ratio' in request.POST:
  1033. lastSetConf.update({'power1': int(request.POST.get('power1', 0))})
  1034. lastSetConf.update({'power1ratio': int(request.POST.get('power1ratio', 0))})
  1035. lastSetConf.update({'power2': int(request.POST.get('power2', 0))})
  1036. lastSetConf.update({'power2ratio': int(request.POST.get('power2ratio', 0))})
  1037. lastSetConf.update({'power3': int(request.POST.get('power3', 0))})
  1038. lastSetConf.update({'power3ratio': int(request.POST.get('power3ratio', 0))})
  1039. lastSetConf.update({'power4': int(request.POST.get('power4', 0))})
  1040. lastSetConf.update({'power4ratio': int(request.POST.get('power4ratio', 0))})
  1041. lastSetConf.update({'power5': int(request.POST.get('power5', 0))})
  1042. lastSetConf.update({'power5ratio': int(request.POST.get('power5ratio', 0))})
  1043. self.set_gear_conf(lastSetConf)
  1044. if 'card1Time' in request.POST and 'card2Time' in request.POST and 'card3Time' in request.POST:
  1045. lastSetConf.update({'card1Time': int(request.POST.get('card1Time', 0))})
  1046. lastSetConf.update({'card2Time': int(request.POST.get('card2Time', 0))})
  1047. lastSetConf.update({'card3Time': int(request.POST.get('card3Time', 0))})
  1048. self.set_card_time_config(lastSetConf)
  1049. if 'fuchongPower' in request.POST and 'fuchongTime' in request.POST:
  1050. fuchongPower = 5 if request.POST.get('fuchongPower') == '' else int(request.POST.get('fuchongPower'))
  1051. fuchongTime = 120 if request.POST.get('fuchongTime') == '' else int(request.POST.get('fuchongTime'))
  1052. lastSetConf.update({'fuchongPower': fuchongPower})
  1053. lastSetConf.update({'fuchongTime': fuchongTime})
  1054. self.set_fuchong_config(lastSetConf)
  1055. if 'refundProtectionTime' in request.POST:
  1056. lastSetConf.update({'refundProtectionTime': int(request.POST.get('refundProtectionTime', 5))})
  1057. dev = Device.objects.get(devNo = self._device['devNo'])
  1058. dev.otherConf.update({'refundProtectionTime': lastSetConf['refundProtectionTime']})
  1059. dev.save()
  1060. if 'coinElec' in request.POST and 'cardElec' in request.POST:
  1061. lastSetConf.update({'coinElec': request.POST['coinElec']})
  1062. lastSetConf.update({'cardElec': request.POST['cardElec']})
  1063. self.set_elec_rule(lastSetConf)
  1064. if 'consumeMode' in request.POST and 'volume' in request.POST:
  1065. lastSetConf.update({'consumeMode': request.POST['consumeMode']})
  1066. lastSetConf.update({'volume': request.POST['volume']})
  1067. self.set_consume_mode_volume_config(lastSetConf)
  1068. Device.get_collection().update_one({'devNo': self._device['devNo']}, {
  1069. '$set': {'otherConf.consumeMode': int(request.POST['consumeMode'])}})
  1070. Device.invalid_device_cache(self._device['devNo'])
  1071. def response_card_status(self, cardNo, balance, status):
  1072. data = 'EE1123{}'.format(make_six_bytes_session_id()) + fill_2_hexByte(hex(int(cardNo)), 4) + fill_2_hexByte(
  1073. hex(int(balance * 10)), 4) + 'AA33' + status
  1074. devInfo = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  1075. {'IMEI': self._device['devNo'], "funCode": '22', 'data': data})
  1076. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1077. if devInfo['rst'] == -1:
  1078. raise ServiceException(
  1079. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1080. elif devInfo['rst'] == 1: # 等于1的时候,说明服务器和远程模块通讯OK,响应已经收到,不需要异常处理
  1081. raise ServiceException(
  1082. {'result': 2, 'description': u'充电桩没有响应,可能是版本不对或者串口接线不良'})
  1083. resultData = devInfo['data']
  1084. if resultData[4:6] != '23':
  1085. return {'status': '00'}
  1086. backCardNo = int(resultData[18:26], 16)
  1087. if backCardNo != int(cardNo):
  1088. return {'status': '00'}
  1089. return {'status': resultData[26:28]}
  1090. def get_all_dev_settings(self):
  1091. devInfo = MessageSender.send(device=self.device, cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  1092. payload={'IMEI': self._device['devNo'], "funCode": '36', 'data': '00'},
  1093. timeout=MQTT_TIMEOUT.SHORT)
  1094. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1095. if devInfo['rst'] == -1:
  1096. raise ServiceException(
  1097. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1098. elif devInfo['rst'] == 1:
  1099. raise ServiceException(
  1100. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  1101. confData = devInfo['data'][18::]
  1102. time1 = int(confData[:4], 16)
  1103. time2 = int(confData[4:8], 16)
  1104. time3 = int(confData[8:12], 16)
  1105. card1Time = int(confData[12:16], 16)
  1106. card2Time = int(confData[16:20], 16)
  1107. card3Time = int(confData[20:24], 16)
  1108. icMoney = int(confData[24:28], 16)
  1109. cardRefund = True if confData[28:30] == u'01' else False
  1110. power1 = int(confData[30:34], 16)
  1111. power1ratio = int(confData[34:36], 16)
  1112. power2 = int(confData[36:40], 16)
  1113. power2ratio = int(confData[40:42], 16)
  1114. power3 = int(confData[42:46], 16)
  1115. power3ratio = int(confData[46:48], 16)
  1116. power4 = int(confData[48:52], 16)
  1117. power4ratio = int(confData[52:54], 16)
  1118. power5 = int(confData[54:58], 16)
  1119. power5ratio = int(confData[58:60], 16)
  1120. autoStop = True if confData[60:62] == u'01' else False
  1121. fuchongPower = int(confData[62:66], 16)
  1122. fuchongTime = int(confData[66:70], 16)
  1123. noloadTime = int(confData[70:74], 16)
  1124. freeMode = int(confData[74:76], 16)
  1125. consumeProcess = int(confData[76:78], 16)
  1126. # consumeMode = int(confData[78:80], 16) #无效
  1127. consumeMode = freeMode
  1128. return {
  1129. 'time1': time1,
  1130. 'time2': time2,
  1131. 'time3': time3,
  1132. 'card1Time': card1Time,
  1133. 'card2Time': card2Time,
  1134. 'card3Time': card3Time,
  1135. 'icMoney': icMoney,
  1136. 'cardRefund': cardRefund,
  1137. 'power1': power1,
  1138. 'power1ratio': power1ratio,
  1139. 'power2': power2,
  1140. 'power2ratio': power2ratio,
  1141. 'power3': power3,
  1142. 'power3ratio': power3ratio,
  1143. 'power4': power4,
  1144. 'power4ratio': power4ratio,
  1145. 'power5': power5,
  1146. 'power5ratio': power5ratio,
  1147. 'autoStop': autoStop,
  1148. 'fuchongPower': fuchongPower,
  1149. 'fuchongTime': fuchongTime,
  1150. # 'noloadTime': noloadTime,
  1151. 'consumeMode': consumeMode,
  1152. # 'consumeProcess': consumeProcess,
  1153. # 'consumeMode': consumeMode,
  1154. }
  1155. def format_upload_power(self, power):
  1156. return float(power / 10)