dianchuan.py 53 KB

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