# -*- 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