1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import random
- import time
- from arrow import Arrow
- from django.conf import settings
- from typing import TYPE_CHECKING, List
- from apilib.monetary import sum_rmb, RMB, VirtualCoin, Ratio
- from apilib.utils_datetime import to_datetime
- from apps.web.south_intf.liangxi_fire import LiangXiXiaoFang
- from apps.web.south_intf.yuhuan_fire import YuhuanNorther
- from apps.web.common.models import District
- from apps.web.constant import Const, FAULT_CODE, FAULT_LEVEL, APP_TYPE, DEALER_CONSUMPTION_AGG_KIND
- from apps.web.core.helpers import ActionDeviceBuilder
- from apps.web.core.accounting import Accounting
- from apps.web.core.device_define.dianchuan import FINISHED_CHARGE_REASON_MAP
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import PortReport, Part, Group, Device
- from apps.web.device.timescale import FluentedEngine
- from apps.web.eventer.base import FaultEvent, WorkEvent, ComNetPayAckEvent, IcStartAckEvent, \
- AckEventProcessorIntf, IcRechargeAckEvent, CardRefundAckEvent
- from apps.web.eventer import EventBuilder
- from apps.web.helpers import get_wechat_auth_bridge
- from apps.web.south_intf.platform import notify_event_to_north, notify_event_to_north_v2, \
- handle_and_notify_event_to_north_Dc
- from apps.web.south_intf.zhejiang_fire import send_event_to_zhejiang
- from apps.web.user.models import VCardConsumeRecord, ServiceProgress, UserVirtualCard, CardRechargeOrder, MyUser, \
- ConsumeRecord, RechargeRecord
- if TYPE_CHECKING:
- from apps.web.user.models import Card
- from apps.web.device.models import GroupDict
- from apps.web.device.models import DeviceDict
- logger = logging.getLogger(__name__)
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- # 订单机制事件
- if 'order_id' in device_event:
- if device_event['order_type'] == 'com_start':
- return MyComNetPayAckEvent(self.deviceAdapter, device_event)
- if device_event['order_type'] == 'ic_recharge':
- return MyIcRechargeAckEvent(self.deviceAdapter, device_event)
- if device_event['order_type'] == 'ic_start':
- return MyIcStartAckEvent(self.deviceAdapter, device_event)
- if device_event['order_type'] == 'card_refund':
- return MyCardRefundAckEvent(self.deviceAdapter, device_event)
- else:
- if 'data' not in device_event:
- return None
- # 100228 互感器事件处理
- if 'type' in device_event:
- if device_event['type'] == 'alert':
- return InteroperatorAlertEvent(self.deviceAdapter, device_event)
- if device_event['type'] == 'report':
- return InteroperatorReport(self.deviceAdapter, device_event)
- else:
- event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
- if event_data is None or 'cmdCode' not in event_data:
- return None
- if 'duration' in device_event:
- event_data.update({'duration': device_event['duration']})
- if 'elec' in device_event:
- event_data.update({'elec': device_event['elec']})
- if 'v' in device_event:
- event_data.update({'v': device_event['v']})
- if 'today_coins' in device_event and 'ts' in device_event:
- event_data.update({'today_coins': device_event['today_coins']})
- event_data.update({'ts': device_event['ts']})
- if event_data.get('cmdCode') in ['03', '05', '11', '12', '17', '22']:
- return ChargingYUZEWorkEvent(self.deviceAdapter, event_data)
- if event_data.get('cmdCode') == '0D':
- return YUZEFaultEvent(self.deviceAdapter, event_data)
- if event_data.get('cmdCode') == '35' or event_data.get('cmdCode') == '41':
- return YUZEInductorEvent(self.deviceAdapter, event_data)
- # 雨泽
- if event_data.get('cmdCode') in ['30', '31', '32']:
- return ChargingYUZEWorkEvent(self.deviceAdapter, event_data)
- return None
- class YUZEFaultEvent(FaultEvent):
- LX_FAULE_CODE_MAP = {
- "01": "07",
- "02": "03",
- "03": "05"
- }
- def do_norther(self):
- """
- 上报其他平台的,都在这个地方处理 可迁移至异步任务
- :return:
- """
- # 玉环的消防对接
- YuhuanNorther.send_dev_event(self.device, self.event_data['FaultCode'], self.event_data['port'])
- # 梁溪消防局的对接
- faultContent = self.event_data["statusInfo"]
- faultCode = self.LX_FAULE_CODE_MAP.get(self.event_data["FaultCode"], "")
- districtInfo = District.get_district(self.device.group["districtId"])
- self.device.update({"districtInfo": districtInfo, "groupAddr": self.device.group["address"]})
- LiangXiXiaoFang.send_to_xf_fault(self.device, faultCode, faultContent, self.event_data["port"])
- def do(self, **args):
- # 将告警的消息打入相应的缓存
- port = self.event_data["port"]
- # 0 表示整机
- if port == 0xFF:
- part = str(0)
- else:
- part = str(port)
- warningData = {
- "warningStatus": 2,
- "warningDesc": self.event_data["statusInfo"],
- "warningTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "warningUart": self.event_data["uart"]
- }
- Device.update_dev_warning_cache(self.device.devNo, {part: warningData})
- self.do_norther()
- super(YUZEFaultEvent, self).do()
- class ChargingYUZEWorkEvent(WorkEvent):
- def __parse_device_finished_data(self, event_data):
- duration = event_data.get('duration', -1)
- if duration != -1:
- if 'v' in event_data:
- duration = ((duration + 59) / 60)
- elec = event_data.get('elec', -1)
- if elec != -1:
- if 'v' in event_data:
- elec = round(elec / (10000.0 * 3600.0), 3)
- else:
- elec = round(elec / 3600.0, 3)
- logger.debug('device duration is {}, device elec is {}'.format(duration, elec))
- return duration, elec
- def do(self, **args):
- logger.info(' charging event detected, devNo=%s,info=%s' % (self.device.devNo, self.event_data))
- if self.event_data['cmdCode'] == '03': # 投币上报
- if 'today_coins' in self.event_data and 'ts' in self.event_data:
- Accounting.syncOfflineCoin(
- self.device,
- datetime.datetime.fromtimestamp(self.event_data['ts']).strftime('%Y-%m-%d'),
- self.event_data['today_coins'])
- if self.event_data['coins'] > 0:
- FluentedEngine().in_put_coins_udp(devNo = self.device.devNo,
- ts = int(time.time()),
- coins = self.event_data['coins'],
- mode = 'uart')
- else:
- # 老的流程会单条记录上报记录
- Accounting.recordOfflineCoin(device = self.device,
- report_ts = int(time.time()),
- coins = int(self.event_data['coins']),
- mode = 'uart',
- port = self.event_data.get('port', None))
- try:
- # 如果是投币,直接把端口状态刷新下
- self.deviceAdapter.get_port_status_from_dev()
- except Exception, e:
- logger.info('some err=%s' % e)
- YuhuanNorther.send_dev_status(self.device, self.event_data['port'], 1)
- elif self.event_data['cmdCode'] == '22': # ID在线卡刷卡查询余额
- cardNo = self.event_data['cardNo']
- fee = RMB(self.event_data['fee'])
- cardType = self.event_data['cardType']
- card = self.update_card_dealer_and_type(cardNo)
- # 首先检查订单,并进行充值
- # 不存在卡的情况下 直接
- if not card:
- res = "03"
- elif not card.openId:
- res = "03"
- elif card.frozen:
- res = "04"
- # 有绑定的卡 并且卡没被冻结的情况下
- else:
- # 刷新卡的金额
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
- result = self.recharge_id_card(card=card, rechargeType='append', order=card_recharge_order)
- card.reload()
- logger.info('cardNo=%s,openId=%s,result=%s,fee=%s, info=%s' % (cardNo, card.openId, result, fee, self.event_data))
- res = "01" if result["balance"] >= fee else "02"
- balance = RMB(0) if not card else card.balance
- try:
- logger.info("card is <{}> fee is <{}> response res is <{}>".format(cardNo, fee, res))
- result = self.deviceAdapter.response_card_status(cardNo, balance, res)
- except Exception, e:
- logger.info('resp back error=%s' % e)
- return
- if fee <= RMB(0):
- # 仅仅是查询余额
- logger.debug(
- 'query the balance of card<cardNo={}> in device<devNo={}>'.format(card.cardNo, self.device.devNo))
- return
- # 设备回复扣款成功,服务器就需要正式扣掉钱
- if result['status'] == '01' and res == '01':
- virtual_card = card.bound_virtual_card
- if virtual_card is not None:
- group = Group.get_group(self.device['groupId'])
- VCardConsumeRecord(
- orderNo = VCardConsumeRecord.make_no(self.device.logicalCode),
- openId = card.openId,
- cardId = str(virtual_card.id),
- dealerId = card.dealerId,
- devNo = self.device.devNo,
- devTypeCode = self.device.devTypeCode,
- devTypeName = self.device.devTypeName,
- logicalCode = self.device['logicalCode'],
- groupId = group['groupId'],
- address = group['address'],
- groupNumber = self.device['groupNumber'],
- groupName = group['groupName'],
- ).save()
- else:
- self.consume_money_for_card(card, fee)
- # 记录卡消费记录以及消费记录
- orderNo, cardOrderNo = self.record_consume_for_card(card, fee)
- # 记录当前服务的progress.没有上报端口号,所以先用-1标记,表示端口未知。端口等消费的时候会报上来
- ServiceProgress.register_card_service(
- self.device, -1, card,
- {
- 'orderNo': orderNo,
- 'money': self.event_data['fee'],
- 'coin': self.event_data['fee'],
- 'needTime': 0,
- 'cardOrderNo': cardOrderNo
- }
- )
- # 通知微信,已经扣费
- self.notify_balance_has_consume_for_card(card, fee)
- elif self.event_data['cmdCode'] == '11' and self.event_data['status'] == '01': # 开始启动某个端口
- # 按下端口,开始使用。IC卡和ID卡都会上报这条信息。IC卡只记录消费记录信息,ID卡主要是上报了具体的某一个端口.ID卡和劲能的类似,主要是表示开始某一个端口以及回收余额
- cardType = self.event_data['cardType']
- card = self.update_card_dealer_and_type(self.event_data['cardNo'], cardType)
-
- if not card:
- logger.info('no card cardNo-<{}>'.format(self.event_data.get('cardNo')))
- return
-
- # 这个地方将计费方式更新到 portDict 刷卡退费的时候会将刷卡的退费金额上报过来 结束事件需要这个字段 主要的是要更新consumeDict的字段
- # 0 按时间收费
- # 1 按度计费
- consumeMode = self.device.get("otherConf", dict()).get("consumeMode", 0)
- if consumeMode == 0 or consumeMode == 2:
- self.event_data["billingType"] = "time"
- else:
- self.event_data["billingType"] = "elec"
- if cardType == 'ID':
- consumeDict = {'chargeIndex': self.event_data['port']}
- queryDict = {'device_imei': self.device.devNo,
- 'port': -1, 'isFinished': False,
- 'cardId': str(card.id), 'start_time': {'$gte': int(time.time()) - 3600}}
- progressDict = {'port': self.event_data['port']}
- ServiceProgress.update_progress_and_consume_rcd(ownerId = self.device.ownerId,
- queryDict = queryDict, consumeDict = consumeDict,
- updateConsume = True, progressDict = progressDict)
- # 找出对应的卡的ID记录到端口内存数据
- queryDict.update(progressDict)
- rcds = ServiceProgress.get_collection().find(queryDict, {'consumeOrder': 1},
- sort = [('start_time', -1)])
- allCoins = sum_rmb([rcd['consumeOrder']['coin'] for rcd in rcds])
- try:
- d = Device.objects(devNo=self.device.devNo).first()
- billingType = d.otherConf.get('billingType', 'time')
- actionBox = ActionDeviceBuilder.create_action_device(Device.get_dev(self.device.devNo))
- cardTime = actionBox.get_freemode_volume_andsoon_config()['card1Time']
- icMoney = int(actionBox.get_IC_coin_power_config()['icMoney']) / 10
- allCardTime = int(int(allCoins) / icMoney) * int(cardTime)
- except Exception as e:
- logger.error('allCardTime error: %s' % e)
- allCardTime = 0
- billingType = 'time'
- self.event_data.update({'cardOrderTime': str(allCardTime)})
- self.event_data.update({'cardId': str(card.id)})
- self.event_data.update({'openId': card.openId})
- self.event_data.update({'coins': str(allCoins)})
- self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
- self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
- self.event_data.update({'billingType': billingType})
- Device.update_port_control_cache(self.device.devNo, self.event_data) # 记录该端口累计需要的时间和钱,cardId
- else: # IC卡,需要记录消费记录
- fee = RMB(self.event_data['fee'])
- card.update(balance=RMB(self.event_data['balance']))
- orderNo, cardOrderNo = self.record_consume_for_card(card, fee)
- ServiceProgress.register_card_service(self.device, self.event_data['port'], card,
- {'orderNo': orderNo, 'money': self.event_data['fee'],
- 'coin': self.event_data['fee'], 'cardOrderNo': cardOrderNo})
- # 通知微信,已经扣费
- self.notify_balance_has_consume_for_card(card, fee)
- self.event_data.update({'cardId': str(card.id)})
- self.event_data.update({'openId': card.openId})
- self.event_data.update({'coins': self.event_data['fee']})
- self.event_data.update({'startTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
- self.event_data.update({'isStart': True, 'status': Const.DEV_WORK_STATUS_WORKING})
- Device.update_port_control_cache(self.device.devNo, self.event_data) # 记录该端口累计需要的时间和钱,cardId
- elif self.event_data['cmdCode'] == '12': # 离线卡充值
- cardNo = self.event_data['cardNo']
- preBalance = RMB(self.event_data['balance'])
- card = self.update_card_dealer_and_type(cardNo, 'IC', balance = preBalance) # type: Card
- if not card:
- return
- if card.frozen:
- logger.debug('{} has been frozen.'.format(repr(card)))
- return
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id)) # type: CardRechargeOrder
- if not card_recharge_order:
- logger.debug('{} has no recharge order.'.format(repr(card)))
- return
- self.recharge_ic_card(card = card,
- preBalance = preBalance,
- rechargeType = 'overwrite',
- order = card_recharge_order)
- elif self.event_data['cmdCode'] == '05':
- # 新版本的结束事件,比就版本多刷卡ID卡的在线退费
- devNo = self.device.devNo
- port = str(self.event_data['port'])
- try:
- # 获取充电的模式
- ctrInfo = Device.get_dev_control_cache(devNo)
- lineInfo = ctrInfo.get(port)
- if 'coins' not in lineInfo:
- logger.debug('get null control cache from {}'.format(repr(self.device)))
- return
- else:
- logger.debug('port cache is: {}'.format(str(lineInfo)))
- if lineInfo.get('isApi', False) is True:
- self.event_data.update({'deviceCode':self.device['logicalCode']})
- return handle_and_notify_event_to_north_Dc(self.device["devNo"], self.event_data)
- billingType = lineInfo.get("billingType", "time")
- if billingType == "elec":
- return self.do_elec_finish(devNo, port, lineInfo, self.event_data)
- else:
- return self.do_time_finish(devNo, port, lineInfo, self.event_data)
- finally:
- Device.clear_port_control_cache(devNo, str(port))
- notify_event_to_north_v2(self.device["devNo"], self.event_data)
- notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
- desc = self.event_data['reason'])
- send_event_to_zhejiang(self.dealer, self.device, self.event_data)
- if self.event_data['reasonCode'] == '04': # 功率过载导致的断电,一条告警,一条恢复告警
- YuhuanNorther.send_dev_event(self.device, '97', port)
- YuhuanNorther.send_dev_event(self.device, '98', port)
- # 发送一条端口使用结束的告警
- YuhuanNorther.send_dev_status(self.device, port, 2)
- def do_elec_finish(self, devNo, port, lineInfo, msgDict):
- """
- 电川的板子 按电量退费
- :return:
- """
- dealer = self.device.owner
- if not dealer:
- logger.error('dealer is not found, dealerId=%s' % self.device['ownerId'])
- return
- leftElec = self.event_data.get("leftTime", 0) / 100.0
- reasonCode = self.event_data.get("endType")
- reasonStr = self.event_data.get("reason")
- cardNo = str(self.event_data.get("cardNo")) if self.event_data.get("cardNo") else None
- cardType = self.event_data.get("cardType")
- price = RMB(lineInfo.get('price', 0))
- startTime = lineInfo.get("startTime")
- # 投币事件
- if not startTime:
- return
- startTime = to_datetime(startTime)
- nowTime = datetime.datetime.now()
- deviceDuration, deviceElec = self.__parse_device_finished_data(self.event_data)
- try:
- consumeDict = {
- "reason": reasonStr,
- "chargeIndex": port,
- "uartData": self.event_data.get('uartData', '')
- }
- # 计算充电的时间
- if deviceDuration and deviceDuration > 0:
- usedTime = deviceDuration
- else:
- if startTime > nowTime:
- usedTime = 0
- else:
- usedTime = int(round(((nowTime - startTime).total_seconds() / 60.0)))
- consumeDict.update({"duration": usedTime})
- # 获取组信息
- group = Group.get_group(self.device["groupId"])
- # 扫码的结束
- if not cardNo:
- needElec = lineInfo.get("needElec")
- if leftElec == int("FFFF", 16):
- leftElec = needElec
- elif leftElec > needElec:
- logger.error('left elec is bigger than need elec. something is wrong')
- leftElec = 0
- spendElec = needElec - leftElec
- coins = VirtualCoin(lineInfo.get("coins"))
- refundCoins = VirtualCoin(0)
- refundedMoney = RMB(0)
- consumeDict.update({
- "reason": reasonStr,
- "chargeIndex": port
- })
- refundSwitch = self.device.is_auto_refund
- if refundSwitch:
- refundCoins = VirtualCoin(coins) * Ratio(leftElec / needElec)
- refundedMoney = RMB(price) * Ratio(leftElec / needElec)
- if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']:
- # 虚拟卡的结束
- consumeRcdId = lineInfo['consumeRcdId']
- vCardId = lineInfo.get("vCardId", "")
- vCard = UserVirtualCard.objects(id = vCardId).first()
- if not vCard:
- logger.info('can not find the vCard id = %s' % vCardId)
- return
- try:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- 'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False
- },
- consumeDict
- )
- if refundCoins > VirtualCoin(0):
- vCardConsumeRcd = VCardConsumeRecord.objects.get(id = consumeRcdId)
- vCard.refund_quota(vCardConsumeRcd, needElec - spendElec, spendElec,
- refundCoins.mongo_amount)
- finally:
- user = MyUser.objects(openId = lineInfo['openId'],
- groupId = self.device.groupId).first()
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = user.managerialOpenId if user else '',
- port = port,
- address = group['address'],
- reason = self.event_data['reason'],
- finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra = [
- {u'虚拟卡号': vCard.cardNo}
- ]
- )
- elif 'openId' in lineInfo and lineInfo['openId']:
- # 扫码使用金币启动
- user = MyUser.objects(openId = lineInfo['openId'],
- groupId = self.device.groupId).first()
- try:
- is_cash = False
- if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
- is_cash = True
- consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
- if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
- consumeDict.update(
- {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
- self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- 'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False
- },
- consumeDict)
- finally:
- extra = []
- if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
- real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
- if real_refund > RMB(0):
- extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
- extra.append({u'退款金额': '{}(元)'.format(real_refund)})
- else:
- extra.append({u'消费金额': '{}(元)'.format(price)})
- elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
- real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
- if real_refund > VirtualCoin(0):
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
- extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = user.managerialOpenId if user else '',
- port = port,
- address = group['address'],
- reason = self.event_data['reason'],
- finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- else:
- logger.error('not net pay rather user virtual card pay. something is wrong.')
- else:
- backMoney = self.event_data.get("backMoney")
- # 刷卡的结束 如果没有开启刷卡退费 则结束上报过来的backMoney = 0
- if cardType == "IC":
- # IC卡结束 只有刷卡结束的IC卡才能够刷新IC卡余额
- card = self.update_card_dealer_and_type(cardNo, "IC")
- if reasonCode == "05" and backMoney > 0:
- # 原因为05表示刷卡结束充电,会把退费金额报上来. 否则只能通过11指令报上来
- self.refund_money_for_card(VirtualCoin(backMoney), card.id)
- consumeDict.update({'balance': str(card.balance + VirtualCoin(backMoney))})
- else:
- consumeDict.update({'balance': str(card.balance)}) # IC卡必须下次刷卡的时候回收上来
- elif cardType == "ID":
- # ID卡结束 直接退费就行了
- card = self.update_card_dealer_and_type(cardNo, "ID")
- if backMoney > 0:
- self.refund_money_for_card(RMB(backMoney), str(card.id))
- consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- else:
- logger.error("invalid card type event data is <{}>".format(self.event_data))
- ServiceProgress.update_progress_and_consume_rcd(
- self.device.ownerId,
- {
- 'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False
- },
- consumeDict
- )
- extra = [{u'实体卡号': cardNo}]
- if backMoney > 0:
- extra.append({
- u'退款金额': u'{}(金币)'.format(backMoney)
- })
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = self.get_managerialOpenId_by_openId(lineInfo['openId']),
- port = port,
- address = group['address'],
- reason = self.event_data['reason'],
- finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra
- )
- except Exception as e:
- logger.exception(e)
- def do_time_finish(self, devNo, port, lineInfo, msgDict):
- try:
- dealer = Dealer.objects(id=self.device['ownerId']).first()
- if not dealer:
- logger.error('dealer is not found, dealerId=%s' % self.device['ownerId'])
- return
- price = RMB(lineInfo.get('price', 0))
- refundProtectionTime = lineInfo.get('refundProtectionTime', 5)
- deviceDuration, deviceElec = self.__parse_device_finished_data(self.event_data)
- if lineInfo is not None and 'startTime' in lineInfo:
- startTime = to_datetime(lineInfo['startTime'])
- nowTime = datetime.datetime.now()
- if startTime > nowTime:
- logger.error('start time is bigger than now time,devNo={}'.format(devNo))
- serverDuration = -1
- else:
- serverDuration = int(round((((nowTime - startTime).total_seconds() + 59) / 60.0)))
- else:
- logger.info('lineinfo has not startTime,devNo=%s' % devNo)
- serverDuration = -1
- if deviceDuration > 0:
- usedTime = deviceDuration
- elif serverDuration >= 0:
- usedTime = serverDuration
- else:
- usedTime = -1
- leftTime = self.event_data['leftTime']
- if leftTime != 65535:
- leftTimeStr = leftTime
- if usedTime == -1:
- actualNeedTime = -1
- else:
- actualNeedTime = usedTime + leftTime
- else:
- leftTimeStr = u'端口未使用'
- actualNeedTime = 0
- group = self.device.group # type: GroupDict
- if actualNeedTime == -1:
- if 'cardNo' in self.event_data and self.event_data['cardNo']:
- card = Card.objects(cardNo = str(self.event_data['cardNo']), agentId = self.dealer.agentId).first()
- if card is not None:
- # todo 生成模板所需要的所有参数, 后续有客户自定义的话, 直接在这个字典里面添加, 不需要删掉之前的.
- # todo 这个变量仅仅用于下面generate_service_complete_title_by_devType()函数的参. 做成配置项更好, 下次不用改代码.
- templateMap = {
- 'cardCoins': 0,
- 'cardOrderTime': 0,
- 'actualNeedTime': 0,
- 'usedTime': 0,
- 'backCoins': 0,
- 'reason': u'没有实际预定时间, 忽略此次消费事件'
- }
- # 先去获取devType上面的模板, 如果没有就走正常的流程
- title = self.generate_service_complete_title_by_devType(self.device['devType']['id'], templateMap)
- if title != '':
- self.notify_user(
- card.managerialOpenId if card else '',
- 'service_complete',
- **{
- 'title': title,
- 'service': u'充电服务',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'动态功率计算时间是指按照你的电动车功率大小进行折算出来的实际充电时间。'
- })
- else:
- self.notify_user_service_complete(
- service_name=u'充电',
- openid=card.managerialOpenId if card else '',
- port=port,
- address=group['address'],
- reason=self.event_data['reason'],
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=[{
- u'实体卡号': self.event_data['cardNo']
- }]
- )
- logger.debug('has no actual need time. ignore this event.')
- return
- consumeDict = {
- 'reason': self.event_data['reason'],
- 'leftTime': leftTimeStr,
- 'chargeIndex': port,
- 'actualNeedTime': u'动态功率计算为%s分钟' % actualNeedTime,
- 'duration': usedTime,
- 'deviceDuration': deviceDuration,
- 'serverDuration': serverDuration,
- 'uartData': self.event_data.get('uartData', '')
- }
- if deviceElec != -1:
- consumeDict.update({'elec': deviceElec})
- else:
- # deviceObj = Device.objects(devNo = self.device.devNo).first()
- groupObj = Group.objects(id=self.device.groupId).first()
- if groupObj.otherConf.get('zhuxing', None) is not None:
- spendElec = round((float(random.randint(15, 19)) / 100) * (float(usedTime) / 60), 3)
- consumeDict.update({'elec': spendElec})
- consumeDict.update({'elecFee': self.deviceAdapter.calc_elec_fee(spendElec)})
- else:
- spendElec = 0.0
- consumeDict.update({'elec': 0.0})
- consumeDict.update({'elecFee': RMB(0.0).mongo_amount})
- # 涉及到卡的退费 不要以缓存为准 以设备上报的为准
- cardNo = self.event_data.get("cardNo")
- if cardNo:
- # 如果是刷卡的,直接更新消费记录,发通知消息,支持ID卡的退费。
- # IC卡的退费, 如果结束原因是刷卡退费(05), 则会把退费信息返回;
- # 否则不会把退费信息传过来,会通过11号命令返回
- cardType = self.event_data.get("cardType")
- if cardType == 'ID':
- card = self.update_card_dealer_and_type(cardNo=cardNo, cardType="ID")
- consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- if self.event_data.has_key('backMoney') and self.event_data['backMoney'] > 0:
- self.refund_money_for_card(VirtualCoin(self.event_data['backMoney']), card.id)
- # 通知微信,已经退费
- self.notify_user(card.managerialOpenId, 'refund_coins', **{
- 'title': u'退币完成!您的卡号是%s,卡别名:%s' % (card.cardNo, card.nickName),
- 'backCount': u'金币:%s' % VirtualCoin(self.event_data['backMoney']),
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- elif cardType == "IC":
- card = self.update_card_dealer_and_type(cardNo=cardNo, cardType="IC")
- # IC 并且结束code是05 表示卡贴上去了
- if self.event_data['endType'] == '05': # 刷卡退费结束的时候,才能够刷新IC卡的余额
- self.refund_money_for_card(VirtualCoin(self.event_data['backMoney']), card.id)
- consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- else:
- consumeDict.update({'balance': str(card.balance)}) # IC卡必须下次刷卡的时候回收上来
- else:
- logger.error("invalid card type event data is <{}>".format(self.event_data))
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {'open_id': lineInfo['openId'], 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False}, consumeDict)
- extra = [{
- u'实体卡号': lineInfo['cardNo']
- }]
- if VirtualCoin(self.event_data['backMoney']) > VirtualCoin(0):
- extra.append({
- u'退费金额': u'{}(金币)'.format(self.event_data['backMoney'])
- })
- templateMap = {
- 'cardCoins': lineInfo.get('coins', 0),
- 'cardOrderTime': lineInfo.get('cardOrderTime', 0),
- 'actualNeedTime': actualNeedTime,
- 'usedTime': usedTime,
- 'backCoins': self.event_data['backMoney'],
- 'reason': self.event_data['reason']
- }
- title = self.generate_service_complete_title_by_devType(self.device['devType']['id'], templateMap)
- if title != '':
- # 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}",
- self.notify_user(
- card.managerialOpenId if card else '',
- 'service_complete',
- **{
- 'title': title,
- 'service': u'充电服务',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'动态功率计算时间是指按照你的电动车功率大小进行折算出来的实际充电时间。'
- })
- else:
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = card.managerialOpenId if card else '',
- port = port,
- address = group['address'],
- reason = self.event_data['reason'],
- finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- else:
- # 计算退费信息
- coins = VirtualCoin(lineInfo['coins'])
- refundCoins = VirtualCoin(0)
- refundedMoney = RMB(0)
- if self.device.is_auto_refund:
- if leftTime != 65535:
- refundCoins = coins * (float(leftTime) / float(actualNeedTime))
- refundedMoney = RMB(price * (float(leftTime) / float(actualNeedTime)))
- else:
- refundCoins = coins
- refundedMoney = RMB(price)
- if usedTime < refundProtectionTime and refundCoins != VirtualCoin(0):
- refundCoins = coins
- refundedMoney = RMB(price)
- if refundCoins > coins:
- refundCoins = coins
- if refundedMoney > RMB(price):
- refundedMoney = RMB(price)
- # 退费保护不受金币退款开关影响, 照样退费
- elif usedTime < refundProtectionTime:
- refundCoins = coins
- refundedMoney = RMB(price)
- if refundCoins > coins:
- refundCoins = coins
- if refundedMoney > RMB(price):
- refundedMoney = RMB(price)
- else:
- pass
- logger.debug(
- 'lefttime = {}, usedTime = {}, need time = {}, back coins = {}'.format(leftTime, usedTime,
- actualNeedTime,
- refundCoins))
- if 'consumeRcdId' in lineInfo and lineInfo['consumeRcdId']:
- vCardId = lineInfo['vCardId']
- vCard = UserVirtualCard.objects(id = vCardId).first() # type: UserVirtualCard
- if not vCard:
- logger.info('can not find the vCard id = %s' % vCardId)
- return
- try:
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False}, consumeDict)
- if refundCoins > VirtualCoin(0):
- vCardConsumeRcd = VCardConsumeRecord.objects.get(id = lineInfo['consumeRcdId'])
- vCard.refund_quota(vCardConsumeRcd, usedTime, 0.0, refundCoins.mongo_amount)
- finally:
- user = MyUser.objects(openId = lineInfo['openId'],
- groupId = self.device.groupId).first()
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = user.managerialOpenId if user else '',
- port = port,
- address = group['address'],
- reason = self.event_data['reason'],
- finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra = [
- {u'虚拟卡号': vCard.cardNo}
- ]
- )
- elif 'openId' in lineInfo and lineInfo['openId']:
- user = MyUser.objects(openId = lineInfo['openId'],
- groupId = self.device.groupId).first()
- try:
- is_cash = False
- if 'refundRMB_device_event' in self.device.owner.features and refundedMoney > RMB(0):
- is_cash = True
- consumeDict.update({DEALER_CONSUMPTION_AGG_KIND.COIN: VirtualCoin(coins).mongo_amount})
- if refundedMoney > RMB(0) or refundCoins > VirtualCoin(0):
- consumeDict.update(
- {DEALER_CONSUMPTION_AGG_KIND.COIN: (VirtualCoin(coins) - refundCoins).mongo_amount})
- self.refund_net_pay(user, lineInfo, refundedMoney, refundCoins, consumeDict, is_cash)
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,
- {'open_id': lineInfo['openId'],
- 'port': int(port),
- 'device_imei': self.device.devNo,
- 'isFinished': False}, consumeDict)
- finally:
- extra = []
- if DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH in consumeDict:
- real_refund = RMB(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_CASH])
- if real_refund > RMB(0):
- extra.append({u'消费金额': '{}(元)'.format(RMB(price) - real_refund)})
- extra.append({u'退款金额': '{}(元)'.format(real_refund)})
- else:
- extra.append({u'消费金额': '{}(元)'.format(price)})
- elif DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS in consumeDict:
- real_refund = VirtualCoin(consumeDict[DEALER_CONSUMPTION_AGG_KIND.REFUNDED_COINS])
- if real_refund > VirtualCoin(0):
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins) - real_refund)})
- extra.append({u'退款金额': '{}(金币)'.format(real_refund)})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(coins))})
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = user.managerialOpenId if user else '',
- port = port,
- address = group['address'],
- reason = self.event_data['reason'],
- finished_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- else:
- logger.error('not net pay rather user virtual card pay. something is wrong.')
- except Exception as e:
- logger.exception(e)
- class YUZEInductorEvent(FaultEvent):
- def do(self, **args):
- # 处理数据
- voltage = self.event_data.get('voltage', -1)
- temperature = self.event_data.get('temperature', -1)
- smokeWarning = self.event_data.get('smokeWarning', False)
- try:
- otherConf = Device.objects.get(devNo = self.device.devNo).otherConf
- maxVoltage = otherConf.get('voltageThre', 230)
- if voltage >= maxVoltage:
- desc = u'当前电压%s伏超过了门限值:%s伏' % (voltage, maxVoltage)
- self.record(faultCode = FAULT_CODE.OVER_VOLTAGE, description = desc, title = u'主机电压过高', detail = None,
- level = FAULT_LEVEL.CRITICAL)
- maxTemperature = otherConf.get('temThre', 60)
- if temperature > maxTemperature:
- desc = u'当前主机温度%s度超过了门限值:%s度' % (temperature, maxTemperature)
- self.record(faultCode = FAULT_CODE.OVER_TEMPERATURE, description = desc, title = u'主机温度过高',
- detail = None, level = FAULT_LEVEL.CRITICAL)
- if smokeWarning:
- desc = u'当前主机出现冒烟,请第一时间确定是否有起火。此告警十万火急,请迅速联系物业、消防相关部门!'
- self.record(faultCode = FAULT_CODE.SMOKE, description = desc, title = u'主机出现冒烟', detail = None,
- level = FAULT_LEVEL.FATAL)
- except Exception, e:
- logger.error('some error=%s' % e)
- return
- class InteroperatorAlertEvent(FaultEvent):
- def __Analyze_alert_data(self, data):
- alertInfo = {'cmdCode': data['cmd'], 'logicalCode': self.device['logicalCode']}
- address = Group.get_group(self.device['groupId'])['address']
- # 这里判断数据格式
- if 'status' not in data:
- logger.error('Data arrays have no keywords status')
- return
- # 这里做漏电告警处理
- if '5' in data['status']:
- electricityNum = str(int(data['values'][0:4], 16)) + 'mA'
- alertInfo['electricity'] = {'electricityNum': electricityNum,
- 'address': address,
- 'reasonCode': '12',
- 'reason': u'在{}编号为{}发生漏电,漏电量为{}'
- .format(address, self.device['logicalCode'], electricityNum)}
- # 这里做高温告警处理
- if '6' in data['status']:
- temperatureAccess = [index for index, acces in enumerate(data['status'], 1) if acces == '6']
- temperatureAlertList = []
- for i in temperatureAccess:
- temperatureValue = str(int(data['values'][(i - 1) * 4:(i - 1) * 4 + 4], 16))
- temperatureAlertList.append(
- {'temperatureValue': temperatureValue,
- 'address': address,
- 'reasonCode': '11',
- 'reason': u'在{}编号为{}的设备有高温预警,当前温度为{}摄氏度'
- .format(address, self.device['logicalCode'], temperatureValue)})
- alertInfo['temperature'] = temperatureAlertList
- return alertInfo
- def do(self, **args):
- # 判断不存在的设备网上报
- if not self.device.ownerId:
- logger.error('This device cant find a dealer')
- return
- # 是否存在温感和电感
- temperaturePart = Part.objects(logicalCode = self.device['logicalCode'], partType = '3001')
- electricityPart = Part.objects(logicalCode = self.device['logicalCode'], partType = '3002')
- if not temperaturePart.count() or not electricityPart.count():
- logger.error(
- 'There are no transformers in the locigalcode {} equipment'.format(self.device['logicalCode']))
- return
- # 处理数据
- eventInfo = self.__Analyze_alert_data(self.event_data['data'])
- try:
- # 先处理高温情况
- if 'temperature' in eventInfo:
- for InfoDetail in eventInfo['temperature']:
- send_event_to_zhejiang(self.dealer, self.device, InfoDetail, partId = temperaturePart[0].id)
- # 提示用户
- group = Group.get_group(self.device['groupId'])
- self.notify_dealer('device_fault', **{
- 'title': u'注意!注意!您的设备发生故障',
- 'device': u'组号::%s, 二维码编号:%s' % (self.device['groupNumber'], self.device['logicalCode']),
- 'location': u'组名称:%s, 地址:%s' % (group['groupName'], group['address']),
- 'fault': InfoDetail['reason'],
- 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- # 上报高温至消防
- # if self.device["ownerId"] in ("5b4ed32e8732d67bd0626528", "5b6c29388732d669f3ae6f94"):
- group = Group.get_group(self.device['groupId'])
- districtInfo = District.get_district(group["districtId"])
- self.device.update({"districtInfo": districtInfo, "groupAddr": group["address"]})
- LiangXiXiaoFang.send_to_xf_fault(self.device, "01", u"设备温度过高")
- # 处理漏电情况
- elif 'electricity' in eventInfo:
- # 获取漏电告警插件
- send_event_to_zhejiang(self.dealer, self.device, eventInfo['electricity'],
- partId = electricityPart[0].id)
- # 提示用户
- group = Group.get_group(self.device['groupId'])
- self.notify_dealer('device_fault', **{
- 'title': u'注意!注意!您的设备发生故障',
- 'device': u'组号::%s, 二维码编号:%s' % (self.device['groupNumber'], self.device['logicalCode']),
- 'location': u'组名称:%s, 地址:%s' % (group['groupName'], group['address']),
- 'fault': eventInfo['electricity']['reason'],
- 'notifyTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
- # 上报漏电至消防
- # if self.device["ownerId"] in ("5b4ed32e8732d67bd0626528", "5b6c29388732d669f3ae6f94"):
- group = Group.get_group(self.device['groupId'])
- districtInfo = District.get_district(group["districtId"])
- self.device.update({"districtInfo": districtInfo, "groupAddr": group["address"]})
- LiangXiXiaoFang.send_to_xf_fault(self.device, "04", u"设备发生漏电")
- except:
- logger.error('Array {} nonspecification'.format(eventInfo))
- return
- self.record(detail = eventInfo)
- class InteroperatorReport(WorkEvent):
- def do(self, **args):
- if 'type' not in self.event_data:
- logger.error('Array {} is not format,lose a key named "type"'.format(self.event_data))
- if self.event_data.get('type') == 'report':
- devReportDict = {'logicalCode': 'logicalCode', 'time': self.event_data['time_stamp'], 'portInfo': {}}
- temperature = ''
- voltage = 220
- try:
- # 拿到个数判断是不是第一次
- reportNum = PortReport.get_collection().find({
- 'logicalCode': self.device['logicalCode']
- }).sort('time', -1).count()
- if reportNum:
- # 获取上一次存储的信息
- reportLast = PortReport.get_collection().find({
- 'logicalCode': self.device['logicalCode']
- }).sort('time', -1)[0]
- for ii in range(10):
- power = self.__saveDate(1, msgDict = self.event_data, ii = ii)
- if power:
- electricity = float(power) / voltage / 10
- else:
- electricity = reportLast['portInfo'][str(ii + 1)]['electricity']
- temperatureR = self.__saveDate(2, msgDict = self.event_data, ii = ii, electricity = electricity,
- devReportDict = devReportDict)
- if temperatureR:
- temperature = temperatureR
- devReportDict.update({'temperature': temperature})
- # 查看现在的跟以前差距多少
- timeInterval = devReportDict['time'] - reportLast['time']
- if timeInterval > 2:
- PortReportNewList = [
- {"logicalCode": self.device['logicalCode'], "temperature": reportLast['temperature'],
- 'portInfo': reportLast['portInfo'],
- 'time': reportLast['time'] + (v + 1) * 2}
- for v in range(int(timeInterval / 2) - 1)]
- PortReport.get_collection().insert_many(PortReportNewList)
- # 首存的情况
- else:
- for ii in range(10):
- power = self.__saveDate(1, msgDict = self.event_data, ii = ii)
- electricity = float(power) / voltage / 10
- temperatureR = self.__saveDate(2, msgDict = self.event_data, ii = ii, electricity = electricity,
- devReportDict = devReportDict)
- if temperatureR:
- temperature = temperatureR
- devReportDict.update({'temperature': temperature})
- except Exception, e:
- logger.error('solve dev=%s device report has an error e=%s' % (self.device.devNo, e))
- finally:
- newInfo = PortReport(
- logicalCode = self.device['logicalCode'],
- temperature = devReportDict['temperature'],
- time = devReportDict['time'],
- portInfo = devReportDict['portInfo']
- )
- newInfo.save()
- def __saveDate(self, data, msgDict, ii, electricity = None, devReportDict = None):
- # 存储数据库
- if data == 1:
- powerData = msgDict['data']['power_data'][0 + 4 * ii:4 + 4 * ii]
- power = int(powerData, 16)
- return power
- if data == 2:
- temperature = ''
- status = 'idle' if electricity == 0 else 'busy'
- devReportDict['portInfo'].update(
- {str(ii + 1): {'electricity': round(electricity, 3), 'status': status}})
- if ii < 4 and msgDict['data']['temp_data'][0 + 4 * ii:4 + 4 * ii] != '0000':
- temperatureNum = msgDict['data']['temp_data'][0 + 4 * ii:4 + 4 * ii]
- temperature = int(temperatureNum, 16)
- return temperature
- class StartAckEventPreProcessor(AckEventProcessorIntf):
- def analysis_reason(self, reason):
- return FINISHED_CHARGE_REASON_MAP.get(reason, reason)
- def pre_processing(self, device, event_data):
- # type:(DeviceDict, dict)->dict
- if 'duration' in event_data:
- duration = event_data.get('duration')
- event_data['duration'] = ((duration + 59) / 60)
- if 'elec' in event_data:
- elec = event_data.get('elec')
- event_data['elec'] = round(elec / (10000.0 * 3600.0), 3)
- if 'cardType' in event_data:
- if event_data['cardType'] == 'AA33':
- event_data['cardType'] = 'ID'
- else:
- event_data['cardType'] = 'IC'
- if 'cardNo' in event_data:
- event_data['cardNo'] = str(event_data['cardNo'])
- if 'reason' in event_data:
- event_data['reasonDesc'] = self.analysis_reason(event_data['reason'])
- if 'fee' in event_data:
- event_data['fee'] = (RMB(event_data['fee']) * Ratio("0.1"))
- if 'balance' in event_data:
- event_data['balance'] = (RMB(event_data['balance']) * Ratio("0.1"))
- if 'backMoney' in event_data:
- event_data['backMoney'] = (RMB(event_data['backMoney']) * Ratio("0.1"))
- if 'sub' in event_data:
- subs = event_data.get('sub', [])
- for item in subs:
- if 'fee' in item:
- item['fee'] = (RMB(item['fee']) * Ratio('0.1'))
- if 'balance' in item:
- item['balance'] = (RMB(item['balance']) * Ratio('0.1'))
- if 'left' in event_data:
- event_data['left'] = event_data.pop('left')
- else:
- event_data['left'] = 0
- return event_data
- class CardRefundAckEventPreProcessor(AckEventProcessorIntf):
- def pre_processing(self, device, event_data):
- # type:(DeviceDict, dict)->dict
- if 'cardType' in event_data:
- if event_data['cardType'] == 'AA33':
- event_data['cardType'] = 'ID'
- else:
- event_data['cardType'] = 'IC'
- if 'cardNo' in event_data:
- event_data['cardNo'] = str(event_data['cardNo'])
- event_data['backMoney'] = (int(event_data['backMoney']) / 10.0)
- return event_data
- class MyComNetPayAckEvent(ComNetPayAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyComNetPayAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- def post_after_start(self, order = None):
- port = order.used_port
- YuhuanNorther.send_dev_status(self.device, int(port), 1)
- def post_after_finish(self, order = None):
- port = order.used_port
- if self.event_data['reason'] < 0:
- logger.debug('reason<{}> is not to report.'.format(self.event_data['reason']))
- return
- notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
- desc = self.event_data.get('reasonDesc', ''))
- send_event_to_zhejiang(self.dealer, self.device, self.event_data)
- if self.event_data['reason'] == '04':
- YuhuanNorther.send_dev_event(self.device, '97', port)
- YuhuanNorther.send_dev_event(self.device, '98', port)
- # 发送一条端口使用结束的告警
- YuhuanNorther.send_dev_status(self.device, port, 2)
- def merge_order(self, master_order, sub_orders):
- # type:(ConsumeRecord, list)->dict
- order_value, unit, billingType = self.deviceAdapter._check_package(master_order.package)
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
- portDict = {
- 'billingType': billingType
- }
- if master_order.paymentInfo['via'] == 'virtualCard':
- portDict.update({
- 'vCardId': master_order.paymentInfo['itemId']
- })
- all_coins = master_order.package['coins']
- all_price = master_order.package['price']
- all_consume_value = order_value
- for sub_order in sub_orders:
- all_coins += sub_order.package['coins']
- all_price += sub_order.package['price']
- sub_consume_value, _, _ = self.deviceAdapter._check_package(sub_order.package)
- all_consume_value += sub_consume_value
- portDict['coins'] = str(all_coins)
- portDict['price'] = str(all_price)
- if billingType == 'time':
- portDict['needKind'] = 'needTime'
- portDict['needValue'] = all_consume_value
- portDict['unit'] = u'分钟'
- portDict['estimatedTs'] = int(start_time.timestamp + all_consume_value * 60)
- else:
- portDict['needKind'] = 'needElec'
- portDict['needValue'] = all_consume_value / 100.0
- portDict['unit'] = u'度'
- portDict['estimatedTs'] = int(start_time.timestamp + 12 * 60 * 60)
- return portDict
- def do_time_finished(self, master_order, sub_orders, merge_order_info):
- # type: (ConsumeRecord, List[ConsumeRecord], dict)->(dict)
- user = MyUser.objects(openId = master_order.openId,
- groupId = master_order.groupId).first() # type: MyUser
- if not user:
- logger.error(
- 'user is not exist. openId = {}, groupId = {}'.format(master_order.openId, master_order.groupId))
- return
- coins = VirtualCoin(merge_order_info['coins'])
- left = self.event_data['left']
- if left == 65535:
- consumeDict = {
- 'reason': self.event_data['reason'],
- 'leftTime': '端口故障',
- 'chargeIndex': str(master_order.used_port),
- 'actualNeedTime': u'动态功率计算为0分钟',
- 'duration': 0,
- 'elec': 0,
- 'elecFee': 0
- }
- real_back_coins = coins
- back_coins = coins
- else:
- duration, elec = self.event_data['duration'], self.event_data['elec']
- actual_time = duration + left
- if (actual_time == 0) or (actual_time > merge_order_info['needValue'] * 60):
- actual_time = merge_order_info['needValue'] * 60
- real_back_coins = coins * (float(left) / float(actual_time))
- consumeDict = {
- 'reason': self.event_data['reason'],
- 'leftTime': str(left),
- 'chargeIndex': str(master_order.used_port),
- 'actualNeedTime': u'动态功率计算为%s分钟' % actual_time,
- 'duration': duration,
- 'elec': elec,
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- if master_order.paymentInfo['via'] == 'free':
- back_coins = VirtualCoin(0)
- else:
- refundProtection = self.device.get('otherConf', {}).get('refundProtection', 0)
- refundProtectionTime = self.device.get('otherConf', {}).get('refundProtectionTime', 5)
- auto_refund = self.device.is_auto_refund
- logger.debug('{} auto refund enable switch is {}. refund protect = {}, refund protect time = {}'.format(
- repr(self.device), str(auto_refund), refundProtection, refundProtectionTime))
- if auto_refund:
- if (refundProtection == 1 and duration < refundProtectionTime):
- back_coins = coins
- else:
- back_coins = real_back_coins
- else:
- back_coins = VirtualCoin(0)
- if back_coins > coins:
- back_coins = coins
- logger.debug(
- 'lefttime = {}, usedTime = {}, need time = {}, real back coins = {}, back coins = {}'.format(
- left, duration, actual_time, real_back_coins, back_coins))
- extra = []
- if master_order.paymentInfo['via'] == 'free':
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(0))})
- elif master_order.paymentInfo['via'] == 'virtualCard':
- vCard = UserVirtualCard.objects(id = master_order.virtual_card_id).first() # type: UserVirtualCard
- if not vCard:
- logger.info('can not find the vCard id = {}'.format(master_order.virtual_card_id))
- return
- if back_coins > VirtualCoin(0):
- success, consumeTotal, consumeDay = vCard.clear_frozen_quota(str(master_order.id), duration, 0.0,
- back_coins.mongo_amount)
- try:
- if success and consumeDay['count'] > 0:
- record = VCardConsumeRecord(
- orderNo = VCardConsumeRecord.make_no(master_order.logicalCode),
- openId = master_order.openId,
- nickname = master_order.nickname,
- cardId = str(vCard.id),
- dealerId = vCard.dealerId,
- devNo = master_order.devNo,
- devTypeCode = self.device.devTypeCode,
- devTypeName = self.device.devTypeName,
- logicalCode = master_order.logicalCode,
- groupId = master_order.groupId,
- address = master_order.address,
- groupNumber = master_order.groupNumber,
- groupName = master_order.groupName,
- attachParas = master_order.attachParas,
- consumeData = consumeTotal,
- consumeDayData = consumeDay
- )
- record.save()
- except Exception, e:
- logger.exception(e)
- extra.append({u'虚拟卡号': vCard.cardNo})
- elif master_order.paymentInfo['via'] in ['netPay', 'coins', 'cash', 'coin']:
- user.clear_frozen_balance(str(master_order.id), master_order.paymentInfo['deduct'], back_coins,
- (coins - back_coins))
- for sub_order in sub_orders:
- user.clear_frozen_balance(str(sub_order.id), sub_order.paymentInfo['deduct'], VirtualCoin(0),
- VirtualCoin(0))
- if back_coins > VirtualCoin(0):
- consumeDict['refundedMoney'] = str(back_coins)
- extra.append({u'消费金额': '{}(金币)'.format(coins - back_coins)})
- extra.append({u'退款金额': '{}(金币)'.format(back_coins)})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(coins)})
- else:
- logger.error('not net pay rather user virtual card pay. something is wrong.')
- return
- master_order.update_service_info(consumeDict)
- auth_bridge = get_wechat_auth_bridge(source = self.device,
- app_type = APP_TYPE.WECHAT_USER_MANAGER)
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = user.get_bound_pay_openid(auth_bridge.bound_openid_key),
- port = str(master_order.used_port),
- address = master_order.address,
- reason = self.event_data.get('reasonDesc'),
- finished_time = master_order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- def do_elec_finished(self, master_order, sub_orders, merge_order_info):
- # type: (ConsumeRecord, List[ConsumeRecord], dict)->None
- """
- 电川的板子 按电量退费
- :return:
- """
- user = MyUser.objects(openId = master_order.openId,
- groupId = self.device.groupId).first() # type: MyUser
- if not user:
- logger.error('not find user<openId={}, groupId={}>'.format(master_order.openId, self.device.groupId))
- return
- leftElec = self.event_data.get("left", 0) / 100.0
- duration, elec = self.event_data['duration'], self.event_data['elec']
- try:
- consumeDict = {
- "reason": self.event_data['reasonDesc'],
- "chargeIndex": master_order.used_port,
- }
- # 获取组信息
- group = Group.get_group(self.device.groupId) # type: GroupDict
- # 扫码的结束
- needElec = merge_order_info['needValue']
- if leftElec == int("FFFF", 16):
- # 端口故障
- left = needElec
- elif leftElec > needElec:
- logger.error('left elec is bigger than need elec. something is wrong')
- left = 0
- spendElec = needElec - leftElec
- coins = VirtualCoin(merge_order_info['coins'])
- back_coins = VirtualCoin(0)
- if master_order.paymentInfo['via'] != 'free':
- auto_refund = self.device.is_auto_refund
- if auto_refund:
- back_coins = VirtualCoin(coins) * Ratio(leftElec / needElec)
- logger.debug(
- 'leftElec = {}, spendElec = {}, usedTime = {}, back coins = {}, auto refund = {}'.format(
- left, spendElec, duration, back_coins, auto_refund))
- else:
- logger.debug(
- 'leftElec = {}, spendElec = {}, usedTime = {}, back coins = {}, free = True'.format(
- left, spendElec, duration, back_coins))
- extra = []
- if master_order.paymentInfo['via'] == 'free':
- extra.append({u'消费金额': '{}(金币)'.format(VirtualCoin(0))})
- elif master_order.paymentInfo['via'] == 'virtualCard':
- vCard = UserVirtualCard.objects(id = master_order.virtual_card_id).first()
- if not vCard:
- logger.info('can not find the vCard id = %s' % master_order.virtual_card_id)
- return
- extra.append({u'虚拟卡号': vCard.cardNo})
- if back_coins > VirtualCoin(0):
- success, consumeTotal, consumeDay = vCard.clear_frozen_quota(str(master_order.id),
- needElec - spendElec,
- spendElec, back_coins)
- try:
- if success and consumeDay['count'] > 0:
- record = VCardConsumeRecord(
- orderNo = VCardConsumeRecord.make_no(master_order.logicalCode),
- openId = master_order.openId,
- nickname = master_order.nickname,
- cardId = str(vCard.id),
- dealerId = vCard.dealerId,
- devNo = master_order.devNo,
- devTypeCode = master_order.devTypeCode,
- devTypeName = master_order.dev_type_name,
- logicalCode = master_order.logicalCode,
- groupId = master_order.groupId,
- address = master_order.address,
- groupNumber = master_order.groupNumber,
- groupName = master_order.groupName,
- attachParas = master_order.attachParas,
- consumeData = consumeTotal,
- consumeDayData = consumeDay
- )
- record.save()
- except Exception, e:
- logger.exception(e)
- elif master_order.paymentInfo['via'] in ['netPay', 'coins', 'cash', 'coin']:
- user.clear_frozen_balance(str(master_order.id), master_order.paymentInfo['deduct'], back_coins,
- (coins - back_coins))
- for sub_order in sub_orders:
- user.clear_frozen_balance(str(sub_order.id), sub_order.paymentInfo['deduct'], VirtualCoin(0),
- VirtualCoin(0))
- if back_coins > VirtualCoin(0):
- consumeDict.update({"refundedMoney": str(back_coins)})
- extra.append({u'消费金额': '{}(金币)'.format(coins - back_coins)})
- extra.append({u'退款金额': '{}(金币)'.format(back_coins)})
- else:
- extra.append({u'消费金额': '{}(金币)'.format(coins)})
- else:
- logger.error('not net pay rather user virtual card pay. something is wrong.')
- return
- for order in [master_order].extend(sub_orders):
- if order.orderNo == master_order.orderNo:
- consumeDict.update({
- "duration": self.event_data['duration']
- })
- order.update_service_info(consumeDict)
- auth_bridge = get_wechat_auth_bridge(source = self.device,
- app_type = APP_TYPE.WECHAT_USER_MANAGER)
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = user.get_bound_pay_openid(auth_bridge.bound_openid_key),
- port = str(master_order.used_port),
- address = master_order.address,
- reason = self.event_data.get('reasonDesc'),
- finished_time = master_order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- except Exception as e:
- logger.exception(e)
- def do_finished_event(self, master_order, sub_orders, merge_order_info):
- # type: (ConsumeRecord, List[ConsumeRecord], dict)->None
- billing_type = merge_order_info['billingType']
- if billing_type == 'time':
- self.do_time_finished(master_order, sub_orders, merge_order_info)
- else:
- self.do_elec_finished(master_order, sub_orders, merge_order_info)
- class MyIcStartAckEvent(IcStartAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyIcStartAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- def post_after_start(self, order = None):
- port = order.used_port
- YuhuanNorther.send_dev_status(self.device, int(port), 1)
- def post_after_finish(self, order = None):
- port = order.used_port
- if self.event_data['reason'] < 0:
- logger.debug('reason<{}> is not to report.'.format(self.event_data['reason']))
- return
- notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
- desc = self.event_data.get('reasonDesc', ''))
- send_event_to_zhejiang(self.dealer, self.device, self.event_data)
- if self.event_data['reason'] == '04':
- YuhuanNorther.send_dev_event(self.device, '97', port)
- YuhuanNorther.send_dev_event(self.device, '98', port)
- # 发送一条端口使用结束的告警
- YuhuanNorther.send_dev_status(self.device, port, 2)
- def merge_order(self, master_order, sub_orders):
- # type:(ConsumeRecord, list)->dict
- consumeMode = self.device.get("otherConf", dict()).get("consumeMode", 0)
- # 按时间计费 线下免费模式
- if consumeMode == 0 or consumeMode == 2:
- billingType = 'time'
- else:
- billingType = 'elec'
- start_time = Arrow.fromdatetime(master_order.startTime, tzinfo = settings.TIME_ZONE)
- portDict = {
- 'billingType': billingType
- }
- if master_order.paymentInfo['via'] == 'virtualCard':
- portDict.update({
- 'vCardId': master_order.paymentInfo['itemId']
- })
- all_coins = master_order.coin
- all_money = master_order.money
- for sub_order in sub_orders:
- all_coins += master_order.coin
- all_money += master_order.money
- portDict['coins'] = str(all_coins)
- portDict['money'] = str(all_money)
- portDict['estimatedTs'] = int(start_time.timestamp + 12 * 60 * 60)
- return portDict
- def do_time_finished(self, card, order, merge_order_info):
- # type: (Card, ConsumeRecord, dict)->(dict)
- duration, elec = self.event_data['duration'], self.event_data['elec']
- coins = VirtualCoin(merge_order_info['coins'])
- left = self.event_data['left']
- consumeDict = {
- 'reason': self.event_data['reason'],
- 'chargeIndex': str(order.used_port),
- 'duration': duration,
- 'elec': elec,
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- # backMoney = VirtualCoin(self.event_data['backMoney'])
- group = self.device.group # type: GroupDict
- extra = [{
- u'实体卡号': self.event_data['cardNo']
- }]
- consumeDict.update({'balance': str(card.balance)})
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = card.managerialOpenId if card else '',
- port = order.used_port,
- address = group.address,
- reason = self.event_data['reason'],
- finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- def do_elec_finished(self, card, order, merge_order_info):
- # type:(Card, ConsumeRecord, dict)->None
- """
- 电川的板子 按电量退费
- :return:
- """
- leftElec = self.event_data.get('left', 0) / 100.0
- duration, elec = self.event_data['duration'], self.event_data['elec']
- try:
- consumeDict = {
- 'reason': self.event_data['reasonDesc'],
- 'chargeIndex': order.used_port,
- 'duration': duration,
- 'elec': elec,
- 'elecFee': self.deviceAdapter.calc_elec_fee(elec)
- }
- # backMoney = self.event_data.get("backMoney")
- extra = [{u'实体卡号': self.event_data['cardNo']}]
- # if self.event_data['cardType'] == 'ID':
- # if backMoney > 0:
- # self.refund_money_for_card(RMB(backMoney), card.id)
- # extra.append({
- # u'退款金额': u'{}(金币)'.format(backMoney)
- # })
- #
- # consumeDict.update({'balance': str(card.balance + VirtualCoin(self.event_data['backMoney']))})
- # else:
- consumeDict.update({'balance': str(card.balance)})
- order.update_service_info(consumeDict)
- self.notify_user_service_complete(
- service_name = u'充电',
- openid = self.get_managerialOpenId_by_openId(order.openId),
- port = order.used_port,
- address = self.device.group.address,
- reason = self.event_data['reason'],
- finished_time = order.finishedTime.strftime('%Y-%m-%d %H:%M:%S'),
- extra = extra)
- except Exception as e:
- logger.exception(e)
- def do_finished_event(self, card, order, merge_order_info):
- # type:(Card, ConsumeRecord, dict)->None
- if 'backMoney' in self.event_data and self.event_data['backMoney'] > RMB(0):
- refund_order = RechargeRecord.objects(orderNo = self.event_data['order_id']).first()
- if not refund_order:
- self.refund_money_for_card(RMB(self.event_data['backMoney']), card.id, self.event_data['order_id'])
- billing_type = merge_order_info['billingType']
- if billing_type == 'time':
- self.do_time_finished(card, order, merge_order_info)
- else:
- self.do_elec_finished(card, order, merge_order_info)
- class MyIcRechargeAckEvent(IcRechargeAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyIcRechargeAckEvent, self).__init__(smartBox, event_data, StartAckEventPreProcessor())
- class MyCardRefundAckEvent(CardRefundAckEvent):
- def __init__(self, smartBox, event_data):
- super(MyCardRefundAckEvent, self).__init__(smartBox, event_data, CardRefundAckEventPreProcessor())
|