yuze5.py 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import random
  6. import time
  7. from arrow import Arrow
  8. from django.conf import settings
  9. from typing import TYPE_CHECKING, List
  10. from apilib.monetary import sum_rmb, RMB, VirtualCoin, Ratio
  11. from apilib.utils_datetime import to_datetime
  12. from apps.web.south_intf.liangxi_fire import LiangXiXiaoFang
  13. from apps.web.south_intf.yuhuan_fire import YuhuanNorther
  14. from apps.web.common.models import District
  15. from apps.web.constant import Const, FAULT_CODE, FAULT_LEVEL, APP_TYPE, DEALER_CONSUMPTION_AGG_KIND
  16. from apps.web.core.helpers import ActionDeviceBuilder
  17. from apps.web.core.accounting import Accounting
  18. from apps.web.core.device_define.dianchuan import FINISHED_CHARGE_REASON_MAP
  19. from apps.web.dealer.models import Dealer
  20. from apps.web.device.models import PortReport, Part, Group, Device
  21. from apps.web.device.timescale import FluentedEngine
  22. from apps.web.eventer.base import FaultEvent, WorkEvent, ComNetPayAckEvent, IcStartAckEvent, \
  23. AckEventProcessorIntf, IcRechargeAckEvent, CardRefundAckEvent
  24. from apps.web.eventer import EventBuilder
  25. from apps.web.helpers import get_wechat_auth_bridge
  26. from apps.web.south_intf.platform import notify_event_to_north, notify_event_to_north_v2, \
  27. handle_and_notify_event_to_north_Dc
  28. from apps.web.south_intf.zhejiang_fire import send_event_to_zhejiang
  29. from apps.web.user.models import VCardConsumeRecord, ServiceProgress, UserVirtualCard, CardRechargeOrder, MyUser, \
  30. ConsumeRecord, RechargeRecord
  31. if TYPE_CHECKING:
  32. from apps.web.user.models import Card
  33. from apps.web.device.models import GroupDict
  34. from apps.web.device.models import DeviceDict
  35. logger = logging.getLogger(__name__)
  36. class builder(EventBuilder):
  37. def __getEvent__(self, device_event):
  38. # 订单机制事件
  39. if 'order_id' in device_event:
  40. if device_event['order_type'] == 'com_start':
  41. return MyComNetPayAckEvent(self.deviceAdapter, device_event)
  42. if device_event['order_type'] == 'ic_recharge':
  43. return MyIcRechargeAckEvent(self.deviceAdapter, device_event)
  44. if device_event['order_type'] == 'ic_start':
  45. return MyIcStartAckEvent(self.deviceAdapter, device_event)
  46. if device_event['order_type'] == 'card_refund':
  47. return MyCardRefundAckEvent(self.deviceAdapter, device_event)
  48. else:
  49. if 'data' not in device_event:
  50. return None
  51. # 100228 互感器事件处理
  52. if 'type' in device_event:
  53. if device_event['type'] == 'alert':
  54. return InteroperatorAlertEvent(self.deviceAdapter, device_event)
  55. if device_event['type'] == 'report':
  56. return InteroperatorReport(self.deviceAdapter, device_event)
  57. else:
  58. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  59. if event_data is None or 'cmdCode' not in event_data:
  60. return None
  61. if 'duration' in device_event:
  62. event_data.update({'duration': device_event['duration']})
  63. if 'elec' in device_event:
  64. event_data.update({'elec': device_event['elec']})
  65. if 'v' in device_event:
  66. event_data.update({'v': device_event['v']})
  67. if 'today_coins' in device_event and 'ts' in device_event:
  68. event_data.update({'today_coins': device_event['today_coins']})
  69. event_data.update({'ts': device_event['ts']})
  70. if event_data.get('cmdCode') in ['03', '05', '11', '12', '17', '22']:
  71. return ChargingYUZEWorkEvent(self.deviceAdapter, event_data)
  72. if event_data.get('cmdCode') == '0D':
  73. return YUZEFaultEvent(self.deviceAdapter, event_data)
  74. if event_data.get('cmdCode') == '35' or event_data.get('cmdCode') == '41':
  75. return YUZEInductorEvent(self.deviceAdapter, event_data)
  76. # 雨泽
  77. if event_data.get('cmdCode') in ['30', '31', '32']:
  78. return ChargingYUZEWorkEvent(self.deviceAdapter, event_data)
  79. return None
  80. class YUZEFaultEvent(FaultEvent):
  81. LX_FAULE_CODE_MAP = {
  82. "01": "07",
  83. "02": "03",
  84. "03": "05"
  85. }
  86. def do_norther(self):
  87. """
  88. 上报其他平台的,都在这个地方处理 可迁移至异步任务
  89. :return:
  90. """
  91. # 玉环的消防对接
  92. YuhuanNorther.send_dev_event(self.device, self.event_data['FaultCode'], self.event_data['port'])
  93. # 梁溪消防局的对接
  94. faultContent = self.event_data["statusInfo"]
  95. faultCode = self.LX_FAULE_CODE_MAP.get(self.event_data["FaultCode"], "")
  96. districtInfo = District.get_district(self.device.group["districtId"])
  97. self.device.update({"districtInfo": districtInfo, "groupAddr": self.device.group["address"]})
  98. LiangXiXiaoFang.send_to_xf_fault(self.device, faultCode, faultContent, self.event_data["port"])
  99. def do(self, **args):
  100. # 将告警的消息打入相应的缓存
  101. port = self.event_data["port"]
  102. # 0 表示整机
  103. if port == 0xFF:
  104. part = str(0)
  105. else:
  106. part = str(port)
  107. warningData = {
  108. "warningStatus": 2,
  109. "warningDesc": self.event_data["statusInfo"],
  110. "warningTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
  111. "warningUart": self.event_data["uart"]
  112. }
  113. Device.update_dev_warning_cache(self.device.devNo, {part: warningData})
  114. self.do_norther()
  115. super(YUZEFaultEvent, self).do()
  116. class ChargingYUZEWorkEvent(WorkEvent):
  117. def __parse_device_finished_data(self, event_data):
  118. duration = event_data.get('duration', -1)
  119. if duration != -1:
  120. if 'v' in event_data:
  121. duration = ((duration + 59) / 60)
  122. elec = event_data.get('elec', -1)
  123. if elec != -1:
  124. if 'v' in event_data:
  125. elec = round(elec / (10000.0 * 3600.0), 3)
  126. else:
  127. elec = round(elec / 3600.0, 3)
  128. logger.debug('device duration is {}, device elec is {}'.format(duration, elec))
  129. return duration, elec
  130. def do(self, **args):
  131. logger.info(' charging event detected, devNo=%s,info=%s' % (self.device.devNo, self.event_data))
  132. if self.event_data['cmdCode'] == '03': # 投币上报
  133. if 'today_coins' in self.event_data and 'ts' in self.event_data:
  134. Accounting.syncOfflineCoin(
  135. self.device,
  136. datetime.datetime.fromtimestamp(self.event_data['ts']).strftime('%Y-%m-%d'),
  137. self.event_data['today_coins'])
  138. if self.event_data['coins'] > 0:
  139. FluentedEngine().in_put_coins_udp(devNo = self.device.devNo,
  140. ts = int(time.time()),
  141. coins = self.event_data['coins'],
  142. mode = 'uart')
  143. else:
  144. # 老的流程会单条记录上报记录
  145. Accounting.recordOfflineCoin(device = self.device,
  146. report_ts = int(time.time()),
  147. coins = int(self.event_data['coins']),
  148. mode = 'uart',
  149. port = self.event_data.get('port', None))
  150. try:
  151. # 如果是投币,直接把端口状态刷新下
  152. self.deviceAdapter.get_port_status_from_dev()
  153. except Exception, e:
  154. logger.info('some err=%s' % e)
  155. YuhuanNorther.send_dev_status(self.device, self.event_data['port'], 1)
  156. elif self.event_data['cmdCode'] == '22': # ID在线卡刷卡查询余额
  157. cardNo = self.event_data['cardNo']
  158. fee = RMB(self.event_data['fee'])
  159. cardType = self.event_data['cardType']
  160. card = self.update_card_dealer_and_type(cardNo)
  161. # 首先检查订单,并进行充值
  162. # 不存在卡的情况下 直接
  163. if not card:
  164. res = "03"
  165. elif not card.openId:
  166. res = "03"
  167. elif card.frozen:
  168. res = "04"
  169. # 有绑定的卡 并且卡没被冻结的情况下
  170. else:
  171. # 刷新卡的金额
  172. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  173. result = self.recharge_id_card(card=card, rechargeType='append', order=card_recharge_order)
  174. card.reload()
  175. logger.info('cardNo=%s,openId=%s,result=%s,fee=%s, info=%s' % (cardNo, card.openId, result, fee, self.event_data))
  176. res = "01" if result["balance"] >= fee else "02"
  177. balance = RMB(0) if not card else card.balance
  178. try:
  179. logger.info("card is <{}> fee is <{}> response res is <{}>".format(cardNo, fee, res))
  180. result = self.deviceAdapter.response_card_status(cardNo, balance, res)
  181. except Exception, e:
  182. logger.info('resp back error=%s' % e)
  183. return
  184. if fee <= RMB(0):
  185. # 仅仅是查询余额
  186. logger.debug(
  187. 'query the balance of card<cardNo={}> in device<devNo={}>'.format(card.cardNo, self.device.devNo))
  188. return
  189. # 设备回复扣款成功,服务器就需要正式扣掉钱
  190. if result['status'] == '01' and res == '01':
  191. virtual_card = card.bound_virtual_card
  192. if virtual_card is not None:
  193. group = Group.get_group(self.device['groupId'])
  194. VCardConsumeRecord(
  195. orderNo = VCardConsumeRecord.make_no(self.device.logicalCode),
  196. openId = card.openId,
  197. cardId = str(virtual_card.id),
  198. dealerId = card.dealerId,
  199. devNo = self.device.devNo,
  200. devTypeCode = self.device.devTypeCode,
  201. devTypeName = self.device.devTypeName,
  202. logicalCode = self.device['logicalCode'],
  203. groupId = group['groupId'],
  204. address = group['address'],
  205. groupNumber = self.device['groupNumber'],
  206. groupName = group['groupName'],
  207. ).save()
  208. else:
  209. self.consume_money_for_card(card, fee)
  210. # 记录卡消费记录以及消费记录
  211. orderNo, cardOrderNo = self.record_consume_for_card(card, fee)
  212. # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
  213. ServiceProgress.register_card_service(
  214. self.device, -1, card,
  215. {
  216. 'orderNo': orderNo,
  217. 'money': self.event_data['fee'],
  218. 'coin': self.event_data['fee'],
  219. 'needTime': 0,
  220. 'cardOrderNo': cardOrderNo
  221. }
  222. )
  223. # 通知微信,已经扣费
  224. self.notify_balance_has_consume_for_card(card, fee)
  225. elif self.event_data['cmdCode'] == '11' and self.event_data['status'] == '01': # 开始启动某个端口
  226. # 按下端口,开始使用。IC卡和ID卡都会上报这条信息。IC卡只记录消费记录信息,ID卡主要是上报了具体的某一个端口.ID卡和劲能的类似,主要是表示开始某一个端口以及回收余额
  227. cardType = self.event_data['cardType']
  228. card = self.update_card_dealer_and_type(self.event_data['cardNo'], cardType)
  229. if not card:
  230. logger.info('no card cardNo-<{}>'.format(self.event_data.get('cardNo')))
  231. return
  232. # 这个地方将计费方式更新到 portDict 刷卡退费的时候会将刷卡的退费金额上报过来 结束事件需要这个字段 主要的是要更新consumeDict的字段
  233. # 0 按时间收费
  234. # 1 按度计费
  235. consumeMode = self.device.get("otherConf", dict()).get("consumeMode", 0)
  236. if consumeMode == 0 or consumeMode == 2:
  237. self.event_data["billingType"] = "time"
  238. else:
  239. self.event_data["billingType"] = "elec"
  240. if cardType == 'ID':
  241. consumeDict = {'chargeIndex': self.event_data['port']}
  242. queryDict = {'device_imei': self.device.devNo,
  243. 'port': -1, 'isFinished': False,
  244. 'cardId': str(card.id), 'start_time': {'$gte': int(time.time()) - 3600}}
  245. progressDict = {'port': self.event_data['port']}
  246. ServiceProgress.update_progress_and_consume_rcd(ownerId = self.device.ownerId,
  247. queryDict = queryDict, consumeDict = consumeDict,
  248. updateConsume = True, progressDict = progressDict)
  249. # 找出对应的卡的ID记录到端口内存数据
  250. queryDict.update(progressDict)
  251. rcds = ServiceProgress.get_collection().find(queryDict, {'consumeOrder': 1},
  252. sort = [('start_time', -1)])
  253. allCoins = sum_rmb([rcd['consumeOrder']['coin'] for rcd in rcds])
  254. try:
  255. d = Device.objects(devNo=self.device.devNo).first()
  256. billingType = d.otherConf.get('billingType', 'time')
  257. actionBox = ActionDeviceBuilder.create_action_device(Device.get_dev(self.device.devNo))
  258. cardTime = actionBox.get_freemode_volume_andsoon_config()['card1Time']
  259. icMoney = int(actionBox.get_IC_coin_power_config()['icMoney']) / 10
  260. allCardTime = int(int(allCoins) / icMoney) * int(cardTime)
  261. except Exception as e:
  262. logger.error('allCardTime error: %s' % e)
  263. allCardTime = 0
  264. billingType = 'time'
  265. self.event_data.update({'cardOrderTime': str(allCardTime)})
  266. self.event_data.update({'cardId': str(card.id)})
  267. self.event_data.update({'openId': card.openId})
  268. self.event_data.update({'coins': str(allCoins)})
  269. self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  270. self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
  271. self.event_data.update({'billingType': billingType})
  272. Device.update_port_control_cache(self.device.devNo, self.event_data) # 记录该端口累计需要的时间和钱,cardId
  273. else: # IC卡,需要记录消费记录
  274. fee = RMB(self.event_data['fee'])
  275. card.update(balance=RMB(self.event_data['balance']))
  276. orderNo, cardOrderNo = self.record_consume_for_card(card, fee)
  277. ServiceProgress.register_card_service(self.device, self.event_data['port'], card,
  278. {'orderNo': orderNo, 'money': self.event_data['fee'],
  279. 'coin': self.event_data['fee'], 'cardOrderNo': cardOrderNo})
  280. # 通知微信,已经扣费
  281. self.notify_balance_has_consume_for_card(card, fee)
  282. self.event_data.update({'cardId': str(card.id)})
  283. self.event_data.update({'openId': card.openId})
  284. self.event_data.update({'coins': self.event_data['fee']})
  285. self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  286. self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
  287. Device.update_port_control_cache(self.device.devNo, self.event_data) # 记录该端口累计需要的时间和钱,cardId
  288. elif self.event_data['cmdCode'] == '12': # 离线卡充值
  289. cardNo = self.event_data['cardNo']
  290. preBalance = RMB(self.event_data['balance'])
  291. card = self.update_card_dealer_and_type(cardNo, 'IC', balance = preBalance) # type: Card
  292. if not card:
  293. return
  294. if card.frozen:
  295. logger.debug('{} has been frozen.'.format(repr(card)))
  296. return
  297. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id)) # type: CardRechargeOrder
  298. if not card_recharge_order:
  299. logger.debug('{} has no recharge order.'.format(repr(card)))
  300. return
  301. self.recharge_ic_card(card = card,
  302. preBalance = preBalance,
  303. rechargeType = 'overwrite',
  304. order = card_recharge_order)
  305. elif self.event_data['cmdCode'] == '05':
  306. # 新版本的结束事件,比就版本多刷卡ID卡的在线退费
  307. devNo = self.device.devNo
  308. port = str(self.event_data['port'])
  309. try:
  310. # 获取充电的模式
  311. ctrInfo = Device.get_dev_control_cache(devNo)
  312. lineInfo = ctrInfo.get(port)
  313. if 'coins' not in lineInfo:
  314. logger.debug('get null control cache from {}'.format(repr(self.device)))
  315. return
  316. else:
  317. logger.debug('port cache is: {}'.format(str(lineInfo)))
  318. if lineInfo.get('isApi', False) is True:
  319. self.event_data.update({'deviceCode':self.device['logicalCode']})
  320. return handle_and_notify_event_to_north_Dc(self.device["devNo"], self.event_data)
  321. billingType = lineInfo.get("billingType", "time")
  322. if billingType == "elec":
  323. return self.do_elec_finish(devNo, port, lineInfo, self.event_data)
  324. else:
  325. return self.do_time_finish(devNo, port, lineInfo, self.event_data)
  326. finally:
  327. Device.clear_port_control_cache(devNo, str(port))
  328. notify_event_to_north_v2(self.device["devNo"], self.event_data)
  329. notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
  330. desc = self.event_data['reason'])
  331. send_event_to_zhejiang(self.dealer, self.device, self.event_data)
  332. if self.event_data['reasonCode'] == '04': # 功率过载导致的断电,一条告警,一条恢复告警
  333. YuhuanNorther.send_dev_event(self.device, '97', port)
  334. YuhuanNorther.send_dev_event(self.device, '98', port)
  335. # 发送一条端口使用结束的告警
  336. YuhuanNorther.send_dev_status(self.device, port, 2)
  337. def do_elec_finish(self, devNo, port, lineInfo, msgDict):
  338. """
  339. 电川的板子 按电量退费
  340. :return:
  341. """
  342. dealer = self.device.owner
  343. if not dealer:
  344. logger.error('dealer is not found, dealerId=%s' % self.device['ownerId'])
  345. return
  346. leftElec = self.event_data.get("leftTime", 0) / 100.0
  347. reasonCode = self.event_data.get("endType")
  348. reasonStr = self.event_data.get("reason")
  349. cardNo = str(self.event_data.get("cardNo")) if self.event_data.get("cardNo") else None
  350. cardType = self.event_data.get("cardType")
  351. price = RMB(lineInfo.get('price', 0))
  352. startTime = lineInfo.get("startTime")
  353. # 投币事件
  354. if not startTime:
  355. return
  356. startTime = to_datetime(startTime)
  357. nowTime = datetime.datetime.now()
  358. deviceDuration, deviceElec = self.__parse_device_finished_data(self.event_data)
  359. try:
  360. consumeDict = {
  361. "reason": reasonStr,
  362. "chargeIndex": port,
  363. "uartData": self.event_data.get('uartData', '')
  364. }
  365. # 计算充电的时间
  366. if deviceDuration and deviceDuration > 0:
  367. usedTime = deviceDuration
  368. else:
  369. if startTime > nowTime:
  370. usedTime = 0
  371. else:
  372. usedTime = int(round(((nowTime - startTime).total_seconds() / 60.0)))
  373. consumeDict.update({"duration": usedTime})
  374. # 获取组信息
  375. group = Group.get_group(self.device["groupId"])
  376. # 扫码的结束
  377. if not cardNo:
  378. needElec = lineInfo.get("needElec")
  379. if leftElec == int("FFFF", 16):
  380. leftElec = needElec
  381. elif leftElec > needElec:
  382. logger.error('left elec is bigger than need elec. something is wrong')
  383. leftElec = 0
  384. spendElec = needElec - leftElec
  385. coins = VirtualCoin(lineInfo.get("coins"))
  386. refundCoins = VirtualCoin(0)
  387. refundedMoney = RMB(0)
  388. consumeDict.update({
  389. "reason": reasonStr,
  390. "chargeIndex": port
  391. })
  392. refundSwitch = self.device.is_auto_refund
  393. if refundSwitch:
  394. refundCoins = VirtualCoin(coins) * Ratio(leftElec / needElec)
  395. refundedMoney = RMB(price) * Ratio(leftElec / needElec)
  396. if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']:
  397. # 虚拟卡的结束
  398. consumeRcdId = lineInfo['consumeRcdId']
  399. vCardId = lineInfo.get("vCardId", "")
  400. vCard = UserVirtualCard.objects(id = vCardId).first()
  401. if not vCard:
  402. logger.info('can not find the vCard id = %s' % vCardId)
  403. return
  404. try:
  405. ServiceProgress.update_progress_and_consume_rcd(
  406. self.device.ownerId,
  407. {
  408. 'open_id': lineInfo['openId'],
  409. 'port': int(port),
  410. 'device_imei': self.device.devNo,
  411. 'isFinished': False
  412. },
  413. consumeDict
  414. )
  415. if refundCoins > VirtualCoin(0):
  416. vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
  417. vCard.refund_quota(vCardConsumeRcd, needElec - spendElec, spendElec,
  418. refundCoins.mongo_amount)
  419. finally:
  420. user = MyUser.objects(openId = lineInfo['openId'],
  421. groupId = self.device.groupId).first()
  422. self.notify_user_service_complete(
  423. service_name = u'充电',
  424. openid = user.managerialOpenId if user else '',
  425. port = port,
  426. address = group['address'],
  427. reason = self.event_data['reason'],
  428. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  429. extra = [
  430. {u'虚拟卡号': vCard.cardNo}
  431. ]
  432. )
  433. elif 'openId' in lineInfo and lineInfo['openId']:
  434. # 扫码使用金币启动
  435. user = MyUser.objects(openId = lineInfo['openId'],
  436. groupId = self.device.groupId).first()
  437. try:
  438. is_cash = False
  439. if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
  440. is_cash = True
  441. consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
  442. if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
  443. consumeDict.update(
  444. {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
  445. self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
  446. ServiceProgress.update_progress_and_consume_rcd(
  447. self.device.ownerId,
  448. {
  449. 'open_id': lineInfo['openId'],
  450. 'port': int(port),
  451. 'device_imei': self.device.devNo,
  452. 'isFinished': False
  453. },
  454. consumeDict)
  455. finally:
  456. extra = []
  457. if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
  458. real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
  459. if real_refund > RMB(0):
  460. extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
  461. extra.append({u'退款金额': '{}(元)'.format(real_refund)})
  462. else:
  463. extra.append({u'消费金额': '{}(元)'.format(price)})
  464. elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
  465. real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
  466. if real_refund > VirtualCoin(0):
  467. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
  468. extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
  469. else:
  470. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  471. else:
  472. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  473. self.notify_user_service_complete(
  474. service_name = u'充电',
  475. openid = user.managerialOpenId if user else '',
  476. port = port,
  477. address = group['address'],
  478. reason = self.event_data['reason'],
  479. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  480. extra = extra)
  481. else:
  482. logger.error('not net pay rather user virtual card pay. something is wrong.')
  483. else:
  484. backMoney = self.event_data.get("backMoney")
  485. # 刷卡的结束 如果没有开启刷卡退费 则结束上报过来的backMoney = 0
  486. if cardType == "IC":
  487. # IC卡结束 只有刷卡结束的IC卡才能够刷新IC卡余额
  488. card = self.update_card_dealer_and_type(cardNo, "IC")
  489. if reasonCode == "05" and backMoney > 0:
  490. # 原因为05表示刷卡结束充电,会把退费金额报上来. 否则只能通过11指令报上来
  491. self.refund_money_for_card(VirtualCoin(backMoney), card.id)
  492. consumeDict.update({'balance': str(card.balance + VirtualCoin(backMoney))})
  493. else:
  494. consumeDict.update({'balance': str(card.balance)}) # IC卡必须下次刷卡的时候回收上来
  495. elif cardType == "ID":
  496. # ID卡结束 直接退费就行了
  497. card = self.update_card_dealer_and_type(cardNo, "ID")
  498. if backMoney > 0:
  499. self.refund_money_for_card(RMB(backMoney), str(card.id))
  500. consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
  501. else:
  502. logger.error("invalid card type event data is <{}>".format(self.event_data))
  503. ServiceProgress.update_progress_and_consume_rcd(
  504. self.device.ownerId,
  505. {
  506. 'open_id': lineInfo['openId'],
  507. 'port': int(port),
  508. 'device_imei': self.device.devNo,
  509. 'isFinished': False
  510. },
  511. consumeDict
  512. )
  513. extra = [{u'实体卡号': cardNo}]
  514. if backMoney > 0:
  515. extra.append({
  516. u'退款金额': u'{}(金币)'.format(backMoney)
  517. })
  518. self.notify_user_service_complete(
  519. service_name = u'充电',
  520. openid = self.get_managerialOpenId_by_openId(lineInfo['openId']),
  521. port = port,
  522. address = group['address'],
  523. reason = self.event_data['reason'],
  524. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  525. extra = extra
  526. )
  527. except Exception as e:
  528. logger.exception(e)
  529. def do_time_finish(self, devNo, port, lineInfo, msgDict):
  530. try:
  531. dealer = Dealer.objects(id=self.device['ownerId']).first()
  532. if not dealer:
  533. logger.error('dealer is not found, dealerId=%s' % self.device['ownerId'])
  534. return
  535. price = RMB(lineInfo.get('price', 0))
  536. refundProtectionTime = lineInfo.get('refundProtectionTime', 5)
  537. deviceDuration, deviceElec = self.__parse_device_finished_data(self.event_data)
  538. if lineInfo is not None and 'startTime' in lineInfo:
  539. startTime = to_datetime(lineInfo['startTime'])
  540. nowTime = datetime.datetime.now()
  541. if startTime > nowTime:
  542. logger.error('start time is bigger than now time,devNo={}'.format(devNo))
  543. serverDuration = -1
  544. else:
  545. serverDuration = int(round((((nowTime - startTime).total_seconds() + 59) / 60.0)))
  546. else:
  547. logger.info('lineinfo has not startTime,devNo=%s' % devNo)
  548. serverDuration = -1
  549. if deviceDuration > 0:
  550. usedTime = deviceDuration
  551. elif serverDuration >= 0:
  552. usedTime = serverDuration
  553. else:
  554. usedTime = -1
  555. leftTime = self.event_data['leftTime']
  556. if leftTime != 65535:
  557. leftTimeStr = leftTime
  558. if usedTime == -1:
  559. actualNeedTime = -1
  560. else:
  561. actualNeedTime = usedTime + leftTime
  562. else:
  563. leftTimeStr = u'端口未使用'
  564. actualNeedTime = 0
  565. group = self.device.group # type: GroupDict
  566. if actualNeedTime == -1:
  567. if 'cardNo' in self.event_data and self.event_data['cardNo']:
  568. card = Card.objects(cardNo = str(self.event_data['cardNo']), agentId = self.dealer.agentId).first()
  569. if card is not None:
  570. # todo 生成模板所需要的所有参数, 后续有客户自定义的话, 直接在这个字典里面添加, 不需要删掉之前的.
  571. # todo 这个变量仅仅用于下面generate_service_complete_title_by_devType()函数的参. 做成配置项更好, 下次不用改代码.
  572. templateMap = {
  573. 'cardCoins': 0,
  574. 'cardOrderTime': 0,
  575. 'actualNeedTime': 0,
  576. 'usedTime': 0,
  577. 'backCoins': 0,
  578. 'reason': u'没有实际预定时间, 忽略此次消费事件'
  579. }
  580. # 先去获取devType上面的模板, 如果没有就走正常的流程
  581. title = self.generate_service_complete_title_by_devType(self.device['devType']['id'], templateMap)
  582. if title != '':
  583. self.notify_user(
  584. card.managerialOpenId if card else '',
  585. 'service_complete',
  586. **{
  587. 'title': title,
  588. 'service': u'充电服务',
  589. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  590. 'remark': u'动态功率计算时间是指按照你的电动车功率大小进行折算出来的实际充电时间。'
  591. })
  592. else:
  593. self.notify_user_service_complete(
  594. service_name=u'充电',
  595. openid=card.managerialOpenId if card else '',
  596. port=port,
  597. address=group['address'],
  598. reason=self.event_data['reason'],
  599. finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  600. extra=[{
  601. u'实体卡号': self.event_data['cardNo']
  602. }]
  603. )
  604. logger.debug('has no actual need time. ignore this event.')
  605. return
  606. consumeDict = {
  607. 'reason': self.event_data['reason'],
  608. 'leftTime': leftTimeStr,
  609. 'chargeIndex': port,
  610. 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
  611. 'duration': usedTime,
  612. 'deviceDuration': deviceDuration,
  613. 'serverDuration': serverDuration,
  614. 'uartData': self.event_data.get('uartData', '')
  615. }
  616. if deviceElec != -1:
  617. consumeDict.update({'elec': deviceElec})
  618. else:
  619. # deviceObj = Device.objects(devNo = self.device.devNo).first()
  620. groupObj = Group.objects(id=self.device.groupId).first()
  621. if groupObj.otherConf.get('zhuxing', None) is not None:
  622. spendElec = round((float(random.randint(15, 19)) / 100) * (float(usedTime) / 60), 3)
  623. consumeDict.update({'elec': spendElec})
  624. consumeDict.update({'elecFee': self.deviceAdapter.calc_elec_fee(spendElec)})
  625. else:
  626. spendElec = 0.0
  627. consumeDict.update({'elec': 0.0})
  628. consumeDict.update({'elecFee': RMB(0.0).mongo_amount})
  629. # 涉及到卡的退费 不要以缓存为准 以设备上报的为准
  630. cardNo = self.event_data.get("cardNo")
  631. if cardNo:
  632. # 如果是刷卡的,直接更新消费记录,发通知消息,支持ID卡的退费。
  633. # IC卡的退费, 如果结束原因是刷卡退费(05), 则会把退费信息返回;
  634. # 否则不会把退费信息传过来,会通过11号命令返回
  635. cardType = self.event_data.get("cardType")
  636. if cardType == 'ID':
  637. card = self.update_card_dealer_and_type(cardNo=cardNo, cardType="ID")
  638. consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
  639. if self.event_data.has_key('backMoney') and self.event_data['backMoney'] > 0:
  640. self.refund_money_for_card(VirtualCoin(self.event_data['backMoney']), card.id)
  641. # 通知微信,已经退费
  642. self.notify_user(card.managerialOpenId, 'refund_coins', **{
  643. 'title': u'退币完成!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
  644. 'backCount': u'金币:%s' % VirtualCoin(self.event_data['backMoney']),
  645. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  646. })
  647. elif cardType == "IC":
  648. card = self.update_card_dealer_and_type(cardNo=cardNo, cardType="IC")
  649. # IC 并且结束code是05 表示卡贴上去了
  650. if self.event_data['endType'] == '05': # 刷卡退费结束的时候,才能够刷新IC卡的余额
  651. self.refund_money_for_card(VirtualCoin(self.event_data['backMoney']), card.id)
  652. consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
  653. else:
  654. consumeDict.update({'balance': str(card.balance)}) # IC卡必须下次刷卡的时候回收上来
  655. else:
  656. logger.error("invalid card type event data is <{}>".format(self.event_data))
  657. ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
  658. {'open_id': lineInfo['openId'], 'port': int(port),
  659. 'device_imei': self.device.devNo,
  660. 'isFinished': False}, consumeDict)
  661. extra = [{
  662. u'实体卡号': lineInfo['cardNo']
  663. }]
  664. if VirtualCoin(self.event_data['backMoney']) > VirtualCoin(0):
  665. extra.append({
  666. u'退费金额': u'{}(金币)'.format(self.event_data['backMoney'])
  667. })
  668. templateMap = {
  669. 'cardCoins': lineInfo.get('coins', 0),
  670. 'cardOrderTime': lineInfo.get('cardOrderTime', 0),
  671. 'actualNeedTime': actualNeedTime,
  672. 'usedTime': usedTime,
  673. 'backCoins': self.event_data['backMoney'],
  674. 'reason': self.event_data['reason']
  675. }
  676. title = self.generate_service_complete_title_by_devType(self.device['devType']['id'], templateMap)
  677. if title != '':
  678. # u"\\n\\n刷卡扣费金额:\\t\\t{cardCoins}\\n\\n刷卡订购时间:\\t\\t{cardOrderTime}\\n\\n动态功率计算时间:\\t\\t{actualNeedTime}\\n\\n使用时间:\\t\\t{usedTime}\\n\\n退款金额:\\t\\t{backCoins}\\n\\n结束原因:\\t\\t{reason}",
  679. self.notify_user(
  680. card.managerialOpenId if card else '',
  681. 'service_complete',
  682. **{
  683. 'title': title,
  684. 'service': u'充电服务',
  685. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  686. 'remark': u'动态功率计算时间是指按照你的电动车功率大小进行折算出来的实际充电时间。'
  687. })
  688. else:
  689. self.notify_user_service_complete(
  690. service_name = u'充电',
  691. openid = card.managerialOpenId if card else '',
  692. port = port,
  693. address = group['address'],
  694. reason = self.event_data['reason'],
  695. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  696. extra = extra)
  697. else:
  698. # 计算退费信息
  699. coins = VirtualCoin(lineInfo['coins'])
  700. refundCoins = VirtualCoin(0)
  701. refundedMoney = RMB(0)
  702. if self.device.is_auto_refund:
  703. if leftTime != 65535:
  704. refundCoins = coins * (float(leftTime) / float(actualNeedTime))
  705. refundedMoney = RMB(price * (float(leftTime) / float(actualNeedTime)))
  706. else:
  707. refundCoins = coins
  708. refundedMoney = RMB(price)
  709. if usedTime < refundProtectionTime and refundCoins != VirtualCoin(0):
  710. refundCoins = coins
  711. refundedMoney = RMB(price)
  712. if refundCoins > coins:
  713. refundCoins = coins
  714. if refundedMoney > RMB(price):
  715. refundedMoney = RMB(price)
  716. # 退费保护不受金币退款开关影响, 照样退费
  717. elif usedTime < refundProtectionTime:
  718. refundCoins = coins
  719. refundedMoney = RMB(price)
  720. if refundCoins > coins:
  721. refundCoins = coins
  722. if refundedMoney > RMB(price):
  723. refundedMoney = RMB(price)
  724. else:
  725. pass
  726. logger.debug(
  727. 'lefttime = {}, usedTime = {}, need time = {}, back coins = {}'.format(leftTime, usedTime,
  728. actualNeedTime,
  729. refundCoins))
  730. if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']:
  731. vCardId = lineInfo['vCardId']
  732. vCard = UserVirtualCard.objects(id = vCardId).first() # type: UserVirtualCard
  733. if not vCard:
  734. logger.info('can not find the vCard id = %s' % vCardId)
  735. return
  736. try:
  737. ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
  738. {'open_id': lineInfo['openId'],
  739. 'port': int(port),
  740. 'device_imei': self.device.devNo,
  741. 'isFinished': False}, consumeDict)
  742. if refundCoins > VirtualCoin(0):
  743. vCardConsumeRcd = VCardConsumeRecord.objects.get(id = lineInfo['consumeRcdId'])
  744. vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, refundCoins.mongo_amount)
  745. finally:
  746. user = MyUser.objects(openId = lineInfo['openId'],
  747. groupId = self.device.groupId).first()
  748. self.notify_user_service_complete(
  749. service_name = u'充电',
  750. openid = user.managerialOpenId if user else '',
  751. port = port,
  752. address = group['address'],
  753. reason = self.event_data['reason'],
  754. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  755. extra = [
  756. {u'虚拟卡号': vCard.cardNo}
  757. ]
  758. )
  759. elif 'openId' in lineInfo and lineInfo['openId']:
  760. user = MyUser.objects(openId = lineInfo['openId'],
  761. groupId = self.device.groupId).first()
  762. try:
  763. is_cash = False
  764. if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
  765. is_cash = True
  766. consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
  767. if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
  768. consumeDict.update(
  769. {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
  770. self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
  771. ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
  772. {'open_id': lineInfo['openId'],
  773. 'port': int(port),
  774. 'device_imei': self.device.devNo,
  775. 'isFinished': False}, consumeDict)
  776. finally:
  777. extra = []
  778. if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
  779. real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
  780. if real_refund > RMB(0):
  781. extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
  782. extra.append({u'退款金额': '{}(元)'.format(real_refund)})
  783. else:
  784. extra.append({u'消费金额': '{}(元)'.format(price)})
  785. elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
  786. real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
  787. if real_refund > VirtualCoin(0):
  788. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
  789. extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
  790. else:
  791. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  792. else:
  793. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  794. self.notify_user_service_complete(
  795. service_name = u'充电',
  796. openid = user.managerialOpenId if user else '',
  797. port = port,
  798. address = group['address'],
  799. reason = self.event_data['reason'],
  800. finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  801. extra = extra)
  802. else:
  803. logger.error('not net pay rather user virtual card pay. something is wrong.')
  804. except Exception as e:
  805. logger.exception(e)
  806. class YUZEInductorEvent(FaultEvent):
  807. def do(self, **args):
  808. # 处理数据
  809. voltage = self.event_data.get('voltage', -1)
  810. temperature = self.event_data.get('temperature', -1)
  811. smokeWarning = self.event_data.get('smokeWarning', False)
  812. try:
  813. otherConf = Device.objects.get(devNo = self.device.devNo).otherConf
  814. maxVoltage = otherConf.get('voltageThre', 230)
  815. if voltage >= maxVoltage:
  816. desc = u'当前电压%s伏超过了门限值:%s伏' % (voltage, maxVoltage)
  817. self.record(faultCode = FAULT_CODE.OVER_VOLTAGE, description = desc, title = u'主机电压过高', detail = None,
  818. level = FAULT_LEVEL.CRITICAL)
  819. maxTemperature = otherConf.get('temThre', 60)
  820. if temperature > maxTemperature:
  821. desc = u'当前主机温度%s度超过了门限值:%s度' % (temperature, maxTemperature)
  822. self.record(faultCode = FAULT_CODE.OVER_TEMPERATURE, description = desc, title = u'主机温度过高',
  823. detail = None, level = FAULT_LEVEL.CRITICAL)
  824. if smokeWarning:
  825. desc = u'当前主机出现冒烟,请第一时间确定是否有起火。此告警十万火急,请迅速联系物业、消防相关部门!'
  826. self.record(faultCode = FAULT_CODE.SMOKE, description = desc, title = u'主机出现冒烟', detail = None,
  827. level = FAULT_LEVEL.FATAL)
  828. except Exception, e:
  829. logger.error('some error=%s' % e)
  830. return
  831. class InteroperatorAlertEvent(FaultEvent):
  832. def __Analyze_alert_data(self, data):
  833. alertInfo = {'cmdCode': data['cmd'], 'logicalCode': self.device['logicalCode']}
  834. address = Group.get_group(self.device['groupId'])['address']
  835. # 这里判断数据格式
  836. if 'status' not in data:
  837. logger.error('Data arrays have no keywords status')
  838. return
  839. # 这里做漏电告警处理
  840. if '5' in data['status']:
  841. electricityNum = str(int(data['values'][0:4], 16)) + 'mA'
  842. alertInfo['electricity'] = {'electricityNum': electricityNum,
  843. 'address': address,
  844. 'reasonCode': '12',
  845. 'reason': u'在{}编号为{}发生漏电,漏电量为{}'
  846. .format(address, self.device['logicalCode'], electricityNum)}
  847. # 这里做高温告警处理
  848. if '6' in data['status']:
  849. temperatureAccess = [index for index, acces in enumerate(data['status'], 1) if acces == '6']
  850. temperatureAlertList = []
  851. for i in temperatureAccess:
  852. temperatureValue = str(int(data['values'][(i - 1) * 4:(i - 1) * 4 + 4], 16))
  853. temperatureAlertList.append(
  854. {'temperatureValue': temperatureValue,
  855. 'address': address,
  856. 'reasonCode': '11',
  857. 'reason': u'在{}编号为{}的设备有高温预警,当前温度为{}摄氏度'
  858. .format(address, self.device['logicalCode'], temperatureValue)})
  859. alertInfo['temperature'] = temperatureAlertList
  860. return alertInfo
  861. def do(self, **args):
  862. # 判断不存在的设备网上报
  863. if not self.device.ownerId:
  864. logger.error('This device cant find a dealer')
  865. return
  866. # 是否存在温感和电感
  867. temperaturePart = Part.objects(logicalCode = self.device['logicalCode'], partType = '3001')
  868. electricityPart = Part.objects(logicalCode = self.device['logicalCode'], partType = '3002')
  869. if not temperaturePart.count() or not electricityPart.count():
  870. logger.error(
  871. 'There are no transformers in the locigalcode {} equipment'.format(self.device['logicalCode']))
  872. return
  873. # 处理数据
  874. eventInfo = self.__Analyze_alert_data(self.event_data['data'])
  875. try:
  876. # 先处理高温情况
  877. if 'temperature' in eventInfo:
  878. for InfoDetail in eventInfo['temperature']:
  879. send_event_to_zhejiang(self.dealer, self.device, InfoDetail, partId = temperaturePart[0].id)
  880. # 提示用户
  881. group = Group.get_group(self.device['groupId'])
  882. self.notify_dealer('device_fault', **{
  883. 'title': u'注意!注意!您的设备发生故障',
  884. 'device': u'组号::%s, 二维码编号:%s' % (self.device['groupNumber'], self.device['logicalCode']),
  885. 'location': u'组名称:%s, 地址:%s' % (group['groupName'], group['address']),
  886. 'fault': InfoDetail['reason'],
  887. 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  888. })
  889. # 上报高温至消防
  890. # if self.device["ownerId"] in ("5b4ed32e8732d67bd0626528", "5b6c29388732d669f3ae6f94"):
  891. group = Group.get_group(self.device['groupId'])
  892. districtInfo = District.get_district(group["districtId"])
  893. self.device.update({"districtInfo": districtInfo, "groupAddr": group["address"]})
  894. LiangXiXiaoFang.send_to_xf_fault(self.device, "01", u"设备温度过高")
  895. # 处理漏电情况
  896. elif 'electricity' in eventInfo:
  897. # 获取漏电告警插件
  898. send_event_to_zhejiang(self.dealer, self.device, eventInfo['electricity'],
  899. partId = electricityPart[0].id)
  900. # 提示用户
  901. group = Group.get_group(self.device['groupId'])
  902. self.notify_dealer('device_fault', **{
  903. 'title': u'注意!注意!您的设备发生故障',
  904. 'device': u'组号::%s, 二维码编号:%s' % (self.device['groupNumber'], self.device['logicalCode']),
  905. 'location': u'组名称:%s, 地址:%s' % (group['groupName'], group['address']),
  906. 'fault': eventInfo['electricity']['reason'],
  907. 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  908. })
  909. # 上报漏电至消防
  910. # if self.device["ownerId"] in ("5b4ed32e8732d67bd0626528", "5b6c29388732d669f3ae6f94"):
  911. group = Group.get_group(self.device['groupId'])
  912. districtInfo = District.get_district(group["districtId"])
  913. self.device.update({"districtInfo": districtInfo, "groupAddr": group["address"]})
  914. LiangXiXiaoFang.send_to_xf_fault(self.device, "04", u"设备发生漏电")
  915. except:
  916. logger.error('Array {} nonspecification'.format(eventInfo))
  917. return
  918. self.record(detail = eventInfo)
  919. class InteroperatorReport(WorkEvent):
  920. def do(self, **args):
  921. if 'type' not in self.event_data:
  922. logger.error('Array {} is not format,lose a key named "type"'.format(self.event_data))
  923. if self.event_data.get('type') == 'report':
  924. devReportDict = {'logicalCode': 'logicalCode', 'time': self.event_data['time_stamp'], 'portInfo': {}}
  925. temperature = ''
  926. voltage = 220
  927. try:
  928. # 拿到个数判断是不是第一次
  929. reportNum = PortReport.get_collection().find({
  930. 'logicalCode': self.device['logicalCode']
  931. }).sort('time', -1).count()
  932. if reportNum:
  933. # 获取上一次存储的信息
  934. reportLast = PortReport.get_collection().find({
  935. 'logicalCode': self.device['logicalCode']
  936. }).sort('time', -1)[0]
  937. for ii in range(10):
  938. power = self.__saveDate(1, msgDict = self.event_data, ii = ii)
  939. if power:
  940. electricity = float(power) / voltage / 10
  941. else:
  942. electricity = reportLast['portInfo'][str(ii + 1)]['electricity']
  943. temperatureR = self.__saveDate(2, msgDict = self.event_data, ii = ii, electricity = electricity,
  944. devReportDict = devReportDict)
  945. if temperatureR:
  946. temperature = temperatureR
  947. devReportDict.update({'temperature': temperature})
  948. # 查看现在的跟以前差距多少
  949. timeInterval = devReportDict['time'] - reportLast['time']
  950. if timeInterval > 2:
  951. PortReportNewList = [
  952. {"logicalCode": self.device['logicalCode'], "temperature": reportLast['temperature'],
  953. 'portInfo': reportLast['portInfo'],
  954. 'time': reportLast['time'] + (v + 1) * 2}
  955. for v in range(int(timeInterval / 2) - 1)]
  956. PortReport.get_collection().insert_many(PortReportNewList)
  957. # 首存的情况
  958. else:
  959. for ii in range(10):
  960. power = self.__saveDate(1, msgDict = self.event_data, ii = ii)
  961. electricity = float(power) / voltage / 10
  962. temperatureR = self.__saveDate(2, msgDict = self.event_data, ii = ii, electricity = electricity,
  963. devReportDict = devReportDict)
  964. if temperatureR:
  965. temperature = temperatureR
  966. devReportDict.update({'temperature': temperature})
  967. except Exception, e:
  968. logger.error('solve dev=%s device report has an error e=%s' % (self.device.devNo, e))
  969. finally:
  970. newInfo = PortReport(
  971. logicalCode = self.device['logicalCode'],
  972. temperature = devReportDict['temperature'],
  973. time = devReportDict['time'],
  974. portInfo = devReportDict['portInfo']
  975. )
  976. newInfo.save()
  977. def __saveDate(self, data, msgDict, ii, electricity = None, devReportDict = None):
  978. # 存储数据库
  979. if data == 1:
  980. powerData = msgDict['data']['power_data'][0 + 4 * ii:4 + 4 * ii]
  981. power = int(powerData, 16)
  982. return power
  983. if data == 2:
  984. temperature = ''
  985. status = 'idle' if electricity == 0 else 'busy'
  986. devReportDict['portInfo'].update(
  987. {str(ii + 1): {'electricity': round(electricity, 3), 'status': status}})
  988. if ii < 4 and msgDict['data']['temp_data'][0 + 4 * ii:4 + 4 * ii] != '0000':
  989. temperatureNum = msgDict['data']['temp_data'][0 + 4 * ii:4 + 4 * ii]
  990. temperature = int(temperatureNum, 16)
  991. return temperature
  992. class StartAckEventPreProcessor(AckEventProcessorIntf):
  993. def analysis_reason(self, reason):
  994. return FINISHED_CHARGE_REASON_MAP.get(reason, reason)
  995. def pre_processing(self, device, event_data):
  996. # type:(DeviceDict, dict)->dict
  997. if 'duration' in event_data:
  998. duration = event_data.get('duration')
  999. event_data['duration'] = ((duration + 59) / 60)
  1000. if 'elec' in event_data:
  1001. elec = event_data.get('elec')
  1002. event_data['elec'] = round(elec / (10000.0 * 3600.0), 3)
  1003. if 'cardType' in event_data:
  1004. if event_data['cardType'] == 'AA33':
  1005. event_data['cardType'] = 'ID'
  1006. else:
  1007. event_data['cardType'] = 'IC'
  1008. if 'cardNo' in event_data:
  1009. event_data['cardNo'] = str(event_data['cardNo'])
  1010. if 'reason' in event_data:
  1011. event_data['reasonDesc'] = self.analysis_reason(event_data['reason'])
  1012. if 'fee' in event_data:
  1013. event_data['fee'] = (RMB(event_data['fee']) * Ratio("0.1"))
  1014. if 'balance' in event_data:
  1015. event_data['balance'] = (RMB(event_data['balance']) * Ratio("0.1"))
  1016. if 'backMoney' in event_data:
  1017. event_data['backMoney'] = (RMB(event_data['backMoney']) * Ratio("0.1"))
  1018. if 'sub' in event_data:
  1019. subs = event_data.get('sub', [])
  1020. for item in subs:
  1021. if 'fee' in item:
  1022. item['fee'] = (RMB(item['fee']) * Ratio('0.1'))
  1023. if 'balance' in item:
  1024. item['balance'] = (RMB(item['balance']) * Ratio('0.1'))
  1025. if 'left' in event_data:
  1026. event_data['left'] = event_data.pop('left')
  1027. else:
  1028. event_data['left'] = 0
  1029. return event_data
  1030. class CardRefundAckEventPreProcessor(AckEventProcessorIntf):
  1031. def pre_processing(self, device, event_data):
  1032. # type:(DeviceDict, dict)->dict
  1033. if 'cardType' in event_data:
  1034. if event_data['cardType'] == 'AA33':
  1035. event_data['cardType'] = 'ID'
  1036. else:
  1037. event_data['cardType'] = 'IC'
  1038. if 'cardNo' in event_data:
  1039. event_data['cardNo'] = str(event_data['cardNo'])
  1040. event_data['backMoney'] = (int(event_data['backMoney']) / 10.0)
  1041. return event_data
  1042. class MyComNetPayAckEvent(ComNetPayAckEvent):
  1043. def __init__(self, smartBox, event_data):
  1044. super(MyComNetPayAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
  1045. def post_after_start(self, order = None):
  1046. port = order.used_port
  1047. YuhuanNorther.send_dev_status(self.device, int(port), 1)
  1048. def post_after_finish(self, order = None):
  1049. port = order.used_port
  1050. if self.event_data['reason'] < 0:
  1051. logger.debug('reason<{}> is not to report.'.format(self.event_data['reason']))
  1052. return
  1053. notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
  1054. desc = self.event_data.get('reasonDesc', ''))
  1055. send_event_to_zhejiang(self.dealer, self.device, self.event_data)
  1056. if self.event_data['reason'] == '04':
  1057. YuhuanNorther.send_dev_event(self.device, '97', port)
  1058. YuhuanNorther.send_dev_event(self.device, '98', port)
  1059. # 发送一条端口使用结束的告警
  1060. YuhuanNorther.send_dev_status(self.device, port, 2)
  1061. def merge_order(self, master_order, sub_orders):
  1062. # type:(ConsumeRecord, list)->dict
  1063. order_value, unit, billingType = self.deviceAdapter._check_package(master_order.package)
  1064. start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
  1065. portDict = {
  1066. 'billingType': billingType
  1067. }
  1068. if master_order.paymentInfo['via'] == 'virtualCard':
  1069. portDict.update({
  1070. 'vCardId': master_order.paymentInfo['itemId']
  1071. })
  1072. all_coins = master_order.package['coins']
  1073. all_price = master_order.package['price']
  1074. all_consume_value = order_value
  1075. for sub_order in sub_orders:
  1076. all_coins += sub_order.package['coins']
  1077. all_price += sub_order.package['price']
  1078. sub_consume_value, _, _ = self.deviceAdapter._check_package(sub_order.package)
  1079. all_consume_value += sub_consume_value
  1080. portDict['coins'] = str(all_coins)
  1081. portDict['price'] = str(all_price)
  1082. if billingType == 'time':
  1083. portDict['needKind'] = 'needTime'
  1084. portDict['needValue'] = all_consume_value
  1085. portDict['unit'] = u'分钟'
  1086. portDict['estimatedTs'] = int(start_time.timestamp + all_consume_value * 60)
  1087. else:
  1088. portDict['needKind'] = 'needElec'
  1089. portDict['needValue'] = all_consume_value / 100.0
  1090. portDict['unit'] = u'度'
  1091. portDict['estimatedTs'] = int(start_time.timestamp + 12 * 60 * 60)
  1092. return portDict
  1093. def do_time_finished(self, master_order, sub_orders, merge_order_info):
  1094. # type: (ConsumeRecord, List[ConsumeRecord], dict)->(dict)
  1095. user = MyUser.objects(openId = master_order.openId,
  1096. groupId = master_order.groupId).first() # type: MyUser
  1097. if not user:
  1098. logger.error(
  1099. 'user is not exist. openId = {}, groupId = {}'.format(master_order.openId, master_order.groupId))
  1100. return
  1101. coins = VirtualCoin(merge_order_info['coins'])
  1102. left = self.event_data['left']
  1103. if left == 65535:
  1104. consumeDict = {
  1105. 'reason': self.event_data['reason'],
  1106. 'leftTime': '端口故障',
  1107. 'chargeIndex': str(master_order.used_port),
  1108. 'actualNeedTime': u'动态功率计算为0分钟',
  1109. 'duration': 0,
  1110. 'elec': 0,
  1111. 'elecFee': 0
  1112. }
  1113. real_back_coins = coins
  1114. back_coins = coins
  1115. else:
  1116. duration, elec = self.event_data['duration'], self.event_data['elec']
  1117. actual_time = duration + left
  1118. if (actual_time == 0) or (actual_time > merge_order_info['needValue'] * 60):
  1119. actual_time = merge_order_info['needValue'] * 60
  1120. real_back_coins = coins * (float(left) / float(actual_time))
  1121. consumeDict = {
  1122. 'reason': self.event_data['reason'],
  1123. 'leftTime': str(left),
  1124. 'chargeIndex': str(master_order.used_port),
  1125. 'actualNeedTime': u'动态功率计算为%s分钟' % actual_time,
  1126. 'duration': duration,
  1127. 'elec': elec,
  1128. 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
  1129. }
  1130. if master_order.paymentInfo['via'] == 'free':
  1131. back_coins = VirtualCoin(0)
  1132. else:
  1133. refundProtection = self.device.get('otherConf', {}).get('refundProtection', 0)
  1134. refundProtectionTime = self.device.get('otherConf', {}).get('refundProtectionTime', 5)
  1135. auto_refund = self.device.is_auto_refund
  1136. logger.debug('{} auto refund enable switch is {}. refund protect = {}, refund protect time = {}'.format(
  1137. repr(self.device), str(auto_refund), refundProtection, refundProtectionTime))
  1138. if auto_refund:
  1139. if (refundProtection == 1 and duration < refundProtectionTime):
  1140. back_coins = coins
  1141. else:
  1142. back_coins = real_back_coins
  1143. else:
  1144. back_coins = VirtualCoin(0)
  1145. if back_coins > coins:
  1146. back_coins = coins
  1147. logger.debug(
  1148. 'lefttime = {}, usedTime = {}, need time = {}, real back coins = {}, back coins = {}'.format(
  1149. left, duration, actual_time, real_back_coins, back_coins))
  1150. extra = []
  1151. if master_order.paymentInfo['via'] == 'free':
  1152. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(0))})
  1153. elif master_order.paymentInfo['via'] == 'virtualCard':
  1154. vCard = UserVirtualCard.objects(id = master_order.virtual_card_id).first() # type: UserVirtualCard
  1155. if not vCard:
  1156. logger.info('can not find the vCard id = {}'.format(master_order.virtual_card_id))
  1157. return
  1158. if back_coins > VirtualCoin(0):
  1159. success, consumeTotal, consumeDay = vCard.clear_frozen_quota(str(master_order.id), duration, 0.0,
  1160. back_coins.mongo_amount)
  1161. try:
  1162. if success and consumeDay['count'] > 0:
  1163. record = VCardConsumeRecord(
  1164. orderNo = VCardConsumeRecord.make_no(master_order.logicalCode),
  1165. openId = master_order.openId,
  1166. nickname = master_order.nickname,
  1167. cardId = str(vCard.id),
  1168. dealerId = vCard.dealerId,
  1169. devNo = master_order.devNo,
  1170. devTypeCode = self.device.devTypeCode,
  1171. devTypeName = self.device.devTypeName,
  1172. logicalCode = master_order.logicalCode,
  1173. groupId = master_order.groupId,
  1174. address = master_order.address,
  1175. groupNumber = master_order.groupNumber,
  1176. groupName = master_order.groupName,
  1177. attachParas = master_order.attachParas,
  1178. consumeData = consumeTotal,
  1179. consumeDayData = consumeDay
  1180. )
  1181. record.save()
  1182. except Exception, e:
  1183. logger.exception(e)
  1184. extra.append({u'虚拟卡号': vCard.cardNo})
  1185. elif master_order.paymentInfo['via'] in ['netPay', 'coins', 'cash', 'coin']:
  1186. user.clear_frozen_balance(str(master_order.id), master_order.paymentInfo['deduct'], back_coins,
  1187. (coins - back_coins))
  1188. for sub_order in sub_orders:
  1189. user.clear_frozen_balance(str(sub_order.id), sub_order.paymentInfo['deduct'], VirtualCoin(0),
  1190. VirtualCoin(0))
  1191. if back_coins > VirtualCoin(0):
  1192. consumeDict['refundedMoney'] = str(back_coins)
  1193. extra.append({u'消费金额': '{}(金币)'.format(coins - back_coins)})
  1194. extra.append({u'退款金额': '{}(金币)'.format(back_coins)})
  1195. else:
  1196. extra.append({u'消费金额': '{}(金币)'.format(coins)})
  1197. else:
  1198. logger.error('not net pay rather user virtual card pay. something is wrong.')
  1199. return
  1200. master_order.update_service_info(consumeDict)
  1201. auth_bridge = get_wechat_auth_bridge(source = self.device,
  1202. app_type = APP_TYPE.WECHAT_USER_MANAGER)
  1203. self.notify_user_service_complete(
  1204. service_name = u'充电',
  1205. openid = user.get_bound_pay_openid(auth_bridge.bound_openid_key),
  1206. port = str(master_order.used_port),
  1207. address = master_order.address,
  1208. reason = self.event_data.get('reasonDesc'),
  1209. finished_time = master_order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
  1210. extra = extra)
  1211. def do_elec_finished(self, master_order, sub_orders, merge_order_info):
  1212. # type: (ConsumeRecord, List[ConsumeRecord], dict)->None
  1213. """
  1214. 电川的板子 按电量退费
  1215. :return:
  1216. """
  1217. user = MyUser.objects(openId = master_order.openId,
  1218. groupId = self.device.groupId).first() # type: MyUser
  1219. if not user:
  1220. logger.error('not find user<openId={}, groupId={}>'.format(master_order.openId, self.device.groupId))
  1221. return
  1222. leftElec = self.event_data.get("left", 0) / 100.0
  1223. duration, elec = self.event_data['duration'], self.event_data['elec']
  1224. try:
  1225. consumeDict = {
  1226. "reason": self.event_data['reasonDesc'],
  1227. "chargeIndex": master_order.used_port,
  1228. }
  1229. # 获取组信息
  1230. group = Group.get_group(self.device.groupId) # type: GroupDict
  1231. # 扫码的结束
  1232. needElec = merge_order_info['needValue']
  1233. if leftElec == int("FFFF", 16):
  1234. # 端口故障
  1235. left = needElec
  1236. elif leftElec > needElec:
  1237. logger.error('left elec is bigger than need elec. something is wrong')
  1238. left = 0
  1239. spendElec = needElec - leftElec
  1240. coins = VirtualCoin(merge_order_info['coins'])
  1241. back_coins = VirtualCoin(0)
  1242. if master_order.paymentInfo['via'] != 'free':
  1243. auto_refund = self.device.is_auto_refund
  1244. if auto_refund:
  1245. back_coins = VirtualCoin(coins) * Ratio(leftElec / needElec)
  1246. logger.debug(
  1247. 'leftElec = {}, spendElec = {}, usedTime = {}, back coins = {}, auto refund = {}'.format(
  1248. left, spendElec, duration, back_coins, auto_refund))
  1249. else:
  1250. logger.debug(
  1251. 'leftElec = {}, spendElec = {}, usedTime = {}, back coins = {}, free = True'.format(
  1252. left, spendElec, duration, back_coins))
  1253. extra = []
  1254. if master_order.paymentInfo['via'] == 'free':
  1255. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(0))})
  1256. elif master_order.paymentInfo['via'] == 'virtualCard':
  1257. vCard = UserVirtualCard.objects(id = master_order.virtual_card_id).first()
  1258. if not vCard:
  1259. logger.info('can not find the vCard id = %s' % master_order.virtual_card_id)
  1260. return
  1261. extra.append({u'虚拟卡号': vCard.cardNo})
  1262. if back_coins > VirtualCoin(0):
  1263. success, consumeTotal, consumeDay = vCard.clear_frozen_quota(str(master_order.id),
  1264. needElec - spendElec,
  1265. spendElec, back_coins)
  1266. try:
  1267. if success and consumeDay['count'] > 0:
  1268. record = VCardConsumeRecord(
  1269. orderNo = VCardConsumeRecord.make_no(master_order.logicalCode),
  1270. openId = master_order.openId,
  1271. nickname = master_order.nickname,
  1272. cardId = str(vCard.id),
  1273. dealerId = vCard.dealerId,
  1274. devNo = master_order.devNo,
  1275. devTypeCode = master_order.devTypeCode,
  1276. devTypeName = master_order.dev_type_name,
  1277. logicalCode = master_order.logicalCode,
  1278. groupId = master_order.groupId,
  1279. address = master_order.address,
  1280. groupNumber = master_order.groupNumber,
  1281. groupName = master_order.groupName,
  1282. attachParas = master_order.attachParas,
  1283. consumeData = consumeTotal,
  1284. consumeDayData = consumeDay
  1285. )
  1286. record.save()
  1287. except Exception, e:
  1288. logger.exception(e)
  1289. elif master_order.paymentInfo['via'] in ['netPay', 'coins', 'cash', 'coin']:
  1290. user.clear_frozen_balance(str(master_order.id), master_order.paymentInfo['deduct'], back_coins,
  1291. (coins - back_coins))
  1292. for sub_order in sub_orders:
  1293. user.clear_frozen_balance(str(sub_order.id), sub_order.paymentInfo['deduct'], VirtualCoin(0),
  1294. VirtualCoin(0))
  1295. if back_coins > VirtualCoin(0):
  1296. consumeDict.update({"refundedMoney": str(back_coins)})
  1297. extra.append({u'消费金额': '{}(金币)'.format(coins - back_coins)})
  1298. extra.append({u'退款金额': '{}(金币)'.format(back_coins)})
  1299. else:
  1300. extra.append({u'消费金额': '{}(金币)'.format(coins)})
  1301. else:
  1302. logger.error('not net pay rather user virtual card pay. something is wrong.')
  1303. return
  1304. for order in [master_order].extend(sub_orders):
  1305. if order.orderNo == master_order.orderNo:
  1306. consumeDict.update({
  1307. "duration": self.event_data['duration']
  1308. })
  1309. order.update_service_info(consumeDict)
  1310. auth_bridge = get_wechat_auth_bridge(source = self.device,
  1311. app_type = APP_TYPE.WECHAT_USER_MANAGER)
  1312. self.notify_user_service_complete(
  1313. service_name = u'充电',
  1314. openid = user.get_bound_pay_openid(auth_bridge.bound_openid_key),
  1315. port = str(master_order.used_port),
  1316. address = master_order.address,
  1317. reason = self.event_data.get('reasonDesc'),
  1318. finished_time = master_order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
  1319. extra = extra)
  1320. except Exception as e:
  1321. logger.exception(e)
  1322. def do_finished_event(self, master_order, sub_orders, merge_order_info):
  1323. # type: (ConsumeRecord, List[ConsumeRecord], dict)->None
  1324. billing_type = merge_order_info['billingType']
  1325. if billing_type == 'time':
  1326. self.do_time_finished(master_order, sub_orders, merge_order_info)
  1327. else:
  1328. self.do_elec_finished(master_order, sub_orders, merge_order_info)
  1329. class MyIcStartAckEvent(IcStartAckEvent):
  1330. def __init__(self, smartBox, event_data):
  1331. super(MyIcStartAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
  1332. def post_after_start(self, order = None):
  1333. port = order.used_port
  1334. YuhuanNorther.send_dev_status(self.device, int(port), 1)
  1335. def post_after_finish(self, order = None):
  1336. port = order.used_port
  1337. if self.event_data['reason'] < 0:
  1338. logger.debug('reason<{}> is not to report.'.format(self.event_data['reason']))
  1339. return
  1340. notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
  1341. desc = self.event_data.get('reasonDesc', ''))
  1342. send_event_to_zhejiang(self.dealer, self.device, self.event_data)
  1343. if self.event_data['reason'] == '04':
  1344. YuhuanNorther.send_dev_event(self.device, '97', port)
  1345. YuhuanNorther.send_dev_event(self.device, '98', port)
  1346. # 发送一条端口使用结束的告警
  1347. YuhuanNorther.send_dev_status(self.device, port, 2)
  1348. def merge_order(self, master_order, sub_orders):
  1349. # type:(ConsumeRecord, list)->dict
  1350. consumeMode = self.device.get("otherConf", dict()).get("consumeMode", 0)
  1351. # 按时间计费 线下免费模式
  1352. if consumeMode == 0 or consumeMode == 2:
  1353. billingType = 'time'
  1354. else:
  1355. billingType = 'elec'
  1356. start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
  1357. portDict = {
  1358. 'billingType': billingType
  1359. }
  1360. if master_order.paymentInfo['via'] == 'virtualCard':
  1361. portDict.update({
  1362. 'vCardId': master_order.paymentInfo['itemId']
  1363. })
  1364. all_coins = master_order.coin
  1365. all_money = master_order.money
  1366. for sub_order in sub_orders:
  1367. all_coins += master_order.coin
  1368. all_money += master_order.money
  1369. portDict['coins'] = str(all_coins)
  1370. portDict['money'] = str(all_money)
  1371. portDict['estimatedTs'] = int(start_time.timestamp + 12 * 60 * 60)
  1372. return portDict
  1373. def do_time_finished(self, card, order, merge_order_info):
  1374. # type: (Card, ConsumeRecord, dict)->(dict)
  1375. duration, elec = self.event_data['duration'], self.event_data['elec']
  1376. coins = VirtualCoin(merge_order_info['coins'])
  1377. left = self.event_data['left']
  1378. consumeDict = {
  1379. 'reason': self.event_data['reason'],
  1380. 'chargeIndex': str(order.used_port),
  1381. 'duration': duration,
  1382. 'elec': elec,
  1383. 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
  1384. }
  1385. # backMoney = VirtualCoin(self.event_data['backMoney'])
  1386. group = self.device.group # type: GroupDict
  1387. extra = [{
  1388. u'实体卡号': self.event_data['cardNo']
  1389. }]
  1390. consumeDict.update({'balance': str(card.balance)})
  1391. order.update_service_info(consumeDict)
  1392. self.notify_user_service_complete(
  1393. service_name = u'充电',
  1394. openid = card.managerialOpenId if card else '',
  1395. port = order.used_port,
  1396. address = group.address,
  1397. reason = self.event_data['reason'],
  1398. finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
  1399. extra = extra)
  1400. def do_elec_finished(self, card, order, merge_order_info):
  1401. # type:(Card, ConsumeRecord, dict)->None
  1402. """
  1403. 电川的板子 按电量退费
  1404. :return:
  1405. """
  1406. leftElec = self.event_data.get('left', 0) / 100.0
  1407. duration, elec = self.event_data['duration'], self.event_data['elec']
  1408. try:
  1409. consumeDict = {
  1410. 'reason': self.event_data['reasonDesc'],
  1411. 'chargeIndex': order.used_port,
  1412. 'duration': duration,
  1413. 'elec': elec,
  1414. 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
  1415. }
  1416. # backMoney = self.event_data.get("backMoney")
  1417. extra = [{u'实体卡号': self.event_data['cardNo']}]
  1418. # if self.event_data['cardType'] == 'ID':
  1419. # if backMoney > 0:
  1420. # self.refund_money_for_card(RMB(backMoney), card.id)
  1421. # extra.append({
  1422. # u'退款金额': u'{}(金币)'.format(backMoney)
  1423. # })
  1424. #
  1425. # consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
  1426. # else:
  1427. consumeDict.update({'balance': str(card.balance)})
  1428. order.update_service_info(consumeDict)
  1429. self.notify_user_service_complete(
  1430. service_name = u'充电',
  1431. openid = self.get_managerialOpenId_by_openId(order.openId),
  1432. port = order.used_port,
  1433. address = self.device.group.address,
  1434. reason = self.event_data['reason'],
  1435. finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
  1436. extra = extra)
  1437. except Exception as e:
  1438. logger.exception(e)
  1439. def do_finished_event(self, card, order, merge_order_info):
  1440. # type:(Card, ConsumeRecord, dict)->None
  1441. if 'backMoney' in self.event_data and self.event_data['backMoney'] > RMB(0):
  1442. refund_order = RechargeRecord.objects(orderNo = self.event_data['order_id']).first()
  1443. if not refund_order:
  1444. self.refund_money_for_card(RMB(self.event_data['backMoney']), card.id, self.event_data['order_id'])
  1445. billing_type = merge_order_info['billingType']
  1446. if billing_type == 'time':
  1447. self.do_time_finished(card, order, merge_order_info)
  1448. else:
  1449. self.do_elec_finished(card, order, merge_order_info)
  1450. class MyIcRechargeAckEvent(IcRechargeAckEvent):
  1451. def __init__(self, smartBox, event_data):
  1452. super(MyIcRechargeAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
  1453. class MyCardRefundAckEvent(CardRefundAckEvent):
  1454. def __init__(self, smartBox, event_data):
  1455. super(MyCardRefundAckEvent, self).__init__(smartBox, event_data, CardRefundAckEventPreProcessor())