123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- from typing import TYPE_CHECKING
- from apilib.monetary import RMB
- from apilib.utils_sys import memcache_lock
- from apps.web.constant import ErrorCode
- from apps.web.device.models import Group
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.weifuleCommon import WeiFuLeStatusEvent, WeiFuLePolicyProcess
- from apps.web.user.models import ServiceProgress, Card, CardRechargeOrder, CardRechargeRecord, UserVirtualCard
- logger = logging.getLogger(__name__)
- created_order_32 = 32
- exec_order_33 = 33
- finished_order_34 = 34
- id_card_request_35 = 35
- card_recharge_order_36 = 36
- status_change_event_44 = 44
- ic_consume_event_48 = 48 # ic卡花钱的时候,会上报此事件
- part_sn_event = 49 # 组件上报相关信息
- card_is_normal = 1
- card_not_in_db = 2
- card_is_forzen = 3
- card_has_not_order = 4 # IC卡适用
- card_less_balance = 5 # ID卡适用
- card_type_is_ic = 6 # IC卡不允许当做ID卡使用
- no_load_code = 7
- if TYPE_CHECKING:
- from apps.web.core.adapter.base import SmartBox
- from apps.web.core.adapter.weifule_policy import POLICYBox
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
- if event_data is None:
- return None
- if event_data['fun_code'] in [created_order_32, exec_order_33, finished_order_34, id_card_request_35,
- card_recharge_order_36]:
- return ChargingSocketWorkEvent(self.deviceAdapter, event_data)
- if event_data['fun_code'] in [status_change_event_44]:
- return WeiFuLeStatusEvent(self.deviceAdapter, device_event)
- class ChargingSocketWorkEvent(WeiFuLePolicyProcess):
- def __init__(self, smartBox, event_data):
- # type:(SmartBox,dict)->None
- super(ChargingSocketWorkEvent, self).__init__(smartBox, event_data)
- self.deviceAdapter = smartBox # type: POLICYBox
- def create_progress_for_socket_order(self, consumeRcd, devInfo):
- try:
- port = int(devInfo['port'])
- progress = ServiceProgress.objects.filter(device_imei=self.device.devNo, port=port,
- devTypeCode=self.device.devTypeCode).first()
- if not progress:
- progress = ServiceProgress(device_imei=self.device.devNo, port=port,
- devTypeCode=self.device.devTypeCode)
- progress.start_time = devInfo['create_time']
- progress.finished_time = devInfo['create_time'] + 60 * 60 * 12
- progress.isFinished = False
- else:
- if devInfo['id'] in progress.consumes:
- return
- if progress.isFinished == False:
- progress.finished_time = progress.finished_time + 60 * 60 * 12
- else:
- progress.consumes = []
- progress.start_time = devInfo['create_time']
- progress.finished_time = devInfo['create_time'] + devInfo.get('amount_time', 60 * 60 * 12)
- progress.isFinished = False
- progress.open_id = consumeRcd.openId
- progress.consumes.append(devInfo['id'])
- progress.status = 'running'
- progress.save()
- except Exception as e:
- logger.exception(e)
- def do(self, **args):
- devNo = self.device['devNo']
- funCode = self.event_data.get('fun_code')
- order = self.event_data.get('order', {})
- if funCode == id_card_request_35:
- return self.response_id_card()
- logger.info('weifule charging event detected, devNo=%s' % (devNo,))
- with memcache_lock(key='%s-%s-%s-finished' % (devNo, order.get('id'), funCode), value='1',
- expire=120) as acquired:
- if acquired:
- self._do_ack_order(order)
- try:
- if funCode == created_order_32:
- self._do_created_order_32(order)
- elif funCode == exec_order_33:
- self._do_exec_order_33(order)
- elif funCode == finished_order_34 and order['order_type'] != 'card_charge':
- self._do_finished_order_34(order)
- elif funCode == finished_order_34 and order['order_type'] == 'card_charge':
- self.update_card_recharge_for_success_event(order['id'], RMB(order['balance'] / 100.0))
- elif funCode == card_recharge_order_36: # 如果是卡充值,直接回复订单
- self.deal_with_ic_charge_event()
- except Exception:
- import traceback
- logger.warn(traceback.format_exc())
- logger.info('deal order is finished < funCode: {} order: {} >'.format(funCode, order.get('id')))
- else:
- logger.info('weifule charging event is doing !!!, devNo=%s' % (devNo,))
- def translate_reason(self, order):
- cause = order.get('cause')
- if cause == 1:
- if self.duration < self.refundProtectionTime:
- return u'充电已结束,如有异常情况,请联系本台设备经销商。'
- else:
- return u'订购的套餐已用完。'
- elif cause == 2:
- return u'用户远程停止。'
- elif cause == 3:
- return u'管理员操作停止。'
- elif cause == 4:
- return u'经销商远程停止。'
- elif cause == 5:
- return u'用户拔掉充电器,或者插座脱落。'
- elif cause == 6:
- return u'端口功率过载,系统为了安全,关闭此充电端口。'
- elif cause == 7:
- return u'整机电压过载,系统为了安全,关闭所有充电端口。'
- elif cause == 8:
- return u'端口电流过载,系统为了安全,关闭此充电端口。'
- elif cause == 9:
- return u'整机功率超限,系统为了安全,关闭所有充电端口。'
- elif cause == 10:
- return u'检测到温度超限,系统为了安全,关闭所有充电端口。'
- elif cause == 11:
- return u'恭喜您电池已经充满'
- elif cause == 12:
- if self.duration < self.refundProtectionTime:
- return u'充电已结束,如有异常情况,请联系本台设备经销商。'
- else:
- return u'订购的时间已用完'
- elif cause == 13:
- if self.duration < self.refundProtectionTime:
- return u'充电已结束,如有异常情况,请联系本台设备经销商。'
- else:
- return u'订购的电量已用完'
- elif cause == 0x0E:
- return u"当前充电功率超过套餐允许最大功率"
- elif cause == 20:
- return u'端口功率过小。可能是电池已经充满,也可能是所接负载功率太小'
- return u'充电结束。'
- def deal_with_ic_charge_event(self):
- cardNo = self.event_data['card_no']
- card = self.update_card_dealer_and_type(cardNo, 'IC')
- if not card:
- return self.deviceAdapter.response_card_charge_result(self.event_data['card_no'], card_not_in_db)
- elif card.frozen:
- return self.deviceAdapter.response_card_charge_result(self.event_data['card_no'], card_is_forzen)
- preBalance = card.balance
- rechargeOrder = CardRechargeOrder.get_last_to_do_one(str(card.id))
- if rechargeOrder:
- self.recharge_ic_card(card=card,
- preBalance=preBalance,
- rechargeType='append',
- order=rechargeOrder,
- need_verify=False)
- else:
- return self.deviceAdapter.response_card_charge_result(self.event_data['card_no'], card_has_not_order)
- def recharge_ic_card(self, card, preBalance, rechargeType, order, need_verify=True):
- # type:(Card, RMB, str, CardRechargeOrder, bool)->bool
- """
- # rechargeType有两种,一种是用直接覆写overwrite的方式,一种是append追加钱的方式。
- # 不同的的设备,充值的方式还不一样.注意:money是实际用户付的钱,coins是给用户充值的钱,比如付10块(money),充15(coins)。
- :param card:
- :param preBalance:
- :param rechargeType:
- :param order:
- :return:
- """
- if not order or order.coins == RMB(0):
- return False
- status = Card.get_card_status(str(card.id))
- if status == 'busy':
- return False
- Card.set_card_status(str(card.id), 'busy')
- try:
- # IC卡需要下发到设备,设备写卡,把余额打入卡中
- if rechargeType == 'overwrite':
- sendMoney = preBalance + order.coins
- else:
- sendMoney = order.coins
- # 先判断order最近一次充值是否OK. 满足三个条件才认为上次充值成功:
- # 1、操作时间已经超过三天
- # 2、操作结果是串口超时, 即result == 1
- # 3、当前余额大于最后一次充值操作的充值前余额
- if need_verify and len(order.operationLog) > 0:
- log = order.operationLog[-1]
- result = log['result']
- time_delta = (datetime.datetime.now() - log['time']).total_seconds()
- last_pre_balance = RMB(log['preBalance'])
- if (result == ErrorCode.DEVICE_CONN_FAIL or result == ErrorCode.BOARD_UART_TIMEOUT) \
- and (time_delta > 3 * 24 * 3600 or preBalance > last_pre_balance):
- logger.debug('{} recharge verify result is finished.'.format(repr(card)))
- order.update_after_recharge_ic_card(device=self.device,
- sendMoney=sendMoney,
- preBalance=preBalance,
- result=ErrorCode.SUCCESS,
- description=u'充值校验结束')
- CardRechargeRecord.add_record(
- card=card,
- group=Group.get_group(order.groupId),
- order=order,
- device=self.device)
- return False
- try:
- operation_result, balance = self.deviceAdapter.recharge_card(card.cardNo, sendMoney,
- orderNo=str(order.id))
- order.update_after_recharge_ic_card(device=self.device,
- sendMoney=sendMoney,
- preBalance=preBalance,
- syncBalance=balance,
- result=operation_result['result'],
- description=operation_result['description'])
- if operation_result['result'] != ErrorCode.SUCCESS:
- return False
- if not balance:
- balance = preBalance + order.coins
- CardRechargeRecord.add_record(
- card=card,
- group=Group.get_group(order.groupId),
- order=order,
- device=self.device)
- # 刷新卡里面的余额
- card.balance = balance
- card.lastMaxBalance = balance
- card.save()
- return True
- except Exception as e:
- order.update_after_recharge_ic_card(device=self.device,
- sendMoney=sendMoney,
- preBalance=preBalance,
- syncBalance=balance,
- result=ErrorCode.EXCEPTION,
- description=e.message)
- return False
- except Exception as e:
- logger.exception(e)
- return False
- finally:
- Card.set_card_status(str(card.id), 'idle')
- def prepaid_end_for_app_start(self, order):
- """
- :param order: 主板上报的 object order 信息
- """
- # 虚拟卡支付的
- if self.consumeRcd and self.consumeRcd.virtual_card_id:
- ue = order["elec"] / 1000 * 1000
- ut = order["time"] / 60.0
- vcardRcd = UserVirtualCard.objects.get(id=self.consumeRcd.virtual_card_id) # type: UserVirtualCard
- modified, consumeTotal, consumeDay = vcardRcd.clear_frozen_quota(str(self.consumeRcd.id), ut, ue, 0)
- # 支付完成之后 穿件一笔消费记录
- if not modified:
- return
- vcardRcd.new_consume_record(self.device, self.consumeRcd.user, consumeTotal)
- else:
- super(ChargingSocketWorkEvent, self).prepaid_end_for_app_start(order)
|