# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime from decimal import Decimal from apilib.monetary import RMB from apilib.utils_AES import EncryptDate from apps.web.constant import DeviceCmdCode, Const, ErrorCode from apps.web.core.adapter.policy_common import PolicyPackageInit from apps.web.core.adapter.weifuleCommon import PolicyBase from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device, DeviceType from apps.web.user.models import Card, ServiceProgress, ConsumeRecord, UserVirtualCard cardKey = 'FR4e1OFCnDdrYA7u' class MyPackageInit(PolicyPackageInit): def get_reg_model(self, dealer, devTypeId, isTemp=False, **kw): policyTemp = self.INIT_POLICY displaySwitchs = self._get_displaySwitch(isTemp) ruleList = [ { 'autoRefund': False, 'autoStop': True, 'billingMethod': 'prepaid', 'coins': 0.0, "name": "60分钟", 'price': 1.0, 'sn': 2, 'switch': True, 'time': 60.0, "unit": "分钟", }, ] if devTypeId in dealer.defaultWashConfig: payload = dealer.defaultWashConfig[devTypeId] if not payload.get('policyTemp'): payload['policyTemp'] = policyTemp if not payload.get('displaySwitchs'): payload['displaySwitchs'] = displaySwitchs if not payload.get('ruleList'): payload['ruleList'] = ruleList else: payload = {'ruleList': ruleList, 'displaySwitchs': displaySwitchs, 'policyTemp': policyTemp} return payload def _formart_ruleList(self, isTemp=False): if not isTemp and not filter(lambda _: _.get('switch') == True, self.ruleList): raise ServiceException( {'result': 0, 'description': '没有可供用户选择的套餐, 请新增或启用 至少一个用户套餐', 'payload': {}}) ids = [str(rule['id']) for rule in self.ruleList if 'id' in rule] for i, rule in enumerate(self.ruleList): ruleId = str(rule.get('id', '')) if not ruleId: ruleId = self._generate_id(ids) ids.append(ruleId) # 充满自停套餐 if ruleId == 'autoPackage': rule['time'] = float(rule.get('time') or 0) # 自定义输入套餐 if ruleId == 'customPackage': rule['time'] = float(rule.get('time') or 0) self.washConfig[ruleId] = { 'price': round(RMB(rule.get('price') or 0), 2), 'coins': round(RMB(rule.get('price') or 0), 2) } if 'switch' in rule: self.washConfig[ruleId].update({'switch': rule.get('switch', True)}) if 'time' in rule: self.washConfig[ruleId].update({'time': round(float(rule.get('time') or 0), 2)}) if 'name' in rule: self.washConfig[ruleId].update({'name': rule.get('name') or '套餐{}'.format(i + 1)}) if 'unit' in rule: self.washConfig[ruleId].update({'unit': rule.get('unit')}) if 'sn' in rule: self.washConfig[ruleId].update({'sn': rule['sn']}) if 'autoStop' in rule: self.washConfig[ruleId]['autoStop'] = rule['autoStop'] if 'autoRefund' in rule: self.washConfig[ruleId]['autoRefund'] = rule.get('autoRefund', False) # 此处有可能传入空字符串 加一个or判断为0 if 'minAfterStartCoins' in rule: self.washConfig[ruleId]['minAfterStartCoins'] = round(RMB(rule['minAfterStartCoins'] or 0), 2) # 此处有可能传入空字符串 加一个or判断为0 self.washConfig[ruleId]['billingMethod'] = 'prepaid' # 检验部分 if RMB(rule.get('price') or 0) > self.dealer.maxPackagePrice: raise ServiceException({'result': 0, 'description': '套餐( {} )金额超限'.format(rule['name']), 'payload': {}}) def _get_displaySwitch(self, isTemp=False): displaySwitchs = { "displayCoinsSwitch": False, "displayPriceSwitch": True, "displayTimeSwitch": True, "setBasePriceAble": False, "setPulseAble": False } return displaySwitchs class POLICYBox(PolicyBase, MyPackageInit): def __init__(self, device): super(POLICYBox, self).__init__(device) def translate_funcode(self, fun_code): fun_codeDict = { '01': u'查询所有端口状态', '02': u'查询端口详细信息', '03': u'上报投币充电事件', '04': u'上报刷卡事件', '05': u'上报充电结束事件', '06': u'远程停止充电', '07': u'远程启动充电', '08': u'查询投币总额', '09': u'清除投币总数', '0A': u'查询订单信息', } return fun_codeDict.get(fun_code, '') def translate_event_cmdcode(self, cmdCode): cmdDict = { } return cmdDict.get(cmdCode, '') def check_feedback_result(self, result): if 'rst' not in result: raise ServiceException({'result': 2, 'description': u'报文异常'}) if result['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'}) if result['rst'] == 1: raise ServiceException({'result': 2, 'description': u'串口通讯失败,您稍候再试,或者联系客服'}) if result['rst'] == 2: raise ServiceException({'result': 2, 'description': u'订单已满'}) if result['rst'] == 3: raise ServiceException({'result': 2, 'description': u'端口已被禁用'}) if result['rst'] == 4: raise ServiceException({'result': 2, 'description': u'检测插头未连接,请先插上插头后再使用'}) if result['rst'] == 5: raise ServiceException({'result': 2, 'description': u'计费类型无效'}) if result['rst'] == 7: raise ServiceException({'result': 2, 'description': u'端口计量故障'}) # def get_port_info(self, port): # data = {'fun_code': 2, 'port': int(port)} # devInfo = self.send_mqtt(data) # portInfo = devInfo.get('data', {}) # result = {'status': portInfo['status']} # # exec_orders = portInfo.get('exec_orders', []) # _wait = [] # for exec_order in exec_orders: # if exec_order['status'] == 'running': # policy = exec_order.get('policy', {}) # result['openId'] = policy['open_id'] # result['billingMethod'] = policy['billingMethod'] # result['policyType'] = policy['type'] # result['voltage'] = round(portInfo.get('volt', 0), 2) # result['power'] = round(portInfo.get('watt', 0), 2) # result['ampere'] = round((portInfo.get('ampr', 0) * 0.001), 2) # result['usedTime'] = round(exec_order.get('time', 0) / 60.0, 1) # result['usedElec'] = round(exec_order.get('elec', 0) * 0.000001, 4) # result['startTime'] = datetime.datetime.fromtimestamp(int(exec_order['exec_time'])).strftime('%m-%d %H:%M:%S') # if 'card_no' in result: # result['cardNo'] = result['card_no'] # # if exec_order['status'] == 'waiting': # _one = {} # # _wait.append(_one) # # if _wait: # result['waittingOrder'] = _wait # # return result def check_params_range(self, params, minData=None, maxData=None, desc=''): # type:(str,float,float,str) -> str """ 检查参数,返回字符串参数 """ if params is None: raise ServiceException({'result': 2, 'description': u'{} 参数错误(值为空).'.format(desc)}) if not isinstance(params, Decimal): params = Decimal(params) if not minData and maxData: if not isinstance(maxData, Decimal): maxData = Decimal(maxData) if params <= maxData: return '%g' % params else: raise ServiceException( {'result': 2, 'description': u'%s超出可选范围(值为: %s),可选最大值为%g' % (desc, params, maxData)}) if not maxData and minData: if not isinstance(minData, Decimal): minData = Decimal(minData) if minData <= params: return '%g' % params else: raise ServiceException( {'result': 2, 'description': u'%s超出可选范围(值为: %s),可选最小值为%g' % (desc, params, minData)}) if not minData and not maxData: return '%g' % params else: if not isinstance(minData, Decimal): minData = Decimal(minData) if not isinstance(maxData, Decimal): maxData = Decimal(maxData) if minData <= params <= maxData: return '%g' % params else: raise ServiceException( {'result': 2, 'description': u'%s参数超出可选范围(值为: %s),可取范围为%g-%g' % (desc, params, minData, maxData)}) def test(self, coins): data = {'fun_code': 0x07, 'order_id': '1111', 'coins': coins, 'port': 1, 'time': 60} devInfo = self.send_mqtt(data) return devInfo def get_port_status_from_dev(self): data = {'fun_code': 0x01, 'all': True} devInfo = self.send_mqtt(data) portData = devInfo['data']['port_stat'] result = {} for k, v in portData.items(): if v == 'idle': result[k] = {'status': Const.DEV_WORK_STATUS_IDLE} elif v == 'link': result[k] = {'status': Const.DEV_WORK_STATUS_CONNECTED} elif v == 'busy': result[k] = {'status': Const.DEV_WORK_STATUS_WORKING} elif v == 'fault': result[k] = {'status': Const.DEV_WORK_STATUS_FAULT} elif v == 'forbid': result[k] = {'status': Const.DEV_WORK_STATUS_FORBIDDEN} else: result[k] = {'status': Const.DEV_WORK_STATUS_FAULT} allPorts, usedPorts, usePorts = self.get_port_static_info(result) Device.update_dev_control_cache(self._device['devNo'], {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts}) # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存 ctrInfo = Device.get_dev_control_cache(self._device['devNo']) for strPort, info in result.items(): if strPort in ctrInfo: ctrInfo[strPort].update({'status': info['status']}) else: ctrInfo[strPort] = info Device.update_dev_control_cache(self._device['devNo'], ctrInfo) return result def get_port_status(self, force=False): if force: return self.get_port_status_from_dev() ctrInfo = Device.get_dev_control_cache(self._device['devNo']) if 'allPorts' not in ctrInfo: self.get_port_status_from_dev() ctrInfo = Device.get_dev_control_cache(self._device['devNo']) allPorts = ctrInfo.get('allPorts', 2) statusDict = {} for ii in range(allPorts): tempDict = ctrInfo.get(str(ii + 1), {}) if 'status' in tempDict: statusDict[str(ii + 1)] = {'status': tempDict.get('status')} elif 'isStart' in tempDict: if tempDict['isStart']: statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING} else: statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE} else: statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE} allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict) Device.update_dev_control_cache(self._device['devNo'], {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts}) return statusDict def active_deactive_port(self, port, active): if active: raise ServiceException({'result': 2, 'description': u'该设备不支持直接打开端口'}) return self.stop_charging_port(port) # 停止该端口下的所有任务 def stop_charging_port(self, port): data = {'fun_code': 0x06, 'port': port} devInfo = self.send_mqtt(data) if devInfo['rst'] == 0: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}}) return True if devInfo['rst'] == 0 else False def analyze_event_data(self, data): if data['fun_code'] == '32': # 成功启动设备需要回复该事件 return data['order'] if data['fun_code'] == '34': # 如果是结束事件,需要把reason翻译出来 descDict = { 'outofmoney': u'购买的充电时间或电量用完了', 'userstop': u'用户远程结束充电', 'adminstop': u'管理员远程结束充电', 'dealerstop': u'经销商远程结束充电', 'unplug': u'未检测到充电器, 结束充电', 'wattoverload': u'功率过载, 结束充电', 'voltoverload': u'电压过载, 结束充电', 'amproverload': u'电流过载, 结束充电', 'machoverload': u'整机功率过载, 结束充电', 'tempexcursion': u'温度过载, 结束充电', 'stopforfull': u'充满自停, 结束充电' } order = data['order'] order['reasonDesc'] = descDict.get(str(order['cause_desc']), u'') data['order'] = order return data def ack_event(self, order_id, fun_code): data = {'order_id': order_id, 'fun_code': fun_code} self.send_mqtt(data) def get_card_pwd(self): devInfo = self.send_mqtt({'fun_code': 17}) data = devInfo.get('data', {}) card_cur_key = data.get('card_cur_key') enObj = EncryptDate(cardKey) card_cur_key = enObj.decrypt(card_cur_key) return {'card_pwd': card_cur_key} def set_device_function(self, request, lastSetConf): if 'clearSum' in request.POST: self.clear_dev_feecount() elif 'reboot' in request.POST: self.reboot_device() def set_device_function_param(self, request, lastSetConf): """ 设置参数 对于计费模式做一下转换 顺便服务器保留一份 :param request: :param lastSetConf: :return: """ # 服务器侧的参数 先处理掉 if request.POST.get('id_card_oncefee') is not None: id_card_oncefee = request.POST['id_card_oncefee'] if not id_card_oncefee: raise ServiceException({'result': 2, 'description': u'在线卡单次刷卡金额不能为0'}) Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': { 'otherConf.id_card_oncefee': round(float(id_card_oncefee), 2), }}) Device.invalid_device_cache(self.device.devNo) if request.POST.get('refundProtection') is not None: refundProtection = request.POST['refundProtection'] Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': { 'otherConf.refundProtection': round(float(refundProtection), 2), }}) Device.invalid_device_cache(self.device.devNo) if request.POST.get('minAfterStartCoins') is not None: minAfterStartCoins = request.POST['minAfterStartCoins'] Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': { 'otherConf.minAfterStartCoins': round(float(minAfterStartCoins), 2), }}) Device.invalid_device_cache(self.device.devNo) # 参数发向设备 11, 16指令 setconfig1 = {'fun_code': 11} setconfig2 = {'fun_code': 16} # 音量适配 if request.POST.get('volume_list'): volume_list = request.POST.get('volume_list') volumes = {} self.check_params_range(params=request.POST.get('volume'), minData=0.0, maxData=7.0, desc='语音音量参数') volumes.update({'default': int(request.POST.get('volume'))}) for obj in volume_list: self.check_params_range(params=obj['volume'], minData=0.0, maxData=7.0, desc='音量参数') volumes.update({'{}-{}'.format(obj['start'], obj['end']): int(obj['volume'])}) setconfig1.update({'volumes': volumes}) if request.POST.get('float_time') or request.POST.get('float_watt') or request.POST.get('check_time'): float_charge = {} if request.POST.get('float_time'): float_charge['float_time'] = int(request.POST.get('float_time')) if request.POST.get('float_watt'): float_charge['float_watt'] = int(request.POST.get('float_watt')) if request.POST.get('check_time'): float_charge['check_time'] = int(request.POST.get('check_time')) setconfig1.update({'float_charge': float_charge}) if request.POST.get('port_max_watt'): setconfig1.update({'port_max_watt': int(request.POST.get('port_max_watt'))}) if request.POST.get('port_max_ampr'): setconfig1.update({'port_max_ampr': int(request.POST.get('port_max_ampr'))}) if request.POST.get('mach_max_watt'): setconfig1.update({'mach_max_watt': int(request.POST.get('mach_max_watt'))}) if request.POST.get('mach_max_temp'): setconfig1.update({'mach_max_temp': int(request.POST.get('mach_max_temp'))}) if request.POST.get('mach_max_volt'): setconfig1.update({'mach_max_volt': int(request.POST.get('mach_max_volt'))}) if request.POST.get('noload_check_watt') or request.POST.get('noload_check_time'): noload_check = {} if request.POST.get('noload_check_watt'): noload_check['watt'] = int(request.POST.get('noload_check_watt')) if request.POST.get('noload_check_time'): noload_check['time'] = int(request.POST.get('noload_check_time')) setconfig1.update({'noload_check': noload_check}) # 离线卡配置 if request.POST.get('policy'): policy = request.POST['policy'] _type = policy['type'] money = int(float(policy['money']) * 100) # 离线卡刷一次金额 单位: 分 auto_stop = policy['auto_stop'] rule = policy['rule'] # 时间套餐格式化 prices = rule.get('prices', []) # 单位准换 for item in prices: item['price'] = int(float(item['price']) * 100) item['power'] = int(item['power']) # 排序 prices = sorted(prices, key=lambda _: _['power']) # 电量部分格式化(电量的价格) price = int(float(policy.get('price', 1) * 100.0)) setconfig1['policy'] = { 'type': _type, 'auto_stop': True if _type == 'elec' else auto_stop, 'over_money_stop': True, 'money': money, 'rule': { 'time': 'full_stop', 'prices': prices, 'elec': 'full_stop', 'price': price } } # 先不放出来: 按次的配置 # if _type == 'count': # elec = rule.get('elec', 1) * 1000000 # 单位 3.6j # time = rule.get('time', 240) * 60 # 单位: 秒 # # setconfig1['policy'] = { # 'type': 'elec', # 'auto_stop': auto_stop, # 'money': 100, # 'over_money_stop': False, # 'rule': { # 'elec': elec, # 'time': time, # 'price': 100 # } # } self.send_mqtt(setconfig1) if request.POST.get('card_pwd'): card_pwd = request.POST.get('card_pwd') card_pwd2 = request.POST.get('card_pwd2') if card_pwd != card_pwd2: raise ServiceException({'result': 2, 'description': u'两次密码输入不一致'}) self.check_pwd(card_pwd) enObj = EncryptDate(cardKey) setconfig2.update({'card_cur_key': enObj.encrypt(card_pwd)}) if request.POST.get('card_refund', None) is not None: setconfig2.update({'card_refund': request.POST.get('card_refund')}) if request.POST.get('card_disable', None) is not None: setconfig2.update({'card_disable': request.POST.get('card_disable')}) if request.POST.get('card_timeout'): setconfig2.update({'card_timeout': int(request.POST.get('card_timeout'))}) if request.POST.get('card_oncefee'): setconfig2.update({'card_oncefee': int(float(request.POST.get('card_oncefee')) * 100)}) self.send_mqtt(setconfig2) def get_dev_setting(self): """ 获取参数显示在前台 :return: """ # 获取主板侧的参数 devInfo = self.send_mqtt({'fun_code': 12}) # 参数整合 data = dict() configs = devInfo['data'] data['mach_max_watt'] = configs.get('mach_max_watt', 0) data['port_max_ampr'] = configs.get('port_max_ampr', 0) data['port_max_watt'] = configs.get('port_max_watt', 0) data['mach_max_volt'] = configs.get('mach_max_volt', 0) data['mach_max_temp'] = configs.get('mach_max_temp', 0) # 浮充参数的添加 float_charge = configs.get('float_charge', {}) data.update(float_charge) # 空载适配 data.update({ 'noload_check_watt': int(configs['noload_check'].get('watt', 0)), 'noload_check_time': int(configs['noload_check'].get('time', 0)), }) # 音量适配 volume_list = [] for k, v in configs['volumes'].items(): item = {} if k == 'default': continue if '-' in k: item['start'], item['end'] = k.split('-') item['volume'] = v volume_list.append(item) data.update({ 'volume': configs['volumes']['default'], 'volume_list': volume_list }) # 价格适配 policy = configs['policy'] policy['money'] = round(float(policy.get('money', 100)) * 0.01, 2) rule = policy.get('rule', {}) # 功率计费部分 prices = rule.get('prices', []) for item in prices: item['price'] = round(float(item['price']) * 0.01, 2) item['power'] = int(item['power']) prices = sorted(prices, key=lambda _: _['power']) # 电量计费部分 price = round(float(rule.get('price', 100)) * 0.01, 2) rule.update({ # 时间部分 'prices': prices, # 电量部分 'price': price }) policy['rule'] = rule data.update({'policy': policy}) # 17 指令 devInfo = self.send_mqtt({'fun_code': 17}) configs2 = devInfo.get('data') data['card_curmode'] = configs2['card_curmode'] data['card_refund'] = configs2['card_refund'] data['card_disable'] = configs2['card_disable'] # data['card_token'] = configs2['card_token'] data['card_timeout'] = configs2['card_timeout'] state = self.get_dev_consume_count() data.update(state) return data def get_dev_consume_count(self): data = {'fun_code': 8} devInfo = self.send_mqtt(data) total_card = round(devInfo.get('data', {}).get('total_card', 0) * 0.01, 2) return {'total_card': total_card} def reset_total_card(self): data = { 'fun_code': 9 } self.send_mqtt(data) def set_max_watt(self, max_watt): self.send_mqtt({'fun_code': 11, 'max_watt': int(max_watt)}) def lock_unlock_port(self, port, lock=True): portInfo = self.get_port_info(port) if portInfo and portInfo['status'] == Const.DEV_WORK_STATUS_WORKING and lock: raise ServiceException({'result': 2, 'description': u'端口正忙,请先关闭端口后,再禁止端口'}) typeStr = not lock self.send_mqtt({'port': int(port), 'enable': typeStr, 'fun_code': 13}) @staticmethod def check_pwd(pwd): if len(pwd) != 6: raise ServiceException({'result': 2, 'description': u'密码必须是6位纯数字密码'}) for char in pwd: if not (char >= '0' and char <= '9'): raise ServiceException({'result': 2, 'description': u'密码必须是6位纯数字密码'}) return def get_card_mode(self): devInfo = self.send_mqtt({'fun_code': 17}) MAP_MODE = { 'NORMAL': 0, 'ISSUE': 1, 'MODKEY': 2, } result = {} result['card_mode'] = MAP_MODE.get(devInfo['data']['card_curmode']) return result def set_card_mode(self, setConf): cardMode = int(setConf.get('card_mode')) data = {'fun_code': 16} if cardMode == 0: data.update({'card_curmode': {'mod': 'NORMAL'}}) elif cardMode == 1: # 格式化为离线卡 self.check_pwd(setConf['new_pwd']) newPwd = setConf['new_pwd'] if not str(setConf['balance']).isdigit(): raise ServiceException({'result': 2, 'description': u'余额必须是数字'}) balance = int(setConf['balance']) if not (balance >= 0 and balance <= 5000): raise ServiceException({'result': 2, 'description': u'余额必须在0和5000元之间'}) card_dft_val = balance * 100 # 硬件模块记录的单位是角 enObj = EncryptDate(cardKey) data.update({'card_curmode': {'mod': 'ISSUE', 'cfg': {'card_new_key': enObj.encrypt(str(newPwd)), 'card_dft_val': card_dft_val}}}) elif cardMode == 2: self.check_pwd(setConf['new_pwd']) oldPwd = setConf.get('old_pwd', '') newPwd = setConf.get('new_pwd', '') enObj = EncryptDate(cardKey) data.update({'card_curmode': {'mod': 'MODKEY', 'cfg': {'card_old_key': enObj.encrypt(str(oldPwd)), 'card_new_key': enObj.encrypt(str(newPwd))}}}) self.send_mqtt(data) def response_card_charge_result(self, cardNo, result): self.send_mqtt({'fun_code': 36, 'card_no': cardNo, 'result': result}) def recharge_card(self, cardNo, money, orderNo=None): self.send_mqtt( {'fun_code': 36, 'result': 1, 'card_no': cardNo, 'charge': int(money * 100), 'order_id': orderNo}) card = Card.objects.filter(cardNo=cardNo, dealerId=self.device.ownerId).first() balance = card.balance + money return { 'result': ErrorCode.SUCCESS, 'description': '' }, balance def get_current_use(self, **kw): base_data = kw.get('base_data') spDict = kw.get('spDict') sp = ServiceProgress.objects.filter(device_imei=self.device.devNo, port=spDict['port']).first() data = {'fun_code': 2, 'port': spDict.get('port')} devInfo = self.send_mqtt(data) portInfo = devInfo.get('data', {}) exec_orders = portInfo.get('exec_orders', []) running_order = None waiting_order = [] for exec_order in exec_orders: # 第一层筛选 if exec_order['id'] not in sp.consumes: if exec_order['id'] in sp.consumes: sp.consumes.remove(exec_order['id']) continue if exec_order['status'] == 'running': running_order = exec_order elif exec_order['status'] == 'waiting': waiting_order.append(exec_order) if len(sp.consumes) == 0: # 上一单没有正常结束 刷新此单的状态 if running_order: sp.consumes.append(running_order['id']) sp.start_time = running_order['exec_time'] sp.isFinished = False sp.finished_time = sp.start_time + 12 * 60 * 60 if waiting_order: for wait_one in waiting_order: sp.consumes.append(wait_one['id']) sp.finished_time = sp.start_time + 12 * 60 * 60 sp.save() pay_unit = self.show_pay_unit result_list = [] # 数据整理返回 for exec_order in exec_orders: item = {} item.update(base_data) item['orderNo'] = exec_order['id'] item['port'] = exec_order['port'] order = ConsumeRecord.objects.filter(orderNo=exec_order['id']).first() if exec_order['status'] == 'running': item['voltage'] = round(portInfo.get('volt', 0), 2) item['power'] = round(portInfo.get('watt', 0), 2) item['ampere'] = round((portInfo.get('ampr', 0) * 0.001), 2) item['usedTime'] = round(exec_order.get('time', 0) / 60.0, 1) # item['elec'] = round(exec_order.get('elec', 0) * 0.000001, 4) if exec_order['order_type'] == 'apps_start': try: item['consumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2), pay_unit) item['leftMoney'] = '{}{}'.format(round(exec_order.get('left_money', 0) * 0.01, 2), pay_unit) item['order'] = { 'orderNo': exec_order['id'], # 停止按钮传订单停单用 'coin': '{}{}'.format(round(order.coin, 2), pay_unit), 'port': exec_order['port'], 'consumeType': 'mobile', } except: pass elif exec_order['order_type'] == 'card_start': try: item['cardNo'] = exec_order['card_no'] item['cardConsumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2), pay_unit) item['cardLeftMoney'] = '{}{}'.format(round(exec_order.get('left_money', 0) * 0.01, 2), pay_unit) item['order'] = { 'orderNo': exec_order['id'], # 停止按钮传订单停单用 'coin': '{}{}'.format(round(exec_order.get('amount', 0) * 0.01, 2), pay_unit), 'port': exec_order['port'], 'consumeType': 'card', } except: pass else: pass elif exec_order['status'] == 'waiting': if exec_order['chrmt'] == 'TIME': item['needTime'] = '{}分钟'.format(round(exec_order.get('amount_time', 0) / 60.0, 1)) item['leftTime'] = round(exec_order.get('left_time', 0) / 60.0, 1) elif exec_order['chrmt'] == 'ELEC': item['needElec'] = round(exec_order.get('amount_elec', 0) * 0.000001, 2) item['leftElec'] = round(exec_order.get('left_elec', 0) * 0.000001, 2) item['desc'] = '此订单已经下发到设备上,上一单运行完毕就会自动运行此订单' item['order'] = { 'orderNo': exec_order['id'], # 停止按钮传订单停单用 'coin': '{}币'.format(round(exec_order.get('amount', 0) * 0.01, 2)), 'port': exec_order['port'], 'consumeType': 'card' if 'cardNo' in exec_order else 'mobile', } if order.monthlyPackageId: # 包月卡抵扣 item.pop('cardConsumeMoney', None) item.pop('cardLeftMoney', None) item.pop('needTime', None) # item.pop('usedTime', None) item.pop('leftTime', None) if 'cardNo' in exec_order: item['cardNo'] = exec_order['card_no'] item.update(DeviceType.get_services_button(self.device['devType']['id'])) result_list.append(item) return result_list def isHaveStopEvent(self): return True def stop_by_order(self, port, orderNo): data = {'fun_code': 4, 'order_id': orderNo, 'operator': 'user'} self.send_mqtt(data) def clear_dev_feecount(self): data = {'fun_code': 0x09, 'total_coin': True, 'total_card': True} self.send_mqtt(data) def reboot_device(self): # 重启单片机 MessageSender.send(self.device, DeviceCmdCode.SET_DEVINFO, {'reset_mcu': True}) # 重启模块 MessageSender.send(self.device, DeviceCmdCode.SET_DEVINFO, {'restart': True}) @property def show_pay_unit(self): """ 前台显示付费的时候,目前有不同的客户希望 显示不同的单位 有的显示金币 有的显示元, 这个地方处理下 :return: """ return u'元' def get_port_using_detail(self, port, ctrInfo, isLazy=False): return self.get_port_info(port) def stop(self, port=None): return self.stop_charging_port(int(port)) def __translate_status_from_str(self, status): dictConf = { 'idle': Const.DEV_WORK_STATUS_IDLE, 'busy': Const.DEV_WORK_STATUS_WORKING, 'forbid': Const.DEV_WORK_STATUS_FORBIDDEN, 'fault': Const.DEV_WORK_STATUS_FAULT, 'running': Const.DEV_WORK_STATUS_WORKING } return dictConf.get(status, Const.DEV_WORK_STATUS_IDLE) def update_show_pg(self, data): for k, v in data.items(): v['showPG'] = True # @SmartBox.life_cycle(after=update_show_pg) def get_many_port_info(self, portList): data = {'fun_code': 1, 'all': True} devInfo = self.send_mqtt(data) portInfo = devInfo['data'] portParam = portInfo.get('port_param', {}) exec_queue = portInfo.get('exec_queue', {}) pay_unit = self.show_pay_unit resultDict = {} for port, exec_orders in exec_queue.items(): if port not in portList: continue result = {'index': port} onePortParam = portParam.get(port, {}) _wait = [] for exec_order in exec_orders: order = ConsumeRecord.objects.filter(orderNo=exec_order['id']).first() # type: ConsumeRecord if exec_order['status'] == 'running': result['voltage'] = round(onePortParam.get('volt', 0), 2) result['power'] = round(onePortParam.get('watt', 0), 2) result['ampere'] = round((onePortParam.get('ampr', 0) * 0.001), 2) result['devTemp'] = round((portInfo.get('mach_temp', 0)), 2) result['status'] = self.__translate_status_from_str(exec_order['status']) result['usedTime'] = round(exec_order.get('time', 0) / 60.0, 2) result['usedElec'] = round(exec_order.get('elec', 0) * 0.000001, 4) result['coins'] = order.coin if order else RMB( (exec_order.get('policy', {}).get('money', 0)) * 0.01) result['startTime'] = order.dateTimeAdded.strftime( '%m-%d %H:%M:%S') if order else datetime.datetime.fromtimestamp( exec_order['create_time']).strftime('%m-%d %H:%M:%S') if exec_order['order_type'] == 'apps_start': if not order: result['nickName'] = '经销商上分' else: result['nickName'] = order.user.nickname result['openId'] = order.openId result['consumeType'] = 'mobile' result['consumeMoney'] = '{}{}'.format(RMB.fen_to_yuan(exec_order['money']), pay_unit) policy = exec_order.get('policy', {}) rule = exec_order.get('policy', {}).get('rule', {}) if rule: if 'time' in rule: if order: result['needTime'] = order.servicedInfo['needTime'] else: result['needTime'] = format(rule['time'] / 60.0, '.1f') + '分钟' else: if order: result['needElec'] = order.servicedInfo['needElec'] else: result['needElec'] = format(rule['elec'] / 1000000.0, '.1f') if policy.get('billingMethod') == 'postpaid': result['consumeType'] = 'postpaid' if exec_order['order_type'] == 'card_start': result['consumeType'] = 'card' if order: result['nickName'] = order.user.nickname result['openId'] = order.openId result['cardNo'] = exec_order['card_no'] result['cardConsumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2), pay_unit) result['cardBalance'] = '{}{}'.format(round(exec_order['balance'] * 0.01, 2), pay_unit) elif exec_order['status'] == 'waiting': _one = {} if 'amount_time' in exec_order: _one['needTime'] = '{}分钟'.format(round(exec_order['amount_time'] / 60.0, 1)) if 'amount_elec' in exec_order: _one['needElec'] = '{}'.format(round(exec_order['amount_elec'] / 1000000.0, 2)) if 'amount' in exec_order: _one['coins'] = '{}{}'.format(round(exec_order['amount'] / 100.0, 2), pay_unit) if 'create_time' in exec_order: _one['createTime'] = datetime.datetime.fromtimestamp( int(exec_order['create_time'])).strftime('%m-%d %H:%M:%S') if exec_order['order_type'] == 'apps_start': _one['consumeType'] = 'mobile' if not order: _one['nickName'] = '经销商上分' else: _one['nickName'] = order.user.nickname elif exec_order['order_type'] == 'card_start': _one['consumeType'] = 'card' _one['cardNo'] = exec_order['card_no'] _one['cardBalance'] = '{}{}'.format(round(exec_order['balance'] * 0.01, 2), pay_unit) if order: _one['nickName'] = order.nickname _wait.append(_one) if _wait: result['waittingOrder'] = _wait resultDict[port] = result return resultDict @property def support_device_package(self): return True