12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import time
- from decimal import Decimal
- from apilib.monetary import RMB
- from apilib.utils_AES import EncryptDate
- from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT, ErrorCode
- 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, DeviceType
- from apps.web.user.models import Card, ServiceProgress, ConsumeRecord
- cardKey = 'FR4e1OFCnDdrYA7u'
- class ChargingSocketBox(SmartBox):
- def __init__(self, device):
- super(ChargingSocketBox, self).__init__(device)
- def translate_funcode(self, fun_code):
- fun_codeDict = {
- '01': u'查询所有端口状态',
- '02': u'查询端口详细信息',
- '03': u'上报投币充电事件',
- '04': u'上报刷卡事件',
- '05': u'上报充电结束事件',
- '06': u'远程停止充电',
- '07': u'远程启动充电',
- '08': u'查询投币总额',
- '09': u'清除投币总数',
- '0A': u'查询订单信息',
- }
- return fun_codeDict.get(fun_code, '')
- def translate_event_cmdcode(self, cmdCode):
- cmdDict = {
- }
- return cmdDict.get(cmdCode, '')
- def check_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)
- port = int(attachParas['chargeIndex'])
- port_stat = self.get_port_status_from_dev().get(str(port), {})
- if port_stat.get('status') not in [Const.DEV_WORK_STATUS_CONNECTED, Const.DEV_WORK_STATUS_WORKING]:
- raise ServiceException({'result': 2, 'description': u'请先连接充电插座,再启动充电'})
- if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get('price') == 0:
- if port_stat.get('status') == Const.DEV_WORK_STATUS_WORKING:
- raise ServiceException({'result': 2, 'description': u'当前端口已处于工作状态,无法使用充满自停套餐, 请换个端口进行充电'})
- def get_port_info(self, port):
- data = {'fun_code': 2, 'port': int(port)}
- devInfo = self.send_mqtt(data)
- portInfo = devInfo.get('data', {})
- result = {}
- pay_unit = self.show_pay_unit
- exec_orders = portInfo.get('exec_orders', [])
- _wait = []
- for exec_order in exec_orders:
- if exec_order['status'] == 'running':
- result['voltage'] = round(portInfo.get('volt', 0), 2)
- result['power'] = round(portInfo.get('watt', 0), 2)
- result['ampere'] = round((portInfo.get('ampr', 0) * 0.001), 2)
- result['coins'] = '{}'.format(round(exec_order['amount'] / 100.0, 2))
- result['usedTime'] = round(exec_order.get('time', 0) / 60.0, 1)
- result['usedElec'] = round(exec_order.get('elec', 0) * 0.000001, 4)
- result['startTime'] = datetime.datetime.fromtimestamp(int(exec_order['exec_time'])).strftime(
- '%m-%d %H:%M:%S')
- if exec_order['chrmt'] == 'TIME':
- result['leftTime'] = round(exec_order.get('left_time', 0) / 60.0, 1)
- result['needTime'] = '{}分钟'.format(round(exec_order['amount_time'] / 60.0, 1))
- elif exec_order['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)
- else:
- pass
- if exec_order['order_type'] == 'apps_start':
- result['consumeType'] = 'mobile'
- result['consumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2), pay_unit)
- result['leftMoney'] = '{}{}'.format(round(exec_order.get('left_money', 0) * 0.01, 2),
- pay_unit)
- try:
- orderNo = exec_order['id']
- order = ConsumeRecord.objects.filter(orderNo=orderNo).first()
- if not order:
- result['nickName'] = '经销商上分'
- else:
- 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'
- result['needTime'] = '充满自停'
- result.pop('needElec', None)
- result.pop('leftMoney', None)
- result.pop('leftTime', None)
- result.pop('leftElec', None)
- except:
- pass
- if exec_order['order_type'] == 'card_start':
- result['consumeType'] = 'card'
- result['cardNo'] = exec_order['card_no']
- result['cardConsumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2),
- pay_unit)
- result['cardLeftMoney'] = '{}{}'.format(round(exec_order.get('left_money', 0) * 0.01, 2),
- pay_unit)
- result['cardBalance'] = '{}{}'.format(round(exec_order['balance'] * 0.01, 2), pay_unit)
- try:
- card = Card.objects.get(cardNo=exec_order['card_no'])
- result['nickName'] = card.cardName or card.nickName
- except:
- pass
- else:
- pass
- if exec_order['status'] == 'waiting':
- _one = {}
- if exec_order['chrmt'] == 'TIME':
- _one['leftTime'] = round(exec_order.get('left_time', 0) / 60.0, 1)
- _one['needTime'] = '{}分钟'.format(round(exec_order['amount_time'] / 60.0, 1))
- elif exec_order['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['order_type'] == 'apps_start':
- _one['consumeType'] = 'mobile'
- _one['coins'] = '{}{}'.format(round(exec_order['amount'] / 100.0, 2), pay_unit)
- try:
- order = ConsumeRecord.objects.filter(orderNo=exec_order['id']).first()
- if not order:
- _one['nickName'] = '经销商上分'
- else:
- _one['nickName'] = order.user.nickname
- except Exception:
- pass
- elif exec_order['order_type'] == 'card_start':
- _one['consumeType'] = 'card'
- _one['coins'] = '{}{}'.format(round(exec_order['amount'] / 100.0, 2), pay_unit)
- _one['cardNo'] = exec_order['card_no']
- _one['cardBalance'] = '{}{}'.format(round(exec_order['balance'] * 0.01, 2), pay_unit)
- try:
- card = Card.objects.get(cardNo=exec_order['card_no'])
- _one['nickName'] = card.cardName or card.nickName
- except:
- pass
- else:
- pass
- _wait.append(_one)
- if _wait:
- result['waittingOrder'] = _wait
- return result
- def send_mqtt(self, data, cmd=DeviceCmdCode.OPERATE_DEV_SYNC, timeout=10):
- """
- 发送mqtt 指令默认210 返回data
- """
- payload = {'IMEI': self.device.devNo, 'data': data}
- result = MessageSender.send(self.device, cmd,
- payload=payload, timeout=timeout)
- if not result.has_key('rst'):
- raise ServiceException({'result': 2, 'description': u'报文异常'})
- if result['rst'] == -1:
- raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- if result['rst'] == 1:
- raise ServiceException({'result': 2, 'description': u'串口通讯失败,您稍候再试,或者联系客服'})
- if result['rst'] == 2:
- raise ServiceException({'result': 2, 'description': u'订单已满'})
- if result['rst'] == 3:
- raise ServiceException({'result': 2, 'description': u'端口已被禁用'})
- if result['rst'] == 4:
- raise ServiceException({'result': 2, 'description': u'检测插头未连接,请先插上插头后再使用'})
- if result['rst'] == 5:
- raise ServiceException({'result': 2, 'description': u'计费类型无效'})
- if result['rst'] == 7:
- raise ServiceException({'result': 2, 'description': u'端口计量故障'})
- else:
- if cmd in [DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE]:
- return
- if result.get('data') == '00':
- raise ServiceException({'result': 2, 'description': u'设备操作失败.请重试'})
- else:
- return result
- def check_params_range(self, params, minData=None, maxData=None, desc=''):
- # type:(str,float,float,str) -> str
- """
- 检查参数,返回字符串参数
- """
- if params is None:
- raise ServiceException({'result': 2, 'description': u'{} 参数错误(值为空).'.format(desc)})
- if not isinstance(params, Decimal):
- params = Decimal(params)
- if not minData and maxData:
- if not isinstance(maxData, Decimal):
- maxData = Decimal(maxData)
- if params <= maxData:
- return '%g' % params
- else:
- raise ServiceException(
- {'result': 2, 'description': u'%s超出可选范围(值为: %s),可选最大值为%g' % (desc, params, maxData)})
- if not maxData and minData:
- if not isinstance(minData, Decimal):
- minData = Decimal(minData)
- if minData <= params:
- return '%g' % params
- else:
- raise ServiceException(
- {'result': 2, 'description': u'%s超出可选范围(值为: %s),可选最小值为%g' % (desc, params, minData)})
- if not minData and not maxData:
- return '%g' % params
- else:
- if not isinstance(minData, Decimal):
- minData = Decimal(minData)
- if not isinstance(maxData, Decimal):
- maxData = Decimal(maxData)
- if minData <= params <= maxData:
- return '%g' % params
- else:
- raise ServiceException(
- {'result': 2, 'description': u'%s参数超出可选范围(值为: %s),可取范围为%g-%g' % (desc, params, minData, maxData)})
- def test(self, coins):
- data = {'fun_code': 0x07, 'order_id': '1111', 'coins': coins, 'port': 1, 'time': 60}
- devInfo = self.send_mqtt(data)
- return devInfo
- def _check_package(self, package):
- """
- 获取设备启动的发送数据 根据设备的当前模式以及套餐获取
- :param package:
- :return:
- """
- 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':
- billingType = 'time'
- if unit == u'小时':
- _time = _time * 60
- elif unit == u'天':
- _time = _time * 24 * 60
- elif unit == u'秒':
- _time = _time / 60
- elif unit == u'分钟':
- _time = _time
- else:
- raise ServiceException({'result': 2, 'description': u'套餐单位错误,应选取单位(时间),请联系经销商'})
- # 按电量计费
- elif chrmt == 'ELEC':
- billingType = 'elec'
- if unit != u'度':
- raise ServiceException({'result': 2, 'description': u'套餐单位错误,应选取单位(度),请联系经销商'})
- else:
- _time = _time * 100
- else:
- raise ServiceException({'result': 2, 'description': u'套餐单位错误,应选取单位(时间,度),请联系经销商'})
- return _time, unit, billingType
- # 访问设备,获取设备端口信息
- def get_port_status_from_dev(self):
- data = {'fun_code': 0x01, 'all': True}
- devInfo = self.send_mqtt(data)
- portData = devInfo['data']['port_stat']
- result = {}
- for k, v in portData.items():
- if v == 'idle':
- result[k] = {'status': Const.DEV_WORK_STATUS_IDLE}
- elif v == 'link':
- result[k] = {'status': Const.DEV_WORK_STATUS_CONNECTED}
- elif v == 'busy':
- result[k] = {'status': Const.DEV_WORK_STATUS_WORKING}
- elif v == 'fault':
- result[k] = {'status': Const.DEV_WORK_STATUS_FAULT}
- elif v == 'forbid':
- result[k] = {'status': Const.DEV_WORK_STATUS_FORBIDDEN}
- else:
- result[k] = {'status': Const.DEV_WORK_STATUS_FAULT}
- allPorts, usedPorts, usePorts = self.get_port_static_info(result)
- Device.update_dev_control_cache(self._device['devNo'],
- {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
- # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- for strPort, info in result.items():
- if 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', 2)
- 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 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'])
- _time, unit, billingType = self._check_package(package)
- if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get('price') == 0:
- coins = 10 * 100
- else:
- coins = int(float(package['coins']) * 100) # 单位为分
- if attachParas.get('onPoints'):
- orderNo = ConsumeRecord.make_no() + self.device.owner.username
- else:
- orderNo = attachParas.get('orderNo')
- data = {
- 'fun_code': 0x07,
- 'port': port,
- 'amount': coins,
- 'order_id': orderNo
- }
- devInfo = self.send_mqtt(data, timeout=MQTT_TIMEOUT.START_DEVICE)
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- lineInfo = ctrInfo.get(str(port), {})
- if not lineInfo or lineInfo.get('status') == Const.DEV_WORK_STATUS_IDLE:
- lineInfo = {
- 'port': str(port),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'order_type': 'apps_start',
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'orderNo': orderNo,
- }
- Device.update_port_control_cache(self._device['devNo'], lineInfo)
- devInfo['consumeOrderNo'] = orderNo
- devInfo['sequanceNo'] = orderNo
- if billingType == 'time':
- devInfo['finished_time'] = int(time.time()) + _time * 60
- else:
- devInfo['finished_time'] = int(time.time()) + 3600 * 12
- devInfo['ignoreService'] = True
- devInfo['servicedInfo'] = {
- 'chargeIndex': port
- }
- return devInfo
- def active_deactive_port(self, port, active):
- if active:
- raise ServiceException({'result': 2, 'description': u'该设备不支持直接打开端口'})
- return self.stop_charging_port(port)
- # 停止该端口下的所有任务
- def stop_charging_port(self, port):
- data = {'fun_code': 0x06, 'port': port}
- devInfo = self.send_mqtt(data)
- if devInfo['rst'] == 0:
- Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
- return True if devInfo['rst'] == 0 else False
- def analyze_event_data(self, data):
- if data['fun_code'] == '32': # 成功启动设备需要回复该事件
- return data['order']
- if data['fun_code'] == '34': # 如果是结束事件,需要把reason翻译出来
- descDict = {
- 'outofmoney': u'购买的充电时间或电量用完了',
- 'userstop': u'用户远程结束充电',
- 'adminstop': u'管理员远程结束充电',
- 'dealerstop': u'经销商远程结束充电',
- 'unplug': u'未检测到充电器, 结束充电',
- 'wattoverload': u'功率过载, 结束充电',
- 'voltoverload': u'电压过载, 结束充电',
- 'amproverload': u'电流过载, 结束充电',
- 'machoverload': u'整机功率过载, 结束充电',
- 'tempexcursion': u'温度过载, 结束充电',
- 'stopforfull': u'充满自停, 结束充电'
- }
- order = data['order']
- order['reasonDesc'] = descDict.get(str(order['cause_desc']), u'')
- data['order'] = order
- return data
- def ack_event(self, order_id, fun_code):
- data = {'order_id': order_id, 'fun_code': fun_code}
- self.send_mqtt(data)
- def get_card_pwd(self):
- devInfo = self.send_mqtt({'fun_code': 17})
- data = devInfo.get('data', {})
- card_cur_key = data.get('card_cur_key')
- enObj = EncryptDate(cardKey)
- card_cur_key = enObj.decrypt(card_cur_key)
- return {'card_pwd': card_cur_key}
- def set_device_function(self, request, lastSetConf):
- if 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):
- """
- 设置参数 对于计费模式做一下转换 顺便服务器保留一份
- :param request:
- :param lastSetConf:
- :return:
- """
- # 服务器侧的参数 先处理掉
- if request.POST.get('id_card_oncefee') is not None:
- id_card_oncefee = request.POST['id_card_oncefee']
- if not id_card_oncefee:
- raise ServiceException({'result': 2, 'description': u'在线卡单次刷卡金额不能为0'})
- Device.get_collection().update_one(filter={'devNo': self.device.devNo},
- update={'$set': {
- 'otherConf.id_card_oncefee': round(float(id_card_oncefee), 2),
- }})
- Device.invalid_device_cache(self.device.devNo)
- if request.POST.get('refundProtection') is not None:
- refundProtection = request.POST['refundProtection']
- Device.get_collection().update_one(filter={'devNo': self.device.devNo},
- update={'$set': {
- 'otherConf.refundProtection': round(float(refundProtection), 2),
- }})
- Device.invalid_device_cache(self.device.devNo)
- if request.POST.get('minAfterStartCoins') is not None:
- minAfterStartCoins = request.POST['minAfterStartCoins']
- Device.get_collection().update_one(filter={'devNo': self.device.devNo},
- update={'$set': {
- 'otherConf.minAfterStartCoins': round(float(minAfterStartCoins), 2),
- }})
- Device.invalid_device_cache(self.device.devNo)
- # 参数发向设备 11, 16指令
- setconfig1 = {'fun_code': 11}
- setconfig2 = {'fun_code': 16}
- # 音量适配
- if request.POST.get('volume_list'):
- volume_list = request.POST.get('volume_list')
- volumes = {}
- self.check_params_range(params=request.POST.get('volume'), minData=0.0, maxData=7.0, desc='语音音量参数')
- volumes.update({'default': int(request.POST.get('volume'))})
- for obj in volume_list:
- self.check_params_range(params=obj['volume'], minData=0.0, maxData=7.0, desc='音量参数')
- volumes.update({'{}-{}'.format(obj['start'], obj['end']): int(obj['volume'])})
- setconfig1.update({'volumes': volumes})
- # 计价模式适配
- chrmt = request.POST.get('chrmt')
- package_time = request.POST.get('package_time', [])
- package_elec = request.POST.get('package_elec', [])
- package_power = request.POST.get('package_power', [])
- if chrmt:
- 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']), round(1.0 / float(_item['price']) * 60 * 60, 1)]
- # 价格倍率 * 固定时间(60分钟) * 60秒
- )
- if not TIME:
- raise ServiceException({'result': 2, 'description': u'计费参数设置(按功率收费)缺少收费标准'})
- setconfig1['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
- setconfig1['chrmt'] = 'TIME'
- elif chrmt == 'ELEC': # 同样也处理一次时间计费规则 用于下发给设备
- for _item in package_time:
- TIME.append(
- [int(_item['power']), int(_item['time']) * 60]
- )
- setconfig1['chrmt'] = 'ELEC'
- price['TIME'] = TIME
- setconfig1.update({'price': price})
- if request.POST.get('auto_close') is not None:
- setconfig1.update({'auto_close': request.POST.get('auto_close')})
- if request.POST.get('float_time') or request.POST.get('float_watt') or request.POST.get('check_time'):
- float_charge = {}
- if request.POST.get('float_time'):
- float_charge['float_time'] = int(request.POST.get('float_time'))
- if request.POST.get('float_watt'):
- float_charge['float_watt'] = int(request.POST.get('float_watt'))
- if request.POST.get('check_time'):
- float_charge['check_time'] = int(request.POST.get('check_time'))
- setconfig1.update({'float_charge': float_charge})
- if request.POST.get('port_max_watt'):
- setconfig1.update({'port_max_watt': int(request.POST.get('port_max_watt'))})
- if request.POST.get('port_max_ampr'):
- setconfig1.update({'port_max_ampr': int(request.POST.get('port_max_ampr'))})
- if request.POST.get('mach_max_watt'):
- setconfig1.update({'mach_max_watt': int(request.POST.get('mach_max_watt'))})
- if request.POST.get('mach_max_temp'):
- setconfig1.update({'mach_max_temp': int(request.POST.get('mach_max_temp'))})
- if request.POST.get('mach_max_volt'):
- setconfig1.update({'mach_max_volt': int(request.POST.get('mach_max_volt'))})
- if request.POST.get('noload_check_watt') or request.POST.get('noload_check_time'):
- noload_check = {}
- if request.POST.get('noload_check_watt'):
- noload_check['watt'] = int(request.POST.get('noload_check_watt'))
- if request.POST.get('noload_check_time'):
- noload_check['time'] = int(request.POST.get('noload_check_time'))
- setconfig1.update({'noload_check': noload_check})
- if request.POST.get('card_pwd'):
- card_pwd = request.POST.get('card_pwd')
- card_pwd2 = request.POST.get('card_pwd2')
- if card_pwd != card_pwd2:
- raise ServiceException({'result': 2, 'description': u'两次密码输入不一致'})
- self.check_pwd(card_pwd)
- enObj = EncryptDate(cardKey)
- setconfig2.update({'card_cur_key': enObj.encrypt(card_pwd)})
- self.send_mqtt(setconfig1)
- unit_price = None
- if chrmt == 'TIME':
- unit_price = {'unit': '分钟', 'value': max(map(lambda _: _[1] / 60.0, setconfig1['price']['TIME']))}
- elif chrmt == 'POWER':
- unit_price = {'unit': '分钟', 'value': max(map(lambda _: _[1] / 60.0, setconfig1['price']['TIME']))}
- elif chrmt == 'ELEC':
- unit_price = {'unit': '度', 'value': round(setconfig1['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)
- if request.POST.get('card_refund', None) is not None:
- setconfig2.update({'card_refund': request.POST.get('card_refund')})
- if request.POST.get('card_disable', None) is not None:
- setconfig2.update({'card_disable': request.POST.get('card_disable')})
- if request.POST.get('card_timeout'):
- setconfig2.update({'card_timeout': int(request.POST.get('card_timeout'))})
- if request.POST.get('card_oncefee'):
- setconfig2.update({'card_oncefee': int(float(request.POST.get('card_oncefee')) * 100)})
- self.send_mqtt(setconfig2)
- def get_dev_setting(self):
- """
- 获取参数显示在前台
- :return:
- """
- # 服务器侧的参数
- otherConf = self.device['otherConf']
- # 获取主板侧的参数
- devInfo = self.send_mqtt({'fun_code': 12})
- # 参数整合
- data = dict()
- # ID卡刷卡一次的费用
- data['id_card_oncefee'] = otherConf.get('id_card_oncefee', 1)
- data['refundProtection'] = otherConf.get('refundProtection', 5)
- data['minAfterStartCoins'] = otherConf.get('minAfterStartCoins', 0)
- configs = devInfo['data']
- # 价格适配
- price_for_time = configs['price']['TIME']
- package_time = []
- chrmt = configs.get('chrmt')
- # 按功率分档收费显示
- for _item in price_for_time:
- package_time.append({'power': _item[0], 'time': round(_item[1] / 60.0, 1)})
- # 按电量收费
- price_for_elec = round(configs['price']['ELEC'] / 1000000.0, 4)
- package_elec = [{'elec': price_for_elec, 'price': 1}] # 电量的固定单位是1
- # 按功率收费显示
- package_power = []
- for _item in price_for_time:
- package_power.append({'power': _item[0], 'price': round(1.0 / (_item[1] / 60.0 / 60.0), 2)})
- # 计费规则的添加 有就显示服务器的, 没有就显示主板的
- data.update({
- 'package_time': package_time,
- 'package_elec': package_elec,
- 'package_power': package_power,
- 'chrmt': otherConf.get('chrmt', chrmt) # 以缓存的为准
- })
- # 浮充参数的添加
- float_charge = configs.get('float_charge', {})
- data.update(float_charge)
- data['auto_close'] = configs.get('auto_close', {})
- data['mach_max_watt'] = configs.get('mach_max_watt', 0)
- data['port_max_ampr'] = configs.get('port_max_ampr', 0)
- data['port_max_watt'] = configs.get('port_max_watt', 0)
- data['mach_max_volt'] = configs.get('mach_max_volt', 0)
- data['mach_max_temp'] = configs.get('mach_max_temp', 0)
- # 空载适配
- data.update({
- 'noload_check_watt': int(configs['noload_check'].get('watt', 0)),
- 'noload_check_time': int(configs['noload_check'].get('time', 0)),
- })
- # 音量适配
- volume_list = []
- for k, v in configs['volumes'].items():
- item = {}
- if k == 'default':
- continue
- if '-' in k:
- item['start'], item['end'] = k.split('-')
- item['volume'] = v
- volume_list.append(item)
- data.update({
- 'volume': configs['volumes']['default'],
- 'volume_list': volume_list
- })
- # 17 指令
- devInfo = self.send_mqtt({'fun_code': 17})
- configs2 = devInfo.get('data')
- data['card_curmode'] = configs2['card_curmode']
- data['card_refund'] = configs2['card_refund']
- data['card_disable'] = configs2['card_disable']
- # data['card_token'] = configs2['card_token']
- data['card_timeout'] = configs2['card_timeout']
- data['card_oncefee'] = round(configs2['card_oncefee'] / 100.0, 2)
- state = self.get_dev_consume_count()
- data.update(state)
- return data
- def get_dev_consume_count(self):
- data = {'fun_code': 8}
- devInfo = self.send_mqtt(data)
- total_card = round(devInfo.get('data', {}).get('total_card', 0) * 0.01, 2)
- return {'total_card': total_card}
- def reset_total_card(self):
- data = {
- 'fun_code': 9
- }
- self.send_mqtt(data)
- def set_max_watt(self, max_watt):
- self.send_mqtt({'fun_code': 11, 'max_watt': int(max_watt)})
- def lock_unlock_port(self, port, lock=True):
- portInfo = self.get_port_info(port)
- if portInfo and portInfo['status'] == Const.DEV_WORK_STATUS_WORKING and lock:
- raise ServiceException({'result': 2, 'description': u'端口正忙,请先关闭端口后,再禁止端口'})
- typeStr = not lock
- self.send_mqtt({'port': int(port), 'enable': typeStr, 'fun_code': 13})
- 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 get_card_mode(self):
- devInfo = self.send_mqtt({'fun_code': 17})
- MAP_MODE = {
- 'NORMAL': 0,
- 'ISSUE': 1,
- 'MODKEY': 2,
- }
- result = {}
- result['card_mode'] = MAP_MODE.get(devInfo['data']['card_curmode'])
- return result
- def set_card_mode(self, setConf):
- cardMode = int(setConf.get('card_mode'))
- data = {'fun_code': 16}
- if cardMode == 0:
- data.update({'card_curmode': {'mod': 'NORMAL'}})
- elif cardMode == 1: # 格式化为离线卡
- self.check_pwd(setConf['new_pwd'])
- newPwd = setConf['new_pwd']
- if not str(setConf['balance']).isdigit():
- raise ServiceException({'result': 2, 'description': u'余额必须是数字'})
- balance = int(setConf['balance'])
- if not (balance >= 0 and balance <= 5000):
- raise ServiceException({'result': 2, 'description': u'余额必须在0和5000元之间'})
- card_dft_val = balance * 100 # 硬件模块记录的单位是角
- enObj = EncryptDate(cardKey)
- data.update({'card_curmode': {'mod': 'ISSUE', 'cfg': {'card_new_key': enObj.encrypt(str(newPwd)),
- 'card_dft_val': card_dft_val}}})
- elif cardMode == 2:
- self.check_pwd(setConf['new_pwd'])
- oldPwd = setConf.get('old_pwd', '')
- newPwd = setConf.get('new_pwd', '')
- enObj = EncryptDate(cardKey)
- data.update({'card_curmode': {'mod': 'MODKEY', 'cfg': {'card_old_key': enObj.encrypt(str(oldPwd)),
- 'card_new_key': enObj.encrypt(str(newPwd))}}})
- self.send_mqtt(data)
- def response_card_charge_result(self, cardNo, result):
- self.send_mqtt({'fun_code': 36, 'card_no': cardNo, 'result': result})
- def recharge_card(self, cardNo, money, orderNo=None):
- self.send_mqtt(
- {'fun_code': 36, 'result': 1, 'card_no': cardNo, 'charge': int(money * 100), 'order_id': orderNo})
- card = Card.objects.filter(cardNo=cardNo, dealerId=self.device.ownerId).first()
- balance = card.balance + money
- return {
- 'result': ErrorCode.SUCCESS,
- 'description': ''
- }, balance
- def response_card_balance(self, cardNo, amount, balance, result):
- return self.send_mqtt({'fun_code': 35, 'card_no': cardNo, 'balance': RMB.yuan_to_fen(balance),
- 'result': result, 'amount': RMB.yuan_to_fen(amount)})
- def get_current_use(self, **kw):
- base_data = kw.get('base_data')
- spDict = kw.get('spDict')
- sp = ServiceProgress.objects.filter(device_imei=self.device.devNo, port=spDict['port']).first()
- data = {'fun_code': 2, 'port': spDict.get('port')}
- devInfo = self.send_mqtt(data)
- portInfo = devInfo.get('data', {})
- exec_orders = portInfo.get('exec_orders', [])
- running_order = None
- waiting_order = []
- for exec_order in exec_orders: # 第一层筛选
- if exec_order['id'] not in sp.consumes:
- 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']
- 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['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, 4)
- else:
- pass
- if exec_order['order_type'] == 'apps_start':
- 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(exec_order.get('amount', 0) * 0.01, 2), pay_unit),
- 'port': exec_order['port'],
- 'consumeType': 'mobile',
- }
- try:
- orderNo = exec_order['id']
- order = ConsumeRecord.objects.filter(orderNo=orderNo).first()
- package = order.package
- if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get(
- 'price') == 0: # 后付费
- item['order'] = {
- 'orderNo': exec_order['id'], # 停止按钮传订单停单用
- 'coin': '{}{}'.format(0, pay_unit),
- 'port': exec_order['port'],
- 'consumeType': 'postpaid'
- }
- item['needTime'] = '充满自停'
- item.pop('needElec', None)
- item.pop('leftMoney', None)
- item.pop('leftTime', None)
- item.pop('leftElec', None)
- elif order.attachParas.get('vCardId'):
- item['order']['consumeType'] = 'mobile_vcard'
- except:
- pass
- elif exec_order['order_type'] == 'card_start':
- item['cardNo'] = exec_order['card_no']
- item['cardConsumeMoney'] = 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',
- }
- 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 'cardNo' in exec_order:
- item['cardNo'] = exec_order['card_no']
- item.update(DeviceType.get_services_button(self.device['devType']['id']))
- result_list.append(item)
- return result_list
- def isHaveStopEvent(self):
- return True
- def stop_by_order(self, port, orderNo):
- data = {'fun_code': 4, 'order_id': orderNo, 'operator': 'user'}
- self.send_mqtt(data)
- def clear_dev_feecount(self):
- data = {'fun_code': 0x09, 'total_coin': True, 'total_card': True}
- self.send_mqtt(data)
- def reboot_device(self):
- # 重启单片机
- MessageSender.send(self.device, DeviceCmdCode.SET_DEVINFO, {'reset_mcu': True})
- # 重启模块
- MessageSender.send(self.device, DeviceCmdCode.SET_DEVINFO, {'restart': True})
- @property
- def show_pay_unit(self):
- """
- 前台显示付费的时候,目前有不同的客户希望 显示不同的单位 有的显示金币 有的显示元, 这个地方处理下
- :return:
- """
- if self.device['otherConf'].get('pay_unit'):
- return self.device['otherConf'].get('pay_unit')
- return u'币'
- def get_port_using_detail(self, port, ctrInfo, isLazy=False):
- return self.get_port_info(port)
- def stop(self, port=None):
- return self.stop_charging_port(int(port))
- # def __translate_status_from_str(self, status):
- # dictConf = {
- # 'idle': Const.DEV_WORK_STATUS_IDLE,
- # 'busy': Const.DEV_WORK_STATUS_WORKING,
- # 'forbid': Const.DEV_WORK_STATUS_FORBIDDEN,
- # 'fault': Const.DEV_WORK_STATUS_FAULT,
- # 'running': Const.DEV_WORK_STATUS_WORKING
- # }
- # return dictConf.get(status, Const.DEV_WORK_STATUS_IDLE)
- #
- # def get_many_port_info(self, portList):
- # data = {'fun_code': 1, 'all': True}
- # devInfo = self.send_mqtt(data)
- # portInfo = devInfo['data']
- # portParam = portInfo.get('port_param', {})
- # exec_queue = portInfo.get('exec_queue', {})
- #
- # pay_unit = self.show_pay_unit
- # resultDict = {}
- # for port, exec_orders in exec_queue.items():
- # if port not in portList:
- # continue
- # result = {'index': port}
- # onePortParam = portParam.get(port, {})
- # _wait = []
- # for exec_order in exec_orders:
- # if exec_order['status'] == 'running':
- #
- # result['voltage'] = round(onePortParam.get('volt', 0), 2)
- # result['power'] = round(onePortParam.get('watt', 0), 2)
- # result['ampere'] = round((onePortParam.get('ampr', 0) * 0.001), 2)
- # result['devTemp'] = round((portInfo.get('mach_temp', 0)), 2)
- # result['status'] = self.__translate_status_from_str(exec_order['status'])
- # result['usedTime'] = round(exec_order.get('time', 0) / 60.0, 2)
- # result['usedElec'] = round(exec_order.get('elec', 0) * 0.000001, 4)
- # result['coins'] = '{}'.format(round(exec_order['amount'] / 100.0, 2))
- #
- # if 'left_time' in exec_order:
- # result['leftTime'] = round(exec_order.get('left_time', 0) / 60.0, 2)
- #
- # elif 'left_elec' in exec_order:
- # result['leftElec'] = round(exec_order.get('left_elec', 0) * 0.000001, 4)
- #
- # if exec_order['order_type'] == 'apps_start':
- # result['consumeType'] = 'mobile'
- # result['consumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2),
- # pay_unit)
- # result['leftMoney'] = '{}{}'.format(round(exec_order.get('left_money', 0) * 0.01, 2),
- # pay_unit)
- # try:
- # orderNo = exec_order['id']
- # order = ConsumeRecord.objects.filter(orderNo=orderNo).first()
- # if not order:
- # result['nickName'] = '经销商上分'
- # else:
- # result['nickName'] = order.user.nickname
- # except Exception:
- # pass
- #
- # if exec_order['order_type'] == 'card_start':
- # result['consumeType'] = 'card'
- # try:
- # card = Card.objects.get(cardNo=exec_order['card_no'])
- # result['nickName'] = card.cardName or card.nickName
- # except:
- # pass
- # result['cardNo'] = exec_order['card_no']
- # result['cardConsumeMoney'] = '{}{}'.format(round(exec_order.get('money', 0) * 0.01, 2),
- # pay_unit)
- # result['cardLeftMoney'] = '{}{}'.format(round(exec_order.get('left_money', 0) * 0.01, 2),
- # pay_unit)
- # result['cardBalance'] = '{}{}'.format(round(exec_order['balance'] * 0.01, 2), pay_unit)
- #
- #
- # elif exec_order['status'] == 'waiting':
- # _one = {}
- # if exec_order['order_type'] == 'apps_start':
- # _one['consumeType'] = 'mobile'
- # try:
- # order = ConsumeRecord.objects.filter(orderNo=exec_order['id']).first()
- # if not order:
- # _one['nickName'] = '经销商上分'
- # else:
- # _one['nickName'] = order.user.nickname
- # except Exception:
- # pass
- # elif exec_order['order_type'] == 'card_start':
- # _one['consumeType'] = 'card'
- # _one['cardNo'] = exec_order['card_no']
- # _one['cardBalance'] = '{}{}'.format(round(exec_order['balance'] * 0.01, 2), pay_unit)
- #
- # try:
- # card = Card.objects.get(cardNo=exec_order['card_no'])
- # _one['nickName'] = card.cardName or card.nickName
- # except Exception:
- # pass
- #
- # if 'amount_time' in exec_order:
- # _one['needTime'] = '{}分钟'.format(round(exec_order['amount_time'] / 60.0, 1))
- # if 'amount_elec' in exec_order:
- # _one['needElec'] = '{}度'.format(round(exec_order['amount_elec'] / 1000000.0, 2))
- # if 'amount' in exec_order:
- # _one['coins'] = '{}{}'.format(round(exec_order['amount'] / 100.0, 2), pay_unit)
- # if 'create_time' in exec_order:
- # _one['createTime'] = datetime.datetime.fromtimestamp(
- # int(exec_order['create_time'])).strftime('%m-%d %H:%M:%S')
- #
- # _wait.append(_one)
- #
- # if _wait:
- # result['waittingOrder'] = _wait
- #
- # resultDict[port] = result
- #
- # return resultDict
|