suzhoubeisiyun.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import time
  6. from apilib.monetary import RMB, VirtualCoin
  7. from apilib.utils_sys import memcache_lock
  8. from apps.web.agent.models import Agent
  9. from apps.web.constant import DEALER_CONSUMPTION_AGG_KIND, Const
  10. from apps.web.core.accounting import Accounting
  11. from apps.web.core.adapter.base import fill_2_hexByte
  12. from apps.web.dealer.models import Dealer
  13. from apps.web.device.models import Group, Device, OfflineCoinStatistics
  14. from apps.web.eventer import EventBuilder
  15. from apps.web.eventer.base import WorkEvent
  16. from apps.web.eventer.errors import RequestInvalid
  17. from apps.web.eventer.hedong import is_server_refund
  18. from apps.web.report.utils import record_consumption_stats
  19. from apps.web.user.models import ServiceProgress, MyUser, ConsumeRecord, CardRechargeOrder, Card
  20. from apilib.utils_datetime import to_datetime
  21. logger = logging.getLogger(__name__)
  22. class builder(EventBuilder):
  23. def __getEvent__(self, device_event):
  24. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  25. if event_data is None or 'cmdCode' not in event_data:
  26. return None
  27. if event_data['cmdCode'] in ['A4', 'A5', 'A6', 'A7', 'A8', 'AB', 'B8']:
  28. return ChargingBeiSiYunWorkEvent(self.deviceAdapter, event_data)
  29. return None
  30. #TODO 现网重新配置
  31. class ChargingBeiSiYunWorkEvent(WorkEvent):
  32. @staticmethod
  33. def cache_key(devNo, cmd):
  34. return "event-{}-{}".format(devNo, cmd)
  35. def do(self, **args):
  36. devNo = self.device['devNo']
  37. logger.info('dian chuan car charging event detected, devNo=%s,curInfo=%s' % (devNo, self.event_data))
  38. if self.event_data['cmdCode'] == 'A4':
  39. port = self.event_data['port']
  40. orderNo = self.event_data['orderNo']
  41. cmdCode = self.event_data['cmdCode']
  42. cacheKey = self.cache_key(devNo, cmdCode)
  43. with memcache_lock(key=cacheKey, value=orderNo, expire=360) as acquired:
  44. if not acquired:
  45. return
  46. self.do_finished()
  47. if self.event_data['cmdCode'] == 'A5':
  48. self.report_power_data()
  49. if self.event_data['cmdCode'] == 'A6':
  50. self.device_status()
  51. if self.event_data['cmdCode'] == 'A7':
  52. self.do_card_start()
  53. if self.event_data['cmdCode'] == 'A8':
  54. self.do_card_balance_check()
  55. if self.event_data['cmdCode'] == 'AB':
  56. self.do_coins_start()
  57. if self.event_data['cmdCode'] == 'B8 ':
  58. self.device_disconnected()
  59. def do_finished(self):
  60. devNo = self.device.devNo
  61. port = self.event_data.get("port")
  62. portStr = str(port+1)
  63. recvTime = to_datetime(self.recvTime)
  64. group = Group.get_group(self.device['groupId'])
  65. lineInfo = Device.get_dev_control_cache(self.device.devNo)
  66. lineInfo = lineInfo[str(port + 1)]
  67. dealer = Dealer.objects(id=group['ownerId']).first()
  68. if not dealer:
  69. logger.error('dealer is not found, dealerId=%s' % group['ownerId'])
  70. self.deviceAdapter._ack(portStr)
  71. return
  72. agent = Agent.objects(id=dealer.agentId).first()
  73. if not agent:
  74. logger.error('agent is not found, agentId=%s' % dealer.agentId)
  75. self.deviceAdapter._ack(portStr)
  76. return
  77. coins = lineInfo.get("coins")
  78. if 'coins' not in lineInfo:
  79. logger.debug('port cache has no coins. no order in port {}'.format(portStr))
  80. self.deviceAdapter._ack(portStr)
  81. return
  82. if 'startTime' not in lineInfo:
  83. logger.debug('startTime is not in lineInfo')
  84. self.deviceAdapter._ack(portStr)
  85. return
  86. startTime = to_datetime(lineInfo['startTime'])
  87. if startTime > recvTime: # 如果web服务器时间和事件监控服务器时间不一致,导致开始时间比事件时间还大
  88. usedTime = 0
  89. else:
  90. usedTime = int(round(((recvTime - startTime).total_seconds() / 60.0)))
  91. cardId = lineInfo.get('cardId', '')
  92. vCardId = lineInfo.get('vCardId', None)
  93. money = VirtualCoin(lineInfo['coins'])
  94. backCoins = VirtualCoin(0.0)
  95. price = RMB(lineInfo.get('price', 0.0))
  96. refundRMB = RMB('0.0')
  97. billingType = lineInfo.get('billingType', 'time')
  98. consumeType = lineInfo.get('consumeType', '')
  99. refundProtectionTime = int(self.device.get_other_conf_item('refundProtectionTime', 5))
  100. minUsedTime = self.device.get_other_conf_item('minUsedTime', 0)
  101. isTempPackage = lineInfo.get('isTempPackage', False)
  102. spendElec = self.event_data["usedElec"]
  103. isRefundProtection = False
  104. if usedTime <= refundProtectionTime:
  105. backCoins = money
  106. isRefundProtection = True
  107. logger.info(
  108. 'exec protection refund devNo=<{}>, port=<{}>, backCoins=<{}>'.format(devNo, portStr, backCoins))
  109. if backCoins > money:
  110. backCoins = money
  111. refundRMB = price * (float(backCoins) / float(money)) if money != VirtualCoin(0) else RMB(0)
  112. logger.debug(
  113. 'refund money is: {}; refund rmb is: {}'.format(str(backCoins.amount), str(refundRMB.amount)))
  114. try:
  115. if cardId == '' and vCardId is None and consumeType != 'coin':
  116. openId = lineInfo['openId']
  117. user = MyUser.objects(openId=openId, groupId=self.device['groupId']).first() #type:MyUser
  118. extra = []
  119. consumeDict = {
  120. 'chargeIndex': portStr,
  121. 'reason': self.event_data['reason'],
  122. 'duration': usedTime,
  123. 'uartData': self.event_data.get('uartData', ''),
  124. 'elec': spendElec
  125. }
  126. need_refund = False
  127. if not group.get('isFree', False):
  128. if isTempPackage is True:
  129. if isRefundProtection is True:
  130. need_refund = True
  131. else:
  132. pass
  133. elif self.device.is_auto_refund:
  134. need_refund = True
  135. elif isRefundProtection is True:
  136. need_refund = True
  137. else:
  138. pass
  139. else:
  140. pass
  141. logger.info("netPay need refund is {}".format(need_refund))
  142. if not need_refund:
  143. ServiceProgress.update_progress_and_consume_rcd(
  144. self.device['ownerId'],
  145. {
  146. 'open_id': openId, 'device_imei': self.device['devNo'],
  147. 'port': int(portStr), 'isFinished': False
  148. },
  149. consumeDict
  150. )
  151. extra.append({u'消费明细': u'消费{}(金币)'.format(money)})
  152. else:
  153. if isTempPackage:
  154. backCoins = VirtualCoin(0)
  155. self.refund_net_pay(user, lineInfo, refundRMB, backCoins, consumeDict, True)
  156. else:
  157. self.refund_net_pay(user, lineInfo, refundRMB, backCoins, consumeDict,
  158. ('refundRMB_device_event' in dealer.features))
  159. ServiceProgress.update_progress_and_consume_rcd(
  160. self.device['ownerId'],
  161. {
  162. 'open_id': openId, 'device_imei': self.device['devNo'],
  163. 'port': int(portStr), 'isFinished': False
  164. },
  165. consumeDict)
  166. if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
  167. extra.append({u'消费明细': u'消费{}金币,退款{}金币'.format(money - backCoins, backCoins)})
  168. extra.append({U'充电量':u'充电{}度'.format(spendElec)})
  169. elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
  170. extra.append({u'消费金额': u'消费{}元,退款{}元'.format(price - refundRMB, refundRMB)})
  171. extra.append({U'充电量': u'充电{}度'.format(spendElec)})
  172. self.notify_user_service_complete(
  173. service_name='充电',
  174. openid=user.managerialOpenId,
  175. port=portStr,
  176. address=group["address"],
  177. reason=self.event_data.get('reason'),
  178. finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  179. extra=extra
  180. )
  181. elif cardId != '':
  182. # 刷的实体卡
  183. logger.info("finished with card")
  184. try:
  185. cardRefundProtectionTime = self.device.get('otherConf', {}).get('cardRefundProtectionTime', 0)
  186. if cardRefundProtectionTime > 0:
  187. if usedTime < cardRefundProtectionTime:
  188. backCoins = money
  189. logger.info(
  190. 'exec protection refund devNo=<{}>, port=<{}>, backCoins=<{}>'.format(devNo, portStr,
  191. backCoins))
  192. if backCoins > money:
  193. backCoins = money
  194. except Exception as e:
  195. logger.exception(e)
  196. card = Card.objects.get(id=cardId)
  197. openId = card.openId
  198. virtual_card = card.bound_virtual_card # type: UserVirtualCard
  199. extra = []
  200. extra.append({u'实体卡': u'{}--{}'.format(card.cardName, card.cardNo)})
  201. consumeDict = {
  202. 'chargeIndex': portStr,
  203. 'reason': self.event_data['reason'],
  204. 'duration': usedTime,
  205. 'elec': spendElec,
  206. 'elecFee': self.calc_elec_fee(spendElec)
  207. }
  208. try:
  209. if virtual_card:
  210. self.refund_virtual_card(backCoins, cardId, consumeDict, lineInfo, spendElec, usedTime,
  211. virtual_card)
  212. extra.append({u'虚拟卡券': u'{}--{}'.format(virtual_card.cardName, virtual_card.cardNo)})
  213. extra.append({u'消费明细': u'消费{}分钟'.format(usedTime)})
  214. else:
  215. if is_server_refund(billingType, self.device, dealer, agent):
  216. logger.info(
  217. 'ready to server refund money <{}> for user card <{}> in device<{}>'.format(
  218. backCoins, str(card.id), self.device.devNo))
  219. consumeDict.update(
  220. {DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: backCoins.mongo_amount})
  221. self.refund_money_for_card(backCoins, str(card.id))
  222. extra.append({u'消费明细': u'消费{}金币,退款{}金币'.format(money - backCoins, backCoins)})
  223. else:
  224. extra.append({u'消费明细': u'消费{}金币'.format(money)})
  225. finally:
  226. ServiceProgress.update_progress_and_consume_rcd(
  227. self.device['ownerId'],
  228. {
  229. 'cardId': cardId,
  230. 'device_imei': self.device['devNo'],
  231. 'port': int(portStr),
  232. 'isFinished': False
  233. }, consumeDict)
  234. self.notify_user_service_complete(
  235. service_name='充电',
  236. openid=openId,
  237. port=portStr,
  238. address=group["address"],
  239. reason=self.event_data.get('reason'),
  240. finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  241. extra=extra
  242. )
  243. elif consumeType == 'coin':
  244. logger.info("finished with coin")
  245. CoinConsumeRcd = ConsumeRecord.objects.get(orderNo=lineInfo['consumeOrderNo']) # type: ConsumeRecord
  246. CoinConsumeRcd.servicedInfo['elec'] = spendElec
  247. CoinConsumeRcd.servicedInfo['actualNeedTime'] = u'动态功率计算为%s分钟' % usedTime
  248. CoinConsumeRcd.servicedInfo['coin'] = u'投币金额为' % coins
  249. CoinConsumeRcd.servicedInfo['reason'] = self.event_data['reason']
  250. CoinConsumeRcd.servicedInfo['chargeIndex'] = portStr
  251. CoinConsumeRcd.finishedTime = recvTime.strftime('%Y-%m-%d %H:%M:%S')
  252. CoinConsumeRcd.save()
  253. valueDict = {
  254. DEALER_CONSUMPTION_AGG_KIND.DURATION: usedTime,
  255. DEALER_CONSUMPTION_AGG_KIND.ELEC: spendElec,
  256. DEALER_CONSUMPTION_AGG_KIND.ELECFEE: self.calc_elec_fee(spendElec)
  257. }
  258. status = CoinConsumeRcd.update_agg_info(valueDict)
  259. if status:
  260. record_consumption_stats(CoinConsumeRcd)
  261. else:
  262. logger.error(
  263. '[update_progress_and_consume_rcd] failed to update_agg_info record=%r' % (
  264. CoinConsumeRcd,))
  265. except Exception as e:
  266. logger.exception('deal with jingneng devNo=%s event e=%s' % (devNo, e))
  267. finally:
  268. self.deviceAdapter._ack(portStr)
  269. dataDict = {'backMoney': str(refundRMB.mongo_amount), 'backCoins': str(backCoins.mongo_amount)}
  270. if 'orderNo' in lineInfo:
  271. dataDict.update({'orderNo': lineInfo['orderNo']})
  272. self.event_data.update({'deviceCode': self.device["logicalCode"]})
  273. self.event_data.update({'spendElec': spendElec})
  274. Device.clear_port_control_cache(self.device.devNo, portStr)
  275. def report_power_data(self):
  276. ctrInfo = Device.get_dev_control_cache(self.device.devNo)
  277. port = self.event_data["port"]
  278. portStr = str(port + 1)
  279. lineInfo = ctrInfo.get(portStr, {})
  280. portStatus = lineInfo.get("portStatusDict")
  281. if portStatus == Const.DEV_WORK_STATUS_WORKING:
  282. self.deviceAdapter._response_data(self.event_data['cmdCode'], portStr)
  283. def device_status(self):
  284. portStatusDict = self.event_data["portStatusDict"]
  285. group = Group.get_group(self.device["groupId"])
  286. fault_list = []
  287. for port, status in portStatusDict.items():
  288. if status["status"] in [Const.DEV_WORK_STATUS_FAULT_RELAY_CONNECT, Const.DEV_WORK_STATUS_FAULT_OVERLOAD, \
  289. Const.DEV_WORK_STATUS_FAULT_OVERLOAD]:
  290. fault_list.append(port)
  291. if not fault_list:
  292. self.deviceAdapter._response_data(self.event_data['cmdCode'], "00")
  293. else:
  294. self.deviceAdapter._response_data(self.event_data['cmdCode'], "00")
  295. for i in fault_list:
  296. faultCode = portStatusDict[i]["statusCode"]
  297. if faultCode == 1:
  298. faultContent = "当前设备第%s号端口警告:插座空闲,功率正常,继电器故障" % (port)
  299. self.notify_dealer(
  300. templateName="device_fault",
  301. title="注意!继电器故障!",
  302. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  303. logicalCode=self.device["logicalCode"]),
  304. location=u"{address}-{groupName}".format(address=group["address"],
  305. groupName=group["groupName"]),
  306. fault=faultContent,
  307. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  308. )
  309. self.record(
  310. faultCode=faultCode,
  311. description=faultContent,
  312. title="注意!继电器故障!",
  313. )
  314. elif faultCode == 2:
  315. faultContent = "当前设备第%s号端口警告:插座空闲,功率故障,继电器正常" % (port)
  316. self.notify_dealer(
  317. templateName="device_fault",
  318. title="注意!功率故障!",
  319. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  320. logicalCode=self.device["logicalCode"]),
  321. location=u"{address}-{groupName}".format(address=group["address"],
  322. groupName=group["groupName"]),
  323. fault=faultContent,
  324. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  325. )
  326. self.record(
  327. faultCode=faultCode,
  328. description=faultContent,
  329. title="注意!功率故障!",
  330. )
  331. elif faultCode == 3:
  332. faultContent = "当前设备第%s号端口警告:插座空闲,功率故障,继电器故障" % (port)
  333. self.notify_dealer(
  334. templateName="device_fault",
  335. title="注意!功率故障,继电器故障!",
  336. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  337. logicalCode=self.device["logicalCode"]),
  338. location=u"{address}-{groupName}".format(address=group["address"],
  339. groupName=group["groupName"]),
  340. fault=faultContent,
  341. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  342. )
  343. self.record(
  344. faultCode=faultCode,
  345. description=faultContent,
  346. title="注意!功率故障,继电器故障!",
  347. )
  348. elif faultCode == 5:
  349. faultContent = "当前设备第%s号端口警告:插座工作,功率正常,继电器故障" % (port)
  350. self.notify_dealer(
  351. templateName="device_fault",
  352. title="注意!继电器故障!",
  353. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  354. logicalCode=self.device["logicalCode"]),
  355. location=u"{address}-{groupName}".format(address=group["address"],
  356. groupName=group["groupName"]),
  357. fault=faultContent,
  358. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  359. )
  360. self.record(
  361. faultCode=faultCode,
  362. description=faultContent,
  363. title="注意!继电器故障!",
  364. )
  365. elif faultCode == 6:
  366. faultContent = "当前设备第%s号端口警告:插座工作,功率故障,继电器正常" % (port)
  367. self.notify_dealer(
  368. templateName="device_fault",
  369. title="注意!功率故障!",
  370. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  371. logicalCode=self.device["logicalCode"]),
  372. location=u"{address}-{groupName}".format(address=group["address"],
  373. groupName=group["groupName"]),
  374. fault=faultContent,
  375. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  376. )
  377. self.record(
  378. faultCode=faultCode,
  379. description=faultContent,
  380. title="注意!功率故障!",
  381. )
  382. elif faultCode == 7:
  383. faultContent = "当前设备第%s号端口警告:插座工作,功率故障,继电器故障" % (port)
  384. self.notify_dealer(
  385. templateName="device_fault",
  386. title="注意!功率故障,继电器故障!",
  387. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  388. logicalCode=self.device["logicalCode"]),
  389. location=u"{address}-{groupName}".format(address=group["address"],
  390. groupName=group["groupName"]),
  391. fault=faultContent,
  392. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  393. )
  394. self.record(
  395. faultCode=faultCode,
  396. description=faultContent,
  397. title="注意!功率故障,继电器故障!",
  398. )
  399. elif faultCode == 9:
  400. faultContent = "当前设备第%s号端口警告:投币工作,功率正常,继电器故障" % (port)
  401. self.notify_dealer(
  402. templateName="device_fault",
  403. title="注意!继电器故障!",
  404. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  405. logicalCode=self.device["logicalCode"]),
  406. location=u"{address}-{groupName}".format(address=group["address"],
  407. groupName=group["groupName"]),
  408. fault=faultContent,
  409. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  410. )
  411. self.record(
  412. faultCode=faultCode,
  413. description=faultContent,
  414. title="注意!继电器故障!",
  415. )
  416. elif faultCode == 10:
  417. faultContent = "当前设备第%s号端口警告:投币工作,功率故障,继电器正常" % (port)
  418. self.notify_dealer(
  419. templateName="device_fault",
  420. title="注意!功率故障!",
  421. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  422. logicalCode=self.device["logicalCode"]),
  423. location=u"{address}-{groupName}".format(address=group["address"],
  424. groupName=group["groupName"]),
  425. fault=faultContent,
  426. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  427. )
  428. self.record(
  429. faultCode=faultCode,
  430. description=faultContent,
  431. title="注意!功率故障!",
  432. )
  433. elif faultCode == 11:
  434. faultContent = "当前设备第%s号端口警告:投币工作,功率故障,继电器故障" % (port)
  435. self.notify_dealer(
  436. templateName="device_fault",
  437. title="注意!,功率故障,继电器故障!",
  438. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  439. logicalCode=self.device["logicalCode"]),
  440. location=u"{address}-{groupName}".format(address=group["address"],
  441. groupName=group["groupName"]),
  442. fault=faultContent,
  443. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  444. )
  445. self.record(
  446. faultCode=faultCode,
  447. description=faultContent,
  448. title="注意!,功率故障,继电器故障!",
  449. )
  450. def do_card_start(self):
  451. cardNo = self.event_data["cardNo"]
  452. mode = self.event_data["mode"]
  453. port = self.event_data["port"]
  454. portStr = str(port + 1)
  455. card = self.update_card_dealer_and_type(cardNo) # type: Card
  456. if not card:
  457. self.deviceAdapter._response_data('A7', '01')
  458. return
  459. balance = card.balance
  460. if balance <= RMB(0):
  461. self.deviceAdapter._response_data('A7', '02')
  462. return
  463. result = self.deviceAdapter._get_device_status_info()
  464. status = result['portStatusDict'][portStr]['status']
  465. if status not in [Const.DEV_WORK_STATUS_IDLE, Const.DEV_WORK_STATUS_WORKING]:
  466. self.deviceAdapter._response_data('A7', '03')
  467. return
  468. needMoney = balance
  469. orderNo, cardOrderNo = self.record_consume_for_card(card, needMoney, desc=u"刷卡消费")
  470. serviceDict = {
  471. "orderNo": orderNo,
  472. "cardOrderNo": cardOrderNo
  473. }
  474. if mode == '00':
  475. billingType = self.device.otherConf.get('billingType')
  476. if billingType == 'time':
  477. method = '01'
  478. elif billingType == 'power':
  479. method = '02'
  480. elif billingType == 'elec':
  481. method = '03'
  482. elif billingType == 'free':
  483. method = '04'
  484. elif billingType == 'interval_quota':
  485. method = '05'
  486. self.deviceAdapter._start_remote(portStr, method, '02', needMoney, orderNo)
  487. else:
  488. self.deviceAdapter._update_charge_balance(portStr, needMoney)
  489. # 记录缓存
  490. ServiceProgress.register_card_service(
  491. self.device,
  492. int(portStr),
  493. card,
  494. serviceDict
  495. )
  496. portDict = {
  497. "orderNo": orderNo, # 订单号码
  498. "cardOrderNo": cardOrderNo,
  499. "cardNo": cardNo, # 卡号 0-99999999
  500. 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  501. 'coins': str(needMoney),
  502. 'price': str(needMoney),
  503. 'isStart': True,
  504. 'openId': card.openId,
  505. 'ZRYH': True,
  506. "cardId": str(card.id),
  507. "billingType": billingType
  508. }
  509. Device.update_dev_control_cache(self.device["devNo"], {portStr: portDict})
  510. def do_card_balance_check(self):
  511. cardNo = self.event_data["cardNo"]
  512. card = self.update_card_dealer_and_type(cardNo)
  513. # 没有到账的卡给它充值, 应该用不上
  514. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  515. self.recharge_id_card(
  516. card=card,
  517. rechargeType='append',
  518. order=card_recharge_order
  519. )
  520. card.reload()
  521. cardBalance = card.balance
  522. cardBalanceHex = fill_2_hexByte(hex(float(cardBalance) * 100), 8)
  523. data = "00" + cardBalanceHex
  524. self.deviceAdapter._response_data(self.event_data['cmdCode'], data)
  525. def do_coins_start(self):
  526. Accounting.recordOfflineCoin(device=self.device,
  527. report_ts=int(time.time()),
  528. coins=int(self.event_data['coins']),
  529. port=self.event_data.get('port', None))
  530. if self.device.ownerId is not None and self.device.ownerId != '':
  531. dealer = Dealer.objects(id=self.device.ownerId).first()
  532. if dealer is not None and 'show_device_offline_coins' in dealer.features:
  533. OfflineCoinStatistics.recordCoinEvent(
  534. self.device['logicalCode'],
  535. self.device.devNo,
  536. int(self.event_data.get('coins', 1)),
  537. self.device['groupId']
  538. )
  539. else:
  540. logger.error('undefined dealer id=%s' % self.device.ownerId)
  541. # 如果是投币,直接把端口状态刷新下
  542. try:
  543. self.deviceAdapter.get_port_status_from_dev()
  544. except Exception, e:
  545. logger.info('some err=%s' % e)
  546. finally:
  547. self.deviceAdapter._ack(self.event_data.get('port'))
  548. def device_disconnected(self):
  549. deviceCode = self.event_data["deviceCode"]
  550. group = Group.get_group(self.device["groupId"])
  551. faultContent = "设备%s警告,充电桩主电断开" % (deviceCode)
  552. self.notify_dealer(
  553. templateName="device_fault",
  554. title="注意!充电桩主电断开!",
  555. device=u"{groupNumber}组-{logicalCode}".format(groupNumber=self.device["groupNumber"],
  556. logicalCode=self.device["logicalCode"]),
  557. location=u"{address}-{groupName}".format(address=group["address"],
  558. groupName=group["groupName"]),
  559. fault=faultContent,
  560. notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  561. )
  562. self.record(
  563. faultCode="00",
  564. description=faultContent,
  565. title="注意!,功率故障,继电器故障!",
  566. )