# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import json import logging import time from copy import deepcopy from typing import TYPE_CHECKING from apilib.monetary import RMB from apilib.utils_sys import memcache_lock from apps.web.constant import FAULT_LEVEL from apps.web.device.models import DeviceUploadInfo, Group from apps.web.eventer import EventBuilder from apps.web.eventer.base import WorkEvent, FaultEvent from apps.web.eventer.weifuleCommon import WeiFuLeStatusEvent, WeiFuLeCarProcess from apps.web.user.models import ConsumeRecord, CardConsumeRecord, Card from apps.web.user.models import CardRechargeOrder from apps.web.utils import concat_user_login_entry_url if TYPE_CHECKING: pass logger = logging.getLogger(__name__) def log_obj(obj): obj = deepcopy(obj) if isinstance(obj, dict): for k, v in obj.items(): if isinstance(v, object): obj[k] = str(v) if isinstance(obj, list) or isinstance(obj, tuple) or isinstance(obj, set): obj = map(lambda x: str(x) if isinstance(x, object) else x, obj) if isinstance(obj, unicode): obj = str(obj) # print('\33[33m' + json.dumps(obj,ensure_ascii=True,encoding='utf-8') + '\33[0m') return '\33[33m' + json.dumps(obj, ensure_ascii=False, encoding='utf-8') + '\33[0m' card_is_normal = 1 card_not_in_db = 2 card_is_forzen = 3 card_has_not_order = 4 # IC卡适用 class builder(EventBuilder): def __getEvent__(self, device_event): logger.info('reve event, event_data:{}'.format(log_obj(device_event))) event_data = device_event.get('data') fun_code = event_data.get('fun_code') if not event_data: return if event_data['fun_code'] in [44]: return WeiFuLeStatusEvent(self.deviceAdapter, device_event) if fun_code in [40, 41, 42, 43]: # 40温度告警/41电流超限/42电压超限/43功率过载 return ChargingWeiFuLeCarFaultEvent(self.deviceAdapter, event_data) else: return ChargingWeiFuLeCarWorkEvent(self.deviceAdapter, event_data) class ChargingWeiFuLeCarWorkEvent(WorkEvent): def do(self, **args): fun_code = self.event_data.get('fun_code') order_id = self.event_data.get('order', {}).get('id') key = '{}.{}.event'.format(self.device.devNo, order_id) if fun_code == 37: # 处理卡充值 self.deal_with_ic_charge_event() elif fun_code == 44: # 上报结束后的状态 pass elif fun_code == 45: # 上传要链接 self.response_the_link() else: with memcache_lock(key=key, value='1', expire=15) as acquired: if acquired: if fun_code == 32 or fun_code == 34 or fun_code == 33: self._do_order_change_event_32_33_34() self._do_ack_order_32_or_remove_order_from_device_34() else: logger.debug('fun_code<{}> is doing. cache_key:{}'.format(repr(fun_code), key)) return def deal_with_ic_charge_event(self): cardNo = self.event_data.get('card_no') card = Card.objects.filter(cardNo=cardNo, cardType='IC', dealerId=self.device.ownerId).first() logger.info(log_obj('Start card recharge operation')) if not card: logger.info(log_obj('Start card recharge operation --> no such card !!! ')) return self.deviceAdapter.send_mqtt({ 'fun_code': 37, 'card_no': cardNo, 'result': card_not_in_db, }) elif card.frozen: logger.info(log_obj('Start card recharge operation --> card is frozen !!! ')) return self.deviceAdapter.send_mqtt({ 'fun_code': 37, 'card_no': cardNo, 'result': card_is_forzen, }) rechargeOrder = CardRechargeOrder.get_last_to_do_one(str(card.id)) if rechargeOrder: preBalance = RMB(self.event_data.get('balance', 0) / 100.0) logger.info(log_obj('Start card recharge operation --> to recharg rechargeAmount:{}'.format(preBalance))) self.recharge_ic_card(card=card, preBalance=preBalance, rechargeType='append', order=rechargeOrder, need_verify=False) else: logger.info(log_obj('Start card recharge operation --> no rechargeOrder !! ')) self.deviceAdapter.send_mqtt({ 'card_no': cardNo, 'fun_code': 37, 'result': card_has_not_order, }) def _do_order_change_event_32_33_34(self): order_info = self.event_data.get('order') if not order_info: logger.info(log_obj('no order info,do over!!')) else: order_processing = WeiFuLeCarProcess(self) order_type = order_info.get('order_type') self.save_upload_log() if hasattr(order_processing, order_type): event = getattr(order_processing, order_type) try: event() except Exception: import traceback logger.info(traceback.format_exc()) else: logger.info(log_obj('no this order_type')) def _do_ack_order_32_or_remove_order_from_device_34(self): order_info = self.event_data.get('order') order_id = order_info.get('id') fun_code = self.event_data.get('fun_code') if (time.time() - order_info.get('create_time', 0)) < 300 and order_info.get('order_type') == 'apps_start': return if fun_code == 32: self.deviceAdapter.do_ack_order_32(order_id) elif fun_code == 34: self.deviceAdapter.do_ack_remove_order_from_device_34(order_id) else: pass def save_upload_log(self): order_info = self.event_data.get('order') order_info = deepcopy(order_info) order_info['order_id'] = order_info.pop('id') DeviceUploadInfo(**order_info).save() def response_the_link(self): qr_code_url = concat_user_login_entry_url(l=self.device['logicalCode']) data = { 'fun_code': 45, 'qrcode': qr_code_url } self.deviceAdapter.send_mqtt(data) def record_consume_for_card(self, card, money, desc=u'', servicedInfo=None, sid=None, attachParas=None): servicedInfo = {} if servicedInfo is None else servicedInfo attachParas = {} if attachParas is None else attachParas group = Group.get_group(self.device['groupId']) address = group['address'] group_number = self.device['groupNumber'] now = datetime.datetime.now() orderNo = attachParas.get('orderNo') 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': '', 'desc': desc, 'attachParas': attachParas, 'servicedInfo': servicedInfo } ConsumeRecord.get_collection().insert_one(new_record) # 刷卡消费也记录一条数据 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['devType']['name'], 'logicalCode': self.device['logicalCode'], 'groupId': self.device['groupId'], 'address': address, 'groupNumber': group_number, 'groupName': group['groupName'], 'result': 'success', 'remarks': u'刷卡消费', 'sequanceNo': '', 'dateTimeAdded': datetime.datetime.now(), 'desc': desc, 'servicedInfo': servicedInfo, 'linkedConsumeRcdOrderNo': str(new_record['orderNo']) } if sid is not None: new_card_record.update({'sid': sid}) CardConsumeRecord.get_collection().insert(new_card_record) return new_record['orderNo'], new_card_record['orderNo'] class ChargingWeiFuLeCarFaultEvent(FaultEvent): def do(self, **args): # 40温度告警/41电流超限/42电压超限/43功率过载 group = Group.get_group(self.device['groupId']) fun_code = self.event_data.get('fun_code') if fun_code == 40: item = self.event_data.get('temp') faultName = r'设备火灾预警' desc = r'主板上报设备过热,设备温度超限(设备温度:{} 度)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) elif fun_code == 41: item = self.event_data.get('ampr') faultName = r'设备电流超过最大限制' desc = r'主板上报电流超限,设备电流超限(设备电流:{} 安)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) elif fun_code == 42: item = self.event_data.get('volt') faultName = r'设备电压超过最限制' desc = r'主板上报电压超限,设备电压超限(设备电压:{} 伏)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) elif fun_code == 43: item = self.event_data.get('watt') faultName = r'设备功率超过最限制' desc = r'主板上报功率超限,设备功率超限(设备电压:{} 瓦)'.format(item) title = r'告警名称:\t\t{}\n\n地址名称:\t\t{}-{}\n'.format(faultName, group['address'], group['groupName']) else: return self.notify_dealer( templateName='device_fault', title=title, device=r'{}号设备({})\n'.format(self.device['groupNumber'], self.device['logicalCode']), location=r'设备告警\n', notifyTime=desc + r'\n', fault=r'%s\n' % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') ) self.record( faultCode=self.event_data.get('FaultCode'), description=desc, title=faultName, level=self.event_data.get('level', FAULT_LEVEL.NORMAL), # detail=self.event_data.get('statusInfo'), )