dianchuan_ronghe.py 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import random
  6. import time
  7. from typing import TYPE_CHECKING
  8. from apilib.monetary import sum_rmb, RMB, VirtualCoin, Ratio
  9. from apilib.utils_datetime import to_datetime
  10. from apps.web.common.models import District
  11. from apps.web.constant import Const, FAULT_CODE, FAULT_LEVEL, DEALER_CONSUMPTION_AGG_KIND
  12. from apps.web.core.accounting import Accounting
  13. from apps.web.core.helpers import ActionDeviceBuilder
  14. from apps.web.dealer.models import Dealer
  15. from apps.web.device.models import PortReport, Part, Group, Device
  16. from apps.web.device.timescale import FluentedEngine
  17. from apps.web.eventer import EventBuilder
  18. from apps.web.eventer.base import FaultEvent, WorkEvent
  19. from apps.web.south_intf.delixi import DelixiNorther
  20. from apps.web.south_intf.liangxi_fire import LiangXiXiaoFang
  21. from apps.web.south_intf.platform import notify_event_to_north, notify_event_to_north_v2, \
  22. handle_and_notify_event_to_north_Dc
  23. from apps.web.south_intf.yuhuan_fire import YuhuanNorther
  24. from apps.web.south_intf.zhejiang_fire import send_event_to_zhejiang
  25. from apps.web.user.models import VCardConsumeRecord, ServiceProgress, UserVirtualCard, CardRechargeOrder, MyUser, \
  26. Redpack, RechargeRecord
  27. from apps.web.user.models import Card
  28. from apps.web.core.adapter.base import fill_2_hexByte
  29. if TYPE_CHECKING:
  30. from apps.web.device.models import GroupDict
  31. logger = logging.getLogger(__name__)
  32. class builder(EventBuilder):
  33. def __getEvent__(self, device_event):
  34. if 'data' not in device_event:
  35. return None
  36. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  37. if event_data is None or 'cmdCode' not in event_data:
  38. return None
  39. if event_data['cmdCode'] == 'C0':
  40. if event_data['FaultCode'] in [3,4]:
  41. return ZHIXIA2FaultEvent(self.deviceAdapter, event_data)
  42. else:
  43. return ZHIXIA2InductorEvent(self.deviceAdapter, event_data)
  44. return ChargingZHIXIA2WorkEvent(self.deviceAdapter, event_data)
  45. class ChargingZHIXIA2WorkEvent(WorkEvent):
  46. def do(self, **args):
  47. logger.info('dianchuan delixi charging event detected, devNo=%s,info=%s' % (self.device.devNo, self.event_data))
  48. cmdCode = self.event_data['cmdCode']
  49. devNo = self.device.devNo
  50. data = self.event_data
  51. if cmdCode == 'A0': # 向平台上传主板模块版本
  52. try:
  53. Device.get_collection().update({'devNo':devNo},{'$set':{'boardNo':data['boardNo'],
  54. 'hardVersion':data['hardVersion'],
  55. 'softId':data['softId'],
  56. 'softVersion':data['softVersion']}})
  57. devObj = Device.objects.get(devNo = devNo)
  58. otherConf = devObj.otherConf
  59. if 'cardFeeMode' not in otherConf:
  60. otherConf['cardFeeMode'] = 'time'
  61. if 'cardFeeValue' not in otherConf:
  62. otherConf['cardFeeValue'] = 180
  63. if 'runMode' not in otherConf:
  64. otherConf['runMode'] = 1
  65. if 'voice' not in otherConf:
  66. otherConf['voice'] = 4
  67. if 'coinTime' not in otherConf:
  68. otherConf['coinTime'] = 180
  69. if 'cardTime' not in otherConf:
  70. otherConf['cardTime'] = 180
  71. if 'icMoney' not in otherConf:
  72. otherConf['icMoney'] = 10
  73. if 'cardRefund' not in otherConf:
  74. otherConf['cardRefund'] = 1
  75. if 'power1' not in otherConf:
  76. otherConf['power1'] = 3000
  77. if 'power2' not in otherConf:
  78. otherConf['power2'] = 4000
  79. if 'power3' not in otherConf:
  80. otherConf['power3'] = 5000
  81. if 'power4' not in otherConf:
  82. otherConf['power4'] = 6000
  83. if 'power5' not in otherConf:
  84. otherConf['power5'] = 7000
  85. if 'power1ratio' not in otherConf:
  86. otherConf['power1ratio'] = 100
  87. if 'power2ratio' not in otherConf:
  88. otherConf['power2ratio'] = 90
  89. if 'power3ratio' not in otherConf:
  90. otherConf['power3ratio'] = 80
  91. if 'power4ratio' not in otherConf:
  92. otherConf['power4ratio'] = 70
  93. if 'power5ratio' not in otherConf:
  94. otherConf['power5ratio'] = 60
  95. if 'autoStop' not in otherConf:
  96. otherConf['autoStop'] = 1
  97. if 'fuchongPower' not in otherConf:
  98. otherConf['fuchongPower'] = 300
  99. if 'fuchongTime' not in otherConf:
  100. otherConf['fuchongTime'] = 7200
  101. if 'noPowerTime' not in otherConf:
  102. otherConf['noPowerTime'] = 60
  103. if 'password' not in otherConf:
  104. otherConf['password'] = 8888
  105. if 'temperature' not in otherConf:
  106. otherConf['temperature'] = 256 #FF 默认关闭
  107. devObj.otherConf = otherConf
  108. devObj.save()
  109. self.deviceAdapter.reply_A0()
  110. except Exception,e:
  111. logger.error('update device info error,e=%s' % e)
  112. elif cmdCode == 'A8':
  113. try:
  114. self.deviceAdapter.reply_A8()
  115. except Exception,e:
  116. logger.error('reply A8 error=%s' % e)
  117. elif cmdCode == 'B1':
  118. if not data['portDict']:
  119. return
  120. for port,power in data['portDict'].items():
  121. logger.info("insert power data into database")
  122. FluentedEngine().in_power_udp(devNo=devNo,port=str(port),ts=int(time.time()),power=power,voltage=None,current=None)
  123. elif cmdCode == 'B4': # 本地离线卡、投币启动充电
  124. # if data['consumeType'] == 0: #投币
  125. # Accounting.recordOfflineCoin(device=self.device,
  126. # report_ts=int(time.time()),
  127. # coins=int(data['chargedMoney']),
  128. # mode='uart',
  129. # port=data['port'])
  130. # elif data['consumeType'] == 1: #离线卡,现在不处理。离线卡不支持充值,也不支持离线卡的余额获取
  131. # pass
  132. try:
  133. self.deviceAdapter.reply_B4(data['port'])
  134. except Exception,e:
  135. logger.error('reply B4 error=%s' % e)
  136. elif cmdCode == 'B6': # 本地刷在线卡
  137. cardNo = data['cardNo']
  138. consumeMoneyValue = data['money']/10.0
  139. card = self.update_card_dealer_and_type(cardNo)
  140. # 首先检查订单,并进行充值
  141. # 不存在卡的情况下 直接不回复
  142. if not card or not card.openId or card.frozen:
  143. return
  144. # 有绑定的卡 并且卡没被冻结的情况下
  145. # 刷新卡的金额
  146. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  147. result = self.recharge_id_card(card=card, rechargeType='append', order=card_recharge_order)
  148. card.reload()
  149. logger.info('cardNo=%s,openId=%s,result=%s,consumeMoneyValue=%s,info=%s' % (
  150. cardNo, card.openId, result, consumeMoneyValue, self.event_data))
  151. #回复,并启动充电
  152. orderNo = self.deviceAdapter.make_dianchuan_order_no(devNo,data['port'])
  153. data = fill_2_hexByte(hex(data['port']))
  154. data += orderNo[16::]
  155. otherConf = Device.objects.get(devNo = devNo).otherConf
  156. consumeType = otherConf.get('cardFeeMode','time')
  157. value = otherConf.get('cardFeeValue',180)
  158. if consumeType == 'time':
  159. data += '0003'
  160. needValue = value*consumeMoneyValue
  161. data += fill_2_hexByte(hex(int(needValue)),2)
  162. else: # 电量的单位需要乘1000
  163. data += '0103'
  164. needValue = value*consumeMoneyValue*1000
  165. data += fill_2_hexByte(hex(int(needValue)),2)
  166. data += data['cardNoStr']
  167. balanceJiao = 0 if not card else int(card.balance.mongo_amount * 10)
  168. data += fill_2_hexByte(hex(balanceJiao),4)
  169. try:
  170. logger.info("card is <{}> balance is <{}> response res is <{}>".format(cardNo, card.balance.mongo_amount, data))
  171. devInfo = self.deviceAdapter.remote_start_charge(data['port'], data)
  172. except Exception, e:
  173. logger.info('resp back error=%s' % e)
  174. return
  175. # 服务器就需要正式扣掉钱
  176. fee = RMB(consumeMoneyValue)
  177. virtual_card = card.bound_virtual_card
  178. if virtual_card is not None:
  179. group = Group.get_group(self.device['groupId'])
  180. VCardConsumeRecord(
  181. orderNo=orderNo,
  182. openId=card.openId,
  183. cardId=str(virtual_card.id),
  184. dealerId=card.dealerId,
  185. devNo=self.device.devNo,
  186. devTypeCode = self.device.devTypeCode,
  187. devTypeName = self.device.devTypeName,
  188. logicalCode=self.device['logicalCode'],
  189. groupId=group['groupId'],
  190. address=group['address'],
  191. groupNumber=self.device['groupNumber'],
  192. groupName=group['groupName'],
  193. ).save()
  194. else:
  195. self.consume_money_for_card(card, fee)
  196. # 记录卡消费记录以及消费记录
  197. servicedInfo = {
  198. 'orderNo': orderNo,
  199. 'money': self.event_data['fee'],
  200. 'coin': self.event_data['fee'],
  201. 'needValue': needValue,
  202. 'consumeTypeFromDev':consumeType,
  203. 'chargeIndex':data['port']
  204. }
  205. orderNo, cardOrderNo = self.record_consume_for_card(card, fee,'',servicedInfo)
  206. # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
  207. servicedInfo.update({'cardOrderNo': cardOrderNo})
  208. ServiceProgress.register_card_service(
  209. self.device, data['port'], card,
  210. servicedInfo
  211. )
  212. # 通知微信,已经扣费
  213. self.notify_balance_has_consume_for_card(card, fee)
  214. # 更新端口状态
  215. queryDict = {'device_imei': devNo,'port': data['port'], 'isFinished': False,'cardId': str(card.id), 'start_time': {'$gte': int(time.time()) - 3600}}
  216. rcds = ServiceProgress.get_collection().find(queryDict, {'consumeOrder': 1},sort=[('start_time', -1)])
  217. allCoins = sum_rmb([rcd['consumeOrder']['coin'] for rcd in rcds])
  218. newValue = {'cardId': str(card.id),'openId': card.openId,'coins': str(allCoins)}
  219. Device.update_port_control_cache(self.device.devNo, newValue)
  220. elif cmdCode == 'BB': # 上传结算订单
  221. port = str(data['port'])
  222. # 收到报文后,先回复报文给设备
  223. self.deviceAdapter.reply_BB(data['port'])
  224. try:
  225. # 这个lineInfo 就是缓存全部的信息
  226. lineInfo = Device.clear_port_control_cache(devNo, port)
  227. if not lineInfo:
  228. logger.debug('get null control cache from {}'.format(repr(self.device)))
  229. return
  230. logger.debug('port<{}> cache is: {}'.format(port, str(lineInfo)))
  231. # 投币只记录下充了多少钱、IC卡的不处理
  232. if data['consumeType'] == 0:
  233. Accounting.recordOfflineCoin(device=self.device,
  234. report_ts=int(time.time()),
  235. coins=int(data['chargedMoney']),
  236. mode='uart',
  237. port=data['port'])
  238. return
  239. elif data['consumeType'] in [1,4]:# 离线IC卡,按键启动
  240. return
  241. if lineInfo.get('isApi', False) is True:
  242. self.event_data.update({'deviceCode': self.device['logicalCode']})
  243. return handle_and_notify_event_to_north_Dc(self.device["devNo"], self.event_data)
  244. # 红包退费的判断处理
  245. if 'redpackInfo' in lineInfo:
  246. for _info in lineInfo['redpackInfo']:
  247. redpack = Redpack.get_one(_info['redpackId'])
  248. redpackCoins = VirtualCoin(redpack['redpackCoins'])
  249. lineInfo['coins'] = float(VirtualCoin(lineInfo['coins']) - redpackCoins)
  250. redpackMoney = RMB(redpack['redpackMoney'])
  251. lineInfo['price'] = float(RMB(lineInfo['price']) - redpackMoney)
  252. logger.debug(
  253. 'redpack is <{}> redpack money is: {}; redpack coins is: {}'.format(redpack.get('id'),
  254. str(redpackMoney.amount),
  255. str(redpackCoins.amount)))
  256. if data['chargeType'] == 1: # 电量
  257. return self.do_elec_finish(devNo, port, lineInfo, data)
  258. else:
  259. return self.do_time_finish(devNo, port, lineInfo, data)
  260. finally:
  261. notify_event_to_north_v2(self.device["devNo"], data)
  262. notify_event_to_north(self.dealer, self.device, level=Const.EVENT_NORMAL,desc=data['reason'])
  263. send_event_to_zhejiang(self.dealer, self.device, data)
  264. if self.event_data['reasonCode'] == '04': # 功率过载导致的断电,一条告警,一条恢复告警
  265. YuhuanNorther.send_dev_event(self.device, '97', port)
  266. YuhuanNorther.send_dev_event(self.device, '98', port)
  267. elif cmdCode == 'C2':
  268. pass
  269. elif cmdCode == 'C7':
  270. self.deviceAdapter.reply_C7()
  271. def do_elec_finish(self, devNo, port, lineInfo, msgDict):
  272. """
  273. 电川的板子 按电量退费
  274. :return:
  275. """
  276. logger.info("[{} do_elec_finish] devNo = {}, port = {}, lineInfo = {}, msgDict = {}, event = {}".format(
  277. self.__class__.__name__, devNo, port, lineInfo, msgDict, self.event_data))
  278. if not self.dealer:
  279. logger.error(
  280. "[{} do_elec_finish] dealer {} is not found!".format(self.__class__.__name__, self.device.ownerId))
  281. return
  282. # 提取事件信息
  283. leftElec = msgDict.get("leftElec", 0) / 100.0
  284. reasonStr = msgDict.get("reason",'')
  285. cardNo = msgDict.get("cardNo", None)
  286. usedTime = msgDict.get('duration') / 60.0 # 转成分钟
  287. price = RMB(lineInfo.get('price', 0))
  288. recvTime = to_datetime(self.recvTime)
  289. try:
  290. consumeDict = {"reason": reasonStr,"chargeIndex": port,'duration':usedTime,"uartData": msgDict.get('uartData', ''),
  291. 'port':msgDict['port'],'elec':msgDict['elec'],'orderNo':msgDict['orderNo'],'startTime':msgDict['startTime'],'endTime':msgDict['endTime'],
  292. 'chargeType':'elec','consumeTypeFromDev':msgDict['consumeType'],'leftElec':msgDict['leftElec'],'elec':msgDict['elec'],'reasonCode':msgDict['reasonCode'],
  293. }
  294. # 计算充电的时间
  295. refundProtectionTime = self.device.get_other_conf_item('refundProtectionTime', 3)
  296. # 获取组信息
  297. group = Group.get_group(self.device["groupId"])
  298. coins = VirtualCoin(lineInfo.get("coins"))
  299. needElec = lineInfo.get("needElec")
  300. refundCoins = VirtualCoin(0)
  301. refundedMoney = RMB(0)
  302. if leftElec == int("FFFF", 16):
  303. refundCoins = VirtualCoin(coins)
  304. refundedMoney = RMB(price)
  305. leftElec = needElec
  306. spendElec = 0
  307. else:
  308. if usedTime < refundProtectionTime:
  309. refundCoins = VirtualCoin(coins)
  310. refundedMoney = RMB(price)
  311. spendElec = 0
  312. else:
  313. if leftElec > needElec:
  314. logger.error('left elec is bigger than need elec. something is wrong')
  315. leftElec = 0
  316. spendElec = needElec - leftElec
  317. refundSwitch = self.device.is_auto_refund
  318. if refundSwitch:
  319. refundCoins = VirtualCoin(coins) * Ratio(leftElec / needElec)
  320. refundedMoney = RMB(price) * Ratio(leftElec / needElec)
  321. logger.debug('left elec = {}, duration = {}, need elec = {}, back coins = {}, refund cash = {}'.format(
  322. leftElec, usedTime, needElec, refundCoins, refundedMoney))
  323. # 扫码的结束
  324. if msgDict['consumeType'] == 2:
  325. if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']:
  326. # 虚拟卡的结束
  327. consumeRcdId = lineInfo['consumeRcdId']
  328. vCardId = lineInfo.get("vCardId", "")
  329. vCard = UserVirtualCard.objects(id=vCardId).first()
  330. if not vCard:
  331. logger.info('can not find the vCard id = %s' % vCardId)
  332. return
  333. try:
  334. ServiceProgress.update_progress_and_consume_rcd(
  335. self.device.ownerId,
  336. {
  337. 'open_id': lineInfo['openId'],
  338. 'port': int(port),
  339. 'device_imei': self.device.devNo,
  340. 'isFinished':False
  341. },
  342. consumeDict
  343. )
  344. if refundCoins > VirtualCoin(0):
  345. vCardConsumeRcd = VCardConsumeRecord.objects.get(id=consumeRcdId)
  346. vCard.refund_quota(vCardConsumeRcd, needElec - spendElec, spendElec,
  347. refundCoins.mongo_amount)
  348. finally:
  349. user = MyUser.objects(openId=lineInfo['openId'],
  350. groupId=self.device.groupId).first()
  351. self.notify_user_service_complete(
  352. service_name=u'充电',
  353. openid=user.managerialOpenId if user else '',
  354. port=port,
  355. address=group['address'],
  356. reason=self.event_data['reason'],
  357. finished_time=recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  358. extra=[
  359. {u'虚拟卡号': vCard.cardNo}
  360. ]
  361. )
  362. elif 'openId' in lineInfo and lineInfo['openId']:
  363. # 扫码使用金币启动
  364. user = MyUser.objects(openId=lineInfo['openId'],
  365. groupId=self.device.groupId).first()
  366. try:
  367. is_cash = False
  368. if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
  369. is_cash = True
  370. consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
  371. if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
  372. consumeDict.update(
  373. {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
  374. self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
  375. if self.device.bill_as_service_feature.on:
  376. serviceFee = round(spendElec * float(self.device.bill_as_service_feature.service_charge),2)
  377. elecFee = round(spendElec * float(self.device.bill_as_service_feature.elec_charge),2)
  378. consumeDict.update({"elec": spendElec, "elecFee": elecFee,"serviceFee":serviceFee})
  379. ServiceProgress.update_progress_and_consume_rcd(
  380. self.device.ownerId,
  381. {
  382. 'open_id': lineInfo['openId'],
  383. 'port': int(port),
  384. 'device_imei': self.device.devNo,
  385. 'isFinished':False
  386. },
  387. consumeDict)
  388. finally:
  389. extra = []
  390. if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
  391. real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
  392. if real_refund > RMB(0):
  393. extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
  394. extra.append({u'退款金额': '{}(元)'.format(real_refund)})
  395. else:
  396. extra.append({u'消费金额': '{}(元)'.format(price)})
  397. if self.device.bill_as_service_feature.on:
  398. elecCharge = round(spendElec * float(self.device.bill_as_service_feature.elec_charge),2)
  399. serviceCharge = round(spendElec * float(self.device.bill_as_service_feature.service_charge),2)
  400. extra.append({u'服务费金额': '{}(元)'.format(serviceCharge)})
  401. extra.append({u'电费金额': '{}(元)'.format(elecCharge)})
  402. elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
  403. real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
  404. if real_refund > VirtualCoin(0):
  405. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
  406. extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
  407. else:
  408. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  409. if self.device.bill_as_service_feature.on:
  410. elecCharge = round(spendElec * float(self.device.bill_as_service_feature.elec_charge),2)
  411. serviceCharge = round(spendElec * float(self.device.bill_as_service_feature.service_charge),2)
  412. extra.append({u'服务费金额': '{}(金币)'.format(serviceCharge)})
  413. extra.append({u'电费金额': '{}(金币)'.format(elecCharge)})
  414. else:
  415. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  416. if self.device.bill_as_service_feature.on:
  417. elecCharge = spendElec * float(self.device.bill_as_service_feature.elec_charge)
  418. serviceCharge = spendElec * float(self.device.bill_as_service_feature.service_charge)
  419. extra.append({u'服务费金额': '{}(金币)'.format(serviceCharge)})
  420. extra.append({u'电费金额': '{}(金币)'.format(elecCharge)})
  421. self.notify_user_service_complete(
  422. service_name=u'充电',
  423. openid=user.managerialOpenId if user else '',
  424. port=port,
  425. address=group['address'],
  426. reason=self.event_data['reason'],
  427. finished_time=recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  428. extra=extra)
  429. else:
  430. logger.error('not net pay rather user virtual card pay. something is wrong.')
  431. else:
  432. backMoney = refundedMoney
  433. # 刷卡的结束 如果没有开启刷卡退费 则结束上报过来的backMoney = 0
  434. # ID卡结束 直接退费就行了
  435. card = self.update_card_dealer_and_type(cardNo, "ID")
  436. if self.device.bill_as_service_feature.on:
  437. total = self.device.otherConf.get('totalCharge')
  438. backMoney = round(leftElec * total,2)
  439. needCoins = float(lineInfo.get('coins'))
  440. usedMoney = needCoins - backMoney
  441. elec = round(usedMoney / total,2)
  442. elecFee = round(elec * float(self.device.bill_as_service_feature.elec_charge),2)
  443. serviceFee = round(elec * float(self.device.bill_as_service_feature.service_charge),2)
  444. consumeDict.update(
  445. {"elec": elec, "elecFee": elecFee, "serviceFee": serviceFee})
  446. if backMoney > 0:
  447. self.refund_money_for_card(RMB(backMoney), str(card.id))
  448. consumeDict.update({
  449. DEALER_CONSUMPTION_AGG_KIND.REFUND_CARD: VirtualCoin(backMoney).mongo_amount
  450. })
  451. consumeDict.update({'balance': str(card.balance + VirtualCoin(backMoney))})
  452. ServiceProgress.update_progress_and_consume_rcd(
  453. self.device.ownerId,
  454. {
  455. 'open_id': lineInfo['openId'],
  456. 'port': int(port),
  457. 'device_imei': self.device.devNo,
  458. 'isFinished':False
  459. },
  460. consumeDict
  461. )
  462. extra = [{u'实体卡号': cardNo}]
  463. if backMoney > 0:
  464. extra.append({
  465. u'退款金额': u'{}(金币)'.format(backMoney)
  466. })
  467. if self.device.bill_as_service_feature.on:
  468. extra.append({
  469. u'消费电量':u'{}(度)'.format(elec),
  470. u'电费金额': u'{}(金币)'.format(elecFee),
  471. u'服务费金额': u'{}(金币)'.format(serviceFee),
  472. })
  473. self.notify_user_service_complete(
  474. service_name=u'充电',
  475. openid=self.get_managerialOpenId_by_openId(lineInfo['openId']),
  476. port=port,
  477. address=group['address'],
  478. reason=self.event_data['reason'],
  479. finished_time=recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  480. extra=extra
  481. )
  482. except Exception as e:
  483. logger.exception(e)
  484. def do_time_finish(self, devNo, port, lineInfo, msgDict):
  485. logger.info("[{} do_time_finish] devNo = {}, port = {}, lineInfo = {}, msgDict = {}, event = {}".format(
  486. self.__class__.__name__, devNo, port, lineInfo, msgDict, self.event_data))
  487. try:
  488. if not self.dealer:
  489. logger.error(
  490. "[{} do_time_finish] dealer {} is not found!".format(self.__class__.__name__, self.device.ownerId))
  491. return
  492. # 提取事件信息
  493. leftTime = msgDict.get("leftTime", 0)
  494. reasonStr = msgDict.get("reason",'')
  495. cardNo = msgDict.get("cardNo", None)
  496. usedTime = round(msgDict.get('duration') / 60.0, 2) # 转成分钟
  497. price = RMB(lineInfo.get('price', 0))
  498. recvTime = to_datetime(self.recvTime)
  499. refundProtectionTime = self.device.get_other_conf_item('refundProtectionTime', 5)
  500. if leftTime == 65535: # 设备返回65535说明端口没有启动
  501. actualNeedTime = 0
  502. else:
  503. actualNeedTime = usedTime + leftTime
  504. if usedTime < refundProtectionTime:
  505. # 通过使用的时间来判断是否可以进行保险的退款
  506. rechargeIds = list()
  507. payInfo = lineInfo.get('payInfo', list())
  508. for item in payInfo:
  509. if 'rechargeRcdId' not in item:
  510. continue
  511. rechargeIds.append(item['rechargeRcdId'])
  512. group = self.device.group # type: GroupDict
  513. consumeDict = {"reason": reasonStr,"chargeIndex": port,'duration':usedTime,"uartData": msgDict.get('uartData', ''),
  514. 'port':msgDict['port'],'elec':msgDict['elec'],'orderNo':msgDict['orderNo'],'startTime':msgDict['startTime'],'endTime':msgDict['endTime'],
  515. 'chargeType':'elec','consumeTypeFromDev':msgDict['consumeType'],'leftElec':msgDict['leftElec'],'elec':msgDict['elec'],'reasonCode':msgDict['reasonCode'],
  516. 'leftTime':round(msgDict['leftTime']/60.0,2)
  517. }
  518. coins = VirtualCoin(lineInfo['coins'])
  519. refundCoins = VirtualCoin(0)
  520. refundedMoney = RMB(0)
  521. if leftTime == 65535 or (usedTime < refundProtectionTime):
  522. refundCoins = coins
  523. refundedMoney = RMB(price)
  524. elif self.device.is_auto_refund:
  525. refundCoins = coins * (float(leftTime) / float(actualNeedTime))
  526. refundedMoney = RMB(price * (float(leftTime) / float(actualNeedTime)))
  527. if refundCoins > coins:
  528. refundCoins = coins
  529. if refundedMoney > RMB(price):
  530. refundedMoney = RMB(price)
  531. logger.debug('left time = {}, duration = {}, need time = {}, back coins = {}'.format(
  532. leftTime, usedTime, actualNeedTime, refundCoins))
  533. # 涉及到卡的退费 不要以缓存为准 以设备上报的为准
  534. if msgDict['consumeType'] == 2:
  535. if 'coins' not in lineInfo:
  536. logger.warning('has no coins fields in lineInfo. may be coins start.')
  537. return
  538. if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']: # 虚拟卡
  539. vCardId = lineInfo['vCardId']
  540. vCard = UserVirtualCard.objects(id=vCardId).first() # type: UserVirtualCard
  541. if not vCard:
  542. logger.info('can not find the vCard id = %s' % vCardId)
  543. return
  544. try:
  545. ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
  546. {
  547. 'open_id': lineInfo['openId'],
  548. 'port': int(port),
  549. 'device_imei': self.device.devNo,
  550. 'isFinished':False
  551. }, consumeDict)
  552. if refundCoins > VirtualCoin(0):
  553. vCardConsumeRcd = VCardConsumeRecord.objects.get(id=lineInfo['consumeRcdId'])
  554. vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, refundCoins.mongo_amount)
  555. finally:
  556. user = MyUser.objects(openId=lineInfo['openId'],
  557. groupId=self.device.groupId).first()
  558. self.notify_user_service_complete(
  559. service_name=u'充电',
  560. openid=user.managerialOpenId if user else '',
  561. port=port,
  562. address=group['address'],
  563. reason=self.event_data['reason'],
  564. finished_time=recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  565. extra=[
  566. {u'虚拟卡号': vCard.cardNo}
  567. ]
  568. )
  569. elif 'openId' in lineInfo and lineInfo['openId']:
  570. user = MyUser.objects(openId=lineInfo['openId'],
  571. groupId=self.device.groupId).first()
  572. try:
  573. is_cash = False
  574. if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
  575. is_cash = True
  576. consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
  577. if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
  578. consumeDict.update(
  579. {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
  580. self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
  581. ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
  582. {
  583. 'open_id': lineInfo['openId'],
  584. 'port': int(port),
  585. 'device_imei': self.device.devNo,
  586. 'isFinished':False
  587. }, consumeDict)
  588. finally:
  589. extra = []
  590. if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
  591. real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
  592. if real_refund > RMB(0):
  593. extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
  594. extra.append({u'退款金额': '{}(元)'.format(real_refund)})
  595. else:
  596. extra.append({u'消费金额': '{}(元)'.format(price)})
  597. elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
  598. real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
  599. if real_refund > VirtualCoin(0):
  600. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
  601. extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
  602. else:
  603. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  604. else:
  605. extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
  606. self.notify_user_service_complete(
  607. service_name=u'充电',
  608. openid=user.managerialOpenId if user else '',
  609. port=port,
  610. address=group['address'],
  611. reason=self.event_data['reason'],
  612. finished_time=recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  613. extra=extra)
  614. elif msgDict['consumeType'] == 3:
  615. # 如果是刷卡的,直接更新消费记录,发通知消息,支持ID卡的退费。
  616. cardNo = self.event_data.get("cardNo", None)
  617. backMoney = refundedMoney
  618. card = self.update_card_dealer_and_type(cardNo=cardNo, cardType="ID")
  619. consumeDict.update({'balance': str(card.balance + VirtualCoin(backMoney))})
  620. if backMoney > 0:
  621. dealer = Dealer.objects(id=self.device.ownerId).first()
  622. if dealer is not None and 'doNotRefundIDcardForDC' in dealer.features:
  623. pass
  624. else:
  625. self.refund_money_for_card(VirtualCoin(backMoney), card.id)
  626. # 通知微信,已经退费
  627. self.notify_user(card.managerialOpenId, 'refund_coins', **{
  628. 'title': u'退币完成!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
  629. 'backCount': u'金币:%s' % VirtualCoin(backMoney),
  630. 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S')
  631. })
  632. ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
  633. {
  634. 'open_id': lineInfo['openId'],
  635. 'port': int(port),
  636. 'device_imei': self.device.devNo,
  637. 'isFinished':False
  638. }, consumeDict)
  639. extra = [{
  640. u'实体卡号': lineInfo['cardNo']
  641. }]
  642. if VirtualCoin(backMoney) > VirtualCoin(0):
  643. extra.append({
  644. u'退费金额': u'{}(金币)'.format(backMoney)
  645. })
  646. templateMap = {
  647. 'cardCoins': lineInfo.get('coins', 0),
  648. 'cardOrderTime': lineInfo.get('cardOrderTime', 0),
  649. 'actualNeedTime': actualNeedTime,
  650. 'usedTime': usedTime,
  651. 'backCoins': backMoney,
  652. 'reason': self.event_data['reason']
  653. }
  654. title = self.generate_service_complete_title_by_devType(self.device['devType']['id'], templateMap)
  655. if title != '':
  656. # 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}",
  657. self.notify_user(
  658. card.managerialOpenId if card else '',
  659. 'service_complete',
  660. **{
  661. 'title': title,
  662. 'service': u'充电服务',
  663. 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  664. 'remark': u'动态功率计算时间是指按照你的电动车功率大小进行折算出来的实际充电时间。'
  665. })
  666. else:
  667. self.notify_user_service_complete(
  668. service_name=u'充电',
  669. openid=card.managerialOpenId if card else '',
  670. port=port,
  671. address=group['address'],
  672. reason=self.event_data['reason'],
  673. finished_time=recvTime.strftime('%Y-%m-%d %H:%M:%S'),
  674. extra=extra)
  675. else:
  676. logger.error('not net pay rather user virtual card pay. something is wrong.')
  677. except Exception as e:
  678. logger.exception(e)
  679. class ZHIXIA2FaultEvent(FaultEvent):
  680. LX_FAULE_CODE_MAP = {
  681. "01": "07",
  682. "02": "03",
  683. "03": "05"
  684. }
  685. def do_norther(self):
  686. """
  687. 上报其他平台的,都在这个地方处理 可迁移至异步任务
  688. :return:
  689. """
  690. # 玉环的消防对接
  691. YuhuanNorther.send_dev_event(self.device, self.event_data['FaultCode'], self.event_data['port'])
  692. DelixiNorther.send_dev_event(self.device, self.event_data)
  693. # # 梁溪消防局的对接
  694. # faultContent = self.event_data["statusInfo"]
  695. # faultCode = self.LX_FAULE_CODE_MAP.get(self.event_data["FaultCode"], "")
  696. # districtInfo = District.get_district(self.device.group["districtId"])
  697. # self.device.update({"districtInfo": districtInfo, "groupAddr": self.device.group["address"]})
  698. #
  699. # LiangXiXiaoFang.send_to_xf_fault(self.device, faultCode, faultContent, self.event_data["port"])
  700. def do(self, **args):
  701. # 将告警的消息打入相应的缓存
  702. port = self.event_data["port"]
  703. # 0 表示整机
  704. if port == 0xFF:
  705. part = str(0)
  706. else:
  707. part = str(port)
  708. warningData = {
  709. "warningStatus": 2,
  710. "warningDesc": self.event_data["statusInfo"],
  711. "warningTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
  712. "warningUart": self.event_data["uart"]
  713. }
  714. Device.update_dev_warning_cache(self.device.devNo, {part: warningData})
  715. # self.do_norther()
  716. super(ZHIXIA2FaultEvent, self).do()
  717. class ZHIXIA2InductorEvent(FaultEvent):
  718. def do(self, **args):
  719. # 处理数据
  720. voltage = self.event_data.get('voltage', -1)
  721. temperature = self.event_data.get('temperature', -1)
  722. try:
  723. otherConf = Device.objects.get(devNo=self.device.devNo).otherConf
  724. maxVoltage = otherConf.get('voltageThre', 230)
  725. if voltage >= maxVoltage:
  726. desc = u'当前电压%s伏超过了门限值:%s伏' % (voltage, maxVoltage)
  727. self.record(faultCode=FAULT_CODE.OVER_VOLTAGE, description=desc, title=u'主机电压过高', detail=None,
  728. level=FAULT_LEVEL.CRITICAL)
  729. maxTemperature = otherConf.get('temThre', 60)
  730. if temperature > maxTemperature:
  731. desc = u'当前主机温度%s度超过了门限值:%s度' % (temperature, maxTemperature)
  732. self.record(faultCode=FAULT_CODE.OVER_TEMPERATURE, description=desc, title=u'主机温度过高',
  733. detail=None, level=FAULT_LEVEL.CRITICAL)
  734. self.send_fault_to_xf()
  735. if self.event_data['alarmType'] == 0xBB:
  736. desc = u'当前主机出现冒烟,请第一时间确定是否有起火。此告警十万火急,请迅速联系物业、消防相关部门!'
  737. self.record(faultCode=FAULT_CODE.SMOKE, description=desc, title=u'主机出现冒烟', detail=None,
  738. level=FAULT_LEVEL.FATAL)
  739. self.send_fault_to_xf()
  740. self.deviceAdapter.reply_C0(self.event_data['port'])
  741. except Exception, e:
  742. logger.error('some error=%s' % e)
  743. return
  744. def send_fault_to_xf(self):
  745. try:
  746. code = self.event_data.get('FaultCode')
  747. # 无锡 梁溪区 粤万通 消防对接 推送
  748. if code == 0xBB:
  749. faultCode = '02'
  750. faultContent = u'烟雾报警'
  751. elif code == 0xAA:
  752. faultCode = '01'
  753. faultContent = u'温度报警'
  754. else:
  755. return
  756. from taskmanager.mediator import task_caller
  757. task_caller('send_to_xf_falut',
  758. dealerId=self.device.ownerId,
  759. devNo=self.device.devNo,
  760. faultCode=faultCode,
  761. faultContent=faultContent)
  762. except Exception:
  763. pass
  764. class InteroperatorAlertEvent(FaultEvent):
  765. def __Analyze_alert_data(self, data):
  766. alertInfo = {'cmdCode': data['FaultCode'], 'logicalCode': self.device['logicalCode']}
  767. address = Group.get_group(self.device['groupId'])['address']
  768. # 这里做高温告警处理
  769. if '6' in data['status']:
  770. temperatureAccess = [index for index, acces in enumerate(data['status'], 1) if acces == '6']
  771. temperatureAlertList = []
  772. for i in temperatureAccess:
  773. temperatureValue = str(int(data['values'][(i - 1) * 4:(i - 1) * 4 + 4], 16))
  774. temperatureAlertList.append(
  775. {'temperatureValue': temperatureValue,
  776. 'address': address,
  777. 'reasonCode': '11',
  778. 'reason': u'在{}编号为{}的设备有高温预警,当前温度为{}摄氏度'
  779. .format(address, self.device['logicalCode'], temperatureValue)})
  780. alertInfo['temperature'] = temperatureAlertList
  781. return alertInfo
  782. def do(self, **args):
  783. # 判断不存在的设备网上报
  784. if not self.device.ownerId:
  785. logger.error('This device cant find a dealer')
  786. return
  787. # 是否存在温感和电感
  788. temperaturePart = Part.objects(logicalCode=self.device['logicalCode'], partType='3001')
  789. electricityPart = Part.objects(logicalCode=self.device['logicalCode'], partType='3002')
  790. if not temperaturePart.count() or not electricityPart.count():
  791. logger.error(
  792. 'There are no transformers in the locigalcode {} equipment'.format(self.device['logicalCode']))
  793. return
  794. # 处理数据
  795. eventInfo = self.__Analyze_alert_data(self.event_data['data'])
  796. try:
  797. # 先处理高温情况
  798. if 'temperature' in eventInfo:
  799. for InfoDetail in eventInfo['temperature']:
  800. send_event_to_zhejiang(self.dealer, self.device, InfoDetail, partId=temperaturePart[0].id)
  801. # 提示用户
  802. group = Group.get_group(self.device['groupId'])
  803. self.notify_dealer('device_fault', **{
  804. 'title': u'注意!注意!您的设备发生故障',
  805. 'device': u'组号::%s, 二维码编号:%s' % (self.device['groupNumber'], self.device['logicalCode']),
  806. 'location': u'组名称:%s, 地址:%s' % (group['groupName'], group['address']),
  807. 'fault': InfoDetail['reason'],
  808. 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  809. })
  810. # 上报高温至消防
  811. # if self.device["ownerId"] in ("5b4ed32e8732d67bd0626528", "5b6c29388732d669f3ae6f94"):
  812. group = Group.get_group(self.device['groupId'])
  813. districtInfo = District.get_district(group["districtId"])
  814. self.device.update({"districtInfo": districtInfo, "groupAddr": group["address"]})
  815. LiangXiXiaoFang.send_to_xf_fault(self.device, "01", u"设备温度过高")
  816. # 处理漏电情况
  817. elif 'electricity' in eventInfo:
  818. # 获取漏电告警插件
  819. send_event_to_zhejiang(self.dealer, self.device, eventInfo['electricity'],
  820. partId=electricityPart[0].id)
  821. # 提示用户
  822. group = Group.get_group(self.device['groupId'])
  823. self.notify_dealer('device_fault', **{
  824. 'title': u'注意!注意!您的设备发生故障',
  825. 'device': u'组号::%s, 二维码编号:%s' % (self.device['groupNumber'], self.device['logicalCode']),
  826. 'location': u'组名称:%s, 地址:%s' % (group['groupName'], group['address']),
  827. 'fault': eventInfo['electricity']['reason'],
  828. 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  829. })
  830. # 上报漏电至消防
  831. # if self.device["ownerId"] in ("5b4ed32e8732d67bd0626528", "5b6c29388732d669f3ae6f94"):
  832. group = Group.get_group(self.device['groupId'])
  833. districtInfo = District.get_district(group["districtId"])
  834. self.device.update({"districtInfo": districtInfo, "groupAddr": group["address"]})
  835. LiangXiXiaoFang.send_to_xf_fault(self.device, "04", u"设备发生漏电")
  836. except:
  837. logger.error('Array {} nonspecification'.format(eventInfo))
  838. return
  839. self.record(detail=eventInfo)
  840. class InteroperatorReport(WorkEvent):
  841. def do(self, **args):
  842. if 'type' not in self.event_data:
  843. logger.error('Array {} is not format,lose a key named "type"'.format(self.event_data))
  844. if self.event_data.get('type') == 'report':
  845. devReportDict = {'logicalCode': 'logicalCode', 'time': self.event_data['time_stamp'], 'portInfo': {}}
  846. temperature = ''
  847. voltage = 220
  848. try:
  849. # 拿到个数判断是不是第一次
  850. reportNum = PortReport.get_collection().find({
  851. 'logicalCode': self.device['logicalCode']
  852. }).sort('time', -1).count()
  853. if reportNum:
  854. # 获取上一次存储的信息
  855. reportLast = PortReport.get_collection().find({
  856. 'logicalCode': self.device['logicalCode']
  857. }).sort('time', -1)[0]
  858. for ii in range(10):
  859. power = self.__saveDate(1, msgDict=self.event_data, ii=ii)
  860. if power:
  861. electricity = float(power) / voltage / 10
  862. else:
  863. electricity = reportLast['portInfo'][str(ii + 1)]['electricity']
  864. temperatureR = self.__saveDate(2, msgDict=self.event_data, ii=ii, electricity=electricity,
  865. devReportDict=devReportDict)
  866. if temperatureR:
  867. temperature = temperatureR
  868. devReportDict.update({'temperature': temperature})
  869. # 查看现在的跟以前差距多少
  870. timeInterval = devReportDict['time'] - reportLast['time']
  871. if timeInterval > 2:
  872. PortReportNewList = [
  873. {"logicalCode": self.device['logicalCode'], "temperature": reportLast['temperature'],
  874. 'portInfo': reportLast['portInfo'],
  875. 'time': reportLast['time'] + (v + 1) * 2}
  876. for v in range(int(timeInterval / 2) - 1)]
  877. PortReport.get_collection().insert_many(PortReportNewList)
  878. # 首存的情况
  879. else:
  880. for ii in range(10):
  881. power = self.__saveDate(1, msgDict=self.event_data, ii=ii)
  882. electricity = float(power) / voltage / 10
  883. temperatureR = self.__saveDate(2, msgDict=self.event_data, ii=ii, electricity=electricity,
  884. devReportDict=devReportDict)
  885. if temperatureR:
  886. temperature = temperatureR
  887. devReportDict.update({'temperature': temperature})
  888. except Exception, e:
  889. logger.error('solve dev=%s device report has an error e=%s' % (self.device.devNo, e))
  890. finally:
  891. newInfo = PortReport(
  892. logicalCode=self.device['logicalCode'],
  893. temperature=devReportDict['temperature'],
  894. time=devReportDict['time'],
  895. portInfo=devReportDict['portInfo']
  896. )
  897. newInfo.save()
  898. def __saveDate(self, data, msgDict, ii, electricity=None, devReportDict=None):
  899. # 存储数据库
  900. if data == 1:
  901. powerData = msgDict['data']['power_data'][0 + 4 * ii:4 + 4 * ii]
  902. power = int(powerData, 16)
  903. return power
  904. if data == 2:
  905. temperature = ''
  906. status = 'idle' if electricity == 0 else 'busy'
  907. devReportDict['portInfo'].update(
  908. {str(ii + 1): {'electricity': round(electricity, 3), 'status': status}})
  909. if ii < 4 and msgDict['data']['temp_data'][0 + 4 * ii:4 + 4 * ii] != '0000':
  910. temperatureNum = msgDict['data']['temp_data'][0 + 4 * ii:4 + 4 * ii]
  911. temperature = int(temperatureNum, 16)
  912. return temperature