123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972 |
- # -*- 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
|