zhixia2.py 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923
  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 typing import TYPE_CHECKING
  8. from apilib.utils import is_number
  9. from apilib.monetary import RMB
  10. from apilib.utils_string import split_str
  11. from apps.web.constant import Const, DeviceCmdCode, ErrorCode, DeviceErrorCodeDesc, MQTT_TIMEOUT, CONSUMETYPE
  12. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, make_six_bytes_session_id
  13. from apps.web.core.exceptions import ServiceException, InvalidParameter
  14. from apps.web.core.networking import MessageSender
  15. from apps.web.device.models import Device, DeviceType
  16. from apps.web.south_intf.yuhuan_fire import YuhuanNorther
  17. logger = logging.getLogger(__name__)
  18. if TYPE_CHECKING:
  19. from apps.web.device.models import GroupDict
  20. class ChargingZHIXIA2Box(SmartBox):
  21. def __init__(self, device):
  22. super(ChargingZHIXIA2Box, self).__init__(device)
  23. def _start_device_for_card(self, needTime, portStr):
  24. """
  25. 刷卡启动
  26. :param needTime:
  27. :param portStr:
  28. :return:
  29. """
  30. hexTime = "{:04X}".format(int(needTime))
  31. hexPort = "{:02X}".format(int(portStr))
  32. MessageSender.send(
  33. device = self.device,
  34. cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  35. payload = {
  36. 'IMEI': self._device['devNo'],
  37. "funCode": '02',
  38. 'data': 'EE0D02{}'.format(make_six_bytes_session_id()) + hexPort + '0000' + hexTime
  39. },
  40. timeout = MQTT_TIMEOUT.START_DEVICE
  41. )
  42. def _check_package(self, package):
  43. """
  44. 获取设备启动的发送数据 根据设备的当前模式以及套餐获取
  45. :param package:
  46. :return:
  47. """
  48. consumeModule = self._device.get("otherConf", dict()).get("consumeModule", 0)
  49. unit = package.get("unit", u"分钟")
  50. _time = float(package.get("time", 0))
  51. # 按时间计费
  52. if consumeModule == 0:
  53. billingType = "time"
  54. if unit == u"小时":
  55. _time = _time * 60
  56. elif unit == u"天":
  57. _time = _time * 24 * 60
  58. elif unit == u"秒":
  59. _time = _time / 60
  60. elif unit == u"分钟":
  61. _time = _time
  62. else:
  63. raise ServiceException({"result": 2, "description": u"套餐单位错误,请联系经销商"})
  64. # 按电量计费
  65. else:
  66. billingType = "elec"
  67. if unit != u"度":
  68. raise ServiceException({"result": 2, "description": u"套餐单位错误,请联系经销商"})
  69. else:
  70. _time = _time * 100
  71. return _time, unit, billingType
  72. def translate_funcode(self, funCode):
  73. funCodeDict = {
  74. '01': u'查询设备每个端口当前的状态',
  75. '02': u'移动支付',
  76. '0C': u'获取设备设置',
  77. '06': u'获取设备端口详情',
  78. '07': u'获取刷卡投币统计数据',
  79. '08': u'设置设备参数',
  80. '09': u'设置刷卡投币使能',
  81. '0A': u'端口使能',
  82. '0B': u'端口关闭',
  83. '16': u'设置设备参数',
  84. '20': u'设备重启',
  85. '13': u'设置卡充满退费',
  86. '15': u'获取功率费率配置',
  87. '14': u'设置功率费率配置',
  88. '12': u'充值',
  89. '22': u'回复卡充值',
  90. }
  91. return funCodeDict.get(funCode, '')
  92. def translate_event_cmdcode(self, cmdCode):
  93. cmdDict = {
  94. '03': u'投币上报',
  95. '04': u'刷卡上报',
  96. '05': u'充电结束',
  97. '16': u'充电结束',
  98. '10': u'刷卡上报',
  99. '0D': u'故障',
  100. '20': u'启动设备',
  101. '11': u'刷卡使用',
  102. '12': u'卡充值',
  103. '22': u'ID卡扣费',
  104. '23': u'ID卡扣费状态',
  105. '17': u'IC卡回收余额成功',
  106. }
  107. return cmdDict.get(cmdCode, '')
  108. def is_port_can_use(self, port, canAdd=False):
  109. # 电川的在启动的时候去判断是否需要续充
  110. return True, ''
  111. def check_dev_status(self, attachParas=None):
  112. """
  113. 如果超过两个心跳周期没有报心跳,并且最后一次更新时间在2个小时内,需要从设备获取状态
  114. 否则以缓存状态为准。
  115. :param attachParas:
  116. :return:
  117. """
  118. if attachParas is None:
  119. raise ServiceException({'result': 0, 'description': u'请您选择合适的充电端口、电池类型信息'})
  120. if not attachParas.has_key('chargeIndex'):
  121. raise ServiceException({'result': 0, 'description': u'请您选择合适的充电端口'})
  122. if not self.device.need_fetch_online:
  123. raise ServiceException(
  124. {'result': 2, 'description': DeviceErrorCodeDesc.get(ErrorCode.DEVICE_CONN_CHECK_FAIL)})
  125. self.get_port_status_from_dev()
  126. group = self.device.group # type: GroupDict
  127. if group.is_free:
  128. logger.debug('{} is free. no need to check continue pay.'.format(repr(self.device)))
  129. return
  130. # 处理是否能够续充
  131. portDict = self.get_port_status()
  132. port = str(attachParas['chargeIndex'])
  133. if port in portDict:
  134. isCanAdd = self.device['devType'].get('payableWhileBusy', False)
  135. if portDict[port]['status'] == Const.DEV_WORK_STATUS_IDLE:
  136. return
  137. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_FAULT:
  138. raise ServiceException({'result': 0, 'description': u'该端口故障,暂时不能使用'})
  139. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_WORKING:
  140. if isCanAdd:
  141. return
  142. else:
  143. raise ServiceException({'result': 0, 'description': u'该端口正在工作不能使用,请您使用其他端口'})
  144. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_FORBIDDEN:
  145. raise ServiceException({'result': 0, 'description': u'该端口已被禁止使用,请您使用其他端口'})
  146. elif portDict[port]['status'] == Const.DEV_WORK_STATUS_CONNECTED:
  147. return
  148. else:
  149. raise ServiceException({'result': 0, 'description': u'端口状态未知,暂时不能使用'})
  150. else:
  151. raise ServiceException({'result': 0, 'description': u'未知端口,暂时不能使用'})
  152. def test(self, coins):
  153. hexPort = fill_2_hexByte(hex(int(1)), 2)
  154. hexTime = fill_2_hexByte(hex(5))
  155. devInfo = MessageSender.send(device = self.device,
  156. cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  157. payload = {
  158. 'IMEI': self._device['devNo'],
  159. "funCode": '02',
  160. 'data': hexPort + '0000' + hexTime
  161. },
  162. timeout = MQTT_TIMEOUT.SHORT)
  163. return devInfo
  164. def port_is_busy(self, port_dict):
  165. if not port_dict:
  166. return False
  167. if 'billingType' not in port_dict:
  168. return False
  169. if 'status' not in port_dict:
  170. return False
  171. if 'coins' not in port_dict:
  172. return False
  173. if 'price' not in port_dict:
  174. return False
  175. if port_dict['billingType'] not in ['time', 'elec']:
  176. return False
  177. if port_dict['billingType'] == 'time':
  178. if 'needTime' not in port_dict:
  179. return False
  180. else:
  181. if 'needElec' not in port_dict:
  182. return False
  183. if port_dict['status'] == Const.DEV_WORK_STATUS_WORKING:
  184. return True
  185. else:
  186. return False
  187. def start_device(self, package, openId, attachParas):
  188. if attachParas is None:
  189. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  190. if not attachParas.has_key('chargeIndex'):
  191. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  192. price = float(package['price'])
  193. port = hex(int(attachParas['chargeIndex']))
  194. hexPort = fill_2_hexByte(port, 2)
  195. _time, unit, billingType = self._check_package(package)
  196. coins = float(package['coins'])
  197. hexTime = fill_2_hexByte(hex(int(_time)))
  198. devInfo = MessageSender.send(
  199. device = self.device,
  200. cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  201. payload = {
  202. 'IMEI': self._device['devNo'],
  203. "funCode": '02',
  204. 'data': 'EE0D02{}'.format(make_six_bytes_session_id()) + hexPort + '0000' + hexTime
  205. }, timeout = MQTT_TIMEOUT.START_DEVICE)
  206. usePort = int(attachParas['chargeIndex'])
  207. if 'rst' not in devInfo:
  208. raise ServiceException(
  209. {
  210. 'result': 2,
  211. 'description': u'启动设备失败,您的支付金额已经退还,请重新扫码设备试试(1001)'
  212. })
  213. if devInfo['rst'] != 0:
  214. if devInfo['rst'] == -1:
  215. raise ServiceException(
  216. {
  217. 'result': 2,
  218. 'description': u'充电桩正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'
  219. })
  220. elif devInfo['rst'] == 1:
  221. self.check_serial_port_for_startcmd(attachParas['chargeIndex'])
  222. devInfo['rst'] = ErrorCode.SUCCESS
  223. else:
  224. raise ServiceException(
  225. {
  226. 'result': 2,
  227. 'description': u'启动设备失败,您的支付金额已经退回,请重新扫码设备({})'.format(devInfo['rst'])
  228. })
  229. else:
  230. if 'data' not in devInfo:
  231. logger.warning('no data in success response. result = {}'.format(str(devInfo)))
  232. raise ServiceException(
  233. {
  234. 'result': 2,
  235. 'description': u'启动设备失败,您的支付金额已经退回,请重试'
  236. })
  237. else:
  238. data = devInfo['data'][18::]
  239. result = data[2:4]
  240. if result == '01': # 成功
  241. pass
  242. elif result == '02':
  243. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
  244. Device.update_dev_control_cache(self._device['devNo'], newValue)
  245. raise ServiceException({'result': 2, 'description': u'充电站故障'})
  246. elif result == '03':
  247. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_WORKING, 'statusInfo': u''}}
  248. Device.update_dev_control_cache(self._device['devNo'], newValue)
  249. raise ServiceException({'result': 2, 'description': u'该端口正在使用中'})
  250. else:
  251. raise ServiceException({
  252. 'result': 2,
  253. 'description': u'启动设备失败({}),您的支付金额已经退回,请重新扫码设备'.format(result)
  254. })
  255. portDict = {
  256. 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  257. 'status': Const.DEV_WORK_STATUS_WORKING,
  258. 'coins': coins,
  259. 'price': price,
  260. 'billingType': billingType,
  261. 'isStart': True,
  262. 'openId': openId,
  263. 'refunded': False,
  264. 'vCardId': self._vcard_id,
  265. 'payInfo': list()
  266. }
  267. ctrInfo = Device.get_dev_control_cache(self._device.devNo)
  268. lastPortInfo = ctrInfo.get(str(usePort), {})
  269. if self.port_is_busy(lastPortInfo) and \
  270. lastPortInfo.get('billingType') == billingType and \
  271. lastPortInfo.get('openId') == openId:
  272. is_continus = True
  273. portDict['coins'] = float(coins) + lastPortInfo['coins']
  274. portDict['price'] = float(price) + lastPortInfo['price']
  275. else:
  276. is_continus = False
  277. portDict['coins'] = float(coins)
  278. portDict['price'] = float(price)
  279. if attachParas.get('redpackId'):
  280. if is_continus:
  281. redpackInfo = lastPortInfo.get("redpackInfo", list())
  282. if not redpackInfo:
  283. logger.warning("miss redpackInfo! {}-{}".format(self._device["devNo"], usePort))
  284. else:
  285. redpackInfo = list()
  286. redpackInfo.append({'redpackId': str(attachParas['redpackId'])})
  287. portDict['redpackInfo'] = redpackInfo
  288. else:
  289. if is_continus:
  290. portDict['redpackInfo'] = lastPortInfo.get("redpackInfo", list())
  291. else:
  292. portDict['redpackInfo'] = list()
  293. if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
  294. if is_continus:
  295. payInfo = lastPortInfo.get("payInfo", list())
  296. if not payInfo:
  297. logger.warning("miss payInfo! {}-{}".format(self._device["devNo"], usePort))
  298. else:
  299. payInfo = list()
  300. payInfo.append({'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])})
  301. portDict['payInfo'] = payInfo
  302. else:
  303. if is_continus:
  304. portDict['payInfo'] = lastPortInfo.get("payInfo", list())
  305. else:
  306. portDict['payInfo'] = list()
  307. if billingType == 'time':
  308. if is_continus:
  309. portDict['needTime'] = _time + lastPortInfo['needTime']
  310. else:
  311. portDict['needTime'] = _time
  312. finishedTime = int(time.time()) + int(portDict['needTime'] * 60)
  313. else:
  314. if is_continus:
  315. portDict['needElec'] = _time / 100.0 + lastPortInfo['needElec']
  316. else:
  317. portDict['needElec'] = _time / 100.0
  318. finishedTime = int(time.time()) + 60 * 60 * 12
  319. portDict.update({'finishedTime': finishedTime})
  320. if 'orderNo' in attachParas:
  321. portDict.update({'orderNo': attachParas['orderNo']})
  322. Device.update_dev_control_cache(
  323. self._device['devNo'],
  324. {
  325. str(usePort): portDict
  326. })
  327. devInfo['finishedTime'] = finishedTime
  328. # 玉环的对接,放这里吧
  329. YuhuanNorther.send_dev_status(self._device, attachParas['chargeIndex'], '1')
  330. return devInfo
  331. def analyze_event_data(self, data):
  332. cmdCode = data[4:6]
  333. if cmdCode == '05':
  334. port = int(data[18:20], 16)
  335. leftTime = int(data[20:24], 16)
  336. reason = data[24:26]
  337. devType = DeviceType.objects(id=self.device['devType']['id']).first()
  338. finishedReasonDict = devType.finishedReasonDict
  339. if finishedReasonDict != {}:
  340. desc_map = finishedReasonDict
  341. else:
  342. desc_map = {
  343. '00': u'购买的充电时间或电量用完了。',
  344. '01': u'插头被拔或者松动,或者电瓶已经充满(系统判断为异常断电,电瓶车充电器种类繁多,可能存在误差)',
  345. '02': u'电池已经充满',
  346. '03': u'设备或者端口故障。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电',
  347. '04': u'警告!您的电池功率超过本机最大限制。为了公共安全,不建议您在该充电桩充电',
  348. '05': u'刷卡退费结束',
  349. '06': u'可能是插头被拔掉或者未连接充电器。如果不是自己操作,建议您到现场检查是否有人误操作',
  350. '07': u'远程方式停止充电。如果不是自己操作,建议到现场尽快恢复充电'
  351. }
  352. desc = desc_map.get(reason, u'电池没有充满!原因未知。')
  353. # 刷卡充电的结束
  354. if len(data) > 34:
  355. cardNo = str(int(data[26:34], 16))
  356. backMoney = int(data[34:36], 16) / 10.0
  357. cardType = 'ID' if data[36:40] == 'AA33' else 'IC'
  358. if cardNo != str(0):
  359. return {'status': Const.DEV_WORK_STATUS_IDLE, 'cmdCode': cmdCode, 'port': port,
  360. 'leftTime': leftTime, 'reason': desc, 'isStart': False, 'cardNo': cardNo,
  361. 'backMoney': backMoney, 'cardType': cardType, 'endType': reason,
  362. 'reasonCode': reason, 'uartData': data}
  363. else:
  364. return {'status': Const.DEV_WORK_STATUS_IDLE, 'cmdCode': cmdCode, 'port': port,
  365. 'leftTime': leftTime, 'reason': desc, 'isStart': False, 'endType': reason,
  366. 'reasonCode': reason, 'uartData': data}
  367. # 非刷卡充电的结束
  368. else:
  369. return {'status': Const.DEV_WORK_STATUS_IDLE, 'cmdCode': cmdCode, 'port': port,
  370. 'leftTime': leftTime, 'reason': desc, 'isStart': False, 'endType': reason,
  371. 'reasonCode': reason, 'uartData': data}
  372. elif cmdCode == '0D':
  373. port = int(data[16:18], 16)
  374. errCode = data[18:20]
  375. if errCode == '01':
  376. return {'statusInfo': u'端口输出故障', 'cmdCode': cmdCode, 'port': port, 'FaultCode': errCode, "uart": data}
  377. elif errCode == '02':
  378. return {'statusInfo': u'机器整体充电功率过大', 'cmdCode': cmdCode, 'port': port, 'FaultCode': errCode, "uart": data}
  379. elif errCode == '03':
  380. return {'statusInfo': u'电源故障', 'cmdCode': cmdCode, 'port': port, 'FaultCode': errCode, "uart": data}
  381. elif cmdCode == '03': # 投币上报
  382. coin = int(data[18:20], 16)
  383. try:
  384. port = int(data[20:22], 16)
  385. except:
  386. port = None
  387. return {'cmdCode': cmdCode, 'coins': coin, 'port': port}
  388. elif cmdCode == '11': # 刷卡后,按下端口,上报的报文
  389. cardNo = int(data[18:26], 16)
  390. cardNo = str(cardNo)
  391. fee = int(data[26:28], 16) / 10.0
  392. balance = int(data[28:32], 16) / 10.0
  393. cardType = 'ID' if data[32:36] == 'AA33' else 'IC'
  394. port = int(data[36:38], 16)
  395. status = data[38:40]
  396. return {'cardNo': cardNo, 'fee': fee, 'balance': balance, 'cardType': cardType, 'port': port,
  397. 'status': status, 'cmdCode': cmdCode}
  398. elif cmdCode == '12':
  399. cardNo = data[18:26]
  400. cardNo = str(int(cardNo, 16))
  401. balance = int(data[26:30], 16) / 10.0
  402. cardType = 'ID' if data[30:34] == 'AA33' else 'IC'
  403. return {'cmdCode': cmdCode, 'balance': balance, 'cardType': cardType, 'cardNo': cardNo}
  404. elif cmdCode == '04': # 旧版本的刷卡报文
  405. money = int(data[18:20], 16)
  406. return {'cmdCode': cmdCode, 'money': money}
  407. elif cmdCode == '30': # 宇泽家的,主动上报电流
  408. portData = data[18:48]
  409. port1 = int(portData[2:4])
  410. port2 = int(portData[4:6])
  411. port3 = int(portData[6:8])
  412. port4 = int(portData[8:10])
  413. port5 = int(portData[10:12])
  414. port6 = int(portData[12:14])
  415. port7 = int(portData[14:16])
  416. port8 = int(portData[16:18])
  417. port9 = int(portData[18:20])
  418. port10 = int(portData[20:22])
  419. device = int(portData[22:24])
  420. return {
  421. 'cmdCode': cmdCode,
  422. 'port1': port1,
  423. 'port2': port2,
  424. 'port3': port3,
  425. 'port4': port4,
  426. 'port5': port5,
  427. 'port6': port6,
  428. 'port7': port7,
  429. 'port8': port8,
  430. 'port9': port9,
  431. 'port10': port10,
  432. 'device': device,
  433. }
  434. elif cmdCode == '31': # 宇泽家的,主动上报温度
  435. portData = data[18:48]
  436. port1 = int(portData[2:4])
  437. port2 = int(portData[4:6])
  438. port3 = int(portData[6:8])
  439. port4 = int(portData[8:10])
  440. port5 = int(portData[10:12])
  441. port6 = int(portData[12:14])
  442. port7 = int(portData[14:16])
  443. port8 = int(portData[16:18])
  444. port9 = int(portData[18:20])
  445. port10 = int(portData[20:22])
  446. device = int(portData[22:24])
  447. return {
  448. 'cmdCode': cmdCode,
  449. 'port1': port1,
  450. 'port2': port2,
  451. 'port3': port3,
  452. 'port4': port4,
  453. 'port5': port5,
  454. 'port6': port6,
  455. 'port7': port7,
  456. 'port8': port8,
  457. 'port9': port9,
  458. 'port10': port10,
  459. 'device': device,
  460. }
  461. elif cmdCode == '32': # 宇泽家的,主动上报温度
  462. if data[18:20] == '01':
  463. return {'isYangan': True, 'cmdCode': cmdCode}
  464. else:
  465. return {'isYangan': False, 'cmdCode': cmdCode}
  466. elif cmdCode == '17':
  467. """
  468. IC卡回收余额成功,上报回收的数目
  469. 样例 660F170048614800052DDA5A0D000001DD
  470. """
  471. cardNo = int(data[18:26], 16)
  472. cardNo = str(cardNo)
  473. backMoney = int(data[26:30], 16) / 10.0
  474. return {'cmdCode': cmdCode, 'cardNo': cardNo, 'backMoney': backMoney}
  475. elif cmdCode == '22': # ID卡,上报上来扣费
  476. cardNo = int(data[18:26], 16)
  477. cardNo = str(cardNo)
  478. fee = int(data[26:28], 16) / 10.0
  479. cardType = 'ID' if data[28:32] == 'AA33' else 'IC'
  480. return {'cmdCode': cmdCode, 'cardNo': cardNo, 'fee': fee, 'cardType': cardType}
  481. elif cmdCode == '23': # ID卡,上报上来扣费
  482. cardNo = int(data[18:26], 16)
  483. cardNo = str(cardNo)
  484. status = data[26:28]
  485. return {'cmdCode': cmdCode, 'cardNo': cardNo, 'status': status}
  486. elif cmdCode == '35':
  487. temperature = int(data[18:20], 16)
  488. smoke = int(data[20:22], 16)
  489. voltage = int(data[22:26], 16)
  490. return {'cmdCode': cmdCode, 'temperature': temperature, 'smokeWarning': (smoke == 0x01), 'voltage': voltage}
  491. elif cmdCode == '41':
  492. return {'cmdCode': cmdCode, 'smokeWarning': True}
  493. elif cmdCode == "2C":
  494. # 中润易和独有 参数意义分别是卡号 端口号 刷卡次数
  495. return {"cmdCode": cmdCode, "cardNo": str(int(data[18:26], 16)), "portStr": str(int(data[26:28], 16)), "num": int(data[28:30], 16)}
  496. def get_dev_consume_count(self):
  497. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  498. {'IMEI': self._device['devNo'], "funCode": '07', 'data': '00'})
  499. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  500. if devInfo['rst'] == -1:
  501. raise ServiceException(
  502. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  503. elif devInfo['rst'] == 1:
  504. raise ServiceException(
  505. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  506. data = devInfo['data'][16::]
  507. cardFee = int(data[2:6], 16) / 10.0 # 以角为单位
  508. coinFee = int(data[6:10], 16) # 以元为单位
  509. return {'cardFee': cardFee, 'coinFee': coinFee}
  510. def get_port_info(self, line):
  511. support_06 = self._device.get('otherConf', {}).get('support_06', True)
  512. if not support_06:
  513. return {'port': line}
  514. data = fill_2_hexByte(hex(int(line)), 2)
  515. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  516. {'IMEI': self._device['devNo'], "funCode": '06', 'data': data})
  517. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  518. if devInfo['rst'] == -1:
  519. raise ServiceException(
  520. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  521. elif devInfo['rst'] == 1:
  522. raise ServiceException(
  523. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  524. data = devInfo['data'][16::]
  525. leftTime = int(data[4:8], 16)
  526. if data[8:12] == 'FFFF':
  527. power = 0
  528. else:
  529. power = int(data[8:12], 16) / 10.0
  530. data = {"port": line, "power": power}
  531. # 电量计费模式
  532. if not self._device.get("otherConf", dict()).get("consumeModule", 0):
  533. data.update({"leftTime": leftTime})
  534. else:
  535. data.update({"leftElec": leftTime / 100.0})
  536. if self.device.bill_as_service_feature.on:
  537. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  538. needElec = ctrInfo[line]['needElec']
  539. usedElec = needElec - leftTime / 100.0
  540. elecCharge = self.device.bill_as_service_feature.elec_charge
  541. serviceCharge = self.device.bill_as_service_feature.service_charge
  542. elecFee = float(elecCharge * usedElec)
  543. serviceFee = float(serviceCharge * usedElec)
  544. consumeMoney = elecFee + serviceFee
  545. data.update({"elecFee": elecFee, "serviceFee" : serviceFee,'consumeMoney':consumeMoney})
  546. return data
  547. # 访问设备电流
  548. def get_port_elec_from_dev(self):
  549. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  550. {'IMEI': self._device['devNo'], "funCode": '21', 'data': '00'})
  551. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  552. if devInfo['rst'] == -1:
  553. raise ServiceException(
  554. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  555. elif devInfo['rst'] == 1:
  556. raise ServiceException(
  557. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  558. portData = devInfo['data'][18::]
  559. port1 = int(portData[2:4], 16)
  560. port2 = int(portData[4:6], 16)
  561. port3 = int(portData[6:8], 16)
  562. port4 = int(portData[8:10], 16)
  563. port5 = int(portData[10:12], 16)
  564. port6 = int(portData[12:14], 16)
  565. port7 = int(portData[14:16], 16)
  566. port8 = int(portData[16:18], 16)
  567. port9 = int(portData[18:20], 16)
  568. port10 = int(portData[20:22], 16)
  569. device = int(portData[22:24], 16)
  570. return {
  571. 'port1': port1,
  572. 'port2': port2,
  573. 'port3': port3,
  574. 'port4': port4,
  575. 'port5': port5,
  576. 'port6': port6,
  577. 'port7': port7,
  578. 'port8': port8,
  579. 'port9': port9,
  580. 'port10': port10,
  581. 'device': device,
  582. }
  583. # 访问设备
  584. def get_port_temperature_from_dev(self):
  585. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  586. {'IMEI': self._device['devNo'], "funCode": '22', 'data': '00'})
  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. portData = devInfo['data'][18::]
  595. port1 = int(portData[2:4], 16)
  596. port2 = int(portData[4:6], 16)
  597. port3 = int(portData[6:8], 16)
  598. port4 = int(portData[8:10], 16)
  599. port5 = int(portData[10:12], 16)
  600. port6 = int(portData[12:14], 16)
  601. port7 = int(portData[14:16], 16)
  602. port8 = int(portData[16:18], 16)
  603. port9 = int(portData[18:20], 16)
  604. port10 = int(portData[20:22], 16)
  605. device = int(portData[22:24], 16)
  606. return {
  607. 'port1': port1,
  608. 'port2': port2,
  609. 'port3': port3,
  610. 'port4': port4,
  611. 'port5': port5,
  612. 'port6': port6,
  613. 'port7': port7,
  614. 'port8': port8,
  615. 'port9': port9,
  616. 'port10': port10,
  617. 'device': device,
  618. }
  619. # 访问设备,获取设备端口信息
  620. def get_port_status_from_dev(self):
  621. devInfo = MessageSender.send(device = self.device,
  622. cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  623. payload = {
  624. 'IMEI': self._device['devNo'],
  625. 'funCode': '01',
  626. 'data': 'EE0901{}'.format(make_six_bytes_session_id()) + '00'
  627. })
  628. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  629. if devInfo['rst'] == -1:
  630. raise ServiceException(
  631. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试', 'rst': -1})
  632. elif devInfo['rst'] == 1:
  633. raise ServiceException(
  634. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能', 'rst': 1})
  635. data = devInfo['data'][16::]
  636. result = {}
  637. portNum = int(data[2:4], 16)
  638. portData = data[4::]
  639. ii = 0
  640. while ii < portNum:
  641. statusTemp = portData[ii * 2:ii * 2 + 2]
  642. if statusTemp == '01':
  643. status = {'status': Const.DEV_WORK_STATUS_IDLE}
  644. elif statusTemp == '02':
  645. status = {'status': Const.DEV_WORK_STATUS_WORKING}
  646. elif statusTemp == '03':
  647. status = {'status': Const.DEV_WORK_STATUS_FORBIDDEN}
  648. elif statusTemp == '04':
  649. status = {'status': Const.DEV_WORK_STATUS_FAULT}
  650. # 不再上述状态之列的 统一为故障状态
  651. else:
  652. status = {'status': Const.DEV_WORK_STATUS_FAULT}
  653. ii += 1
  654. result[str(ii)] = status
  655. allPorts, usedPorts, usePorts = self.get_port_static_info(result)
  656. # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
  657. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  658. for strPort, info in result.items():
  659. if ctrInfo.has_key(strPort):
  660. ctrInfo[strPort].update({'status': info['status']})
  661. else:
  662. ctrInfo[strPort] = info
  663. ctrInfo.update({
  664. 'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts
  665. })
  666. Device.update_dev_control_cache(self.device.devNo, ctrInfo)
  667. return result
  668. def get_default_port_nums(self):
  669. default_num = 10
  670. if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_CHARGING_DIANCHUAN_HIGH:
  671. default_num = 2
  672. return default_num
  673. def get_port_status(self, force = False):
  674. if force:
  675. return self.get_port_status_from_dev()
  676. ctrInfo = Device.get_dev_control_cache(self.device.devNo)
  677. if 'allPorts' in ctrInfo and ctrInfo['allPorts'] > 0:
  678. allPorts = ctrInfo['allPorts']
  679. else:
  680. allPorts = self.get_default_port_nums()
  681. statusDict = {}
  682. for ii in range(allPorts):
  683. tempDict = ctrInfo.get(str(ii + 1), {})
  684. if tempDict.has_key('status'):
  685. statusDict[str(ii + 1)] = {'status': tempDict.get('status')}
  686. elif tempDict.has_key('isStart'):
  687. if tempDict['isStart']:
  688. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
  689. else:
  690. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  691. else:
  692. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  693. return statusDict
  694. def lock_unlock_port(self, port, lock = True):
  695. lockStr = '00' if lock else '01'
  696. portStr = fill_2_hexByte(hex(int(port)), 2)
  697. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  698. payload = {'IMEI': self._device['devNo'], "funCode": '0A',
  699. 'data': portStr + lockStr}, timeout = MQTT_TIMEOUT.SHORT)
  700. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  701. if devInfo['rst'] == -1:
  702. raise ServiceException(
  703. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  704. elif devInfo['rst'] == 1:
  705. raise ServiceException(
  706. {'result': 2, 'description': u'端口禁用功能只有带保险丝版本的才有。可能是您的设备版本过低,暂时不支持此功能,也可能是设备繁忙无响应。'})
  707. data = devInfo['data'][18::]
  708. if data[0:2] == '01': # 表示成功
  709. pass
  710. else:
  711. raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
  712. if lock:
  713. Device.update_dev_control_cache(self._device['devNo'],
  714. {str(port): {'status': Const.DEV_WORK_STATUS_FORBIDDEN}})
  715. else:
  716. Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
  717. def active_deactive_port(self, port, active):
  718. if active:
  719. raise ServiceException({'result': 2, 'description': u'该设备不支持直接打开端口'})
  720. self.stop_charging_port(port)
  721. devInfo = Device.get_dev_control_cache(self._device['devNo'])
  722. portCtrInfo = devInfo.get(str(port), {})
  723. portCtrInfo.update({'isStart': False, 'status': Const.DEV_WORK_STATUS_IDLE, 'needTime': 0, 'leftTime': 0,
  724. 'endTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  725. newValue = {str(port): portCtrInfo}
  726. Device.update_dev_control_cache(self._device['devNo'], newValue)
  727. def stop_charging_port(self, port):
  728. portStr = fill_2_hexByte(hex(int(port)), 2)
  729. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  730. payload = {'IMEI': self._device['devNo'], "funCode": '0B', 'data': portStr},
  731. timeout = MQTT_TIMEOUT.SHORT)
  732. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  733. if devInfo['rst'] == -1:
  734. raise ServiceException(
  735. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  736. elif devInfo['rst'] == 1:
  737. raise ServiceException(
  738. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  739. data = devInfo['data'][16::]
  740. port = int(data[2:4], 16)
  741. leftTime = int(data[4:8], 16)
  742. data = {"port": port}
  743. # 电量计费模式
  744. if not self._device.get("otherConf", dict()).get("consumeModule", 0):
  745. data.update({"remainder_time": leftTime})
  746. else:
  747. data.update({"remainder_time": leftTime / 100.0})
  748. return data
  749. def stop(self, port = None):
  750. return self.stop_charging_port(port)
  751. @property
  752. def isHaveStopEvent(self):
  753. return True
  754. # 获取IC卡、投币、最大功率设置
  755. def get_IC_coin_power_config(self):
  756. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  757. payload = {'IMEI': self._device['devNo'], "funCode": '0C', 'data': '00'},
  758. timeout = MQTT_TIMEOUT.SHORT)
  759. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  760. if devInfo['rst'] == -1:
  761. raise ServiceException(
  762. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  763. elif devInfo['rst'] == 1:
  764. raise ServiceException(
  765. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  766. confData = devInfo['data'][18::]
  767. maxPower = int(confData[0:4], 16)
  768. icMoney = int(confData[4:6], 16)
  769. if len(confData) > 6:
  770. time1 = int(confData[6:10], 16)
  771. time2 = int(confData[10:14], 16)
  772. time3 = int(confData[14:18], 16)
  773. else:
  774. time1, time2, time3 = 0, 0, 0
  775. return {'maxPower': maxPower, 'icMoney': icMoney, 'time1': time1,
  776. 'time2': time2, 'time3': time3}
  777. def set_IC_coin_power_config(self, infoDict):
  778. data = ''
  779. data += fill_2_hexByte(hex(int(infoDict['maxPower'])), 4)
  780. data += fill_2_hexByte(hex(int(infoDict['icMoney'])), 2)
  781. data += fill_2_hexByte(hex(int(infoDict['time1'])), 4)
  782. data += fill_2_hexByte(hex(int(infoDict['time2'])), 4)
  783. data += fill_2_hexByte(hex(int(infoDict['time3'])), 4)
  784. devInfo = MessageSender.send(
  785. device = self.device,
  786. cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  787. payload = {'IMEI': self._device['devNo'], "funCode": '08', 'data': data},
  788. timeout = MQTT_TIMEOUT.SHORT
  789. )
  790. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  791. if devInfo['rst'] == -1:
  792. raise ServiceException(
  793. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  794. elif devInfo['rst'] == 1:
  795. raise ServiceException(
  796. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  797. otherConf = self.device.get("otherConf") or dict()
  798. otherConf.update(infoDict)
  799. Device.objects.filter(devNo=self.device.devNo).update(otherConf=otherConf)
  800. Device.invalid_device_cache(self.device.devNo)
  801. def get_coin_card_enable(self):
  802. devs = Device.get_collection().find({'devNo': self._device['devNo']})
  803. if devs.count == 0:
  804. raise ServiceException(
  805. {'result': 2, 'description': u'没有找到设备哦'})
  806. return {'putCoins': devs[0].get('otherConf', {}).get('putCoins', False),
  807. 'icCard': devs[0].get('otherConf', {}).get('icCard', False)}
  808. def set_coin_card_enable(self, infoDict):
  809. data = ''
  810. if infoDict['putCoins']:
  811. data += '01'
  812. else:
  813. data += '00'
  814. if infoDict['icCard']:
  815. data += '01'
  816. else:
  817. data += '00'
  818. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  819. payload = {'IMEI': self._device['devNo'], "funCode": '09', 'data': data},
  820. timeout = MQTT_TIMEOUT.SHORT)
  821. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  822. if devInfo['rst'] == -1:
  823. raise ServiceException(
  824. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  825. elif devInfo['rst'] == 1:
  826. raise ServiceException(
  827. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  828. try:
  829. conf = Device.objects.get(devNo = self._device['devNo']).otherConf
  830. conf.update({'putCoins': infoDict['putCoins'], 'icCard': infoDict['icCard']})
  831. Device.get_collection().update_one({'devNo': self._device['devNo']}, {'$set': {'otherConf': conf}})
  832. except Exception, e:
  833. logger.error('update dev=%s coin enable ic enable e=%s' % (self._device['devNo'], e))
  834. def get_dev_all_settings(self):
  835. """
  836. 电川PCB- DC_Crg_10L_C4.0及以上版本 支持全部参数一起查询 多参数消费流程 消费方式
  837. :return:
  838. """
  839. result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = {
  840. "IMEI": self._device["devNo"],
  841. "data": "00",
  842. "funCode": "36"
  843. }, timeout = MQTT_TIMEOUT.SHORT)
  844. rst = result.get("rst")
  845. if rst == -1:
  846. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  847. elif rst == 1:
  848. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  849. elif rst == 0:
  850. data = split_str(result.get('data'), lens = "4444444242424224442222", startIndex = 18, toInt = True)
  851. resultDict = {
  852. "time1": data[0],
  853. "time2": data[1],
  854. "time3": data[2],
  855. "card1Time": data[3],
  856. "card2Time": data[4],
  857. "card3Time": data[5],
  858. "icMoney": data[6], # 前台单位为角
  859. "cardRefund": bool(data[7]),
  860. "power1": data[8],
  861. "power1ratio": data[9] * 10,
  862. "power2": data[10],
  863. "power2ratio": data[11] * 10,
  864. "power3": data[12],
  865. "power3ratio": data[13] * 10,
  866. "autoStop": bool(data[14]),
  867. "fuchongPower": data[15] * 0.1,
  868. "fuchongTime": data[16],
  869. "noPowerTime": data[17],
  870. "chargeFree": bool(data[18]),
  871. "volume": data[19],
  872. "consumeProcess": data[20],
  873. "consumeModule": data[21]
  874. }
  875. else:
  876. raise ServiceException({'result': 2, 'description': u"数据读取失败,请您稍后再试"})
  877. # TODO zjl 这个地方主板的读取所有参数对于icMoney这个字段读取的是错误的值,需要再使用旧的读取指令读取一遍,然后更新,等主板更正过来之后删除这一次的读取
  878. oldGetSettingsData = self.get_IC_coin_power_config()
  879. resultDict['icMoney'] = oldGetSettingsData.get("icMoney")
  880. resultDict['maxPower'] = oldGetSettingsData.get("maxPower")
  881. coinCardEnable = self.get_coin_card_enable()
  882. resultDict['putCoins'] = coinCardEnable['putCoins']
  883. resultDict['icCard'] = coinCardEnable['icCard']
  884. return resultDict
  885. # 获取设备配置参数
  886. def get_dev_setting(self):
  887. driverCode = self._device.get("devType", dict()).get("code", "")
  888. dev = Device.objects.get(devNo = self._device['devNo']) # type: Device
  889. if driverCode == Const.DEVICE_TYPE_CODE_CHARGING_DIANCHUAN_HIGH:
  890. resultDict = self.get_dev_all_settings()
  891. else:
  892. resultDict = self.get_IC_coin_power_config()
  893. tempDict = self.get_coin_card_enable()
  894. resultDict.update(tempDict)
  895. tempDict = self.get_gear_conf()
  896. resultDict.update(tempDict)
  897. tempDict = self.get_fullstop_cardrefund()
  898. resultDict.update(tempDict)
  899. # 兼容刷卡时间 2a指令
  900. try:
  901. tempDict = self.get_freemode_volume_andsoon_config()
  902. except Exception:
  903. tempDict = {
  904. 'volume': '',
  905. 'card1Time': '',
  906. 'card2Time': '',
  907. 'card3Time': '',
  908. 'fuchongPower': dev.otherConf.get('fuchongPower', ''),
  909. 'fuchongTime': dev.otherConf.get('fuchongTime', '')
  910. }
  911. finally:
  912. resultDict.update(tempDict)
  913. cardNoRangeStart = dev.otherConf.get('cardNoRangeStart', '')
  914. resultDict.update({'cardNoRangeStart': cardNoRangeStart})
  915. cardNoRangeEnd = dev.otherConf.get('cardNoRangeEnd', '')
  916. resultDict.update({'cardNoRangeEnd': cardNoRangeEnd})
  917. tempDict = self.get_temperature_voltage_threshold()
  918. resultDict.update(tempDict)
  919. return resultDict
  920. # 获取设备配置参数
  921. def set_dev_setting(self, setConf):
  922. keys = setConf.keys()
  923. if 'putCoins' in keys or 'icCard' in keys:
  924. self.set_coin_card_enable(setConf)
  925. if 'maxPower' in keys or 'icMoney' in keys or 'time1' in keys or 'time2' in keys or 'time3' in keys:
  926. self.set_IC_coin_power_config(setConf)
  927. def get_IC_card_password(self):
  928. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  929. payload = {'IMEI': self._device['devNo'], "funCode": '1A', 'data': '00'},
  930. timeout = MQTT_TIMEOUT.SHORT)
  931. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  932. if devInfo['rst'] == -1:
  933. raise ServiceException(
  934. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  935. elif devInfo['rst'] == 1:
  936. raise ServiceException(
  937. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  938. confData = devInfo['data'][18::]
  939. result = confData[0:2]
  940. if result == '00':
  941. cardPassword = ''
  942. else:
  943. cardPassword = str(int(confData[2:12]))
  944. return {'cardPassword': cardPassword}
  945. def get_fullstop_cardrefund(self):
  946. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  947. payload = {'IMEI': self._device['devNo'], "funCode": '0C', 'data': '00'},
  948. timeout = MQTT_TIMEOUT.SHORT)
  949. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  950. if devInfo['rst'] == -1:
  951. raise ServiceException(
  952. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  953. elif devInfo['rst'] == 1:
  954. raise ServiceException(
  955. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  956. confData = devInfo['data'][18::]
  957. maxPower = int(confData[0:4], 16)
  958. icMoney = int(confData[4:6], 16)
  959. if len(confData) > 6:
  960. time1 = int(confData[6:10], 16)
  961. time2 = int(confData[10:14], 16)
  962. time3 = int(confData[14:18], 16)
  963. else:
  964. time1, time2, time3 = 0, 0, 0
  965. return {'autoStop': True if confData[20:22] == u'01' else False,
  966. 'cardRefund': True if confData[18:20] == u'01' else False}
  967. def set_fullstop_cardrefund(self, infoDict):
  968. data = ''
  969. if infoDict['autoStop']:
  970. data += '01'
  971. else:
  972. data += '00'
  973. if infoDict['cardRefund']:
  974. data += '01'
  975. else:
  976. data += '00'
  977. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  978. payload = {'IMEI': self._device['devNo'], "funCode": '13', 'data': data},
  979. timeout = MQTT_TIMEOUT.SHORT)
  980. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  981. if devInfo['rst'] == -1:
  982. raise ServiceException(
  983. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  984. elif devInfo['rst'] == 1:
  985. raise ServiceException(
  986. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  987. try:
  988. conf = Device.objects.get(devNo = self._device['devNo']).otherConf
  989. conf.update({'autoStop': infoDict['autoStop'], 'cardRefund': infoDict['cardRefund']})
  990. Device.get_collection().update({'devNo': self._device['devNo']}, {'$set': {'otherConf': conf}})
  991. except Exception, e:
  992. logger.error('update dev=%s coin enable ic enable e=%s' % (self._device['devNo'], e))
  993. def get_gear_conf(self):
  994. resultDict = {'power1': 0, 'power1ratio': 0, 'power2': 0,
  995. 'power2ratio': 0, 'power3': 0, 'power3ratio': 0}
  996. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  997. payload = {'IMEI': self._device['devNo'], "funCode": '15', 'data': '00'},
  998. timeout = MQTT_TIMEOUT.SHORT)
  999. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1000. if devInfo['rst'] == -1:
  1001. raise ServiceException(
  1002. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1003. elif devInfo['rst'] == 1:
  1004. return resultDict
  1005. confData = devInfo['data'][18::]
  1006. power1 = int(confData[0:4], 16)
  1007. power1ratio = int(confData[4:6], 16) * 10
  1008. power2 = int(confData[6:10], 16)
  1009. power2ratio = int(confData[10:12], 16) * 10
  1010. power3 = int(confData[12:16], 16)
  1011. power3ratio = int(confData[16:18], 16) * 10
  1012. result = {
  1013. 'power1': power1, 'power1ratio': power1ratio, 'power2': power2,
  1014. 'power2ratio': power2ratio, 'power3': power3, 'power3ratio': power3ratio
  1015. }
  1016. if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_ZHANGRUNYIHE:
  1017. power4 = int(confData[18:22], 16)
  1018. power4ratio = int(confData[22:24], 16) * 10
  1019. power5ratio = int(confData[24:26], 16) * 10
  1020. result.update({'power4': power4, 'power4ratio': power4ratio,
  1021. 'power5ratio': power5ratio})
  1022. else:
  1023. if len(confData) > 31:
  1024. power4 = int(confData[18:22], 16)
  1025. power4ratio = int(confData[22:24], 16) * 10
  1026. power5 = int(confData[24:28], 16)
  1027. power5ratio = int(confData[28:30], 16) * 10
  1028. result.update({'power4': power4, 'power4ratio': power4ratio,
  1029. 'power5': power5, 'power5ratio': power5ratio,
  1030. 'support5PowerTi': True})
  1031. return result
  1032. def set_gear_conf(self, infoDict):
  1033. data = ''
  1034. data += fill_2_hexByte(hex(int(infoDict['power1'])), 4)
  1035. data += fill_2_hexByte(hex(int(infoDict['power1ratio']) / 10), 2)
  1036. data += fill_2_hexByte(hex(int(infoDict['power2'])), 4)
  1037. data += fill_2_hexByte(hex(int(infoDict['power2ratio']) / 10), 2)
  1038. data += fill_2_hexByte(hex(int(infoDict['power3'])), 4)
  1039. data += fill_2_hexByte(hex(int(infoDict['power3ratio']) / 10), 2)
  1040. if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_ZHANGRUNYIHE:
  1041. data += fill_2_hexByte(hex(int(infoDict['power4'])), 4)
  1042. data += fill_2_hexByte(hex(int(infoDict['power4ratio']) / 10), 2)
  1043. data += fill_2_hexByte(hex(int(infoDict['power5ratio']) / 10), 2)
  1044. else:
  1045. if 'power4' in infoDict:
  1046. data += fill_2_hexByte(hex(int(infoDict['power4'])), 4)
  1047. data += fill_2_hexByte(hex(int(infoDict['power4ratio']) / 10), 2)
  1048. data += fill_2_hexByte(hex(int(infoDict['power5'])), 4)
  1049. data += fill_2_hexByte(hex(int(infoDict['power5ratio']) / 10), 2)
  1050. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1051. payload = {'IMEI': self._device['devNo'], "funCode": '14', 'data': data},
  1052. timeout = MQTT_TIMEOUT.SHORT)
  1053. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1054. if devInfo['rst'] == -1:
  1055. raise ServiceException(
  1056. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1057. elif devInfo['rst'] == 1:
  1058. raise ServiceException(
  1059. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  1060. # 给实体卡充值
  1061. def recharge_card(self, cardNo, money, orderNo = None):
  1062. # type:(str,RMB)->(dict, RMB)
  1063. try:
  1064. data = 'EE1012{}'.format(make_six_bytes_session_id())
  1065. cardNo = fill_2_hexByte(hex(int(cardNo)), 8)
  1066. data += cardNo + fill_2_hexByte(hex(int(money * 10)), 4) + '0001'
  1067. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  1068. payload = {'IMEI': self._device['devNo'], 'data': data, 'funCode': '12'},
  1069. timeout = MQTT_TIMEOUT.LONGEST)
  1070. if devInfo['rst'] != 0:
  1071. if devInfo['rst'] == ErrorCode.DEVICE_CONN_FAIL:
  1072. # 离线无法判断是否成功, 认为充值成功, 走售后解决
  1073. return {
  1074. 'result': ErrorCode.DEVICE_CONN_FAIL,
  1075. 'description': u'当前充电桩正在玩命找网络,请您稍候再试'
  1076. }, None
  1077. elif devInfo['rst'] == ErrorCode.BOARD_UART_TIMEOUT:
  1078. return {
  1079. 'result': ErrorCode.BOARD_UART_TIMEOUT,
  1080. 'description': u'当前充电桩忙,无响应,请您稍候再试'
  1081. }, None
  1082. else:
  1083. return {
  1084. 'result': devInfo['rst'],
  1085. 'description': u'系统异常'
  1086. }, None
  1087. resultData = devInfo['data']
  1088. if resultData[4:6] != '16':
  1089. return {
  1090. 'result': ErrorCode.PARAMETER_ERROR_TO_BOX,
  1091. 'description': u'充值返回报文命令码不为16'
  1092. }, None
  1093. balance = RMB(int(resultData[26:30], 16)) * Decimal('0.1')
  1094. result = True if resultData[34:36] == '01' else False
  1095. if result:
  1096. return {
  1097. 'result': ErrorCode.SUCCESS,
  1098. 'description': ''
  1099. }, balance
  1100. else:
  1101. return {
  1102. 'result': ErrorCode.IC_RECHARGE_FAIL,
  1103. 'description': u'充值失败'
  1104. }, balance
  1105. except Exception as e:
  1106. logger.exception(e)
  1107. return {
  1108. 'result': ErrorCode.EXCEPTION,
  1109. 'description': e.message
  1110. }, None
  1111. # 获取IC卡、投币、最大功率设置
  1112. def get_freemode_volume_andsoon_config(self):
  1113. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1114. payload = {'IMEI': self._device['devNo'], "funCode": '2A', 'data': '00'},
  1115. timeout = MQTT_TIMEOUT.SHORT)
  1116. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1117. if devInfo['rst'] == -1:
  1118. raise ServiceException(
  1119. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1120. elif devInfo['rst'] == 1:
  1121. raise ServiceException(
  1122. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  1123. confData = devInfo['data'][18::]
  1124. card1Time = int(confData[0:4], 16)
  1125. card2Time = int(confData[4:8], 16)
  1126. card3Time = int(confData[8:12], 16)
  1127. # chargeFree = True if confData[12:14] == '01' else False
  1128. chargeFree = int(confData[12:14])
  1129. volume = int(confData[14:16], 16)
  1130. fuchongPower = int(confData[16:20], 16) * 0.1
  1131. fuchongTime = int(confData[20:24], 16)
  1132. return {'card1Time': card1Time, 'card2Time': card2Time, 'card3Time': card3Time,
  1133. 'chargeFree': chargeFree, 'volume': volume, 'fuchongPower': fuchongPower,
  1134. 'fuchongTime': fuchongTime}
  1135. def get_mcu_version(self):
  1136. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1137. payload = {'IMEI': self._device['devNo'], "funCode": '25', 'data': '00'},
  1138. timeout = MQTT_TIMEOUT.SHORT)
  1139. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1140. if devInfo['rst'] == -1:
  1141. raise ServiceException(
  1142. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1143. elif devInfo['rst'] == 1:
  1144. raise ServiceException(
  1145. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  1146. confData = devInfo['data'][18::]
  1147. mcuVersion = int(confData[0:4], 16)
  1148. return {'mcuVersion': mcuVersion}
  1149. def set_freemode_volume_config(self, infoDict):
  1150. data = '01' if infoDict['chargeFree'] == '1' else '00'
  1151. data += fill_2_hexByte(hex(int(infoDict.get('volume', 5))), 2)
  1152. devInfo = MessageSender.send(device = self.device, cmd = self.make_random_cmdcode(),
  1153. payload = {'IMEI': self._device['devNo'], "funCode": '27', 'data': data},
  1154. timeout = MQTT_TIMEOUT.SHORT)
  1155. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1156. if devInfo['rst'] == -1:
  1157. raise ServiceException(
  1158. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1159. elif devInfo['rst'] == 1:
  1160. raise ServiceException(
  1161. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  1162. def set_fuchong_config(self, infoDict):
  1163. data = fill_2_hexByte(hex(int(infoDict['fuchongPower']) * 10), 4)
  1164. data += fill_2_hexByte(hex(int(infoDict['fuchongTime'])), 4)
  1165. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1166. payload = {'IMEI': self._device['devNo'], "funCode": '28', 'data': data},
  1167. timeout = MQTT_TIMEOUT.SHORT)
  1168. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1169. if devInfo['rst'] == -1:
  1170. raise ServiceException(
  1171. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1172. elif devInfo['rst'] == 1:
  1173. raise ServiceException(
  1174. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  1175. dev = Device.objects.get(devNo = self._device['devNo'])
  1176. dev.otherConf.update({'fuchongPower': int(infoDict['fuchongPower'])})
  1177. dev.otherConf.update({'fuchongTime': int(infoDict['fuchongTime'])})
  1178. dev.save()
  1179. def set_card_time_config(self, infoDict):
  1180. data = fill_2_hexByte(hex(int(infoDict['card1Time'])), 4)
  1181. data += fill_2_hexByte(hex(int(infoDict['card2Time'])), 4)
  1182. data += fill_2_hexByte(hex(int(infoDict['card3Time'])), 4)
  1183. devInfo = MessageSender.send(device = self.device, cmd = self.make_random_cmdcode(),
  1184. payload = {'IMEI': self._device['devNo'], "funCode": '29', 'data': data},
  1185. timeout = MQTT_TIMEOUT.SHORT)
  1186. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1187. if devInfo['rst'] == -1:
  1188. raise ServiceException(
  1189. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1190. elif devInfo['rst'] == 1:
  1191. raise ServiceException(
  1192. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  1193. def set_IC_card_password(self, infoDict):
  1194. passwordStr = str(infoDict['cardPassword'])
  1195. if len(passwordStr) < 6 or len(passwordStr) > 12:
  1196. raise ServiceException({'result': 2, 'description': u'密码长度不合法, 请重新设置'})
  1197. data = passwordStr.rjust(12, '0')
  1198. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1199. payload = {'IMEI': self._device['devNo'], 'funCode': '18', 'data': data},
  1200. timeout = MQTT_TIMEOUT.SHORT)
  1201. def set_IC_card_range(self, infoDict):
  1202. cardNoRangeStart = str(infoDict['cardNoRangeStart'])
  1203. cardNoRangeEnd = str(infoDict['cardNoRangeEnd'])
  1204. if int(cardNoRangeStart) > 4294967295 or int(cardNoRangeEnd) > 4294967295 or int(cardNoRangeStart) > int(
  1205. cardNoRangeEnd):
  1206. raise ServiceException({'result': 2, 'description': u'卡号设置不合法, 请重新设置'})
  1207. cardNoRangeStart = cardNoRangeStart.rjust(10, '0')
  1208. cardNoRangeEnd = cardNoRangeEnd.rjust(10, '0')
  1209. data = cardNoRangeStart + cardNoRangeEnd
  1210. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1211. payload = {'IMEI': self._device['devNo'], 'funCode': '19', 'data': data},
  1212. timeout = MQTT_TIMEOUT.SHORT)
  1213. dev = Device.objects.get(devNo = self._device['devNo'])
  1214. dev.otherConf.update({'cardNoRangeStart': str(infoDict['cardNoRangeStart'])})
  1215. dev.otherConf.update({'cardNoRangeEnd': str(infoDict['cardNoRangeEnd'])})
  1216. dev.save()
  1217. def set_no_power_time(self, infoDict):
  1218. """
  1219. 指令是0x37 可能是 双路大功率独有的 需要找主板厂家确认一下
  1220. 设置充电器移除时间 相当于负载检测 5-999秒
  1221. 设置浮充功率 进入浮充时间的最低功率 单位0.1w 0-99.9w
  1222. 设置浮充时间 进入浮充之后 的充电时间 120-999秒
  1223. :param infoDict:
  1224. :return:
  1225. """
  1226. fuchongPower = infoDict["fuchongPower"]
  1227. fuchongTime = infoDict["fuchongTime"]
  1228. noPowerTime = infoDict["noPowerTime"]
  1229. if fuchongPower > 99.9:
  1230. raise ServiceException({"result": 2, "description": u"浮充功率设置范围为0-99.9w"})
  1231. if fuchongTime > 999 or fuchongTime < 100:
  1232. raise ServiceException({"result": 2, "description": u"浮充时间设置范围为120-999秒"})
  1233. if noPowerTime > 999 or noPowerTime < 5:
  1234. raise ServiceException({"result": 2, "decription": u"充电器移除时间设置范围为5-999秒"})
  1235. result = MessageSender.send(
  1236. device=self.device,
  1237. cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  1238. payload={
  1239. "IMEI": self.device.devNo,
  1240. "funCode": "37",
  1241. "data": "{:0>4X}{:0>4X}{:0>4X}".format(int(fuchongPower*10), int(fuchongTime), int(noPowerTime))
  1242. }
  1243. )
  1244. if result.get('rst') == -1:
  1245. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1246. elif result.get('rst') == 1:
  1247. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  1248. else:
  1249. if result["data"][18:20] != "01":
  1250. raise ServiceException({"result": 2, "description": u"设置失败,请您稍后再试"})
  1251. otherConf = self.device.get("otherConf", dict())
  1252. otherConf.update({"fuchongPower": fuchongPower, "fuchongTime": fuchongTime, "noPowerTime": noPowerTime})
  1253. Device.objects.filter(devNo=self.device.devNo).update(otherConf=otherConf)
  1254. def set_device_function(self, request, lastSetConf):
  1255. if request.POST.has_key('putCoins'):
  1256. # putCoins = True if request.POST.get('putCoins') == 'true' else False
  1257. putCoins = request.POST.get("putCoins", False)
  1258. lastSetConf.update({'putCoins': putCoins})
  1259. self.set_coin_card_enable(lastSetConf)
  1260. if request.POST.has_key('icCard'):
  1261. # icCard = True if request.POST.get('icCard') == 'true' else False
  1262. icCard = request.POST.get("icCard", False)
  1263. lastSetConf.update({'icCard': icCard})
  1264. self.set_coin_card_enable(lastSetConf)
  1265. if request.POST.has_key('autoStop'):
  1266. # autoStop = True if request.POST.get('autoStop') == 'true' else False
  1267. autoStop = request.POST.get("autoStop", False)
  1268. lastSetConf.update({'autoStop': autoStop})
  1269. self.set_fullstop_cardrefund(lastSetConf)
  1270. if request.POST.has_key('cardRefund'):
  1271. # cardRefund = True if request.POST.get('cardRefund') == 'true' else False
  1272. cardRefund = request.POST.get("cardRefund", False)
  1273. lastSetConf.update({'cardRefund': cardRefund})
  1274. self.set_fullstop_cardrefund(lastSetConf)
  1275. if request.POST.has_key('chargeFree'):
  1276. # chargeFree = True if request.POST.get('chargeFree') == 'true' else False
  1277. chargeFree = request.POST.get("chargeFree", False)
  1278. lastSetConf.update({'chargeFree': chargeFree})
  1279. self.set_freemode_volume_config(lastSetConf)
  1280. def set_elecCharge_function(self,elecCharge):
  1281. data = fill_2_hexByte(hex(int(elecCharge * 100)), 4)
  1282. devInfo = MessageSender.send(
  1283. device=self.device,
  1284. cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  1285. payload={'IMEI': self._device['devNo'], "funCode": '50', 'data': data},
  1286. timeout=MQTT_TIMEOUT.SHORT
  1287. )
  1288. if "rst" in devInfo and devInfo.get("rst") != 0:
  1289. if devInfo.get("rst") == -1:
  1290. raise ServiceException({"result": 2, "description": u"网络故障,请重新试试"})
  1291. if devInfo.get("rst") == 1:
  1292. raise ServiceException({"result": 2, "description": u"充电桩无响应,请稍后再试试"})
  1293. return devInfo
  1294. def get_elecCharge_function(self):
  1295. time.sleep(15)
  1296. data = 'EE0951{}'.format(make_six_bytes_session_id()) + '01'
  1297. devInfo = MessageSender.send(
  1298. device=self.device,
  1299. cmd=DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  1300. payload={'IMEI': self._device['devNo'], "funCode": '51', 'data': data},
  1301. timeout=MQTT_TIMEOUT.SHORT
  1302. )
  1303. if "rst" in devInfo and devInfo.get("rst") != 0:
  1304. if devInfo.get("rst") == -1:
  1305. raise ServiceException({"result": 2, "description": u"网络故障,请重新试试"})
  1306. if devInfo.get("rst") == 1:
  1307. raise ServiceException({"result": 2, "description": u"充电桩无响应,请稍后再试试"})
  1308. elecCharge = round(float(int(devInfo['data'][18:22],16)) / 100,2)
  1309. return elecCharge
  1310. def set_device_function_param(self, request, lastSetConf):
  1311. # 和 主板厂家沟通 目前已经不会存在 有maxPower这个控制选项 maxPower 就是分档功率中的最高档功率
  1312. if request.POST.has_key('icMoney'):
  1313. lastSetConf.update({'icMoney': int(request.POST.get('icMoney', 0))})
  1314. self.set_IC_coin_power_config(lastSetConf)
  1315. if "noPowerTime" in request.POST:
  1316. lastSetConf.update({
  1317. "noPowerTime": int(request.POST["noPowerTime"]),
  1318. "fuchongPower": int(request.POST["fuchongPower"]),
  1319. "fuchongTime": int(request.POST["fuchongTime"]),
  1320. })
  1321. self.set_no_power_time(lastSetConf)
  1322. if request.POST.has_key('time1') and request.POST.has_key('time2') and request.POST.has_key('time3'):
  1323. lastSetConf.update({'time1': int(request.POST.get('time1', 0))})
  1324. lastSetConf.update({'time2': int(request.POST.get('time2', 0))})
  1325. lastSetConf.update({'time3': int(request.POST.get('time3', 0))})
  1326. self.set_IC_coin_power_config(lastSetConf)
  1327. if request.POST.has_key('power1') and request.POST.has_key('power1ratio'):
  1328. lastSetConf.update({'power1': int(request.POST.get('power1', 0))})
  1329. lastSetConf.update({'power1ratio': int(request.POST.get('power1ratio', 0))})
  1330. lastSetConf.update({'power2': int(request.POST.get('power2', 0))})
  1331. lastSetConf.update({'power2ratio': int(request.POST.get('power2ratio', 0))})
  1332. lastSetConf.update({'power3': int(request.POST.get('power3', 0))})
  1333. lastSetConf.update({'power3ratio': int(request.POST.get('power3ratio', 0))})
  1334. lastSetConf.update({'power4': int(request.POST.get('power4', 0))})
  1335. lastSetConf.update({'power4ratio': int(request.POST.get('power4ratio', 0))})
  1336. lastSetConf.update({'power5': int(request.POST.get('power5', 0))})
  1337. lastSetConf.update({'power5ratio': int(request.POST.get('power5ratio', 0))})
  1338. self.set_gear_conf(lastSetConf)
  1339. if request.POST.has_key('card1Time') and request.POST.has_key('card2Time') and request.POST.has_key(
  1340. 'card3Time'):
  1341. lastSetConf.update({'card1Time': int(request.POST.get('card1Time', 0))})
  1342. lastSetConf.update({'card2Time': int(request.POST.get('card2Time', 0))})
  1343. lastSetConf.update({'card3Time': int(request.POST.get('card3Time', 0))})
  1344. self.set_card_time_config(lastSetConf)
  1345. if 'fuchongPower' in request.POST and 'fuchongTime' in request.POST:
  1346. fuchongPower = 0 if request.POST.get('fuchongPower') == '' else int(request.POST.get('fuchongPower'))
  1347. fuchongTime = 0 if request.POST.get('fuchongTime') == '' else int(request.POST.get('fuchongTime'))
  1348. lastSetConf.update({'fuchongPower': fuchongPower})
  1349. lastSetConf.update({'fuchongTime': fuchongTime})
  1350. self.set_fuchong_config(lastSetConf)
  1351. if "consumeProcess" in request.POST and "consumeModule" in request.POST:
  1352. lastSetConf.update({"consumeProcess": request.POST.get("consumeProcess")})
  1353. lastSetConf.update({"consumeModule": request.POST.get("consumeModule")})
  1354. self.set_consume_module(lastSetConf)
  1355. if 'cardPassword' in request.POST:
  1356. lastSetConf.update({'cardPassword': int(request.POST.get('cardPassword', 0))})
  1357. self.set_IC_card_password(lastSetConf)
  1358. if 'cardNoRangeStart' in request.POST and 'cardNoRangeEnd' in request.POST:
  1359. lastSetConf.update({'cardNoRangeStart': int(request.POST.get('cardNoRangeStart', 0))})
  1360. lastSetConf.update({'cardNoRangeEnd': int(request.POST.get('cardNoRangeEnd', 0))})
  1361. self.set_IC_card_range(lastSetConf)
  1362. if request.POST.has_key('voltageThre') and request.POST.has_key('temThre'):
  1363. lastSetConf.update({'voltageThre': int(request.POST.get('voltageThre', 230))})
  1364. lastSetConf.update({'temThre': int(request.POST.get('temThre', 60))})
  1365. self.set_temperature_voltage_threshold(lastSetConf)
  1366. def response_card_status(self, cardNo, balance, status):
  1367. data = 'EE1123{}'.format(make_six_bytes_session_id()) + fill_2_hexByte(hex(int(cardNo)), 4) + fill_2_hexByte(
  1368. hex(int(balance * 10)), 4) + 'AA33' + status
  1369. devInfo = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  1370. {'IMEI': self._device['devNo'], "funCode": '22', 'data': data})
  1371. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1372. if devInfo['rst'] == -1:
  1373. raise ServiceException(
  1374. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1375. elif devInfo['rst'] == 1: # 等于1的时候,说明服务器和远程模块通讯OK,响应已经收到,不需要异常处理
  1376. raise ServiceException(
  1377. {'result': 2, 'description': u'充电桩没有响应,可能是版本不对或者串口接线不良'})
  1378. resultData = devInfo['data']
  1379. if resultData[4:6] != '23':
  1380. return {'status': '00'}
  1381. backCardNo = int(resultData[18:26], 16)
  1382. if backCardNo != int(cardNo):
  1383. return {'status': '00'}
  1384. return {'status': resultData[26:28]}
  1385. def set_consume_module(self, infoDict):
  1386. """
  1387. 设置消费模式以及消费流程
  1388. 包含两个参数 consumeProcess 消费流程 consumeModule 消费方式
  1389. :param infoDict:
  1390. :return:
  1391. """
  1392. consumeProcess = infoDict.get("consumeProcess", 0)
  1393. consumeModule = infoDict.get("consumeModule", 0)
  1394. consumeProcessHex = fill_2_hexByte(hex(int(consumeProcess)), 2)
  1395. consumeModuleHex = fill_2_hexByte(hex(int(consumeModule)), 2)
  1396. result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = {
  1397. "IMEI": self._device["devNo"],
  1398. "funCode": "38",
  1399. "data": consumeProcessHex + consumeModuleHex
  1400. }, timeout = MQTT_TIMEOUT.SHORT)
  1401. rst = result.get("rst")
  1402. data = result.get("data")
  1403. if rst == 0 and data[-4:-2] == "01":
  1404. # OtherConf中也保留一份 方便启动的时候随时查询
  1405. otherConf = self._device.get("otherConf", dict())
  1406. otherConf.update({
  1407. "consumeProcess": int(consumeProcess),
  1408. "consumeModule": int(consumeModule)
  1409. })
  1410. Device.objects.filter(devNo = self._device["devNo"]).update(otherConf = otherConf)
  1411. Device.invalid_device_cache(self._device["devNo"])
  1412. return
  1413. elif data[-4: -2] != "01":
  1414. raise ServiceException({'result': 2, 'description': u'设置失败,请重新试试'})
  1415. elif rst == -1:
  1416. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1417. elif rst == 1:
  1418. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  1419. else:
  1420. raise ServiceException({'result': 2, 'description': u'未知错误'})
  1421. def get_temperature_voltage_threshold(self):
  1422. devObj = Device.objects.get(devNo = self._device['devNo'])
  1423. return {'temThre': devObj.otherConf.get('temThre', 230), 'voltageThre': devObj.otherConf.get('voltageThre', 60)}
  1424. def set_temperature_voltage_threshold(self, infoDict):
  1425. data = ''
  1426. data += fill_2_hexByte(hex(int(infoDict['temThre'])), 2)
  1427. data += fill_2_hexByte(hex(int(infoDict['voltageThre'])), 4)
  1428. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  1429. payload = {'IMEI': self._device['devNo'], "funCode": 'AA', 'data': data},
  1430. timeout = MQTT_TIMEOUT.SHORT)
  1431. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  1432. if devInfo['rst'] == -1:
  1433. raise ServiceException(
  1434. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  1435. elif devInfo['rst'] == 1:
  1436. raise ServiceException(
  1437. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试'})
  1438. devObj = Device.objects.get(devNo = self._device['devNo'])
  1439. devObj.otherConf['temThre'] = int(infoDict['temThre'])
  1440. devObj.otherConf['voltageThre'] = int(infoDict['voltageThre'])
  1441. devObj.save()
  1442. def format_upload_power(self, power):
  1443. return float(power / 10)
  1444. ################ api相关接口
  1445. def apiGetPortStatusFromDc(self, record):
  1446. return self.get_port_status_from_dev()
  1447. def apiGetDevSettingsFromDc(self, record):
  1448. result = self.get_dev_setting()
  1449. data = dict()
  1450. data['power1'] = result['power1']
  1451. data['power2'] = result['power2']
  1452. data['power3'] = result['power3']
  1453. data['power1ratio'] = result['power1ratio']
  1454. data['power2ratio'] = result['power2ratio']
  1455. data['power3ratio'] = result['power3ratio']
  1456. data['fuchongTime'] = result['fuchongTime']
  1457. data['fuchongPower'] = result['fuchongPower']
  1458. data['maxPower'] = result['maxPower']
  1459. data['icMoney'] = result['icMoney']
  1460. data['time1'] = result['time1']
  1461. data['time2'] = result['time2']
  1462. data['time3'] = result['time3']
  1463. return data
  1464. def apisetDevSettingsFromDc(self, record):
  1465. self.set_IC_coin_power_config(record)
  1466. self.set_gear_conf(record)
  1467. self.set_fuchong_config(record)
  1468. return {}
  1469. def apiGetPortInfoFromDc(self, record):
  1470. return self.get_port_info(record['port'])
  1471. def apiStartDeviceForDc(self, record):
  1472. port = hex(int(record['port']))
  1473. hexPort = fill_2_hexByte(port, 2)
  1474. coins = float(record['price'])
  1475. hexTime = fill_2_hexByte(hex(int(record['time'])))
  1476. devInfo = MessageSender.send(
  1477. device=self.device,
  1478. cmd=DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  1479. payload={
  1480. 'IMEI': self._device['devNo'],
  1481. "funCode": '02',
  1482. 'data': 'EE0D02{}'.format(make_six_bytes_session_id()) + hexPort + '0000' + hexTime
  1483. }, timeout=MQTT_TIMEOUT.START_DEVICE)
  1484. usePort = int(record['port'])
  1485. if 'rst' not in devInfo:
  1486. raise ServiceException(
  1487. {
  1488. 'result': 2,
  1489. 'description': u'启动设备失败,您的支付金额已经退还,请重新扫码设备试试(1001)'
  1490. })
  1491. if devInfo['rst'] != 0:
  1492. if devInfo['rst'] == -1:
  1493. raise ServiceException(
  1494. {
  1495. 'result': 2,
  1496. 'description': u'充电桩正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'
  1497. })
  1498. elif devInfo['rst'] == 1:
  1499. raise ServiceException(
  1500. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  1501. else:
  1502. raise ServiceException(
  1503. {
  1504. 'result': 2,
  1505. 'description': u'启动设备失败,您的支付金额已经退回,请重新扫码设备({})'.format(devInfo['rst'])
  1506. })
  1507. portDict = {
  1508. 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  1509. 'status': Const.DEV_WORK_STATUS_WORKING,
  1510. 'coins': coins,
  1511. 'price': coins,
  1512. 'isApi': True
  1513. }
  1514. Device.update_dev_control_cache(
  1515. self._device['devNo'],
  1516. {
  1517. str(usePort): portDict
  1518. })
  1519. return devInfo
  1520. def get_server_setting(self):
  1521. if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_CHARGING_DIANCHUAN_HIGH:
  1522. default_refund_protection_time = 3
  1523. else:
  1524. default_refund_protection_time = 5
  1525. return {
  1526. 'refundProtectionTime': int(
  1527. self.device.get_other_conf_item('refundProtectionTime', default_refund_protection_time)),
  1528. }
  1529. def set_server_setting(self, payload):
  1530. refundProtectionTime = int(payload['refundProtectionTime'])
  1531. self.device.update_other_conf(refundProtectionTime=refundProtectionTime)
  1532. def set_service_fee_info(self, payload):
  1533. elecCharge = round(float(payload['billAsService'].get('elecCharge', 0.5)), 2)
  1534. serviceCharge = round(float(payload['billAsService'].get('serviceCharge', 0.5)), 2)
  1535. total = elecCharge + serviceCharge
  1536. result = self.set_elecCharge_function(total)
  1537. if result['data'][18:20] != '01':
  1538. raise InvalidParameter(u'电费参数设置失败')
  1539. # 显示展示给用户信息部分
  1540. if payload.get('displaySwitchs'):
  1541. displaySwitchs = payload.get('displaySwitchs')
  1542. else:
  1543. displaySwitchs = {'displayCoinsSwitch': False,
  1544. 'displayTimeSwitch': True,
  1545. 'displayPriceSwitch': True,
  1546. 'setPulseAble': False,
  1547. 'setBasePriceAble': False}
  1548. # 套餐部分
  1549. packages = payload.get('packages')
  1550. # 调整SN套餐顺序
  1551. for i, item in enumerate(packages):
  1552. item['sn'] = i
  1553. # 套餐id 去重
  1554. existIds = list(map(lambda _: _.get('id'), packages))
  1555. washConfig = {}
  1556. for rule in packages:
  1557. if 'price' in rule:
  1558. if not is_number(rule['price'] and is_number(rule.get('time', 0))):
  1559. raise InvalidParameter(u'金币数目或者时间或者价格必须是数字')
  1560. if RMB(rule['price']) >= self.device.owner.maxPackagePrice:
  1561. raise InvalidParameter(u'套餐金额超限')
  1562. if len(rule['name']) > 20:
  1563. raise InvalidParameter(u'套餐名字只能取1-20位')
  1564. if 'id' in rule:
  1565. ruleId = rule['id']
  1566. else:
  1567. ruleId = list(set(range(1, 71)) - set([int(ruleId) for ruleId in washConfig.keys()]) - set(existIds))[0]
  1568. washConfig[str(ruleId)] = {
  1569. 'billingMethod': CONSUMETYPE.BILL_AS_SERVICE,
  1570. 'name': rule['name'],
  1571. 'coins': float(rule['price']),
  1572. 'price': float(rule['price']),
  1573. 'time': float(rule.get('time', 0)),
  1574. 'description': rule.get('description', ''),
  1575. 'imgList': rule.get('imgList', []),
  1576. 'unit': rule.get('unit', u'分钟'),
  1577. 'switch': rule.get('switch', True),
  1578. 'sn': rule.get('sn')
  1579. }
  1580. total = elecCharge + serviceCharge
  1581. self.device.update_device_obj(**{
  1582. 'washConfig': washConfig,
  1583. 'otherConf.displaySwitchs': displaySwitchs,
  1584. 'otherConf.consumeModule': 1,
  1585. 'otherConf.billingType': 'elec',
  1586. 'otherConf.totalCharge': total,
  1587. 'devType.features.billAsService.elecCharge': elecCharge,
  1588. 'devType.features.billAsService.serviceCharge': serviceCharge
  1589. })
  1590. dealer = self.device.owner
  1591. dealer.defaultWashConfig[self.device.devTypeId] = self.device['washConfig'].values()
  1592. dealer.save()
  1593. def get_service_fee_info(self):
  1594. ruleList = []
  1595. for packageId, rule in self.device['washConfig'].items():
  1596. item = {
  1597. 'id': packageId,
  1598. 'name': rule['name'],
  1599. 'coins': rule['coins'],
  1600. 'price': rule.get('price', rule['coins']),
  1601. 'time': rule.get('time', 20),
  1602. 'description': rule.get('description', ''),
  1603. 'imgList': rule.get('imgList', []),
  1604. 'unit': rule.get('unit', u'分钟'),
  1605. 'switch': rule.get('switch', True),
  1606. }
  1607. if 'sn' in rule:
  1608. item['sn'] = rule['sn']
  1609. ruleList.append(item)
  1610. billAsService = self.device.bill_as_service_feature
  1611. devData = {
  1612. 'id': self.device.devNo,
  1613. 'isManager': True,
  1614. 'groupName': self.device.group['groupName'],
  1615. 'groupNumber': self.device['groupNumber'],
  1616. 'devNo': self.device.devNo,
  1617. 'devTypeName': self.device.devTypeName,
  1618. 'devTypeCode': self.device.devTypeCode
  1619. }
  1620. if "displaySwitchs" in self.device.my_obj.otherConf:
  1621. displaySwitchs = self.device.my_obj.otherConf.get('displaySwitchs')
  1622. else:
  1623. displaySwitchs = {
  1624. 'displayCoinsSwitch': True,
  1625. 'displayTimeSwitch': True,
  1626. 'displayPriceSwitch': True,
  1627. "setPulseAble": False,
  1628. "setBasePriceAble": False
  1629. }
  1630. ruleList = sorted(ruleList, key=lambda x: (x.get('sn'), x.get('id')))
  1631. return {
  1632. 'ruleList': ruleList,
  1633. 'billAsService': billAsService,
  1634. 'devData': devData,
  1635. 'displaySwitchs': displaySwitchs,
  1636. }