nengpai.py 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. # -*- coding: utf-8 -*-
  2. #!/usr/bin/env python
  3. import datetime
  4. import logging
  5. import time
  6. from mongoengine import DoesNotExist
  7. from apilib.monetary import RMB, VirtualCoin
  8. from apps.web.constant import Const
  9. from apps.web.dealer.models import Dealer
  10. from apps.web.device.models import WeifuleDeviceOrder, Group, Device
  11. from apps.web.device.timescale import FluentedEngine
  12. from apps.web.eventer import EventBuilder
  13. from apps.web.eventer.base import WorkEvent, FaultEvent
  14. from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, \
  15. ConsumeRecord, Card, CardConsumeRecord, CardRechargeOrder, MyUser, RechargeRecord
  16. from django.conf import settings
  17. from apps.web.core.adapter.base import reverse_hex,make_cartcp_order_no,asc_to_string
  18. from apps.web.device.models import Part
  19. from apps.web.south_intf.swap_carcharger import SwapContract
  20. from apps.web.constant import DeviceOnlineStatus
  21. import time
  22. logger = logging.getLogger(__name__)
  23. class builder(EventBuilder):
  24. def __getEvent__(self, device_event):
  25. return NengpaiBox(self.deviceAdapter, device_event)
  26. class NengpaiFaultEvent(FaultEvent):
  27. def do(self, **args):
  28. return
  29. # if self.event_data['fun_code'] == fault_event_mcu_36:
  30. # self.event_data.update({
  31. # 'faultName':u'单片机告警',
  32. # 'faultCode':FAULT_CODE.MCU_REBOOT,
  33. # 'level':FAULT_LEVEL.NORMAL,
  34. # 'desc':u'充电主板上的单片机重启。'
  35. # })
  36. # elif self.event_data['fun_code'] == fault_event_relay_39:
  37. # self.event_data.update({
  38. # 'faultName':u'继电器告警',
  39. # 'port':int(self.event_data['port']),
  40. # 'faultCode':FAULT_CODE.RELAY_FAULT,
  41. # 'level':FAULT_LEVEL.CRITICAL,
  42. # 'desc':u'继电器发送粘连。'
  43. # })
  44. # elif self.event_data['fun_code'] == fault_event_counter_40:
  45. # self.event_data.update({
  46. # 'faultName':u'计量芯片告警',
  47. # 'port':int(self.event_data['port']),
  48. # 'faultCode':FAULT_CODE.COUNTER_FAULT,
  49. # 'level':FAULT_LEVEL.CRITICAL,
  50. # 'desc':u'计量芯片获取功率失败。'
  51. # })
  52. # elif self.event_data['fun_code'] == fault_event_overload_38:
  53. # self.event_data.update({
  54. # 'faultName':u'整机功率过载告警',
  55. # 'faultCode':FAULT_CODE.DEV_OVERLOAD,
  56. # 'level':FAULT_LEVEL.FATAL,
  57. # 'desc':u'整机功率超过7500瓦。'
  58. # })
  59. # else:
  60. # pass
  61. # super(NengpaiFaultEvent, self).do()
  62. class NengpaiBox(WorkEvent):
  63. # 用于计数上报的电压、电流、功率
  64. countMap = {}
  65. # 时段数组
  66. shiduanList = []
  67. # 分时数组
  68. fenshiList = []
  69. # 服务费
  70. serverMoneyList = []
  71. # 电费
  72. eleMoneyList = []
  73. current_dict = {
  74. 'startTime': '', # 区间开始时间
  75. 'endTime': '', # 区间结束时间
  76. 'ele': '', # 当前区间充电总电数
  77. 'money': '', # 当前区间已充金额
  78. 'perServeMoney': '', # 当前区间服务费(元/度)
  79. 'elecFee': '', # 当前区间电费(元/度)
  80. 'eleMoney': '', # 当前区间总电费
  81. 'serveMoney': '', # 当前区间服务费
  82. 'chargedMoney': '', # 已充金额
  83. 'totalEle': '', # 充电度数
  84. }
  85. # 微付乐的板子:根据设备上报上来的订单,创建正在服务的信息
  86. def create_progress_for_weifule_order(self, dev, consumeRcd, order):
  87. try:
  88. progress = ServiceProgress.objects.filter(weifuleOrderNo=order['id']).first()
  89. if progress:
  90. return
  91. port = int(order['port'])
  92. attachParas = consumeRcd.attachParas
  93. needKind, needValue, unit = self.analyse_need_from_package(order)
  94. consumeOrder = {
  95. 'orderNo': consumeRcd.orderNo,
  96. 'coin': consumeRcd.coin.mongo_amount,
  97. 'money': consumeRcd.money.mongo_amount,
  98. 'unit': unit,
  99. 'consumeType':'mobile_vcard' if u'虚拟卡' in consumeRcd.remarks else 'mobile'
  100. }
  101. if needKind:
  102. consumeOrder.update({needKind:needValue})
  103. new_service_progress = ServiceProgress(
  104. open_id=consumeRcd.openId,
  105. device_imei=consumeRcd.devNo,
  106. devTypeCode=dev['devType']['code'],
  107. port=port,
  108. attachParas=attachParas if attachParas else {},
  109. start_time=int(order['create_time']),
  110. finished_time=24 * 60 * 60,
  111. consumeOrder=consumeOrder
  112. )
  113. new_service_progress.save()
  114. except Exception as e:
  115. logger.exception(e)
  116. def consume_money_for_ID_card(self, agentId, cardNo, balance, money):
  117. card = Card.objects.get(agentId=agentId, cardNo=cardNo)
  118. if card.balance < money:
  119. card.balance = RMB(0)
  120. else:
  121. card.balance = (card.balance - money)
  122. # card.showBalance = card.balance #只有微付乐是创建订单成功后才真正扣费
  123. try:
  124. card.save()
  125. except Exception as e:
  126. logger.exception(e)
  127. return card
  128. def update_balance_for_IC_card(self, card, balance):
  129. card.balance = balance
  130. try:
  131. card.save()
  132. except Exception, e:
  133. pass
  134. def is_order_accepted(self, orderNo, cmdCode):
  135. return True if WeifuleDeviceOrder.objects.filter(orderNo=orderNo, cmdCode=cmdCode).count() > 0 else False
  136. def record_order_event(self, order, cmdCode):
  137. newObj = WeifuleDeviceOrder(orderNo=order['id'], cmdCode=cmdCode, order=order)
  138. try:
  139. newObj.save()
  140. except Exception, e:
  141. logger.exception('save order event error=%s' % e)
  142. pass
  143. def record_consume_for_card(self, card,port,orderNo):
  144. group = Group.get_group(self.device['groupId'])
  145. address = group['address']
  146. group_number = self.device['groupNumber']
  147. now = datetime.datetime.now()
  148. new_record = {
  149. 'orderNo': orderNo,
  150. 'time': now.strftime("%Y-%m-%d %H:%M:%S"),
  151. 'dateTimeAdded': now,
  152. 'openId': card.openId,
  153. 'ownerId': self.device['ownerId'],
  154. 'coin': VirtualCoin(0.0).mongo_amount,
  155. 'money': RMB(0.00).mongo_amount,
  156. 'devNo': self.device['devNo'],
  157. 'logicalCode': self.device['logicalCode'],
  158. 'groupId': self.device['groupId'],
  159. 'address': address,
  160. 'groupNumber': group_number,
  161. 'groupName': group['groupName'],
  162. 'devTypeCode': self.device.devTypeCode,
  163. 'devTypeName': self.device.devTypeName,
  164. 'isNormal': False,
  165. 'status': ConsumeRecord.Status.RUNNING,
  166. 'remarks': u'刷卡消费',
  167. 'errorDesc': '',
  168. 'sequanceNo': '',
  169. 'desc': '',
  170. 'attachParas': {},
  171. 'servicedInfo': {}
  172. }
  173. ConsumeRecord.get_collection().insert_one(new_record)
  174. # 刷卡消费也记录一条数据
  175. new_card_record = {
  176. 'orderNo': orderNo,
  177. 'openId': card.openId,
  178. 'cardId': str(card.id),
  179. 'money': RMB(0.00).mongo_amount,
  180. 'balance': card.balance.mongo_amount,
  181. 'devNo': self.device['devNo'],
  182. 'devType': self.device['devType']['name'],
  183. 'logicalCode': self.device['logicalCode'],
  184. 'groupId': self.device['groupId'],
  185. 'address': address,
  186. 'groupNumber': group_number,
  187. 'groupName': group['groupName'],
  188. 'result': 'success',
  189. 'remarks': u'刷卡消费',
  190. 'sequanceNo': '',
  191. 'dateTimeAdded': datetime.datetime.now(),
  192. 'desc': '',
  193. 'servicedInfo': {},
  194. 'linkedConsumeRcdOrderNo':str(new_record['orderNo'])
  195. }
  196. CardConsumeRecord.get_collection().insert_one(new_card_record)
  197. return new_record['orderNo'], new_card_record['orderNo']
  198. # 解析报文内容的函数
  199. def get_msg_info(self):
  200. data = self.event_data['data']
  201. cmdCode = self.event_data['cmd']
  202. result = {}
  203. if cmdCode == '01':
  204. result['type'] = 'jl' if data[26:28] == '00' else 'zl'
  205. result['portNum'] = int(data[28:30])
  206. result['conVersion'] = 'V%s' % int(data[30:32],16)
  207. result['driverVersion'] = asc_to_string(data[32:48])
  208. result['iccid'] = str(data[50:70])
  209. return result
  210. # 获取设备是交流还是直流
  211. def get_charger_type(self):
  212. if u'交流' in self.device.majorDeviceType:
  213. return 'ac'
  214. if u'直流' in self.device.majorDeviceType:
  215. return 'dc'
  216. return 'ac'
  217. # 登记设备
  218. def register_dev(self,data):
  219. server,port,proto = self.device.network_address
  220. devObj = Device.objects.get(devNo = self.device['devNo'])
  221. # 获取sim卡,卡号
  222. msgInfo = self.get_msg_info()
  223. devObj.iccid = msgInfo['iccid']
  224. devObj.softVer = msgInfo['driverVersion']
  225. devObj.driverCode = Const.DEVICE_TYPE_CODE_CAR_NENGPAI # 驱动必须赋值
  226. # 第一次上线的时候,需要把server以及feeMode的数据初始化
  227. if server != settings.CAR_TCPIP_SERVER or port != settings.CAR_TCPIP_SERVER_PORT or 'feeMode' not in devObj.otherConf:
  228. devObj.server= settings.CAR_TCPIP_SERVER + ":" + str(settings.CAR_TCPIP_SERVER_PORT)
  229. if 'feeMode' not in devObj.otherConf:
  230. logger.info('init feemode to device,devNo=%s' % self.device['devNo'])
  231. devObj.otherConf['feeMode'] = {'modeNo':'0000','jianFee':1.20000,
  232. 'fengFee':1.20000,
  233. 'pingFee':1.20000,
  234. 'guFee':1.20000,
  235. 'jianServe':0,
  236. 'fengServe':0,
  237. 'pingServe':0,
  238. 'guServe':0,
  239. 'jishunScale':0,
  240. 'shiduan':'000000000000000000000000000000000000000000000000'
  241. }
  242. devObj.save()
  243. Device.invalid_device_cache(self.device['devNo'])
  244. Device.update_dev_control_cache(self.device['devNo'],{'allPorts': msgInfo['portNum']})
  245. Device.update_online_cache(self.device['devNo'], True,32)# 设备没有返回信号量,所以就用32
  246. def update_port_by_heartbeat(self):
  247. data = self.event_data['data']
  248. port = int(data[-8:-6])
  249. part = Part.insert_part_if_not_exist(self.device['logicalCode'],self.device['ownerId'],port, '%s号充电枪' % port,self.get_charger_type())# 交流电
  250. if data[-6:-4] == '01':
  251. lastStatus = Device.get_dev_control_cache(self.device['devNo']).get(str(port),{}).get('status',None)
  252. Device.update_dev_control_cache(self.device['devNo'], {
  253. str(port):{'status':Const.DEV_WORK_STATUS_FAULT}
  254. }
  255. )
  256. Part.update_part_work_status(self.device['logicalCode'], port, Part.Status.FAULT)
  257. Part.update_part_network_status(self.device['logicalCode'], port, Part.OnlineStatus.OFFLINE)
  258. if lastStatus != Const.DEV_WORK_STATUS_FAULT:
  259. SwapContract.notify_2_all_northers_port_status(self.device,port,Const.DEV_WORK_STATUS_FAULT)
  260. else:
  261. portStatus = Device.get_dev_control_cache(self.device['devNo']).get(str(port),{}).get('status',None)
  262. if portStatus is None or portStatus != Const.DEV_WORK_STATUS_WORKING:
  263. Device.update_dev_control_cache(self.device['devNo'], {
  264. str(port):{'status':Const.DEV_WORK_STATUS_IDLE}
  265. }
  266. )
  267. Part.update_part_network_status(self.device['logicalCode'], port, Part.OnlineStatus.ONLINE)
  268. # 刷新端口详细信息
  269. def update_order_info(self):
  270. data = self.event_data['data']
  271. orderNo = data[12:44]
  272. port = int(data[58:60])
  273. valueDict = self.deviceAdapter.get_values_from_data(data)
  274. portStatus = valueDict['status']
  275. lastStatus = Device.get_dev_control_cache(self.device['devNo']).get(str(port),{}).get('status',None)
  276. Device.update_dev_control_cache(self.device['devNo'],{str(port):valueDict})
  277. ConsumeRecord.get_collection().update_one({'orderNo': orderNo},
  278. {'$set': {'isNormal': True, 'status': ConsumeRecord.Status.RUNNING}})
  279. CardConsumeRecord.get_collection().update_one({'orderNo':orderNo},{'$set':{'result':'success'}})
  280. # 更新part的状态
  281. Part.insert_part_if_not_exist(self.device['logicalCode'],self.device['ownerId'],port, '%s号充电枪' % port,self.get_charger_type())# 交流电
  282. Part.update_part_work_status(self.device['logicalCode'], port, portStatus)
  283. Part.update_part_network_status(self.device['logicalCode'], port,Part.OnlineStatus.ONLINE)
  284. # 比较端口状态,如果发生变化,需要通知北向
  285. group = Group.get_group(self.device['groupId'])
  286. if lastStatus != portStatus and group.get('swapFlag',False):
  287. SwapContract.notify_2_all_northers_port_status(self.device,port,portStatus)
  288. # 将功率,电流,电压推入时间数据库
  289. devNo = self.device['devNo']
  290. key = '%s-%s' % (devNo, port)
  291. # 初始化计数器
  292. if key not in NengpaiBox.countMap:
  293. NengpaiBox.countMap[key] = 0
  294. else:
  295. NengpaiBox.countMap[key] += 1
  296. print('!!!!!!!!!!!!!!!!!!!NengpaiBox.countMap', NengpaiBox.countMap[key])
  297. # 充电时,事件上报间隔为15s,每60s记录一次,ts为当前时间
  298. if NengpaiBox.countMap[key] % 4 == 0:
  299. voltage = int(reverse_hex(data[66:70]), 16) / 10.0
  300. current = int(reverse_hex(data[70:74]), 16) / 10.0
  301. power = voltage * current
  302. print('!---------------!insert one record into timedatabase')
  303. # 插入时间数据库
  304. FluentedEngine().in_power_udp(devNo=devNo,
  305. port=port,
  306. ts=int(time.time()),
  307. power=power,
  308. voltage=voltage,
  309. current=current)
  310. # 进行分时计算
  311. devObj = Device.objects.get(devNo=self.device['devNo'])
  312. feeMode = devObj.otherConf.get('feeMode', {})
  313. shiduan = feeMode.get('shiduan', '000000000000000000000000000000000000000000000000')
  314. # 尖峰平谷的服务费从数据库中取得(元/度)
  315. jianServe = feeMode['jianServe']
  316. fengServe = feeMode['fengServe']
  317. pingServe = feeMode['pingServe']
  318. guServe = feeMode['guServe']
  319. # 尖峰平谷的电费从数据库中取得(元/度)
  320. jianFee = feeMode['jianFee']
  321. fengFee = feeMode['fengFee']
  322. pingFee = feeMode['pingFee']
  323. guFee = feeMode['guFee']
  324. # 判断缓存中是否有shuduanList,serverMoneyList,eleMoneyList
  325. if not Device.get_dev_control_cache(self.device['devNo']).get('shiduanList',None):
  326. for ii in range(48):
  327. startHour = 0 + ii / 2
  328. startMin = '00' if ii % 2 == 0 else '30'
  329. startTime = '%02d%s00' % (startHour, startMin)
  330. if (ii == 0) or (ii > 0 and shiduan[ii] != shiduan[ii - 1]):
  331. self.shiduanList.append(startTime)
  332. # 添加服务费,电费列表
  333. if shiduan[ii] == '0':
  334. self.serverMoneyList.append(jianServe)
  335. self.eleMoneyList.append(jianFee)
  336. elif shiduan[ii] == '1':
  337. self.serverMoneyList.append(fengServe)
  338. self.eleMoneyList.append(fengFee)
  339. elif shiduan[ii] == '2':
  340. self.serverMoneyList.append(pingServe)
  341. self.eleMoneyList.append(pingFee)
  342. elif shiduan[ii] == '3':
  343. self.serverMoneyList.append(guServe)
  344. self.eleMoneyList.append(guFee)
  345. self.shiduanList.append('235959')
  346. Device.update_dev_control_cache(self.device['devNo'], {'shiduanList':self.shiduanList})
  347. Device.update_dev_control_cache(self.device['devNo'], {'serverMoneyList':self.serverMoneyList})
  348. Device.update_dev_control_cache(self.device['devNo'], {'eleMoneyList':self.eleMoneyList})
  349. else:
  350. self.shiduanList = Device.get_dev_control_cache(self.device['devNo']).get(str(port),{}).get('shiduanList',None)
  351. self.serverMoneyList = Device.get_dev_control_cache(self.device['devNo']).get(str(port),{}).get('serverMoneyList',None)
  352. self.eleMoneyList = Device.get_dev_control_cache(self.device['devNo']).get(str(port),{}).get('eleMoneyList',None)
  353. # 将current_dict,fenshiList放入缓存中
  354. if not Device.get_dev_control_cache(self.device['devNo']).get('current_dict', None) \
  355. and not Device.get_dev_control_cache(self.device['devNo']).get('fenshiList', None):
  356. Device.update_dev_control_cache(self.device['devNo'], {'current_dict': self.current_dict})
  357. Device.update_dev_control_cache(self.device['devNo'], {'fenshiList': self.fenshiList})
  358. else:
  359. self.current_dict = Device.get_dev_control_cache(self.device['devNo']).get('current_dict', None)
  360. self.fenshiList = Device.get_dev_control_cache(self.device['devNo']).get('fenshiList', None)
  361. # 获取当前时间戳并解析
  362. timestamp = int(time.time())
  363. current_time = time.strftime("%H%M%S", time.localtime(timestamp))
  364. #已充金额,充电度数
  365. current_money = int(reverse_hex(data[120:128]), 16) / 10000.0
  366. current_ele = int(reverse_hex(data[104:112]), 16) / 10000.0
  367. # 记录分时
  368. if self.shiduanList:
  369. for i in range(0, len(self.shiduanList) - 1):
  370. # 查看当前时刻所在时间段
  371. if int(self.shiduanList[i]) <= int(current_time) <= int(self.shiduanList[i + 1]):
  372. # 存startTime,查看当前时间段的startTime是否为空
  373. if not self.current_dict['startTime']:
  374. # 第一次startTime为当前时间
  375. if len(self.fenshiList) == 0:
  376. self.current_dict['startTime'] = current_time
  377. self.current_dict['chargedMoney'] = current_money
  378. self.current_dict['totalEle'] = current_ele
  379. self.current_dict['elecFee'] = self.eleMoneyList[i]
  380. self.current_dict['perServeMoney'] = self.serverMoneyList[i]
  381. Device.update_dev_control_cache(self.device['devNo'], {'current_dict': self.current_dict})
  382. # 非第一次startTime为shiduanList最后一段的endTime,同时更新当前区间电费和服务费
  383. else:
  384. self.current_dict['startTime'] = self.fenshiList[-1]['endTime']
  385. self.current_dict['chargedMoney'] = self.fenshiList[-1]['chargedMoney']
  386. self.current_dict['totalEle'] = self.fenshiList[-1]['totalEle']
  387. self.current_dict['elecFee'] = self.eleMoneyList[i]
  388. self.current_dict['perServeMoney'] = self.serverMoneyList[i]
  389. Device.update_dev_control_cache(self.device['devNo'], {'current_dict': self.current_dict})
  390. break
  391. # 存endTime,先处理特殊情况,判断是否快到下一个时间段,或者是否是最后一个时间段,是的话将数据更新到fenshiList中(eg:140000-135945=4055):
  392. if int(current_time) >= int(self.shiduanList[i + 1]) - 4055 or int(current_time) >= 235944:
  393. self.fenshiList[-1]['endTime'] = current_time
  394. self.fenshiList[-1]['money'] = current_money - self.current_dict['chargedMoney']
  395. self.fenshiList[-1]['ele'] = current_ele - self.current_dict['totalEle']
  396. self.fenshiList[-1]['chargedMoney'] = current_money
  397. self.fenshiList[-1]['totalEle'] = current_ele
  398. self.fenshiList[-1]['serveMoney'] = self.fenshiList[-1]['perServeMoney'] * self.fenshiList[-1][
  399. 'ele']
  400. # 当前区间电费可以使用计算,也可以使用当前区间已充金额减去当前区间服务费
  401. self.fenshiList[-1]['eleMoney'] = self.fenshiList[-1]['money'] - self.fenshiList[-1]['serveMoney']
  402. self.current_dict = {
  403. 'startTime': '',
  404. 'endTime': '',
  405. 'ele': '',
  406. 'money': '',
  407. 'perServeMoney': '',
  408. 'elecFee': '',
  409. 'eleMoney': '',
  410. 'serveMoney': '',
  411. 'chargedMoney': '',
  412. 'totalEle': '',
  413. }
  414. Device.update_dev_control_cache(self.device['devNo'], {'current_dict': self.current_dict})
  415. Device.update_dev_control_cache(self.device['devNo'], {'fenshiList': self.fenshiList})
  416. break
  417. # 存endTime,如果startTime不为空,则记录其他数据,并填入到list中
  418. # fenshiList有当前时间段的数据,则更新数据
  419. elif len(self.fenshiList) != 0 and int(self.shiduanList[i]) <= int(
  420. self.fenshiList[-1]['endTime']) <= int(self.shiduanList[i + 1]):
  421. self.fenshiList[-1]['endTime'] = current_time
  422. self.fenshiList[-1]['money'] = current_money - self.fenshiList[-1]['chargedMoney']
  423. self.fenshiList[-1]['ele'] = current_ele - self.fenshiList[-1]['totalEle']
  424. self.fenshiList[-1]['serveMoney'] = float(self.fenshiList[-1]['perServeMoney']) * float(
  425. self.fenshiList[-1]['ele'])
  426. self.fenshiList[-1]['eleMoney'] = float(self.fenshiList[-1]['money']) - float(
  427. self.fenshiList[-1]['serveMoney'])
  428. Device.update_dev_control_cache(self.device['devNo'], {'fenshiList': self.fenshiList})
  429. # fenshiList没有当前的数据
  430. else:
  431. self.current_dict['endTime'] = current_time
  432. self.current_dict['money'] = current_money - float(self.current_dict['chargedMoney'])
  433. self.current_dict['ele'] = current_ele - float(self.current_dict['totalEle'])
  434. self.current_dict['serveMoney'] = float(self.current_dict['perServeMoney']) * float(
  435. self.current_dict['ele'])
  436. self.current_dict['eleMoney'] = float(self.current_dict['money']) - float(
  437. self.current_dict['serveMoney'])
  438. self.fenshiList.append(self.current_dict)
  439. Device.update_dev_control_cache(self.device['devNo'], {'fenshiList': self.fenshiList})
  440. break
  441. # 针对互联互通,进行订单状态的推送
  442. consumeRcd = ConsumeRecord.objects(orderNo = orderNo).first()
  443. if not consumeRcd or not consumeRcd.rechargeRcdId:
  444. return
  445. rechargeRcd = RechargeRecord.objects(id = consumeRcd.rechargeRcdId).first()
  446. if not rechargeRcd or rechargeRcd.via != 'swap':
  447. return
  448. part = Part.objects(logicalCode = self.device['logicalCode'],partNo = str(rechargeRcd.extraInfo['portNo'])).first()
  449. if not part:
  450. return
  451. adapterDict = {str(Const.DEV_WORK_STATUS_IDLE):1,str(Const.DEV_WORK_STATUS_FAULT):255,str(Const.DEV_WORK_STATUS_WORKING):3}
  452. orderStatus ={
  453. 'StartChargeSeq':str(rechargeRcd.wxOrderNo),
  454. 'StartChargeSeqStat':4 if valueDict.get('status') == Const.DEV_WORK_STATUS_IDLE else 2,
  455. 'ConnectorID':str(part.id),
  456. 'ConnectorStatus':adapterDict.get(valueDict.get('status'),1),
  457. 'CurrentA':valueDict.get('current'),
  458. 'VoltageA':220.0,
  459. 'Soc':0,
  460. 'StartTime':str(rechargeRcd.time),
  461. 'EndTime':datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  462. 'TotalPower':round(valueDict.get('elec'),2),
  463. 'TotalMoney':round(valueDict.get('chargedMoney'),2),
  464. 'ConnectorId':str(part.id),
  465. }
  466. SwapContract.notify_2_all_northers_order_status(self.device,orderStatus)
  467. def __translate_reason(self, code):
  468. descDict = {
  469. '40':u'结束充电,远程停止。','41':u'结束充电,SOC 达到 100%。','42':u'结束充电,充电电量满足设定条件。','43':u'结束充电,充电金额满足设定条件',
  470. '44':u'结束充电,充电时间满足设定条件','45':u'结束充电,手动停止充电','46':u'其他原因','47':u'其他原因','48':u'其他原因','49':u'其他原因',
  471. '4A':u'充电启动失败,充电桩控制系统故障(需要重启或自动恢复)','4B':u'充电启动失败,控制导引断开','4C':u'充电启动失败,断路器跳位',
  472. '4D':u'充电启动失败,电表通信中断','4E':u'充电启动失败,余额不足','4F':u'充电启动失败,充电模块故障','50':u'充电启动失败,急停开入',
  473. '51':u'充电启动失败,防雷器异常','52':u'充电启动失败,BMS 未就绪','53':u'充电启动失败,温度异常','54':u'充电启动失败,电池反接故障',
  474. '55':u'充电启动失败,电子锁异常','56':u'充电启动失败,合闸失败','57':u'充电启动失败,绝缘异常','58':u'其他原因','59':u'充电启动失败,接收 BMS 握手报文 BHM 超时',
  475. '5A':u'充电启动失败,接收 BMS 和车辆的辨识报文超时 BRM','5B':u'充电启动失败,接收电池充电参数报文超时 BCP','5C':u'充电启动失败,接收 BMS 完成充电准备报文超时 BRO AA',
  476. '5D':u'充电启动失败,接收电池充电总状态报文超时 BCS','5E':u'充电启动失败,接收电池充电要求报文超时 BCL','5F':u'充电启动失败,接收电池状态信息报文超时 BSM',
  477. '60':u'充电启动失败,GB2015 电池在 BHM 阶段有电压不允许充电','61':u'充电启动失败,GB2015 辨识阶段在 BRO_AA 时候电池实际电压与 BCP 报文电池电压差距大于 5%',
  478. '62':u'充电启动失败,B2015 充电机在预充电阶段从 BRO_AA 变成BRO_00 状态','63':u'充电启动失败,接收主机配置报文超时',
  479. '64':u'充电启动失败,充电机未准备就绪,我们没有回 CRO AA,对应老国标','65':u'其他原因','66':u'其他原因','67':u'其他原因','68':u'其他原因','69':u'其他原因',
  480. '6A':u'充电异常中止,系统闭锁','6B':u'充电异常中止,导引断开','6C':u'充电异常中止,断路器跳位','6D':u'充电异常中止,电表通信中断','6E':u'充电异常中止,余额不足',
  481. '6F':u'充电异常中止,交流保护动作','70':u'充电异常中止,直流保护动作','71':u'充电异常中止,充电模块故障','72':u'充电异常中止,急停开入',
  482. '73':u'充电异常中止,防雷器异常','74':u'充电异常中止,温度异常','75':u'充电异常中止,输出异常','76':u'充电异常中止,充电无流','77':u'充电异常中止,电子锁异常',
  483. '78':u'其他原因','79':u'充电异常中止,总充电电压异常','7A':u'充电异常中止,总充电电流异常','7B':u'充电异常中止,单体充电电压异常','7C':u'充电异常中止,电池组过温',
  484. '7D':u'充电异常中止,最高单体充电电压异常','7E':u'充电异常中止,最高电池组过温','7F':u'充电异常中止,BMV 单体充电电压异常','80':u'充电异常中止,BMT 电池组过温',
  485. '81':u'充电异常中止,电池状态异常停止充电','82':u'充电异常中止,车辆发报文禁止充电','83':u'充电异常中止,充电桩断电','84':u'充电异常中止,接收电池充电总状态报文超时',
  486. '85':u'充电异常中止,接收电池充电要求报文超时','86':u'充电异常中止,接收电池状态信息报文超时','87':u'充电异常中止,接收 BMS 中止充电报文超时','88':u'充电异常中止,接收 BMS 充电统计报文超时',
  487. '89':u'充电异常中止,接收对侧 CCS 报文超时','8A':u'其他原因','8B':u'其他原因','8C':u'其他原因','8D':u'其他原因','8E':u'其他原因','8F':u'其他原因','90':u'其他原因'
  488. }
  489. return descDict.get(code,u'其他原因')
  490. def get_finished_value_dict(self,data):
  491. resultDict = {}
  492. resultDict['chargeIndex'] = int(data[58:60])
  493. resultDict['startTime'] = '20%02d-%02d-%02d %02d:%02d:%02d' % (int(data[72:74],16),int(data[70:72],16),int(data[68:70],16),int(data[66:68],16),int(data[64:66],16),int('%s%s' % (data[62:64],data[60:62]),16)/1000)
  494. resultDict['finishTime'] = '20%02d-%02d-%02d %02d:%02d:%02d' % (int(data[86:88],16),int(data[84:86],16),int(data[82:84],16),int(data[80:82],16),int(data[78:80],16),int('%s%s' % (data[76:78],data[74:76]),16)/1000)
  495. resultDict['jianFee'] = int(reverse_hex(data[88:96]),16)/100000.0
  496. resultDict['jianElec'] = int(reverse_hex(data[96:104]),16)/10000.0
  497. resultDict['jianShun'] = int(reverse_hex(data[104:112]),16)/10000.0
  498. resultDict['jianSpend'] = int(reverse_hex(data[112:120]),16)/10000.0
  499. resultDict['fengFee'] = int(reverse_hex(data[120:128]),16)/100000.0
  500. resultDict['fengElec'] = int(reverse_hex(data[128:136]),16)/10000.0
  501. resultDict['fengShun'] = int(reverse_hex(data[136:144]),16)/10000.0
  502. resultDict['fengSpend'] = int(reverse_hex(data[144:152]),16)/10000.0
  503. resultDict['pingFee'] = int(reverse_hex(data[152:160]),16)/100000.0
  504. resultDict['pingElec'] = int(reverse_hex(data[160:168]),16)/10000.0
  505. resultDict['pingShun'] = int(reverse_hex(data[168:176]),16)/10000.0
  506. resultDict['pingSpend'] = int(reverse_hex(data[176:184]),16)/10000.0
  507. resultDict['guFee'] = int(reverse_hex(data[184:192]),16)/100000.0
  508. resultDict['guElec'] = int(reverse_hex(data[192:200]),16)/10000.0
  509. resultDict['guShun'] = int(reverse_hex(data[200:208]),16)/10000.0
  510. resultDict['guSpend'] = int(reverse_hex(data[208:216]),16)/10000.0
  511. resultDict['meterStart'] = int(reverse_hex(data[216:226]),16)/10000.0
  512. resultDict['meterEnd'] = int(reverse_hex(data[226:236]),16)/10000.0
  513. resultDict['allElec'] = int(reverse_hex(data[236:244]),16)/10000.0
  514. resultDict['elec'] = int(reverse_hex(data[244:252]),16)/10000.0# 计损总电量
  515. if resultDict['elec'] == 0:# 用这个总电量吧,如果数据不对
  516. resultDict['elec'] = resultDict['allElec']
  517. resultDict['spendMoney'] = int(reverse_hex(data[252:260]),16)/10000.0
  518. typeDict = {'01':'app_start','02':'card_start','04':'offline_card_start','05':'vin_code_start'}
  519. resultDict['orderType'] = typeDict.get(data[294:296],'')
  520. resultDict['orderTime'] = '20%02d-%02d-%02d %02d:%02d:%02d' % (int(data[308:310],16),int(data[306:308],16),int(data[304:306],16),int(data[302:304],16),int(data[300:302],16),int('%s%s' % (data[298:300],data[296:298]),16)/1000)
  521. resultDict['reason'] = self.__translate_reason(data[310:312])
  522. resultDict['cardNo'] = int(data[312:328],16)
  523. return resultDict
  524. def get_finished_value_dict_old(self,data):
  525. resultDict = {}
  526. resultDict['chargeIndex'] = int(data[58:60])
  527. resultDict['startTime'] = '20%02d-%02d-%02d %02d:%02d:%02d' % (int(data[72:74],16),int(data[70:72],16),int(data[68:70],16),int(data[66:68],16),int(data[64:66],16),int('%s%s' % (data[62:64],data[60:62]),16)/1000)
  528. resultDict['finishTime'] = '20%02d-%02d-%02d %02d:%02d:%02d' % (int(data[86:88],16),int(data[84:86],16),int(data[82:84],16),int(data[80:82],16),int(data[78:80],16),int('%s%s' % (data[76:78],data[74:76]),16)/1000)
  529. resultDict['jianFee'] = int(reverse_hex(data[88:96]),16)/100000.0
  530. resultDict['jianElec'] = int(reverse_hex(data[96:104]),16)/10000.0
  531. resultDict['jianShun'] = int(reverse_hex(data[104:112]),16)/10000.0
  532. resultDict['jianSpend'] = int(reverse_hex(data[112:120]),16)/10000.0
  533. resultDict['fengFee'] = int(reverse_hex(data[120:128]),16)/100000.0
  534. resultDict['fengElec'] = int(reverse_hex(data[128:136]),16)/10000.0
  535. resultDict['fengShun'] = int(reverse_hex(data[136:144]),16)/10000.0
  536. resultDict['fengSpend'] = int(reverse_hex(data[144:152]),16)/10000.0
  537. resultDict['pingFee'] = int(reverse_hex(data[152:160]),16)/100000.0
  538. resultDict['pingElec'] = int(reverse_hex(data[160:168]),16)/10000.0
  539. resultDict['pingShun'] = int(reverse_hex(data[168:176]),16)/10000.0
  540. resultDict['pingSpend'] = int(reverse_hex(data[176:184]),16)/10000.0
  541. resultDict['guFee'] = int(reverse_hex(data[184:192]),16)/100000.0
  542. resultDict['guElec'] = int(reverse_hex(data[192:200]),16)/10000.0
  543. resultDict['guShun'] = int(reverse_hex(data[200:208]),16)/10000.0
  544. resultDict['guSpend'] = int(reverse_hex(data[208:216]),16)/10000.0
  545. resultDict['meterStart'] = int(reverse_hex(data[216:224]),16)/10000.0 #旧版本4个字节,新版本5个字节
  546. resultDict['meterEnd'] = int(reverse_hex(data[224:232]),16)/10000.0 #旧版本4个字节,新版本5个字节
  547. resultDict['allElec'] = int(reverse_hex(data[232:240]),16)/10000.0
  548. resultDict['elec'] = int(reverse_hex(data[240:248]),16)/10000.0# 计损总电量
  549. if resultDict['elec'] == 0:# 用这个总电量吧,如果数据不对
  550. resultDict['elec'] = resultDict['allElec']
  551. resultDict['spendMoney'] = int(reverse_hex(data[248:256]),16)/10000.0
  552. typeDict = {'01':'app_start','02':'card_start','04':'offline_card_start','05':'vin_code_start'}
  553. resultDict['orderType'] = typeDict.get(data[290:292],'')
  554. resultDict['orderTime'] = '20%02d-%02d-%02d %02d:%02d:%02d' % (int(data[304:306],16),int(data[302:304],16),int(data[300:302],16),int(data[298:300],16),int(data[296:298],16),int('%s%s' % (data[294:296],data[292:294]),16)/1000)
  555. resultDict['reason'] = self.__translate_reason(data[306:308])
  556. resultDict['cardNo'] = int(data[308:324],16)
  557. return resultDict
  558. def deal_with_finished_order(self):
  559. data = self.event_data['data']
  560. orderNo = data[12:44]
  561. port = int(data[58:60])
  562. devNo = self.device['devNo']
  563. if self.event_data['cmd'] == '3B': # 1.4旧版本的 电表总起始值是4个直接,1.5后,换成了5个字节
  564. consumeDict = self.get_finished_value_dict(data)
  565. else:
  566. consumeDict = self.get_finished_value_dict_old(data)
  567. logger.info('the data dict is %s ' % consumeDict)
  568. progress = ServiceProgress.objects.filter(weifuleOrderNo=orderNo).first()
  569. if progress is None :
  570. return False
  571. if progress.status == 'finished':# 防止重复的报文上来,导致重复退费
  572. return True
  573. progress.status = 'finished'
  574. progress.isFinished = True
  575. progress.save()
  576. consumeRcd = ConsumeRecord.objects.filter(orderNo=orderNo).first()
  577. if not consumeRcd:
  578. return False
  579. try:
  580. # 首先把consumeRcd 更新状态
  581. consumeRcd.status = ConsumeRecord.Status.FINISHED
  582. consumeRcd.save()
  583. # 更新part的状态
  584. Part.update_part_work_status(self.device['logicalCode'], port, Part.Status.IDLE)
  585. group = Group.get_group(self.device['groupId'])
  586. coins = RMB(consumeDict['spendMoney'])
  587. backCoins = consumeRcd.coin - VirtualCoin(consumeDict['spendMoney']) if consumeRcd.coin > VirtualCoin(consumeDict['spendMoney']) else VirtualCoin(0)
  588. refundMoney = consumeRcd.money - RMB(consumeDict['spendMoney']) if consumeRcd.money > RMB(consumeDict['spendMoney']) else RMB(0.00)
  589. orderTitleDictList = [
  590. # {u'尖电':u'单价:%s元,充电%s度,花费%s元' % (round(consumeDict['jianFee'],1),round(consumeDict['jianShun'],1),round(consumeDict['jianSpend'],1))},
  591. # {u'峰电':u'单价:%s元,充电%s度,花费%s元' % (round(consumeDict['fengFee'],1),round(consumeDict['fengShun'],1),round(consumeDict['fengSpend'],1))},
  592. # {u'平电':u'单价:%s元,充电%s度,花费%s元' % (round(consumeDict['pingFee'],1),round(consumeDict['pingShun'],1),round(consumeDict['pingSpend'],1))},
  593. # {u'谷电':u'单价:%s元,充电%s度,花费%s元' % (round(consumeDict['guFee'],1),round(consumeDict['guShun'],1),round(consumeDict['guSpend'],1))},
  594. {u'总电量':u'%s度' % round(consumeDict['elec'],1)},
  595. {u'总金额':u'%s元' % round(consumeDict['spendMoney'],1)},
  596. ]
  597. if u'虚拟卡' in consumeRcd.remarks:
  598. # 退额度
  599. try:
  600. vRcd = VCardConsumeRecord.objects.get(orderNo=orderNo)
  601. vCard = UserVirtualCard.objects.get(id=vRcd.cardId)
  602. except DoesNotExist, e:
  603. logger.info('can not find the vCard id = %s' % vRcd.cardId)
  604. return
  605. # 通知服务结束
  606. notifyOpenId = self.get_managerialOpenId_by_openId(vRcd.openId) if vCard else ''
  607. self.notify_user_service_complete(
  608. service_name = u'充电',
  609. openid = notifyOpenId,
  610. port = port,
  611. address = group['address'],
  612. reason = consumeDict['reason'],
  613. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  614. extra = orderTitleDictList
  615. )
  616. # 不需要退款,直接返回,不通知
  617. if self.device.is_auto_refund:
  618. vCard.refund_quota(vRcd, 0.0, 0, backCoins.mongo_amount)
  619. # 刷卡的方式。不存在退费,直接从卡里面扣费
  620. elif u'刷卡' in consumeRcd.remarks:
  621. dealer = Dealer.get_dealer(ownerId=self.device['ownerId'])
  622. card = Card.objects.filter(agentId=dealer['agentId'], cardNo=str(consumeDict['cardNo'])).first()
  623. if card is None: # 离线卡没有绑定或者在线卡被解绑了
  624. return False
  625. # 先把消费记录的数据刷到准确值
  626. consumeRcd.coin = VirtualCoin(consumeDict['spendMoney'])
  627. consumeRcd.money = RMB(consumeDict['spendMoney'])
  628. consumeRcd.save()
  629. cardRcd = CardConsumeRecord.objects(orderNo = orderNo).first()
  630. if cardRcd is None:
  631. return False
  632. cardRcd.money = RMB(consumeDict['spendMoney'])
  633. cardRcd.balance = card.balance - RMB(consumeDict['spendMoney'])
  634. cardRcd.finishedTime = datetime.datetime.now()
  635. cardRcd.save()
  636. # 然后扣费
  637. self.consume_money_for_card(card,RMB(consumeDict['spendMoney']))
  638. # 通知
  639. self.notify_user_service_complete(
  640. service_name = u'充电',
  641. openid=card.managerialOpenId,
  642. port = port,
  643. address = group['address'],
  644. reason = consumeDict['reason'],
  645. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  646. extra = orderTitleDictList
  647. )
  648. elif u'扫码' in consumeRcd.remarks: # 扫码的
  649. user = MyUser.objects(openId=consumeRcd.openId, groupId=self.device['groupId']).first()
  650. if not user:
  651. return False
  652. # 通知服务结束
  653. notifyOpenId = user.managerialOpenId if user else ''
  654. # 如果需要退款,计算退款数据.
  655. if not self.device.is_auto_refund:
  656. return True
  657. if refundMoney > RMB(0):
  658. rechargeRcdId = consumeRcd.rechargeRcdId
  659. if rechargeRcdId:
  660. rechargeRcd = RechargeRecord.objects.filter(id=rechargeRcdId).first()
  661. else:
  662. rechargeRcd = None
  663. if rechargeRcd: # 退现金特征 + 有充值订单
  664. self.refund_net_pay(user, {'rechargeRcdId': rechargeRcdId, 'openId': user.openId},
  665. refundMoney, VirtualCoin(0), consumeDict, True)
  666. orderTitleDictList.append({u'退款':u'%s元' % refundMoney})
  667. else:
  668. self.refund_net_pay(user, {'openId': user.openId}, RMB(0), backCoins, consumeDict,
  669. False)
  670. self.notify_user_service_complete(
  671. service_name = u'充电',
  672. openid = notifyOpenId,
  673. port = port,
  674. address = group['address'],
  675. reason = consumeDict['reason'],
  676. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  677. extra = orderTitleDictList
  678. )
  679. elif u'互联互通' in consumeRcd.remarks and consumeRcd.rechargeRcdId:
  680. rechargeRcd = RechargeRecord.objects(id = consumeRcd.rechargeRcdId).first()
  681. if rechargeRcd is None or rechargeRcd.via != 'swap':
  682. return
  683. part = Part.objects(logicalCode = self.device['logicalCode'],partNo = str(rechargeRcd.extraInfo['portNo'])).first()
  684. if part is None:
  685. return
  686. devObj = Device.objects(devNo = self.device['devNo']).first()
  687. if devObj is None:
  688. return
  689. feeMode= devObj.otherConf.get('feeMode')
  690. serveMoney = feeMode['jianServe'] * consumeDict['jianElec'] + feeMode['fengServe'] * consumeDict['fengElec'] \
  691. + feeMode['pingServe'] * consumeDict['pingElec'] + feeMode['guServe'] * consumeDict['guElec']
  692. reasonAdapter = {'40':1,'41':2,'42':1,'43':1,'44':1,'45':0,'00':1}
  693. result = {
  694. 'StartChargeSeq':str(rechargeRcd.wxOrderNo),
  695. 'ConnectorID':str(part.id),
  696. 'StartTime':str(rechargeRcd.time),
  697. 'EndTime':str(consumeDict['finishTime']),
  698. 'TotalPower':round(consumeDict['elec'],2),
  699. 'TotalElecMoney':round(consumeDict['spendMoney'] - serveMoney,2),
  700. 'TotalSeviceMoney':round(serveMoney,2),
  701. 'TotalMoney':round(consumeDict['spendMoney'],2),
  702. 'StopReason':reasonAdapter.get(data[310:312],0) if int(data[310:312]) <= 45 else int(data[310:312]) - 65
  703. }
  704. consumeDict.update({'northerResult':result}) # 把通知北向的结果,也记录到数据库中,便于后续对账核对数据
  705. SwapContract.notify_2_all_northers_order_info(self.device,result)
  706. # ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'weifuleOrderNo':orderNo}, consumeDict)
  707. except Exception, e:
  708. logger.exception('some exception happed,devNo=%s,e=%s' % (devNo, e))
  709. finally:
  710. logger.info('update progress and consume rcd')
  711. ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'], {'weifuleOrderNo':orderNo}, consumeDict)
  712. logger.info('clear_port_control_cache')
  713. Device.clear_port_control_cache(devNo, port)
  714. return True
  715. # 根据报文以及卡的信息,获取服务器发给设备的回复
  716. def deal_card_start(self):
  717. data = self.event_data['data']
  718. port = int(data[26:28])
  719. sqNo = str(data[4:8])
  720. cardNo = str(int(data[32:48], 16))
  721. Card.record_dev_card_no(self.device['devNo'], cardNo)
  722. card = self.find_card_by_card_no(cardNo)
  723. # : 首先检查订单,并进行充值
  724. # : 用户首先在手机客户端充值,需要这个时刻刷卡上报事件将充值的订单同步上来
  725. if card:
  726. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  727. if card_recharge_order:
  728. result = self.recharge_id_card(card=card,
  729. rechargeType='append',
  730. order=card_recharge_order)
  731. card.reload()
  732. else:
  733. self.deviceAdapter.reply_card_start(sqNo,'00000000000000000000000000000000',port,cardNo,0,'00','01')
  734. return
  735. replyResult = '00'
  736. # 如果没有卡,直接返回
  737. if card.frozen:
  738. replyResult = '02'
  739. elif card.balance <= RMB(0):
  740. replyResult = '03'
  741. if self.device['status'] in [Const.DEV_WORK_STATUS_FAULT,Const.DEV_WORK_STATUS_FORBIDDEN]:
  742. replyResult = '05'
  743. # 如果没有dealerId,更新一次,记录到数据库,以后这个卡,就只能在这个经销商名下刷卡,不能在其他家刷卡了
  744. if not card.dealerId:
  745. card = self.update_card_dealer_and_type(cardNo, 'ID')
  746. elif card.dealerId != self.device.ownerId:
  747. replyResult = '06'
  748. # 查找下是否出现刷多次。不允许出现刷多次
  749. count = ServiceProgress.objects(cardId = str(card.id),isFinished=False,startTime__gte = datetime.datetime.now() - datetime.timedelta(hours=24)).count()
  750. if count > 0:
  751. replyResult = '04'
  752. devObj = Device.objects.get(devNo = self.device['devNo']) # 端口被禁用,也不允许使用
  753. if devObj.otherConf.get(str(port),False):
  754. replyResult = '05'
  755. if replyResult == '00':
  756. success = '01'
  757. else:
  758. success = '00'
  759. orderNo = make_cartcp_order_no(self.device['devNo'],port)
  760. self.deviceAdapter.reply_card_start(sqNo,orderNo,port,card.cardNo,card.balance,success,replyResult)
  761. # 记录卡消费记录以及消费记录
  762. orderNo, cardOrderNo = self.record_consume_for_card(card,port,orderNo)
  763. # 记录当前服务的progress,便于手机界面查询进度
  764. consumeDict = {'orderNo': orderNo, 'cardOrderNo': cardOrderNo,'unit':u'次'}
  765. ServiceProgress.register_card_service_for_weifule(self.device, port, card, consumeDict)
  766. # 通知用户,已经扣费
  767. self.notify_balance_has_consume_for_card(card, 0 ,u'(使用结束后,根据实际使用情况进行扣费结算)')
  768. Device.update_port_control_cache(self.device['devNo'], {'coins':0,'port':port}, 'overwrite') # 重新写端口数据,覆写掉
  769. def do(self, **args):
  770. cmdCode = self.event_data['cmd']
  771. if cmdCode == '01': # 登录鉴权
  772. logger.info('this is authentication')
  773. self.register_dev(self.event_data)
  774. self.deviceAdapter.reply_authentication(self.event_data)
  775. try:
  776. # 先下发F0,如果报错则下发9C(北科新能源)
  777. self.deviceAdapter.send_qrcode()
  778. except Exception as e:
  779. self.deviceAdapter.send_qrcode2()
  780. elif cmdCode == '05': # 计费模型验证请求回复
  781. self.deviceAdapter.reply_feemode(self.event_data)
  782. logger.info('send current time to device')
  783. self.deviceAdapter.send_current_time()
  784. elif cmdCode == '09': # 充电桩发现计费模型不一致的时候,主动请求计费模型
  785. self.deviceAdapter.reply_new_feemode(self.event_data)
  786. elif cmdCode == '03': # 心跳应答
  787. if self.device['ownerId']: # 没有注册,或者注销设备后,仍然有可能有数据上来
  788. self.update_port_by_heartbeat()
  789. self.deviceAdapter.reply_heartbeat(self.event_data)
  790. elif cmdCode == '13':
  791. if self.device['ownerId']: # 没有注册,或者注销设备后,仍然有可能有数据上来
  792. self.update_order_info()
  793. elif cmdCode == '19': # 充电结束,直接放在账单确认做处理
  794. pass
  795. elif cmdCode in ['3B','3F']: # 充电的账单,3F是1.4以前的协议,内容没有变化
  796. if self.device['ownerId']: # 没有注册,或者注销设备后,仍然有可能有数据上来
  797. result = self.deal_with_finished_order()
  798. strTemp = '00' if result else '01'
  799. else:
  800. strTemp = '00'
  801. self.deviceAdapter.reply_finished_order(self.event_data,strTemp)
  802. elif cmdCode == '31':
  803. self.deal_card_start()
  804. else: # 处理任务事件
  805. pass