1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import logging
- import time
- import datetime
- from mongoengine import DoesNotExist
- from apilib.utils_string import make_title_from_dict
- from apilib.monetary import VirtualCoin, Ratio, RMB
- from apps.web.constant import Const
- from apps.web.device.models import Device, Group
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.base import WorkEvent
- from apps.web.user.models import ConsumeRecord, ServiceProgress, MyUser, CardConsumeRecord, Card, VCardConsumeRecord, \
- UserVirtualCard
- from apps.web.user.transaction_deprecated import refund_money
- logger = logging.getLogger(__name__)
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- return BolaiTenWorkEvent(self.deviceAdapter, device_event)
- class BolaiTenWorkEvent(WorkEvent):
- def __translate_reason(self, cause):
- if cause == 0:
- return u'结束充电。'
- elif cause == 1:
- return u'正在充电的时候,结束了,可能是用户拔掉充电器,或者插座脱落,或者没有接入充电器'
- elif cause == 2:
- return u'充满自停。'
- elif cause == 3:
- return u'金额已经用完。'
- elif cause == 4:
- return u'平台下发停止充电'
- return u'充电结束。'
- # 网关心跳
- def event_gateway_heartbeat(self):
- rssi = self.event_data.get('rssi')
- logger.info('receive EVENT_GATEWAY_HEARTBEAT')
- Device.update_online_cache(self.device.devNo, True, rssi, (long(time.time() * 1000) - 600000))
- # 充电结束上报按量
- def do_finished_by_quantity(self, data):
- """
- {
- "type": "EVENT_CHARGE_FINISHED",
- "time": 1548141575, # 事件时间戳
- "gateway_id": "99503935742305", # 网关uid
- "data": {
- "node_index": 1, # 插座号
- "port_index": 1, # 插孔号
- "transaction_id": "1", # 业务号
- "charge_status": 2, # 0表示未充电,1表示充电,2表示充满自停 ,3金额用完(时间到)
- "time_consumed": 0, # 已耗时,单位分
- "energy_consumed": 0, # 已耗电能,单位Wh
- "flag_over_load": 0, # 过载标志
- "flag_no_load": 0, # 空载标志
- "flag_over_current": 0, # 过流标志
- }
- }
- """
- reason = self.__translate_reason(data['data']['charge_status'])
- orderNo = data['data']['transaction_id']
- dev = self.device
- devNo = dev['devNo']
- consumeRcd = ConsumeRecord.objects.filter(sequanceNo=orderNo).first()
- if not consumeRcd: # 投币的不会生成订单
- return
- port = consumeRcd.attachParas['chargeIndex']
- try:
- servicedInfo = consumeRcd.servicedInfo
- cardNo = servicedInfo.get('cardNo') or ''
- if cardNo:
- data['data'].update({'card_no': cardNo})
- self.do_card_finished(data)
- except Exception, e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (devNo, e))
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo,
- port=int(port), isFinished=False).first() # type: ServiceProgress
- if progress is None:
- return
- progress.status = 'finished'
- progress.isFinished = True
- progress.expireAt = datetime.datetime.now()
- progress.save()
- try:
- group = Group.get_group(dev['groupId'])
- billingType = servicedInfo['billingType']
- usedTime = data['data']['time_consumed']
- usedElec = data['data']['energy_consumed'] * 0.001
- consumeDict = {
- 'reason': reason,
- 'chargeIndex': str(port),
- 'duration': usedTime,
- 'elec': usedElec
- }
- consumeDict.update(servicedInfo)
- notifyDict = {
- 'service': u'充电服务完成',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- }
- refundDict = {
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- coins = consumeRcd.coin
- if billingType == 'time': # 按照时间计费
- needTime = servicedInfo['needTime']
- leftTime = needTime - usedTime if needTime > usedTime else 0
- leftTimeStr = leftTime
- consumeDict.update({
- 'needTime': needTime,
- 'leftTime': leftTimeStr,
- })
- titleDictList = [
- {u'设备编号': devNo},
- {u'端口': str(port)},
- {u'地址': group['address']},
- {u'结束原因': reason},
- {u'订购时间': u'%s分钟' % needTime},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'剩余时间': u'%s分钟' % leftTimeStr}
- ]
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
- backCoins = Ratio(float(leftTime) / float(needTime)) * VirtualCoin(coins)
- titleDictList = [
- {u'设备编号': devNo},
- {u'端口': str(port)},
- {u'付款': u'%s元' % coins},
- {u'预定时间': u'%s分钟' % needTime},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'剩余时间': u'%s分钟' % leftTimeStr},
- ]
- refundDict.update(
- {
- 'title': make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
- else: # 按电量付费的
- needElec = servicedInfo['needElec']
- leftElec = needElec - usedElec if needElec > usedElec else 0.0
- consumeDict.update({
- 'needElec': needElec,
- 'leftElec': leftElec
- })
- titleDictList = [
- {u'设备编号': devNo},
- {u'端口': str(port)},
- {u'结束原因': reason},
- {u'订购电量': u'%s度' % needElec},
- {u'消耗电量': u'%s度' % usedElec},
- {u'剩余电量': u'%s度' % leftElec},
- ]
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
- backCoins = Ratio(float(leftElec) / float(needElec)) * VirtualCoin(coins)
- titleDictList = [
- {u'设备编号': devNo},
- {u'端口': str(port)},
- {u'结束原因': reason},
- {u'订购电量': u'%s度' % needElec},
- {u'消耗电量': u'%s度' % usedElec},
- {u'剩余电量': u'%s度' % leftElec},
- ]
- refundDict.update(
- {
- 'title': make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
- if u'虚拟卡' in consumeRcd.remarks:
- # 退额度
- try:
- vRcd = VCardConsumeRecord.objects.get(orderNo=consumeRcd.orderNo)
- vCard = UserVirtualCard.objects.get(id=vRcd.cardId)
- except DoesNotExist, e:
- logger.info('can not find the vCard id = %s' % vRcd.cardId)
- return
- # 通知服务结束
- notifyOpenId = self.get_managerialOpenId_by_openId(vRcd.openId) if vCard else ''
- self.notify_user(notifyOpenId, 'service_complete', **notifyDict)
- # 不需要退款,直接返回,不通知
- if self.device.is_auto_refund:
- refundProtectionTime = self.device.get("otherConf", dict()).get("refundProtectionTime", 5)
- if usedTime <= refundProtectionTime:
- backCoins = coins
- if billingType == 'time':
- vCard.refund_quota(vRcd, usedTime, 0.0, backCoins.mongo_amount)
- else:
- vCard.refund_quota(vRcd, 0.0, usedElec, backCoins.mongo_amount)
- else: # 扫码的
- user = MyUser.objects(openId=consumeRcd.openId, groupId=dev['groupId']).first()
- if not user:
- return
- # 通知服务结束
- notifyOpenId = user.managerialOpenId if user else ''
- self.notify_user(notifyOpenId, 'service_complete', **notifyDict)
- # 如果需要退款,计算退款数据.
- if self.device.is_auto_refund:
- refundProtectionTime = self.device.get("otherConf", dict()).get("refundProtectionTime",5)
- if usedTime <= refundProtectionTime:
- backCoins = coins
- consumeDict.update({'refundedMoney': str(backCoins)})
- refund_money(dev, backCoins, consumeRcd.openId)
- self.notify_user(notifyOpenId, 'refund_coins', **refundDict)
- ServiceProgress.update_progress_and_consume_rcd(dev['ownerId'], {
- "open_id": notifyOpenId,
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False
- },
- consumeDict)
- except Exception, e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (devNo, e))
- finally:
- Device.clear_port_control_cache(self.device.devNo,port)
- self.deviceAdapter.get_port_status_from_dev()
- # 充电结束上报按功率
- def do_finished_by_power(self, data):
- """
- {
- "type": "EVENT_CHARGE_FINISHED_3",
- "time": 1548141575, # 事件时间戳
- "gateway_id": "99503935742305", # 网关uid
- "data": {
- "node_index": 1, # 插座号
- "port_index": 1, # 插孔号
- "charge_status": 2, # 0表示未充电,1表示充电,2表示充满自停 ,3金额用完(时间到)
- "flag_over_load": 0, # 过载标志
- "flag_no_load": 0, # 空载标志
- "flag_over_current": 0, # 过流标志
- "transaction_id": "1", # 业务号
- "power": 1, # 当前功率
- "current": 1, # 当前电流
- "energy_consumed": 0, # 已耗电能,单位Wh
- "time_consumed": 0, # 已耗时,单位分
- "finish_time": 1548141575, # 结束时间
- "finish_reason": 2, # 结束原因,1表示充满自停,2表示异常停止,3表示正常停止(时间到),4平台下发停止
- "money_consumed": 100, # 该参数禁止使用
- "settle_power": 600, # 结算功率,单位W
- "power_time_stat": "2,0" # 结算功率档位时间统计,时间用半角逗号","隔开,单位分
- }
- }
- """
- reason = self.__translate_reason(data['data']['charge_status'])
- orderNo = data['data']['transaction_id']
- dev = self.device
- devNo = dev['devNo']
- consumeRcd = ConsumeRecord.objects.filter(sequanceNo=orderNo).first()
- if not consumeRcd: # 投币的不会生成订单
- return
- port = consumeRcd.attachParas['chargeIndex']
- try:
- servicedInfo = consumeRcd.servicedInfo
- cardNo = servicedInfo.get('cardNo') or ''
- if cardNo:
- data['data'].update({'card_no': cardNo})
- self.do_card_finished(data)
- except Exception, e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (devNo, e))
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo,
- port=int(port), isFinished=False).first() # type: ServiceProgress
- if progress is None or progress.status == 'finished':
- return
- progress.status = 'finished'
- progress.isFinished = True
- progress.expireAt = datetime.datetime.now()
- progress.save()
- try:
- group = Group.get_group(dev['groupId'])
- spendMoney = self.calc_spend_money(data)
- coins = consumeRcd.coin
- if spendMoney >= coins:
- spendMoney = coins
- usedTime = data['data']['time_consumed']
- usedElec = data['data']['energy_consumed']
- consumeDict = {
- 'reason': reason,
- 'chargeIndex': str(int(port)+1),
- 'spendMoney': str(spendMoney),
- 'settlePower': data['data']['settle_power'],
- 'usedTime': usedTime,
- 'usedElec': usedElec,
- 'power': data['data']['power'],
- 'current': data['data']['current']
- }
- consumeDict.update(consumeRcd.servicedInfo)
- notifyDict = {
- 'service': u'充电服务完成',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- }
- refundDict = {
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- backCoins = coins - spendMoney if coins > spendMoney else VirtualCoin(0.0)
- usedTime = data['data']['time_consumed']
- consumeDict.update({
- 'duration': usedTime,
- })
- titleDictList = [
- {u'设备编号': devNo},
- {u'端口': str(port)},
- {u'地址': group['address']},
- {u'结束原因': reason},
- {u'结算功率': u'%s瓦' % data['data']['settle_power']},
- {u'使用时间': u'%s分钟' % usedTime}
- ]
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
- refundDict.update(
- {
- 'title': make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
- if u'虚拟卡' in consumeRcd.remarks:
- # 退额度
- try:
- vRcd = VCardConsumeRecord.objects.get(orderNo=consumeRcd.orderNo)
- vCard = UserVirtualCard.objects.get(id=vRcd.cardId)
- except DoesNotExist, e:
- logger.info('can not find the vCard id = %s' % vRcd.cardId)
- return
- # 通知服务结束
- notifyOpenId = self.get_managerialOpenId_by_openId(vRcd.openId) if vCard else ''
- self.notify_user(notifyOpenId, 'service_complete', **notifyDict)
- # 不需要退款,直接返回,不通知
- if self.device.is_auto_refund:
- refundProtectionTime = self.device.get("otherConf", dict()).get("refundProtectionTime", 5)
- if usedTime <= refundProtectionTime:
- backCoins = coins
- vCard.refund_quota(vRcd, 0.0, 0.0, backCoins.mongo_amount)
- else: # 扫码的
- user = MyUser.objects(openId=consumeRcd.openId, groupId=dev['groupId']).first()
- if not user:
- return
- # 通知服务结束
- notifyOpenId = user.managerialOpenId if user else ''
- self.notify_user(notifyOpenId, 'service_complete', **notifyDict)
- # 如果需要退款,计算退款数据.
- if self.device.is_auto_refund:
- refundProtectionTime = self.device.get("otherConf", dict()).get("refundProtectionTime", 5)
- if usedTime <= refundProtectionTime:
- backCoins = coins
- consumeDict.update({'refundedMoney': str(backCoins)})
- refund_money(dev, backCoins, consumeRcd.openId)
- self.notify_user(notifyOpenId, 'refund_coins', **refundDict)
- ServiceProgress.update_progress_and_consume_rcd(dev['ownerId'], {
- "open_id": notifyOpenId,
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False
- },
- consumeDict)
- except Exception, e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (devNo, e))
- finally:
- self.deviceAdapter.get_port_status_from_dev()
- # NFC刷卡充电启动上报
- def do_card_start(self, data):
- """
- {
- "type": "EVENT_NFC_CHARGE_STARTED", # 组网版事件名称
- "type": "EVENT_CARD_CHARGE_STARTED", # 独立版 & 六路机 & 十二路机事件名称(组网版中带金额上报事件也为该事件)
- "time": 1548141575, # 事件时间戳
- "gateway_id": "99503935742305", # 网关uid
- "data": {
- "node_index": 1, # 插座号
- "port_index": 1, # 插孔号
- "charge_status": 2, # 0表示未充电,1表示充电,2表示充满自停 ,3金额用完(时间到)
- "flag_over_load": 0, # 过载标志
- "flag_no_load": 0, # 空载标志
- "flag_over_current": 0, # 过流标志
- "transaction_id": "1", # 业务号
- "card": {
- "no": "112233445566", # 卡号
- "charge_money":888, # 12路机专有,表示用户选择刷卡扣费的金额,单位0.01元。
- "type": 1, # 卡类型,0表示在线卡,1表示离线卡目前对接,只支持在线卡对接, 离线卡不考虑
- "balance": 100, # [仅离线卡含此字段]余额
- "charge_type": 3, # [仅离线卡含此字段]结算类型,1表示按时,2表示按量,3表示分功率
- "charge_limit_per_transaction": 1, # [仅离线卡含此字段]一次消费额度,单位元
- "price_by_time": 1, # [仅离线卡含此字段]按时单价
- "price_by_power": 1, # [仅离线卡含此字段]按量单价
- "power_config": [{
- "power": 200, # 档位
- "price": 1 # 单价
- },
- {
- "power": 400, # 目前对接,只支持在线卡对接, 离线卡不考虑
- "price": 1
- },
- {
- "power": 600,
- "price": 1
- },
- {
- "power": 800,
- "price": 1
- }] # [仅离线卡含此字段]分功率配置
- }
- }
- }
- """
- cardInfo = data['data'].get('card') # 获取上报的卡信息
- if not cardInfo:
- logger.debug("bolaiTen_get null card infomation from {}".format(repr(self.device)))
- return
- cardNo = cardInfo.get('no').upper() # 获取上报卡号
- if not cardNo:
- logger.debug("bolaiTen get null card number from {}".format(repr(self.device)))
- return
- card = self.find_card_by_card_no(cardNo) # 查找此卡是否存在
- if not card:
- logger.debug("bolaiTen get null card from {}".format(repr(self.device)))
- return
- self.update_card_dealer_and_type(cardNo)
- port = self.event_data['data']['port_index'] # 获取上报需要启动的端口号
- chargeMoney = self.event_data['data']['card']['charge_money'] * 0.01 # 总刷卡金额
- # 获取卡充电相关配置
- otherConf = self.device.my_obj.otherConf
- billingType = otherConf.get('billingType', 'time') # elec :电量 time:时间 power:功率
- config_list = otherConf.get('config_list', []) # 参数设置中,将分档功率存入otherConf
- onceCard = otherConf.get('onceCard', 100) # 参数设置中,将刷一次卡所以需要消费的金额存入otherConf
- cardTime = otherConf.get('cardTime', 180) # 参数设置中,将刷一次卡获得的充电时间存入otherConf
- cardElec = otherConf.get('cardElec', 1) # 参数设置中,将刷一次卡获得的电量存入otherConf
- cardTimes = chargeMoney / onceCard # 刷卡次数
- if card.balance < RMB(onceCard * 0.01): # 如果卡内约小于1分钱,则不给启动
- return
- if card.frozen: # 如果卡被冻结,则不给启动
- return
- # 组合启动设备所需要的参数
- jsonPara = {
- 'gateway_id': data['gateway_id'],
- 'port_index': port,
- 'node_index': 0,
- # 'transaction_id': sequanceNo,
- 'switch_state': 1,
- 'timeout': 15,
- 'control__type': 2,
- }
- servicedInfo = {}
- if billingType == 'time':
- jsonPara.update({
- 'charge_type': 1,
- 'charge_time': cardTimes * cardTime,
- 'charge_energy': 0
- })
- servicedInfo.update(
- {'billingType': 'time', 'cardNo': cardNo,
- 'needTime': cardTime * cardTimes,'unit':'分钟'})
- finishedTime = int(time.time()) + cardTime * cardTimes * 60
- elif billingType == 'elec':
- jsonPara.update({
- 'charge_type': 2,
- 'charge_energy': cardTimes * cardElec * 1000,
- 'charge_time': 0
- })
- servicedInfo.update(
- {'billingType': 'elec', 'cardNo': cardNo,
- 'needElec': cardTimes * cardElec,'unit':'度'})
- finishedTime = int(time.time()) + 60 * 60 * 10
- else:
- jsonPara.update({
- 'charge_type': 3,
- 'charge_power': {'money': onceCard, 'config_list': config_list}
- })
- servicedInfo.update(
- {'billingType': 'power', 'cardNo': cardNo,
- 'configList': config_list,'unit':'瓦'})
- finishedTime = int(time.time()) + 60 * 60 * 10
- devInfo = self.deviceAdapter._start_device(jsonPara)
- if devInfo['data']['code'] != 0:
- logger.info('start device by card failed,devNo=%s', self.device.devNo)
- return
- if devInfo['rst'] != 0: # 成功
- logger.info('start device by card failed,devNo=%s', self.device.devNo)
- return
- port = port + 1
- newValue = {
- str(port): {
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'controlType': 1
- }
- }
- sequanceNo = devInfo['data']['data']['transaction_id']
- newValue[str(port)].update({'finishedTime': finishedTime, 'sequanceNo': sequanceNo})
- Device.clear_port_control_cache(self.device['devNo'], port)
- Device.update_dev_control_cache(self.device['devNo'], newValue)
- attachParas = {'category': 'chargeIndex', 'chargeIndex': port}
- order, card_order = self.new_card_consume_record(card=card,
- money=RMB(onceCard),
- sid=sequanceNo,
- servicedInfo=servicedInfo,
- attachParas=attachParas)
- self.create_progress_for_card(self.device, order, port, card_order,attachParas)
- self.consume_money_for_card(card, RMB(onceCard))
- # NFC刷卡充电结束上报
- def do_card_finished(self, data):
- """
- {
- "type": "EVENT_NFC_CHARGE_FINISHED", # 组网版事件名称
- "type": "EVENT_CARD_CHARGE_FINISHED", # 独立版&六路机事件名称
- "time": 1548141575, # 事件时间戳
- "gateway_id": "99503935742305", # 网关uid
- "data": {
- "node_index": 1, # 插座号
- "port_index": 1, # 插孔号
- "charge_status": 2, # 0 表示未充电,1 表示充电,2 表示充满自停 ,3金额用完(时间到)
- "flag_over_load": 0, # 过载标志
- "flag_no_load": 0, # 空载标志
- "flag_over_current": 0, # 过流标志
- "transaction_id": "1", # 业务号
- "power": 1, # 当前功率
- "current": 1, # 当前电流
- "energy_consumed": 0, # 已耗电能,单位Wh
- "time_consumed": 0, # 已耗时,单位分
- "card_no": "112233445566", # 卡号
- "card_type": 0, # 卡类型,0表示在线卡,1表示离线卡
- "charge_type": 3, # 结算类型,1表示按时,2表示按量,3表示分功率
- "money_consumed": 100, # 该参数禁止使用
- "settle_power": 600, # 结算功率,单位W
- "power_time_stat": "2,0" # 结算功率档位时间统计,时间用半角逗号","隔开,单位分
- }
- }
- """
- reason = self.__translate_reason(data['data']['charge_status'])
- sequanceNo = data['data']['transaction_id']
- devNo = self.device.devNo
- order = ConsumeRecord.objects.filter(sequanceNo=sequanceNo).first()
- if not order: # 投币的不会生成订单
- return
- port = order.attachParas['chargeIndex']
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo,
- port=int(port), isFinished=False).first() # type: ServiceProgress
- if progress is None or progress.status == 'finished':
- return
- progress.status = 'finished'
- progress.isFinished = True
- progress.expireAt = datetime.datetime.now()
- progress.save()
- try:
- group = Group.get_group(self.device.groupId)
- servicedInfo = order.servicedInfo
- billingType = servicedInfo['billingType']
- usedTime = data['data']['time_consumed']
- usedElec = data['data']['energy_consumed'] * 0.001
- consumeDict = {
- 'reason': reason,
- 'chargeIndex': port,
- 'duration': usedTime,
- 'elec': usedElec
- }
- consumeDict.update(servicedInfo)
- notifyDict = {
- 'service': u'充电服务完成',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- }
- refundDict = {
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- coins = order.coin
- if billingType == 'time': # 按照时间计费
- needTime = servicedInfo['needTime']
- leftTime = needTime - usedTime if needTime > usedTime else 0
- consumeDict.update({
- 'needTime': needTime,
- 'leftTime': leftTime,
- })
- titleDictList = [
- {u'设备编号': self.device.logicalCode},
- {u'端口': str(port)},
- {u'地址': group['address']},
- {u'结束原因': reason},
- {u'订购时间': u'%s分钟' % needTime},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'剩余时间': u'%s分钟' % leftTime}
- ]
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
- backCoins = coins * (float(leftTime) / float(needTime))
- titleDictList = [
- {u'设备编号': self.device.logicalCode},
- {u'端口': str(port)},
- {u'付款': u'%s元' % coins},
- {u'预定时间': u'%s分钟' % needTime},
- {u'充电时间': u'%s分钟' % usedTime},
- {u'剩余时间': u'%s分钟' % leftTime},
- ]
- refundDict.update(
- {
- 'title': make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
- elif billingType == 'elec': # 按电量付费的
- needElec = servicedInfo['needElec']
- leftElec = needElec - usedElec if needElec > usedElec else 0.0
- consumeDict.update({
- 'needElec': needElec,
- 'leftElec': leftElec
- })
- titleDictList = [
- {u'设备编号': self.device.logicalCode},
- {u'端口': str(port) },
- {u'结束原因': reason},
- {u'订购电量': u'%s度' % needElec},
- {u'消耗电量': u'%s度' % usedElec},
- {u'剩余电量': u'%s度' % leftElec},
- ]
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
- backCoins = coins * (float(leftElec) / float(needElec))
- titleDictList = [
- {u'设备编号': self.device.logicalCode},
- {u'端口': str(port)},
- {u'结束原因': reason},
- {u'订购电量': u'%s度' % needElec},
- {u'消耗电量': u'%s度' % usedElec},
- {u'剩余电量': u'%s度' % leftElec},
- ]
- refundDict.update(
- {
- 'title': make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
- else: # 功率付费
- spendMoney = self.calc_spend_money(data)
- if spendMoney >= coins:
- spendMoney = coins
- consumeDict.update(
- {
- 'settlePower': data['data']['settle_power'],
- 'power': data['data']['power'],
- 'current': data['data']['current'],
- 'spendMoney': str(spendMoney),
- }
- )
- consumeDict.update(order.servicedInfo)
- notifyDict = {
- 'service': u'充电服务完成',
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- }
- refundDict = {
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- coins = order.coin
- backCoins = coins - spendMoney if coins > spendMoney else VirtualCoin(0.0)
- usedTime = data['data']['time_consumed']
- consumeDict.update({
- 'duration': usedTime,
- })
- titleDictList = [
- {u'设备编号': self.device.logicalCode},
- {u'端口': str(port)},
- {u'地址': group['address']},
- {u'结束原因': reason},
- {u'结算功率': u'%s瓦' % data['data']['settle_power']},
- {u'使用时间': u'%s分钟' % usedTime}
- ]
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
- refundDict.update(
- {
- 'title': make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
- dealer = self.device.owner
- card = Card.objects.filter(agentId=dealer.agentId, cardNo=str(servicedInfo['cardNo'])).first()
- if card is None: # 离线卡没有绑定或者在线卡被解绑了
- return
- # 先通知
- notifyOpenId = card.managerialOpenId if card else ''
- self.notify_user(notifyOpenId, 'service_complete', **notifyDict)
- # 不需要退款,直接返回.在线卡需要退费,离线卡只登记使用记录就OK
- if self.device.is_auto_refund and card.cardType == 'ID':
- refundProtectionTime = self.device.get("otherConf", dict()).get("refundProtectionTime", 5)
- if usedTime <= refundProtectionTime:
- backCoins = coins
- card = self.refund_money_for_card(RMB(backCoins), card.id)
- card.showBalance = card.balance
- card.save()
- consumeDict.update({'refundedMoney': str(backCoins)})
- self.notify_user(notifyOpenId, 'refund_coins', **refundDict)
- ServiceProgress.update_progress_and_consume_rcd(self.device.ownerId,{
- "open_id": notifyOpenId,
- "port": int(port),
- "device_imei": self.device.devNo,
- "isFinished": False
- },
- consumeDict)
- except Exception, e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (devNo, e))
- finally:
- self.deviceAdapter.get_port_status_from_dev()
- # 插座心跳
- def update_port_info(self, data):
- devNo = data['gateway_id']
- port_list = data['data']['port_list']
- temperature = data['data']['temperature']
- portInfos = dict()
- for portInfo in port_list:
- power = portInfo['power']
- current = portInfo['current']
- port = portInfo['port_index'] + 1
- voltage = portInfo['voltage']
- usedElec = portInfo['energy_consumed'] * 0.001
- usedTime = portInfo['time_consumed']
- tempStatus = portInfo['charge_status']
- order = portInfo['transaction_id']
- if tempStatus == 0:
- status = Const.DEV_WORK_STATUS_IDLE
- elif tempStatus == 1:
- status = Const.DEV_WORK_STATUS_WORKING
- else:
- status = Const.DEV_WORK_STATUS_WORKING
- portInfos[str(port)] = {
- 'power': power, 'current': current, 'voltage': voltage,\
- 'usedElec':usedElec, 'usedTime':usedTime, 'order':order, 'status':status
- }
- # allPorts, usedPorts, usePorts = self.deviceAdapter.get_port_static_info(portInfos)
- # 端口信息更新
- devCache = Device.get_dev_control_cache(devNo) or dict()
- for portStr, value in devCache.items():
- if not portStr.isdigit() or not isinstance(value, dict):
- continue
- # 更新每个端口的信息
- tempPortInfo = portInfos.get(portStr, dict())
- value.update(tempPortInfo)
- devCache[portStr] = value
- devCache['temperature'] = temperature
- Device.update_dev_control_cache(devNo, devCache)
- def do(self):
- data = self.event_data
- if 'type' in self.event_data:
- massageTpye = self.event_data['type']
- if massageTpye == "EVENT_GATEWAY_HEARTBEAT": # 网关心跳
- self.event_gateway_heartbeat()
- elif massageTpye == "EVENT_PLUG_MP_HEARTBEAT": # 心跳上报3.9
- self.update_port_info(data)
- elif massageTpye == "EVENT_CHARGE_FINISHED": # 充电结束上报
- self.do_finished_by_quantity(data)
- elif massageTpye == "EVENT_CHARGE_FINISHED_3": # 按功率充电结束上报
- self.do_finished_by_power(data)
- elif massageTpye == "EVENT_CARD_CHARGE_STARTED": # NFC刷卡充电开始上报
- self.do_card_start(data)
- elif massageTpye == "EVENT_CARD_CHARGE_FINISHED": # NFC刷卡充电结束上报
- self.do_card_finished(data)
- # elif massageTpye == "EVENT_PLUG_MP_HEARTBEAT": # 插座心跳
- # self.update_port_info(data)
- def new_card_consume_record(self, card, money, sid, servicedInfo, attachParas):
- group = self.device.group # type: GroupDict
- address = group.address
- group_number = self.device.groupNumber
- now = datetime.datetime.now()
- orderNo = ConsumeRecord.make_no()
- new_record = {
- 'orderNo': orderNo,
- 'time': now.strftime("%Y-%m-%d %H:%M:%S"),
- 'dateTimeAdded': now,
- 'openId': card.openId,
- 'ownerId': self.device.ownerId,
- 'coin': money.mongo_amount,
- 'money': money.mongo_amount,
- 'devNo': self.device.devNo,
- 'logicalCode': self.device.logicalCode,
- 'groupId': self.device.groupId,
- 'address': address,
- 'groupNumber': group_number,
- 'groupName': group.groupName,
- 'devTypeCode': self.device.devTypeCode,
- 'devTypeName': self.device.devTypeName,
- 'isNormal': True,
- 'status': ConsumeRecord.Status.RUNNING,
- 'remarks': u'刷卡消费',
- 'errorDesc': '',
- 'sequanceNo': sid,
- 'desc': '',
- 'attachParas': attachParas,
- 'servicedInfo': servicedInfo
- }
- order = ConsumeRecord(**new_record)
- order.save()
- # 刷卡消费也记录一条数据
- new_card_record = {
- 'orderNo': orderNo,
- 'openId': card.openId,
- 'cardId': str(card.id),
- 'money': money.mongo_amount,
- 'balance': card.balance.mongo_amount,
- 'devNo': self.device.devNo,
- 'devType': self.device.devTypeName,
- 'logicalCode': self.device.logicalCode,
- 'groupId': self.device.groupId,
- 'address': address,
- 'groupNumber': group_number,
- 'groupName': group.groupName,
- 'result': 'success',
- 'remarks': u'刷卡消费',
- 'sid': sid,
- 'dateTimeAdded': datetime.datetime.now(),
- 'desc': '',
- 'servicedInfo': servicedInfo,
- 'linkedConsumeRcdOrderNo': str(order.orderNo)
- }
- card_order = CardConsumeRecord(**new_card_record)
- card_order.save()
- return order, card_order
- def create_progress_for_card(self, dev, consumeRcd, port, card_order,attachParas):
- try:
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo,
- port=int(port), isFinished=False).first()
- if progress:
- return
- consumeOrder = consumeRcd.servicedInfo
- new_service_progress = ServiceProgress(
- open_id=consumeRcd.openId,
- device_imei=consumeRcd.devNo,
- devTypeCode=dev['devType']['code'],
- port=port,
- attachParas=attachParas,
- start_time=int(time.time()),
- finished_time=int(time.time()) + 24 * 60 * 60,
- consumeOrder=consumeOrder,
- expireAt=datetime.datetime.now() + datetime.timedelta(days=91),
- cardId=card_order.cardId,
- )
- new_service_progress.save()
- except Exception as e:
- logger.exception(e)
- # 功率计费模式下,根据返回的数据,计算消耗的钱
- def calc_spend_money(self, data):
- settle_power = data['data']['settle_power']
- usedTime = data['data']['time_consumed']
- config_list = self.device.my_obj.otherConf.get('config_list', [])
- powerList = []
- configDict = {}
- for _ in config_list:
- configDict[_['power']] = _
- powerList.append(_['power'])
- powerList.sort()
- for power in powerList:
- if settle_power <= power:
- break
- else:
- continue
- pricePower = power
- priceConfig = configDict[pricePower]
- # spendMoney = VirtualCoin(float(usedTime) / priceConfig['time'] * 100 * 0.01)
- spendMoney = VirtualCoin(float(usedTime) * (float(priceConfig['price']) / float(priceConfig['time'])) * 0.01)
- return spendMoney
|