# -*- coding: utf-8 -*- # !/usr/bin/env python import copy import datetime import time import uuid from decimal import Decimal from apilib.utils_AES import EncryptDate from apilib.utils_datetime import to_datetime from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT, FAULT_CODE, ErrorCode, CONSUMETYPE from apps.web.core.adapter.base import SmartBox from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device from apps.web.user.models import ConsumeRecord, Card cardKey = 'FR4e1OFCnDdrYA7u' class ChargingWEIFULEBox(SmartBox): def __init__(self, device): super(ChargingWEIFULEBox, 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 _check_package(self, package): unit = package.get("unit") _time = package.get("time") chrmt = self.device['otherConf'].get('chrmt') if not chrmt: chrmt = self.get_dev_setting().get('chrmt') if chrmt == 'TIME' or chrmt == 'POWER': if unit == u'秒': if int(package['time']) < 60: raise ServiceException({'result': 2, 'description': u'套餐的最小时间不能小于60秒'}) _time = int(package['time']) unit = '秒' elif unit == u'分钟': _time = int(package['time']) * 60 unit = '秒' elif unit == u'小时': _time = int(float(package['time']) * 60 * 60) unit = '秒' elif unit == u'天': _time = int(float(package['time']) * 60 * 60 * 24) unit = '秒' else: raise ServiceException({"result": 2, "description": u"套餐单位错误,应选取单位(时间),请联系经销商"}) elif chrmt == 'ELEC': if unit == u'度': _time = int(float(package['time']) * 1000000) # 微度,需要乘于16个零 else: raise ServiceException({"result": 2, "description": u"套餐单位错误,应选取单位(度),请联系经销商"}) else: raise ServiceException({"result": 2, "description": u"套餐单位错误,应选取单位(时间,度),请联系经销商"}) return _time, unit def check_dev_status(self, attachParas=None): if attachParas.get("isTempPackage") == True: washConfig = self.device.get("tempWashConfig", {}) else: washConfig = self.device.get("washConfig", {}) packageId = attachParas.get("packageId") if not packageId: # 快捷支付过来的 第一次拉起支付的时候已经校验通过了 return package = washConfig.get(packageId) # self._check_package(package) if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get('price') == 0: port = int(attachParas['chargeIndex']) lineInfo = Device.get_dev_control_cache(self.device.devNo).get(str(port), {}) if lineInfo.get('status') == Const.DEV_WORK_STATUS_WORKING: raise ServiceException({'result': 2, 'description': u'当前端口已处于工作状态,无法使用充满自停套餐, 请换个端口进行充电'}) def start_device(self, package, openId, attachParas): if attachParas is None: raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'}) if not attachParas.has_key('chargeIndex'): raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'}) port = int(attachParas['chargeIndex']) unit = package.get('unit', u'分钟') needTime, power = None, None coins = int(float(package['coins']) * 100) # 单位为分 onPoints = attachParas.get('onPoints') if onPoints: # 远程上分 self.stop_charging_port(port) order_no = ConsumeRecord.make_no() else: order_no = str(attachParas.get("orderNo")) if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get('price') == 0: lineInfo = Device.get_dev_control_cache(self.device.devNo).get(str(port), {}) if lineInfo.get('status') == Const.DEV_WORK_STATUS_WORKING: raise ServiceException({'result': 2, 'description': u'当前端口已处于工作状态, 请换个端口使用充电'}) needTime = 999 * 60 data = {'fun_code': 0x07, 'order_id': order_no, 'coins': 10 * 100, 'port': port, 'time': needTime} else: if unit == u'秒': if int(package['time']) < 60: raise ServiceException({'result': 2, 'description': u'套餐的最小时间不能小于60秒'}) needTime = int(float(package['time'])) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'分钟': needTime = int(package['time']) * 60 data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'小时': needTime = int(float(package['time']) * 60 * 60) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'天': needTime = int(float(package['time']) * 60 * 60 * 24) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'度': power = int(float(package['time']) * 1000000) # 微度,需要乘于16个零 data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'elec': power} else: needTime = int(package['time']) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}, timeout = MQTT_TIMEOUT.START_DEVICE) self.check_feedback_result(devInfo) data = devInfo['data'] if devInfo['rst'] == 0: # 成功 devInfo['consumeOrderNo'] = order_no newValue = { str(port): { 'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') } } else: # TODO result的枚举列出原因 raise ServiceException({'result': 2, 'description': u'充电桩响应异常,请您稍后再试哦'}) if needTime: finishedTime = int(time.time()) + needTime devInfo['needTime'] = needTime / 60 if power: finishedTime = int(time.time()) + 60 * 60 * 10 # 设定10个小时,确实很难知道可以用多久结束 devInfo['needElec'] = float(package['time']) newValue.update({'finishedTime': finishedTime}) Device.update_dev_control_cache(self._device['devNo'], newValue) devInfo['finished_time'] = finishedTime devInfo['consumeOrderNo'] = order_no return devInfo def bill_as_service_start_device(self, package, openId, attachParas): if attachParas is None: raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'}) if not attachParas.has_key('chargeIndex'): raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'}) if package.get('billingMethod') != CONSUMETYPE.BILL_AS_SERVICE: raise ServiceException({'result': 2, 'description': u'当前设备模式选择错误, 请联系经销商修改设备模式为服务费模式, 并重新填写套餐'}) chrmt = self.device.otherConf.get('chrmt') if not chrmt: self.switch_bill_as_service(True) port = int(attachParas['chargeIndex']) onPoints = attachParas.get('onPoints') if onPoints: # 远程上分 self.stop_charging_port(port) order_no = ConsumeRecord.make_no() else: order_no = str(attachParas.get("orderNo")) elec = int(float(package['time']) * 1000000) # 微度,需要乘于6个零 data = {'fun_code': 0x07, 'order_id': order_no, 'coins': int(float(package['time']) * 100), 'port': port, 'elec': elec} devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}, timeout = MQTT_TIMEOUT.START_DEVICE) self.check_feedback_result(devInfo) if devInfo['rst'] == 0: # 成功 devInfo['consumeOrderNo'] = order_no newValue = { str(port): { 'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') } } else: # TODO result的枚举列出原因 raise ServiceException({'result': 2, 'description': u'充电桩响应异常,请您稍后再试哦'}) finishedTime = int(time.time()) + 60 * 60 * 10 # 设定10个小时,确实很难知道可以用多久结束 devInfo['needElec'] = float(package['time']) newValue.update({'finishedTime': finishedTime}) Device.update_dev_control_cache(self._device['devNo'], newValue) devInfo['finished_time'] = finishedTime devInfo['consumeOrderNo'] = order_no return devInfo 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': 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) 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: 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('time', 0) / exec_order.get( 'amount_time', 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) except: pass elif 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['nickName'] = 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: 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 elif 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['nickName'] = 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 elif exec_order.get('status') == 'waiting': _one = {} if exec_order.get('chrmt') == 'TIME': _one['leftTime'] = round(exec_order.get('left_time', 0) / 60.0, 1) _one['needTime'] = '{}分钟'.format(round(exec_order.get('amount_time', 0) / 60.0, 1)) elif exec_order.get('chrmt') == 'ELEC': _one['leftElec'] = round(exec_order.get('left_elec', 0) * 0.000001, 4) _one['needElec'] = round(exec_order.get('amount_elec', 0) * 0.000001, 2) else: pass if exec_order.get('order_type') == 'apps_start': _one['consumeType'] = 'mobile' try: _one['nickName'] = order.user.nickname _one['coins'] = '{}{}'.format(round(order.coin, 2), pay_unit) except Exception: pass elif exec_order.get('order_type') == 'card_start': _one['consumeType'] = 'card' _one['coins'] = '{}{}'.format(round(order.coin, 2), pay_unit) _one['cardNo'] = str(int(exec_order.get('card_no', 0), 16)) _one['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))) _one['nickName'] = card.cardName or card.nickName if card.cardType == 'ID': # id卡 订单余额显示有问题 _one['cardBalance'] = '{}{}'.format(round(exec_order.get('balance', 0) * 0.001, 2), pay_unit) except: pass else: pass _wait.append(_one) else: pass if _wait: result['waittingOrder'] = _wait resultDict[port] = result return resultDict def get_port_info(self, line): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x02, 'port': int(line)}}) self.check_feedback_result(devInfo) # 找出当前正在执行的订单 result = {} data = devInfo['data'] 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) curOrder = None for order in data['orders']: if order['status'] == 'running': curOrder = order break if curOrder: result['elec'] = curOrder['elec'] if curOrder['order_type'] == 'apps_start': result['consumeType'] = 'mobile' try: rcd = ConsumeRecord.objects.get(orderNo=curOrder['id']) if u'虚拟卡' in rcd.remarks: result['consumeType'] = 'mobile_vcard' except Exception, e: pass elif curOrder['order_type'] == 'coin_start': result['consumeType'] = 'coin' elif curOrder['order_type'] == 'card_start': result['consumeType'] = 'card' if curOrder.has_key('amount_time'): result['needTime'] = round(curOrder['amount_time'] / 60.0, 1) if curOrder.has_key('time'): result['duration'] = round(curOrder['time'] / 60.0, 1) result['usedTime'] = round(curOrder['time'] / 60.0, 1) if curOrder.has_key('left_time'): result['leftTime'] = round(curOrder['left_time'] / 60.0, 1) if curOrder.has_key('amount_elec'): result['needElec'] = round(curOrder['amount_elec'] / 1000000.0, 3) if curOrder.has_key('elec'): result['elec'] = round(curOrder.get('elec') / 1000000.0, 3) if curOrder.has_key('execute_time'): result['startTime'] = datetime.datetime.fromtimestamp(int(curOrder['execute_time'])).strftime( '%m-%d %H:%M:%S') if curOrder.has_key('card_no'): result['cardNo'] = str(int(curOrder['card_no'], 16)) if curOrder.has_key('id') and (curOrder['order_type'] not in ['coin_start', 'card_charge']): # card_charge try: rcd = ConsumeRecord.objects.get(orderNo=curOrder['id']) result['openId'] = rcd['openId'] result['coins'] = float(str(rcd['coin'])) # 都用coins result['money'] = float(str(rcd['money'])) result['orderNo'] = str(curOrder['id']) except Exception, e: pass return result 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': 0x0C} } ) 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), }) # 按功率分档收费 TIME = result['price']['TIME'] # [{"max":"xxx","time":"xxx"}] result['package_time'] = [] for _ in TIME: item = {} item['power'] = _[0] item['time'] = int(_[1]) / 60 # 时间未秒转换为分 result['package_time'].append(item) # 按功率收费显示 package_power = [] for _item in TIME: package_power.append({'power': _item[0], 'price': round(1.0 / (_item[1] / 60.0 / 60.0), 2)}) result['package_power'] = package_power # 按电量收费 result['package_elec'] = [] elec = Decimal(result['price']['ELEC']) / 1000000 # 默认为毫度 price = result['price'].get('price', 1) # 默认为一块钱 result['package_elec'].append({'price': price, 'elec': elec}) 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 result['once_card'] = result['once_card'] / 100.0 result['once_coin'] = result['once_coin'] / 100.0 state = self.get_dev_consume_count() result.update(state) result['minAfterStartCoins'] = self.device['otherConf'].get('minAfterStartCoins', 0) result['refundProtection'] = self.device['otherConf'].get('refundProtection', 5) # 兼容显示(如果用户自己烧程序. 如果模式变更则以主板为主 ,否则以缓存为准) if result['chrmt'] != 'ELEC': chrmt = self.device['otherConf'].get('chrmt') if chrmt and chrmt != 'ELEC': result['chrmt'] = self.device['otherConf'].get('chrmt') or result['chrmt'] else: pass result['billAsServiceOn'] = self.device.bill_as_service_feature.on 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 "package_time" in setConf and not len(setConf['package_time']): raise ServiceException({'result': 2, 'description': u'按时间计费的套餐不能为空'}) if "package_power" in setConf and not len(setConf["package_power"]) and setConf["chrmt"] == "POWER": raise ServiceException({'result': 2, 'description': u'按功率计费的套餐不能为空'}) # 浮充时间、浮充检测时间、浮充功率以及音量的范围检测 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']) <= 100): raise ServiceException({'result': 2, 'description': u'浮充功率必须大于等于20瓦,小于等于100瓦'}) if not (0 <= int(setConf['volume']) <= 7): raise ServiceException({'result': 2, 'description': u'音量必须大于等于0,小于等于7'}) if not (50 <= int(setConf['max_watt']) <= 1000): raise ServiceException({'result': 2, 'description': u'最大功率必须大于等于50瓦,小于等于1000瓦'}) # 音量区间的处理 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['once_card'] = int(float(setConf['once_card']) * 100) setConf['once_coin'] = int(float(setConf['once_coin']) * 100) 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')), } chrmt = setConf.get('chrmt') if chrmt: package_time = setConf.pop('package_time', []) package_elec = setConf.pop('package_elec', []) package_power = setConf.pop('package_power', []) price = {'ELEC': int(float(package_elec[0]['elec']) * 1000000)} # 组织功率收费价格参数 TIME = [] if chrmt == 'POWER': # 主板实际并没有power计费方式 实际为功率分档模式的换一种显示 for _item in package_power: if float(_item['price']) == 0: raise ServiceException({'result': 2, 'description': u'计费参数设置(按功率收费)价格不能为0'}) TIME.append( [int(_item['power']), int(1.0 / float(_item['price']) * 60 * 60)] # 价格倍率 * 固定时间(60分钟) * 60秒 ) if not TIME: raise ServiceException({'result': 2, 'description': u'计费参数设置(按功率收费)缺少收费标准'}) setConf['chrmt'] = 'TIME' elif chrmt == 'TIME': # 时间模式下 的时间计费规则 for _item in package_time: TIME.append( [int(_item['power']), int(_item['time']) * 60] ) if not TIME: raise ServiceException({'result': 2, 'description': u'计费参数设置(按时间收费)缺少收费标准'}) price['TIME'] = TIME setConf['chrmt'] = 'TIME' elif chrmt == 'ELEC': # 同样也处理一次时间计费规则 用于下发给设备 for _item in package_time: TIME.append( [int(_item['power']), int(_item['time']) * 60] ) setConf['chrmt'] = 'ELEC' else: pass price['TIME'] = TIME setConf.update({'price': price}) # 空载检测参数配置 setConf['noload_check'] = {} setConf['noload_check']['watt'] = int(setConf.pop('emptyPower')) setConf['noload_check']['time'] = int(setConf.pop('emptyTime')) # 加入funCode setConf.update({'fun_code': 0x0B}) # 发送设备参数 devInfo = MessageSender.send( self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': setConf} ) self.check_feedback_result(devInfo) # 服务器侧需要保存的参数处理 unit_price = None if chrmt == 'TIME': unit_price = {'unit': '分钟', 'value': max(map(lambda _: _[1] / 60.0, setConf['price']['TIME']))} elif chrmt == 'POWER': unit_price = {'unit': '分钟', 'value': max(map(lambda _: _[1] / 60.0, setConf['price']['TIME']))} elif chrmt == 'ELEC': unit_price = {'unit': '度', 'value': round(setConf['price']['ELEC'] / 1000000.0, 2)} if unit_price: Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': { 'otherConf.unit_price': unit_price, 'otherConf.chrmt': chrmt, }}) Device.invalid_device_cache(self.device.devNo) 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 'minAfterStartCoins' in newConf: minAfterStartCoins = round(float(newConf.get('minAfterStartCoins', 0.0)), 1) Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set':{'otherConf.minAfterStartCoins': minAfterStartCoins}}) Device.invalid_device_cache(self.device.devNo) if 'refundProtection' 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 # api相关 def apiStartDeviceForYtb(self, record): port = int(record['port']) packageId = record['packageId'] device = Device.objects(devNo=self.device['devNo']).first() package = device.washConfig[str(packageId)] coins = int(float(package['coins']) * 100) order_no = 'YTB' + str(uuid.uuid4()) needTime, power = None, None unit = package.get('unit', u'分钟') if unit == u'秒': if int(package['time']) < 60: raise ServiceException({'result': 2, 'description': u'套餐的最小时间不能小于60秒'}) needTime = int(float(package['time'])) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'分钟': needTime = int(package['time']) * 60 data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'小时': needTime = int(float(package['time']) * 60 * 60) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'天': needTime = int(float(package['time']) * 60 * 60 * 24) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} elif unit == u'度': power = int(float(package['time']) * 1000000) # 微度,需要乘于16个零 data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'elec': power} else: needTime = int(package['time']) data = {'fun_code': 0x07, 'order_id': order_no, 'coins': coins, 'port': port, 'time': needTime} devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}, timeout=MQTT_TIMEOUT.START_DEVICE) self.check_feedback_result(devInfo) value = { str(port): { 'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'port': port, 'coins': coins, 'order_id': order_no, 'needTime': needTime, 'power': power, 'isAPI': True } } Device.update_dev_control_cache(self._device['devNo'], value) return devInfo def apiGetPortInfoFromYtb(self, record): return self.get_port_info(int(record['port'])) def apiGetPortStatusFromYtb(self, record): return self.get_port_status_from_dev() def apiStopChargingPortForYtb(self, record): self.stop_charging_port(int(record['port'])) return {} @property def show_pay_unit(self): """ 前台显示付费的时候,目前有不同的客户希望 显示不同的单位 有的显示金币 有的显示元, 这个地方处理下 :return: """ if self.device['otherConf'].get('pay_unit'): return self.device['otherConf'].get('pay_unit') if self.device.bill_as_service_feature.on: return "元" return u"币" def stop(self, port = None): return self.stop_charging_port(port) def switch_bill_as_service(self, onOrOff): if onOrOff: conf = self.get_dev_setting() if self.device.otherConf.get('unit_price') and self.device.otherConf.get('chrmt'): self.set_dev_setting(conf) oldTempModel = { 'chrmt': conf.get('chrmt'), 'price': conf.get('price'), 'washconfig': self.device['washConfig'], } devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 11, 'chrmt': 'ELEC', 'price': { 'ELEC': 1000000, 'TIME': conf['price']['TIME'] }}}) self.check_feedback_result(devInfo) newPackage = { "1": { "name": "套餐一", "price": 1.0, "coins": 1.0, "sn": 0, "time": 1.0, "imgList": [], "unit": "度", "description": "" }} Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': { 'washConfig': newPackage, 'otherConf.unit_price': {}, 'otherConf.chrmt': 'ELEC', 'otherConf.oldTempModel': oldTempModel, 'devType.features.billAsService.on': onOrOff, 'devType.features.billAsService.elecCharge': 0.5, 'devType.features.billAsService.serviceCharge': 0.5, }}) Device.invalid_device_cache(self.device.devNo) else: oldTempModel = self.device.otherConf.get('oldTempModel') if not oldTempModel: super(ChargingWEIFULEBox, self).switch_bill_as_service(onOrOff) else: washconfig = oldTempModel['washconfig'] devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self.device['devNo'], 'data': {'fun_code': 11, 'chrmt': oldTempModel['chrmt'], 'price': oldTempModel['price']}}) self.check_feedback_result(devInfo) conf = self.get_dev_setting() self.set_dev_setting(conf) Device.get_collection().update_one(filter={'devNo': self.device.devNo}, update={'$set': { 'washConfig': washconfig, 'otherConf.oldTempModel': {}, 'devType.features.billAsService.on': onOrOff, }}) Device.invalid_device_cache(self.device.devNo) def get_customize_score_unit(self): return u'元' def get_customize_package_unit(self): chrmt = self.device['otherConf'].get('chrmt') if not chrmt: chrmt = self.get_dev_setting().get('chrmt') # 按时间计费 if chrmt == 'TIME' or chrmt == 'POWER': return u'分钟' # 按电量计费 elif chrmt == 'ELEC': return u'度' return u'元' def start_customize_point(self,pointNum,openId,port): unit = self.get_customize_package_unit() package = {'name':'customizePoint','price':pointNum,'coins':pointNum,'unit':unit,'time':999} attachParas = {'chargeIndex':port,'onPoints':True} return self.start_device(package, openId, attachParas)