# -*- coding: utf-8 -*- # !/usr/bin/env python import copy import datetime from apilib.utils_AES import EncryptDate from apilib.utils_datetime import to_datetime from apps.web.constant import DeviceCmdCode, Const, FAULT_CODE, ErrorCode, CONSUMETYPE 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 ConsumeRecord, Card, ServiceProgress cardKey = 'FR4e1OFCnDdrYA7u' class PolicyWEIFULEBox(PolicyBase): def __init__(self, device): super(PolicyWEIFULEBox, 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 test(self, coins): data = {'fun_code': 0x07, 'order_id': '1111', 'coins': coins, 'port': 1, 'time': 60} devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}) return devInfo def check_feedback_result(self, devInfo): if not devInfo.has_key('rst'): raise ServiceException({'result': 2, 'description': u'报文异常'}) if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'}) if devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'串口通讯失败,您稍候再试,或者联系客服'}) if devInfo['rst'] == 2: raise ServiceException({'result': 2, 'description': u'端口被禁用'}) if devInfo['rst'] == 3: raise ServiceException({'result': 2, 'description': u'端口计量器故障'}) if devInfo['rst'] == 4: raise ServiceException({'result': 2, 'description': u'设备订单已达上限'}) if devInfo['rst'] == 5: raise ServiceException({'result': 2, 'description': u'设备正在自检'}) if devInfo['rst'] == 6: raise ServiceException({'result': 2, 'description': u'续充单计费模式不一致'}) if devInfo['rst'] == 7: raise ServiceException({'result': 2, 'description': u'端口故障'}) if devInfo['rst'] == 8: raise ServiceException({'result': 2, 'description': u'未连接充电器'}) if devInfo['rst'] == 9: raise ServiceException({'result': 2, 'description': u'订单已存在'}) def analyze_event_data(self, data): if data['fun_code'] == '34': # 如果是结束事件,需要把reason翻译出来 descDict = { '1': u'开始充电,但是没有接充电器', '2': u'充电过程中,插座脱落', '3': u'用户按下关闭按钮关闭', '4': u'用户刷卡结束充电', '5': u'远程结束充电', '6': u'充电端口故障,为了安全主动关闭', '7': u'订购的时间使用完毕', '8': u'订购的电量使用完毕', '9': u'本端口功率过载,主动关闭', '10': u'整机功率过载,主动关闭', '11': u'其他异常导致的关闭' } order = data['order'] order['reason'] = descDict.get(str(order['closeType']), u'') data['order'] = order return data def get_dev_consume_count(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x08}}) self.check_feedback_result(devInfo) data = devInfo['data'] return {'cardFee': round(data['total_card'] / 100.0,2), 'coinFee': data['total_coin'] / 100.0} # 单位为分 def get_many_port_info(self, portList): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x12}}) self.check_feedback_result(devInfo) pay_unit = self.show_pay_unit resultDict = {} for port, data in devInfo['data']['details'].items(): if port not in portList: continue result = {'index': port} result['status'] = self.__translate_status_from_str(data['status']) result['power'] = round(data.get('watt', 0), 2) result['ampere'] = round(data.get('ampr', 0) / 1000.0, 2) result['voltage'] = round(data.get('volt'), 2) _wait = [] for exec_order in data['orders']: orderNo = exec_order.get('id') order = ConsumeRecord.objects.filter(orderNo=orderNo).first() if exec_order.get('status') == 'running': result['usedTime'] = round(exec_order.get('time', 0) / 60.0, 1) result['usedElec'] = round(exec_order.get('elec') / 1000000.0, 2) result['startTime'] = datetime.datetime.fromtimestamp(exec_order['execute_time']).strftime('%m-%d %H:%M:%S') result['nickName'] = order and order.nickname if 'card_no' in exec_order: result['cardNo'] = str(int(exec_order.get('card_no', 0), 16)) policy = exec_order.get('policy', {}) policyType = policy.get('type') billingMethod = policy.get('billingMethod') result['openId'] = policy.get('open_id') result['consumeMoney'] = '{}元'.format(round(exec_order.get('money') * 0.01, 2)) if billingMethod == 'prepaid': result['coins'] = round(policy.get('money') * 0.01, 2) if exec_order.get('order_type') == 'apps_start': result['consumeType'] = 'mobile' elif exec_order.get('order_type') == 'card_start': result['consumeType'] = 'card' result['cardBalance'] = '{}元'.format(round(exec_order.get('balance') * 0.01, 2)) elif billingMethod == 'postpaid': result['consumeType'] = 'postpaid' if exec_order.get('order_type') == 'apps_start': needFiled = 'need{}'.format(policyType.capitalize()) result[needFiled] = order and order.servicedInfo.get(needFiled) elif exec_order.get('order_type') == 'card_start': result['cardBalance'] = '{}元'.format(round(exec_order.get('balance') * 0.01, 2)) else: pass elif exec_order.get('status') == 'waiting': _one = {} # if policyType == 'time': # if exec_order.get('order_type') == 'apps_start': # pass # # elif exec_order.get('order_type') == 'card_start': # pass _wait.append(_one) else: pass if _wait: result['waittingOrder'] = _wait resultDict[port] = result return resultDict 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, 'link': Const.DEV_WORK_STATUS_CONNECTED } return dictConf.get(status, Const.DEV_WORK_STATUS_IDLE) # 访问设备,获取设备端口信息 def get_port_status_from_dev(self): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x01}}) self.check_feedback_result(devInfo) data = devInfo['data'] result = {} portNum = data.get('total', 10) ii = 0 while ii < portNum: ii += 1 result[str(ii)] = {'status': self.__translate_status_from_str(data['status'].get(str(ii)))} 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 ctrInfo.has_key(strPort): 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 not ctrInfo.has_key('allPorts'): self.get_port_status_from_dev() ctrInfo = Device.get_dev_control_cache(self._device['devNo']) allPorts = ctrInfo.get('allPorts', 10) statusDict = {} for ii in range(allPorts): tempDict = ctrInfo.get(str(ii + 1), {}) if tempDict.has_key('status'): statusDict[str(ii + 1)] = {'status': tempDict.get('status')} elif tempDict.has_key('isStart'): 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 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 = 'deactive' if lock else 'active' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'port': int(port), 'type': typeStr, 'fun_code': 0x0D}}) self.check_feedback_result(devInfo) if devInfo['rst'] == 0: if lock: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_FORBIDDEN}}) else: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}}) else: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}}) 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): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x06, 'port': port}}) self.check_feedback_result(devInfo) 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 get_order(self, order_no): order = ConsumeRecord.objects.filter(orderNo=order_no).first() port = order.used_port devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x02, 'port': int(port)}}) self.check_feedback_result(devInfo) data = devInfo.get('data', {}) exec_orders = data.get('orders', []) if not exec_orders: return {} result = {} for exec_order in exec_orders: if not exec_order.get('order_type'): # 有可能没有订单,应该返回空 return result if exec_order.get('status') != 'running': return {} result['power'] = round(data.get('watt', 0), 2) pay_unit = self.show_pay_unit # result['ampere'] = round(data.get('ampr', 0) / 1000.0, 2) # result['voltage'] = round(data.get('volt'), 2) result['status'] = exec_order.get('status', 0) orderNo = exec_order.get('id') order = ConsumeRecord.objects.filter(orderNo=orderNo).first() if order: result['coins'] = round(order.coin, 2) else: result['coins'] = round(exec_order.get('coins', 0) * 0.01, 2) result['usedTime'] = round(exec_order.get('time', 0) / 60.0, 1) result['usedElec'] = round(exec_order.get('elec') / 1000000.0, 2) if exec_order.get('status') == 'running': result['startTime'] = datetime.datetime.fromtimestamp(int(exec_order.get('execute_time', 0))).strftime( '%m-%d %H:%M:%S') if exec_order.get('chrmt') == 'TIME': result['needTime'] = round(exec_order.get('amount_time', 0) / 60.0, 1) result['leftTime'] = round(exec_order.get('left_time', 0) / 60.0, 1) leftMoney = round((result['coins'] * exec_order.get('left_time', 0) / exec_order.get('amount_time', 0)), 2) consumeMoney = round((result['coins'] - leftMoney), 2) if exec_order.get('order_type') == 'apps_start': result['consumeType'] = 'mobile' result['consumeMoney'] = '{}{}'.format(consumeMoney, pay_unit) result['leftMoney'] = '{}{}'.format(leftMoney, pay_unit) try: orderNo = exec_order.get('id', 0) order = ConsumeRecord.objects.get(orderNo=orderNo) result['nickName'] = order.user.nickname package = order.package if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get( 'price') == 0: # 后付费 coins = round(exec_order.get('coins', 0) * 0.01, 2) consumeMoney = round( (coins * exec_order.get('time', 0) / exec_order.get( 'amount_time', 0)), 2) result['consumeMoney'] = '{}{}'.format(consumeMoney, pay_unit) result['consumeType'] = 'postpaid' result['needTime'] = '充满自停' result.pop('needElec', None) result.pop('leftMoney', None) result.pop('leftTime', None) result.pop('leftElec', None) except: pass if exec_order.get('order_type') == 'card_start': result['consumeType'] = 'card' result['cardNo'] = str(int(exec_order.get('card_no', 0), 16)) result['cardConsumeMoney'] = '{}{}'.format(consumeMoney, pay_unit) result['cardLeftMoney'] = '{}{}'.format(leftMoney, pay_unit) result['cardBalance'] = '{}{}'.format(round(exec_order.get('balance', 0) * 0.01, 2), pay_unit) try: card = Card.objects.get(cardNo=str(int(exec_order.get('card_no', 0), 16))) result['cardName'] = card.cardName or card.nickName if card.cardType == 'ID': # id卡 订单余额显示有问题 result['cardBalance'] = '{}{}'.format(round(exec_order.get('balance', 0) * 0.001, 2), pay_unit) except: pass elif exec_order.get('chrmt') == 'ELEC': result['needElec'] = round(exec_order.get('amount_elec', 0) * 0.000001, 2) result['leftElec'] = round(exec_order.get('left_elec', 0) * 0.000001, 4) leftMoney = round((result['coins'] * exec_order.get('left_elec', 0) / exec_order.get('amount_elec', 0)), 2) consumeMoney = round((result['coins'] - leftMoney), 2) if exec_order.get('order_type') == 'apps_start': result['consumeType'] = 'mobile' result['consumeMoney'] = '{}{}'.format(consumeMoney, pay_unit) result['leftMoney'] = '{}{}'.format(leftMoney, pay_unit) try: orderNo = exec_order.get('id', 0) order = ConsumeRecord.objects.get(orderNo=orderNo) result['nickName'] = order.user.nickname package = order.package if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get( 'price') == 0: # 后付费 result['consumeType'] = 'postpaid' coins = round(exec_order.get('coins', 0) * 0.01, 2) consumeMoney = round( (coins * exec_order.get('elec', 0) / exec_order.get( 'amount_elec', 0)), 2) result['consumeMoney'] = '{}{}'.format(consumeMoney, pay_unit) result['needTime'] = '充满自停' result.pop('needElec', None) result.pop('leftMoney', None) result.pop('leftTime', None) result.pop('leftElec', None) if package.get('billingMethod') == CONSUMETYPE.BILL_AS_SERVICE: result.pop('consumeMoney', None) result['elecFee'] = self.device.bill_as_service_feature.current_elec_fee( consumeMoney).mongo_amount result['serviceFee'] = self.device.bill_as_service_feature.current_service_fee( consumeMoney).mongo_amount except: pass if exec_order.get('order_type') == 'card_start': result['consumeType'] = 'card' result['cardNo'] = str(int(exec_order.get('card_no', 0), 16)) result['cardConsumeMoney'] = '{}{}'.format(consumeMoney, pay_unit) result['cardLeftMoney'] = '{}{}'.format(leftMoney, pay_unit) result['cardBalance'] = '{}{}'.format(round(exec_order.get('balance', 0) * 0.01, 2), pay_unit) try: card = Card.objects.get(cardNo=str(int(exec_order.get('card_no', 0), 16))) result['cardName'] = card.cardName or card.nickName if card.cardType == 'ID': # id卡 订单余额显示有问题 result['cardBalance'] = '{}{}'.format(round(exec_order.get('balance', 0) * 0.001, 2), pay_unit) except: pass else: pass return result def response_card_balance(self, cardNo, balance, result): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 35, 'card_no': cardNo, 'balance': int(100 * float(balance)), 'result': result}}) self.check_feedback_result(devInfo) # 获取设备配置参数 def get_dev_setting(self): """ 从主板上读取数据显示在前台 :return: """ # 从主板读取一部分 devInfo = MessageSender.send( self.device, DeviceCmdCode.OPERATE_DEV_SYNC, { 'IMEI': self._device['devNo'], 'data': {'fun_code': 12} } ) self.check_feedback_result(devInfo) result = devInfo['data'] # 浮充相关参数的获取解析 result.update({ 'fcharge_watt': result['fcharge']['watt'], 'fcharge_time': result['fcharge']['time'], 'fcharge_check': result['fcharge'].get('check', 10), }) # 空载部分适配 noload_check = result.get('noload_check') or {'time': 99, 'watt': 99} result['emptyPower'] = noload_check['watt'] result['emptyTime'] = noload_check['time'] # 音量部分适配 defaultVolume = 0 volumeList = [] for k, v in result['volume'].items(): if k == 'default': defaultVolume = v else: tempList = k.split('-') volumeList.append({'start': tempList[0], 'end': tempList[1], 'volume': v}) result.pop('volume') result['volume'] = defaultVolume result['volume_list'] = volumeList state = self.get_dev_consume_count() result.update(state) # 离线卡刷一次金额, 投币器一次脉冲金额 policy = result['policy'] policy['money'] = round(float(policy.get('money', 100)) * 0.01, 2) policy['once_coin'] = round(float(policy.get('once_coin', 100)) * 0.01, 2) rule = policy.pop('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 result.update({'policy': policy}) result['refundProtectionTime'] = self.device['otherConf'].get('refundProtectionTime', 5) return result # 获取设备配置参数 def set_dev_setting(self, setConf): """ 功率计费 : x 功率设备 充电t小时 需要 y元 总价列式 y = t x 时间计费: x 功率设备 y元 能够充电 t 小时 总价列式 y = t x 其实参数一样 仅仅表现形式不一样 (前提: 以最大的功率进行计算金额) 服务器保存两套 x y t 的模板 当用户选择时间计费的时候 下发时间计费的一套 选择功率计费的时候 下发功率计费的一套 :param setConf: :return: """ # 如果是卡密码,直接进行修改 if "card_pwd" in setConf: return self.set_card_pwd(setConf['card_pwd']) if 'policy' in setConf: policy = setConf['policy'] _type = policy['type'] money = int(float(policy['money']) * 100) # 离线卡刷一次金额 单位: 分 once_coin = int(float(policy.get('once_coin') or 1.0) * 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)) setConf['policy'] = { 'type': _type, 'auto_stop': True if _type == 'elec' else auto_stop, 'over_money_stop': True, 'money': money, 'once_coin': once_coin, '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 # } # } # 浮充时间、浮充检测时间、浮充功率以及音量的范围检测 if not (1 <= int(setConf['fcharge_time']) <= 300): raise ServiceException({'result': 2, 'description': u'浮充时间必须大于等于1分钟,小于等于300分钟'}) if not (2 <= int(setConf['fcharge_check']) <= 30): raise ServiceException({'result': 2, 'description': u'浮充检测时间必须大于等于2分钟,小于等于30分钟'}) if not (20 <= int(setConf['fcharge_watt']) <= 200): raise ServiceException({'result': 2, 'description': u'浮充功率必须大于等于20瓦,小于等于200瓦'}) if not (0 <= int(setConf['volume']) <= 7): raise ServiceException({'result': 2, 'description': u'音量必须大于等于0,小于等于7'}) if not (50 <= int(setConf['max_watt']) <= 10000): raise ServiceException({'result': 2, 'description': u'最大功率必须大于等于50瓦,小于等于10000瓦'}) # 音量区间的处理 volumeDict = {'default': int(setConf['volume'])} for vl in setConf['volume_list']: startTime = to_datetime('2020-01-01 %s:00' % vl['start']) endTime = to_datetime('2020-01-01 %s:00' % vl['end']) if endTime <= startTime: raise ServiceException({'result': 2, 'description': u'结束时间一定要大于起始时间。比如起始时间为07:00,结束时间为23:59'}) volumeDict['%s-%s' % (vl['start'], vl['end'])] = int(vl['volume']) # 更新音量设置 并且去除不需要的音量中间量 setConf['volume'] = volumeDict setConf.pop('volume_list') # 更新参数的类型以及参数的单位比例 setConf['max_watt'] = int(setConf['max_watt']) # 浮充相关参数的设置 setConf['fcharge'] = { 'watt': int(setConf.pop('fcharge_watt')), 'time': int(setConf.pop('fcharge_time')), 'check': int(setConf.pop('fcharge_check')), } # 空载检测参数配置 setConf['noload_check'] = {} setConf['noload_check']['watt'] = int(setConf.pop('emptyPower')) setConf['noload_check']['time'] = int(setConf.pop('emptyTime')) # 加入funCode setConf.update({'fun_code': 11}) # 发送设备参数 devInfo = MessageSender.send( self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': setConf} ) self.check_feedback_result(devInfo) def ack_event(self, orderNo, funCode): devInfo = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], 'data': {'fun_code': funCode, 'order_id': orderNo}}) self.check_feedback_result(devInfo) def clear_dev_feecount(self): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x09, 'total_coin': True, 'total_card': True}}) self.check_feedback_result(devInfo) def response_card_charge_result(self, cardNo, result): MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SERVER_ASYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 37, 'card_no': cardNo, 'result': result}}) def reboot_device(self): data = {'fun_code':0x0B,'reset_mcu':True} MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}) MessageSender.async_send(self.device, DeviceCmdCode.SET_DEVINFO, {'IMEI': self._device['devNo'], 'restart': True}) def set_device_function(self, request, lastSetConf): if request.POST.has_key('clearSum'): self.clear_dev_feecount() elif request.POST.has_key('reboot'): self.reboot_device() def set_device_function_param(self, request, lastSetConf): newConf = copy.deepcopy(request.POST) newConf.pop('logicalCode', None) if 'refundProtectionTime' in newConf: refundProtection = round(float(newConf.get('refundProtection', 0.0)), 1) Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': {'otherConf.refundProtection': refundProtection}}) Device.invalid_device_cache(self.device.devNo) self.set_dev_setting(newConf) def get_card_pwd(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x11}}) self.check_feedback_result(devInfo) result = devInfo['data'] enObj = EncryptDate(cardKey) cardPwd = enObj.decrypt(result['card_pwd']) if not cardPwd: cardPwd = '' return {'card_pwd': cardPwd} def translante_card_no(self, hexCardNo): return int(hexCardNo, 16) def check_pwd(self, 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 set_card_pwd(self, pwd): self.check_pwd(pwd) enObj = EncryptDate(cardKey) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x0B, 'card_pwd': enObj.encrypt(pwd)}}) self.check_feedback_result(devInfo) def set_card_mode(self, setConf): cardMode = int(setConf.get('card_mode')) valueDict = {'fun_code': 0x10} if cardMode == 0: valueDict.update({'mode': cardMode}) 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元之间'}) balance = balance * 10 # 硬件模块记录的单位是角 enObj = EncryptDate(cardKey) valueDict.update({'mode': 1, 'new_pwd': enObj.encrypt(str(newPwd)), 'balance': balance}) elif cardMode == 2: self.check_pwd(setConf['old_pwd']) self.check_pwd(setConf['new_pwd']) newPwd = setConf['new_pwd'] oldPwd = setConf['old_pwd'] enObj = EncryptDate(cardKey) valueDict.update({'mode': 2, 'old_pwd': enObj.encrypt(str(oldPwd)), 'new_pwd': enObj.encrypt(str(newPwd))}) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': valueDict}) self.check_feedback_result(devInfo) def get_card_mode(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x11}}) self.check_feedback_result(devInfo) cardMode = devInfo['data']['card_mode'] return {'card_mode': cardMode} def check_alarm(self, alarm): if alarm.faultCode == FAULT_CODE.MCU_REBOOT: return u'此告警,建议您多观察,如果比较频繁不停上报单台设备的告警,可能会运行不稳定。需要您联系技术支持确认。' elif alarm.faultCode == FAULT_CODE.COUNTER_FAULT: portInfo = self.get_port_info(alarm.portNo) if portInfo['status'] == Const.DEV_WORK_STATUS_FAULT: return u'此端口目前已经为故障状态,继电器可能运行不稳定,建议您联系技术支持,以确认设备运行情况。' else: return u'端口状态检查正常,继电器或存偶尔无法获取数据。暂不影响使用。' elif alarm.faultCode == FAULT_CODE.RELAY_FAULT: return u'无法进行远程诊断,建议您到现场,直接插上插座,然后检查是否不用付款,就能够充电。如果是的,就属于继电器粘连。' elif alarm.faultCode == FAULT_CODE.DEV_OVERLOAD: return u'整机功率最大限定为7500瓦,接入的负载超过此负载,为了安全,将强行关闭所有充电端口。' elif alarm.faultCode == FAULT_CODE.COPY_CARD: return u'出现一模一样的卡,可能是用户复制了另外一张离线卡,然后使用,会给您造成经济上的损失,建议冻结。' return '' def get_part_info(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x05}}) self.check_feedback_result(devInfo) partInfo = devInfo['data'] result = {} nameDesc = {'networkBoard': u'网络板', 'chargeBoard': u'充电板', 'cardBoard': u'刷卡板'} for k, v in partInfo.items(): if k not in nameDesc: continue result[nameDesc.get(k)] = {'SN': v} return result def recharge_card(self, cardNo, money, orderNo=None): hex_cardNo = hex(int(cardNo))[2::].replace('L', '').upper() result = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self.device['devNo'], 'data': {'fun_code': 37, 'result': 1, 'card_no': hex_cardNo, 'charge': int(money * 100), 'order_id': orderNo}}) # 返回验证 self.check_feedback_result(result) card = Card.objects.filter(cardNo=cardNo,dealerId=self.device.ownerId).first() if not card: return { 'result': ErrorCode.EXCEPTION, 'description': '' }, None balance = card.balance + money return { 'result': ErrorCode.SUCCESS, 'description': '' }, balance def recharge_card_async(self, cardNo, money, orderNo): cardNo = hex(int(cardNo))[2::].replace('L', '').upper() MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SERVER_ASYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 37, 'result': 1, 'card_no': cardNo, 'charge': int(money * 100), 'order_id': orderNo}}) @property def isHaveStopEvent(self): return True def stop(self, port = None): return self.stop_charging_port(port) 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('orders', []) running_order = None waiting_order = [] for exec_order in exec_orders: # 第一层筛选 if exec_order['id'] not in sp.consumes: sp.consumes.remove(exec_order['id']) 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 + running_order['amount_time'] if waiting_order: for wait_one in waiting_order: sp.consumes.append(wait_one['id']) sp.finished_time = sp.start_time + wait_one['amount_time'] 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'] = int(exec_order['card_no'], 16) item.update(DeviceType.get_services_button(self.device['devType']['id'])) result_list.append(item) return result_list