123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import re
- import threading
- import time
- from decimal import Decimal
- from django.core.cache import cache
- from mongoengine import Q
- from apilib.monetary import RMB
- from apilib.utils_AES import EncryptDate
- from apps import serviceCache
- from apps.web.common.proxy import ClientConsumeModelProxy
- from apps.web.constant import DeviceCmdCode, ErrorCode, Const, MQTT_TIMEOUT
- from apps.web.core.adapter.base import SmartBox
- from apps.web.core.exceptions import ServiceException, DeviceNetworkTimeoutError, StartDeviceError
- from apps.web.core.networking import MessageSender
- from apps.web.device.models import Device, DeviceType
- from apps.web.user.models import ServiceProgress, Card, MyUser, ConsumeRecord
- cardKey = 'FR4e1OFCnDdrYA7u'
- logger = logging.getLogger(__name__)
- class WeiFuLeCar(SmartBox):
- def __init__(self, device):
- super(WeiFuLeCar, self).__init__(device)
- self.port = '1'
- def analyze_event_data(self, device_data):
- uart_data = device_data.get('data')
- if not uart_data:
- return
- fun_code = uart_data.get('fun_code')
- if not fun_code:
- return
- billingType = 'elec'
- cmd = fun_code
- if cmd == '32':
- return uart_data.get('order')
- def disable_app_device(self, switch=True):
- # type:(bool) -> None
- otherConf = self.device.get('otherConf', {})
- otherConf['disableDevice'] = switch
- Device.objects.filter(devNo=self.device['devNo']).update(otherConf=otherConf)
- Device.invalid_device_cache(self.device['devNo'])
- @staticmethod
- def check_params_range(params, minData=None, maxData=None, desc=''):
- # type:(str,float,float,str) -> str
- """
- 检查参数,返回字符串参数
- """
- if params is None:
- raise ServiceException({'result': 2, 'description': u'参数错误.'})
- 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超出可选范围,可选最大值为%g' % (desc, 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超出可选范围,可选最小值为%g' % (desc, 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参数超出可选范围,可取范围为%g-%g' % (desc, minData, maxData)})
- def send_mqtt(self, data=None, cmd=DeviceCmdCode.OPERATE_DEV_SYNC, otherData=None, timeout=5):
- """
- 发送mqtt 指令默认210 返回data
- """
- if data:
- payload = {'data': data}
- else:
- payload = otherData
- result = MessageSender.send(self.device, cmd,
- payload, timeout=timeout)
- if 'rst' in result and result['rst'] != 0:
- if result['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'该设备正在玩命找网络,请您稍候再试', 'rst': -1})
- elif result['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'该设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能', 'rst': 1})
- 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.get('data', 'ok')
- def _do_update_configs(self, updateDict):
- dev = Device.objects.get(devNo=self.device.devNo)
- deviceConfigs = dev.otherConf.get('deviceConfigs', {})
- deviceConfigs.update(updateDict)
- dev.otherConf['deviceConfigs'] = deviceConfigs
- dev.save()
- Device.invalid_device_cache(self.device.devNo)
- self._device = Device.get_dev(self.device.devNo)
- def _get_device_configs(self):
- return self.device.otherConf.get('deviceConfigs', {})
- def _start(self, port, money, order_id):
- amount = int(float(money) * 100)
- data = {
- 'fun_code': 7,
- 'port': port,
- 'amount': amount,
- 'order_id': order_id
- }
- payload = {'data': data}
- return MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, payload,
- timeout=MQTT_TIMEOUT.START_DEVICE)
- def do_ack_order_32(self, order_id):
- data = {
- 'fun_code': 32,
- 'order_id': order_id
- }
- self.send_mqtt(data)
- def do_ack_remove_order_from_device_34(self, order_id):
- data = {
- 'fun_code': 34,
- 'order_id': order_id
- }
- self.send_mqtt(data)
- def _check_dev_status(self, port):
- data = {
- 'fun_code': 2,
- 'port': int(port)
- }
- data = self.send_mqtt(data)
- exec_orders = data.get('exec_task') or []
- order_list = list(map(lambda x: x['id'], exec_orders))
- result = False
- status = data.get('status')
- if status == 'fault':
- raise ServiceException({'result': 2, 'description': u'该充电桩出现故障,请使用其他充电桩'})
- elif status == 'idle':
- raise ServiceException({'result': 2, 'description': u'请先连接充电枪'})
- elif status == 'link':
- result = True
- elif status == 'estop':
- raise ServiceException({'result': 2, 'description': u'该充电桩处于 紧急停止 状态,请确认充电桩安全状态后,再次扫码使用或选择其他充电桩'})
- elif status == 'ready':
- result = True
- elif status == 'busy':
- result = True
- else:
- pass
- return {'result': result, 'order_list': order_list}
- def _check_package(self, package):
- """
- 获取设备启动的发送数据 根据设备的当前模式以及套餐获取
- :param package:
- :return:
- """
- unit = package.get('unit')
- _time = package.get('time')
- billingType = 'elec'
- if unit != u'度':
- raise ServiceException({'result': 2, 'description': u'套餐单位错误,应选取单位(度),请联系经销商'})
- else:
- _time = _time
- return _time, unit, billingType
- def _transform_prices(self, prices, mode='send'):
- if mode == 'send':
- send_list = []
- default_price = round(float(prices.get('default_price', 0)), 2)
- item = ['default', default_price]
- send_list.append(item)
- if all([prices.get('time1_start_m'), prices.get('time1_start_h'), prices.get('time1_end_m'),
- prices.get('time1_end_h'), prices.get('price1')]):
- time1_start_m = '{0:0>2}'.format(prices.get('time1_start_m'))
- time1_start_h = '{0:0>2}'.format(prices.get('time1_start_h'))
- time1_end_m = '{0:0>2}'.format(prices.get('time1_end_m'))
- time1_end_h = '{0:0>2}'.format(prices.get('time1_end_h'))
- price1 = round(float(prices.get('price1', 0)), 2)
- if time1_end_h + ':' + time1_end_m <= time1_start_h + ':' + time1_start_m:
- raise ServiceException({'result': 2, 'description': u'时段1结束时间必须大于起始时间'})
- str = time1_start_h + ':' + time1_start_m + '-' + time1_end_h + ':' + time1_end_m
- item = [str, price1]
- send_list.append(item)
- else:
- raise ServiceException({'result': 2, 'description': u'时段1参数不完整'})
- if all([prices.get('time2_start_m'), prices.get('time2_start_h'), prices.get('time2_end_m'),
- prices.get('time2_end_h'), prices.get('price2')]):
- time2_start_m = '{0:0>2}'.format(prices.get('time2_start_m'))
- time2_start_h = '{0:0>2}'.format(prices.get('time2_start_h'))
- time2_end_m = '{0:0>2}'.format(prices.get('time2_end_m'))
- time2_end_h = '{0:0>2}'.format(prices.get('time2_end_h'))
- price2 = round(float(prices.get('price2', 0)), 2)
- if time2_end_h + ':' + time2_end_m <= time2_start_h + ':' + time2_start_m:
- raise ServiceException({'result': 2, 'description': u'时段2结束时间必须大于起始时间'})
- str = time2_start_h + ':' + time2_start_m + '-' + time2_end_h + ':' + time2_end_m
- item = [str, price2]
- send_list.append(item)
- else:
- raise ServiceException({'result': 2, 'description': u'时段2参数不完整'})
- if all([prices.get('time3_start_m'), prices.get('time3_start_h'), prices.get('time3_end_m'),
- prices.get('time3_end_h'), prices.get('price3')]):
- time3_start_m = '{0:0>2}'.format(prices.get('time3_start_m'))
- time3_start_h = '{0:0>2}'.format(prices.get('time3_start_h'))
- time3_end_m = '{0:0>2}'.format(prices.get('time3_end_m'))
- time3_end_h = '{0:0>2}'.format(prices.get('time3_end_h'))
- price3 = round(float(prices.get('price3', 0)), 2)
- if time3_end_h + ':' + time3_end_m <= time3_start_h + ':' + time3_start_m:
- raise ServiceException({'result': 2, 'description': u'时段3结束时间必须大于起始时间'})
- str = time3_start_h + ':' + time3_start_m + '-' + time3_end_h + ':' + time3_end_m
- item = [str, price3]
- send_list.append(item)
- else:
- raise ServiceException({'result': 2, 'description': u'时段3参数不完整'})
- if not (
- time3_start_h + ':' + time3_start_m >= time2_end_h + ':' + time2_end_m and time2_start_h + ':' + time2_start_m >= time1_end_h + ':' + time1_end_m):
- raise ServiceException({'result': 2, 'description': u'时段的其实时间不能小于上一个时段的结束时间'})
- return send_list
- else:
- price_dict = {}
- index = 1
- for price in prices:
- if price[0] == 'default':
- price_dict.update({'default_price': price[1]})
- else:
- time1_start, time1_end = price[0].split('-')
- price_dict.update({
- 'time{}_start_h'.format(index): time1_start.split(':')[0],
- 'time{}_start_m'.format(index): time1_start.split(':')[1],
- 'time{}_end_h'.format(index): time1_end.split(':')[0],
- 'time{}_end_m'.format(index): time1_end.split(':')[1],
- 'price{}'.format(index): price[1]
- })
- index += 1
- return price_dict
- def _reboot_device(self):
- data = {
- 'fun_code': 11,
- 'reset_mcu': True,
- }
- self.send_mqtt(data)
- def _restart_device(self):
- data = {
- 'restart': True,
- }
- self.send_mqtt(otherData=data, cmd=DeviceCmdCode.SET_DEVINFO)
- def _factory_set_device(self):
- data = {
- 'factory_set': True,
- }
- self.send_mqtt(otherData=data, cmd=DeviceCmdCode.SET_DEVINFO)
- def _get_current_order(self):
- data = {
- 'fun_code': 2,
- 'exec_orders': True,
- }
- data = self.send_mqtt(data)
- return data.get('exec_orders', [])
- def _get_total_card(self):
- data = {
- 'fun_code': 8
- }
- data = self.send_mqtt(data)
- return {'total_card': int(data.get('total_card', 0)) / 100.0}
- def _reset_total_card(self):
- data = {
- 'fun_code': 9
- }
- self.send_mqtt(data)
- def is_port_can_use(self, port, canAdd=False):
- return True, ''
- # data = {
- # 'fun_code': 2,
- # 'status': True,
- # 'exec_orders': True,
- # 'wait_orders': True,
- # }
- # data = self.send_mqtt(data)
- # exec_orders = data.get('exec_orders')
- # wait_orders = data.get('wait_orders')
- #
- # order_list = []
- # if exec_orders:
- # order_list.append(exec_orders[0]['id'])
- # if wait_orders:
- # order_list += list(map(lambda x: x['id'], wait_orders))
- #
- # status = data.get('status')
- # if status == 'fault':
- # return False, '该充电桩出现故障,请使用其他充电桩'
- # elif status == 'idle':
- # return False, '请先连接充电枪'
- # elif status == 'link':
- # return True, ''
- # elif status == 'estop':
- # raise False, '该充电桩处于 紧急停止 状态,请确认充电桩安全状态后,再次扫码使用或选择其他充电桩'
- # elif status == 'ready':
- # return True, ''
- # elif status == 'busy':
- # return True, ''
- # else:
- # return False, '该充电桩出现故障,请使用其他充电桩'
- 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', '1')
- package = washConfig.get(packageId)
- # self._check_package(package)
- port = attachParas.get('chargeIndex')
- if not port:
- raise ServiceException({'result': 2, 'description': u'请选择端口后再启动设备'})
- data = self._check_dev_status(port)
- openId = attachParas.get('openId')
- order_list = data.get('order_list')
- result = data.get('result')
- if not order_list:
- return result
- else:
- consumeRcd = ConsumeRecord.objects.filter(devNo=self.device.devNo, orderNo=order_list[0]).first()
- if not consumeRcd: # 没有找到订单 证明是刷卡启动的 或则经销商远程上分
- raise ServiceException({'result': 2, 'description': u'当前设备已经有其他人启动充电,请不要操作设备或充电枪, 小心触电!'})
- else:
- if consumeRcd.openId != openId:
- raise ServiceException({'result': 2, 'description': u'当前设备已有人在使用,请您选择空闲的设备进行操作'})
- else:
- return result
- def get_port_status(self, force=False):
- return self._get_port_status()
- def async_update_portinfo_from_dev(self):
- class Sender(threading.Thread):
- def __init__(self, smartBox):
- super(Sender, self).__init__()
- self._smartBox = smartBox
- def run(self):
- try:
- self._smartBox._get_port_status()
- except Exception as e:
- logger.info('get port stats from dev,e=%s' % e)
- sender = Sender(self)
- sender.start()
- 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.get('chargeIndex'))
- if not port:
- raise ServiceException({'result': 2, 'description': u'请选择端口后再启动设备'})
- onPoints = attachParas.get('onPoints')
- if onPoints: # 远程上分
- self._check_dev_status(port)
- orderNo = ConsumeRecord.make_no()
- logger.info('dealer onPoints package<{}> order<{}>'.format(package, orderNo))
- else:
- orderNo = str(attachParas.get('orderNo'))
- coins = package.get('coins')
- result = self._start(port, coins, orderNo)
- if result['rst'] == 0:
- consumeOrder = {
- 'orderNo': orderNo,
- 'coin': package.get('coins'),
- 'consumeType': 'coin',
- }
- self.register_service_progress(openId, orderNo, port, consumeOrder, attachParas)
- elif result['rst'] == -1: # 网络丢失
- raise DeviceNetworkTimeoutError()
- elif result['rst'] == 1:
- raise StartDeviceError('订单号已存在')
- elif result['rst'] == 2:
- raise StartDeviceError('订单已满')
- elif result['rst'] == 3:
- raise StartDeviceError('{}号端口被禁用'.format(port))
- elif result['rst'] == 4:
- raise StartDeviceError('计量器故障')
- elif result['rst'] == 5:
- raise StartDeviceError('检查电压异常')
- elif result['rst'] == 6:
- raise StartDeviceError('设备急停状态')
- elif result['rst'] == 7:
- raise StartDeviceError('继电器故障')
- elif result['rst'] == 8:
- raise StartDeviceError('请连接充电器')
- elif result['rst'] == 9:
- raise StartDeviceError('车辆侧充电器开关未闭合')
- event_info = {
- 'cmd': 100,
- 'data': {
- 'fun_code': 32,
- 'order': {
- 'order_type': 'apps_start',
- 'id': orderNo,
- 'status': 'running',
- 'adapter': True
- }
- },
- 'IMEI': '862167056713559',
- 'rst': 0
- }
- return event_info
- def register_service_progress(self, openId, weifuleOrderNo, port, consumeOrder=None, attachParas=None):
- return ServiceProgress.objects.create(
- open_id=openId,
- device_imei=self.device.devNo,
- devTypeCode=self.device.devTypeCode,
- port=port,
- attachParas=attachParas if attachParas else {},
- start_time=int(time.time()),
- finished_time=int(time.time() + 12 * 60 * 60),
- consumeOrder=consumeOrder if consumeOrder else {},
- weifuleOrderNo=weifuleOrderNo,
- expireAt=datetime.datetime.now() + datetime.timedelta(days=1)
- ).id
- def get_port_info(self, port):
- data = cache.get('port_info_{}_{}'.format(self.device.devNo, port))
- if data:
- return data
- else:
- data = {
- 'fun_code': 2,
- 'all': True
- }
- data = self.send_mqtt(data)
- exec_task = data.get('exec_orders', [])
- for task in exec_task:
- # 电量
- task['elec'] = round((task.pop('elec', 0) / 1000000.0), 4)
- # 时间
- task['time'] = round((task.pop('time', 0) / 60.0), 1)
- # 金额
- task['money'] = round((task.pop('money', 0) / 100.0), 2)
- task['left_money'] = round((task.pop('left_money', 0) / 100.0), 2)
- task['amount'] = round((task.pop('amount', 0) / 100.0), 2)
- # 卡余额
- if 'balance' in task:
- task['balance'] = round((task.pop('balance', 0) / 100.0), 2)
- data['power'] = round(data.pop('watt', 0), 2)
- data['voltage'] = round(data.pop('volt', 0), 2)
- data['ampere'] = round(data.pop('ampr', 0) / 1000.0, 2)
- cache.set('port_info_{}_{}'.format(self.device.devNo, port), data, 5)
- return data
- def lock_unlock_port(self, port, lock=True):
- data = {
- "fun_code": 13,
- "port": int(port),
- "enable": not lock
- }
- self.send_mqtt(data)
- def recharge_card(self, cardNo, money, orderNo=None):
- data = {
- 'card_no': cardNo,
- 'fun_code': 37,
- 'result': 1,
- 'charge': int(money * 100),
- 'order_id': orderNo
- }
- self.send_mqtt(data)
- card = Card.objects.filter(cardNo=cardNo, dealerId=self.device.ownerId).first()
- balance = card.balance + money
- return {
- 'result': ErrorCode.SUCCESS,
- 'description': ''
- }, balance
- def set_device_function(self, request, lastSetConf):
- update_dict = {'fun_code': 11}
- if request.POST.get('pile_disable') == True or request.POST.get('pile_disable') == False:
- update_dict.update({'pile_disable': request.POST['pile_disable']})
- if request.POST.get('pile_restart') == True:
- self._restart_device()
- return
- if request.POST.get('czskze') == True:
- self._reset_total_card()
- return
- self.send_mqtt(update_dict)
- self.get_dev_setting()
- def set_device_function_param(self, request, lastSetConf):
- update_dict = {'fun_code': 11}
- if request.POST.get('volume'):
- self.check_params_range(request.POST.get('volume'), minData=0, maxData=7, desc='音量')
- update_dict.update({'volume': int(request.POST.get('volume'))})
- if request.POST.get('max_ampr'):
- self.check_params_range(request.POST.get('max_ampr'), minData=0, maxData=32, desc='最大电流')
- update_dict.update({'max_ampr': int(request.POST.get('max_ampr'))})
- if request.POST.get('temp_threshold'):
- self.check_params_range(request.POST.get('temp_threshold'), minData=0, maxData=150, desc='温度阈值')
- update_dict.update({'temp_threshold': int(request.POST.get('temp_threshold'))})
- if request.POST.get('card_timeout'):
- self.check_params_range(request.POST.get('card_timeout'), minData=0, maxData=20, desc='刷卡超时时间')
- update_dict.update({'card_timeout': int(request.POST.get('card_timeout'))})
- if request.POST.get('prices'):
- prices = []
- for i, price in enumerate(request.POST.get('prices', [])):
- if i == 0:
- prices.append(['default', round(RMB(price['elec_fee']), 2), round(RMB(price['server_fee']), 2)])
- else:
- prices.append(
- ['{}-{}'.format(price['start_time'], price['end_time']), round(RMB(price['elec_fee']), 2),
- round(RMB(price['server_fee']), 2)])
- update_dict.update({'prices': prices})
- if len(update_dict) > 1:
- self.send_mqtt(update_dict)
- if request.POST.get('sys_old_pwd'):
- password = serviceCache.get(self.pwd_cache_key())
- if not password:
- raise ServiceException({'result': 2, 'description': u'当前页面已过期,请刷新后重试'})
- enObj = EncryptDate(cardKey)
- password = enObj.decrypt(password)
- sys_old_pwd = request.POST.get('sys_old_pwd')
- sys_new_pwd = request.POST.get('sys_new_pwd')
- if password != sys_old_pwd:
- raise ServiceException({'result': 2, 'description': u'旧密码输入错误'})
- result = re.findall(r'[0-9]{6}', sys_new_pwd)
- if not result or len(result[0]) != len(sys_new_pwd) or len(result[0]) < 6 or len(result[0]) > 10:
- raise ServiceException({'result': 2, 'description': u'新密码只能是6位数字'})
- update_dict.update({'sys_pwd': enObj.encrypt(sys_new_pwd)})
- self.send_mqtt(update_dict)
- serviceCache.set(self.pwd_cache_key(), enObj.encrypt(sys_new_pwd), 600)
- self.get_dev_setting()
- def get_dev_setting(self):
- def format_prices(prices):
- result = []
- for price in prices:
- if price[0] == 'default':
- result.append({
- 'elec_fee': price[1],
- 'server_fee': price[2],
- })
- else:
- result.append({
- 'start_time': price[0].split('-')[0],
- 'end_time': price[0].split('-')[1],
- 'elec_fee': price[1],
- 'server_fee': price[2],
- })
- return result
- data = {
- 'fun_code': 12,
- 'all': True,
- }
- data = self.send_mqtt(data)
- result = {}
- result['max_ampr'] = data.get('max_ampr', 0)
- result['volume'] = data.get('volume', 0)
- result['pile_disable'] = data.get('pile_disable', False)
- result['card_timeout'] = data.get('card_timeout', 0)
- result['temp_threshold'] = data.get('temp_threshold', 0)
- result['prices'] = format_prices(data.get('prices', []))
- if 'sys_pwd' in data:
- serviceCache.set(self.pwd_cache_key(), data['sys_pwd'], 600)
- self._do_update_configs(data)
- return result
- def get_port_status_from_dev(self):
- data = {
- 'fun_code': 2,
- 'all': True
- }
- data = self.send_mqtt(data)
- status = data.get('status')
- port = self.port
- result = []
- item = {
- 'index': port,
- 'voltage': round(data.get('volt', 0), 2),
- 'power': round(data.get('watt', 0), 2),
- 'ampere': round(data.get('ampr', 0) * 0.001, 2),
- 'devTemp': round(data.get('temp', 0), 2),
- }
- if status == 'busy' or status == 'ready':
- item.update({'status': status})
- exec_task = data.get('exec_orders', [])
- waittingOrder = []
- for task in exec_task:
- # 启动方式 个人信息
- consumeOrder = ConsumeRecord.objects.filter(Q(orderNo=task['id']) | Q(sequanceNo=task['id']), devNo=self.device.devNo).first()
- if task['order_type'] == 'apps_start':
- item['consumeType'] = 'mobile'
- if not consumeOrder:
- people = MyUser(nickname='经销商远程上分')
- else:
- people = consumeOrder.user
- item['nickName'] = people.nickname
- else:
- item['consumeType'] = 'card'
- item['cardNo'] = task['card_no']
- if consumeOrder:
- card = Card.objects.filter(cardNo=task['card_no'], dealerId=self.device.ownerId).first()
- card and item.update({'nickName': card.nickName or card.cardName})
- else:
- item.update({'nickName': '匿名用户'})
- # 订单状态
- if task['status'] == 'running':
- # 设备参数
- # 电量
- item['elec'] = round(task['elec'] / 1000000.0, 2)
- # 时间
- item['usedTime'] = round(task['time'] / 60.0, 1)
- # 金额
- records = task['records']
- item['elecFee'] = round(sum(map(lambda _: _['elec_money'], records)) * 0.01, 2)
- item['serviceFee'] = round(sum(map(lambda _: _['serv_money'], records)) * 0.01, 2)
- item['consumeMoney'] = '{}{}'.format(item['elecFee'] + item['serviceFee'], self.show_pay_unit)
- item['coins'] = '{}{}'.format(RMB.fen_to_yuan(task['amount']), self.show_pay_unit)
- # 开始时间
- start_time = task.get('create_time')
- start_time = datetime.datetime.fromtimestamp(start_time)
- item['startTime'] = start_time.strftime('%m-%d %H:%M:%S')
- if consumeOrder: # 后付费
- payAfterUse = consumeOrder.attachParas.get('payAfterUse')
- if payAfterUse:
- item['consumeType'] = 'postpaid'
- item.pop('leftMoney', None)
- item.pop('coins', None)
- elif task['status'] == 'waiting':
- one = {}
- one['coins'] = '{}{}'.format(task['amount'], self.show_pay_unit)
- createTime = datetime.datetime.fromtimestamp(task['create_time'])
- one['createTime'] = createTime.strftime('%m-%d %H:%M:%S')
- if task['order_type'] == 'apps_start':
- one['consumeType'] = 'mobile'
- if not consumeOrder:
- people = MyUser(nickname='经销商远程上分')
- else:
- people = consumeOrder.user
- consumeOne = ConsumeRecord.objects.filter(Q(orderNo=task['id']) | Q(sequanceNo=task['id']), devNo=self.device.devNo).first()
- if consumeOne.attachParas.get('payAfterUse'):
- one['consumeType'] = 'postpaid'
- one['nickName'] = people.nickname
- elif task['order_type'] == 'card_start':
- one['consumeType'] = 'card'
- one['cardNo'] = task.get('card_no')
- if consumeOrder:
- card = Card.objects.filter(cardNo=task['card_no'], dealerId=self.device.ownerId).first()
- one.update({'nickName': card.nickName or card.cardName})
- else:
- one.update({'nickName': '匿名用户'})
- one['cardBalance'] = '{}{}'.format(task['balance'], self.show_pay_unit)
- waittingOrder.append(one)
- if waittingOrder:
- item['waittingOrder'] = waittingOrder
- elif status == 'fault':
- item.update({'status': status})
- elif status == 'estop':
- item.update({'status': status})
- elif status == 'idle':
- item.update({'status': status})
- elif status == 'link':
- item.update({'status': 'connected'})
- elif status == 'forbiden':
- item.update({'status': 'ban'})
- result.append(item)
- return result
- def stop(self, port=None):
- data = {
- 'fun_code': 6,
- 'operator': 'dealer',
- 'port': int(port)
- }
- self.send_mqtt(data)
- def active_deactive_port(self, port, active):
- if active == False:
- self.stop(port)
- def stop_by_order(self, port=None, orderNo=''):
- order = ConsumeRecord.objects.filter(orderNo=orderNo, isNormal=True).first()
- if not order:
- logger.info('no this order <{}>'.format(orderNo))
- return
- people = MyUser.objects.filter(openId=order.openId, groupId=self.device['groupId']).first()
- data = {
- 'fun_code': 4,
- 'operator': 'user',
- 'operator_id': str(people.id),
- 'order_id': orderNo
- }
- self.send_mqtt(data)
- @property
- def isHaveStopEvent(self):
- return True
- def pwd_cache_key(self):
- return 'sys_pwd_{}'.format(self.device.devNo)
- def _get_port_status(self):
- data = {
- 'fun_code': 2,
- 'all': True
- }
- data = self.send_mqtt(data)
- status = data.get('status')
- result = {}
- if status == 'fault':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_FAULT, 'port': self.port}
- elif status == 'idle':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_IDLE, 'port': self.port}
- elif status == 'link':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_CONNECTED, 'port': self.port}
- elif status == 'estop':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_ESTOP, 'port': self.port}
- elif status == 'ready':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_READY, 'port': self.port}
- elif status == 'busy':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_WORKING, 'port': self.port}
- elif status == 'forbiden':
- result[self.port] = {'status': Const.DEV_WORK_STATUS_FORBIDDEN, 'port': self.port}
- else:
- result[self.port] = {'status': Const.DEV_WORK_STATUS_FAULT, 'port': self.port}
- Device.update_dev_control_cache(self.device['devNo'], result)
- return result
- 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, weifuleOrderNo=spDict.get('weifuleOrderNo')).first()
- port = spDict.get('port')
- result_list = []
- # 订单信息组织
- _info = self.get_port_info(port)
- exec_task = _info.get('exec_orders', [])
- for task in exec_task:
- item = base_data
- if spDict['weifuleOrderNo'] != task['id']:
- continue
- # 启动方式
- if task['order_type'] == 'apps_start':
- consumeType = 'mobile'
- else:
- consumeType = 'card'
- item['cardNo'] = task['card_no']
- # 订单状态
- if task['status'] == 'running':
- # 设备参数
- item['voltage'] = _info.get('voltage', 0)
- item['power'] = _info.get('power', 0)
- item['ampere'] = _info.get('ampere', 0)
- # 时间
- item['elec'] = task['elec']
- # 电量
- item['usedTime'] = task['time']
- # 金额
- records = task['records']
- item['elecFee'] = round(sum(map(lambda _: _['elec_money'], records)) * 0.01, 2)
- item['serviceFee'] = round(sum(map(lambda _: _['serv_money'], records)) * 0.01, 2)
- item['consumeMoney'] = '{}{}'.format(item['elecFee'] + item['serviceFee'], self.show_pay_unit)
- # 订单内部信息
- item['order'] = {
- 'orderNo': task['id'], # 停止按钮传订单停单用
- 'coin': '{}{}'.format(task['amount'], self.show_pay_unit),
- 'consumeType': consumeType,
- }
- if 'card_no' in task:
- item['cardNo'] = task['card_no']
- elif task['status'] == 'waiting':
- item['desc'] = '此订单已经下发到设备上,上一单运行完毕就会自动运行此订单'
- item['order'] = {
- 'orderNo': task['id'], # 停止按钮传订单停单用
- 'coin': '{}{}'.format(task['amount'], self.show_pay_unit),
- 'consumeType': consumeType,
- }
- try:
- consumeRcd = ConsumeRecord.objects.filter(orderNo=task['id']).first()
- if consumeRcd and consumeRcd.attachParas.get('payAfterUse') == True:
- item['order'] = {
- 'orderNo': task['id'], # 停止按钮传订单停单用
- 'coin': '{}{}'.format(0, self.show_pay_unit),
- 'consumeType': 'postpaid',
- }
- item.pop('leftMoney', None)
- except:
- pass
- item.update(DeviceType.get_services_button(self.device['devType']['id']))
- result_list.append(item)
- if not result_list:
- ServiceProgress.objects.filter(device_imei=self.device.devNo,
- weifuleOrderNo=spDict.get('weifuleOrderNo')).update(
- isFinished=True,
- expireAt=datetime.datetime.now())
- ConsumeRecord.objects.filter(devNo=self.device.devNo, isNormal=True,
- orderNo=spDict.get('weifuleOrderNo')).update(isNormal=False,
- errorDesc='异常结束,设备订单丢失 code:4',
- finishedTime=datetime.datetime.now())
- return result_list
- @property
- def show_pay_unit(self):
- """
- 前台显示付费的时候,目前有不同的客户希望 显示不同的单位 有的显示金币 有的显示元, 这个地方处理下
- :return:
- """
- if self.device['otherConf'].get('pay_unit'):
- return self.device['otherConf'].get('pay_unit')
- return u'元'
- def dealer_get_port_status(self):
- """
- 远程上分的时候获取端口状态
- :return:
- """
- return self.get_port_status(force=True)
- def check_order_state(self, openId):
- dealerId = self.device.ownerId
- return ClientConsumeModelProxy.get_not_finished_record(ownerId=dealerId, openId=openId,
- devTypeCode=self._device['devType']['code'],
- attachParas__payAfterUse=True)
- def force_stop_order(self, order, **kwargs):
- if not order.attachParas.get('payAfterUse'):
- pass
- else:
- errorDesc = order.errorDesc + '经销商手动强制关单<{}>'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
- order.update(status='finished', errorDesc=errorDesc, isNormal=False)
- def get_policy_infos(self):
- data = {
- 'fun_code': 12,
- 'all': True,
- }
- data = self.send_mqtt(data)
- price = data.pop('prices')
- price_dict = self._transform_prices(price, 'get')
- return price_dict
- def set_policy_infos(self, payload):
- update_dict = {'fun_code': 11}
- if payload.get('price1'):
- prices = self._transform_prices(payload)
- update_dict.update({'prices': prices})
- return self.send_mqtt(update_dict)
- def get_policy_for_user(self):
- data = self._get_device_configs()
- if not data:
- self.get_dev_setting()
- data = self._get_device_configs()
- prices = data.get('prices')
- str_to_datetime = lambda _: datetime.datetime.strptime(_, "%H:%M")
- datetime_to_str = lambda _: _.strftime("%H:%M")
- # 用默认时间填满缝隙
- defaultElecPrice = 0.5
- defaultSevicePrice = 0.5
- time_points = []
- priceList = []
- for price in prices:
- if price[0] == 'default':
- defaultElecPrice = price[1]
- defaultSevicePrice = price[2]
- # priceList.append([to_datetime('00:00'), to_datetime('23:59'), defaultElecPrice, defaultSevicePrice])
- else:
- st_point = str_to_datetime(price[0].split('-')[0])
- ft_point = str_to_datetime(price[0].split('-')[1])
- time_points.extend([st_point, ft_point])
- priceList.append([st_point, ft_point, price[1], price[2]])
- dst_point = str_to_datetime('00:00')
- dft_point = str_to_datetime('23:59')
- dst_point not in time_points and time_points.append(dst_point)
- dft_point not in time_points and time_points.append(dft_point)
- time_points = sorted(time_points)
- resultList = []
- for point in time_points:
- if point == dft_point:
- break
- price_model = None
- for price in priceList:
- if point == price[0]:
- price_model = price
- break
- if price_model:
- resultList.append(
- {"startTime": datetime_to_str(price_model[0]), "elecPrice": price_model[2],
- "sevicePrice": price_model[3]})
- else:
- resultList.append(
- {"startTime": datetime_to_str(point), "elecPrice": defaultElecPrice,
- "sevicePrice": defaultSevicePrice})
- return resultList
- def get_customize_score_unit(self):
- return u'元'
- def start_customize_point(self, pointNum, openId, port):
- package = {'name': 'customizePoint', 'price': pointNum, 'coins': pointNum, 'unit': u'次', 'time': 1}
- attachParas = {'chargeIndex': port, 'onPoints': True}
- return self.start_device(package, openId, attachParas)
- def support_device_package(self):
- return True
- def format_device_package(self, isTemp=False, **kw):
- def __generate_id(ids):
- i = 1
- while True:
- if str(i) in ids:
- i += 1
- else:
- return str(i)
- def __formart_ruleList():
- packageList = kw['serviceData']
- ids = [str(rule['id']) for rule in packageList if 'id' in rule]
- washConfig = {}
- for i, rule in enumerate(packageList):
- ruleId = str(rule.get('id', ''))
- if not ruleId:
- ruleId = __generate_id(ids)
- ids.append(ruleId)
- washConfig[ruleId] = {}
- if 'switch' in rule:
- washConfig[ruleId].update({'switch': rule['switch']})
- if 'billingMethod' in rule:
- washConfig[ruleId].update({'billingMethod': rule['billingMethod']})
- if 'price' in rule:
- washConfig[ruleId].update(
- {'price': round(float(rule['price']), 2) or 0, 'coins': round(float(rule['price']), 2) or 0})
- # if 'time' in rule:
- # washConfig[ruleId].update({'time': rule['time'] or 0})
- if 'name' in rule:
- washConfig[ruleId].update({'name': rule['name'] or '套餐{}'.format(i + 1)})
- if 'unit' in rule:
- washConfig[ruleId].update({'unit': rule['unit']})
- if 'sn' in rule:
- washConfig[ruleId].update({'sn': rule['sn']})
- if 'autoStop' in rule:
- washConfig[ruleId]['autoStop'] = rule['autoStop']
- if 'autoRefund' in rule:
- washConfig[ruleId]['autoRefund'] = rule['autoRefund']
- if 'minAfterStartCoins' in rule:
- washConfig[ruleId]['minAfterStartCoins'] = rule['minAfterStartCoins']
- if 'minFee' in rule:
- washConfig[ruleId]['minFee'] = rule['minFee']
- if isTemp:
- pass
- # 检验部分
- if RMB(rule.get('price') or 0) > self.device.owner.maxPackagePrice:
- raise ServiceException(
- {'result': 0, 'description': '套餐( {} )金额超限'.format(rule['name']), 'payload': {}})
- return washConfig
- def __formart_displaySwitchs():
- return {'displayCoinsSwitch': False,
- 'displayTimeSwitch': False,
- 'displayPriceSwitch': True,
- 'setPulseAble': False,
- 'setBasePriceAble': False}
- washConfig = __formart_ruleList()
- displaySwitchs = __formart_displaySwitchs()
- return washConfig, displaySwitchs
- def dealer_show_package(self, isTemp=False, **kw):
- def get_rule_list():
- if isTemp:
- config = self.device.get('tempWashConfig', {})
- else:
- config = self.device['washConfig']
- ruleList = []
- for packageId, rule in config.items():
- item = {
- 'id': packageId
- }
- if 'switch' in rule:
- item['switch'] = rule['switch']
- if 'name' in rule:
- item['name'] = rule['name']
- if 'coins' in rule:
- item['coins'] = rule['coins']
- if 'price' in rule:
- item['price'] = rule['price']
- if 'time' in rule:
- item['time'] = rule['time']
- if 'description' in rule:
- item['description'] = rule['description']
- if 'unit' in rule:
- item['unit'] = rule['unit']
- if 'imgList' in rule:
- item['imgList'] = rule['imgList']
- if 'sn' in rule:
- item['sn'] = rule['sn']
- if 'autoStop' in rule:
- item['autoStop'] = rule['autoStop']
- if 'minAfterStartCoins' in rule:
- item['minAfterStartCoins'] = rule['minAfterStartCoins']
- if 'minFee' in rule:
- item['minFee'] = rule['minFee']
- ruleList.append(item)
- return sorted(ruleList, key=lambda x: (x.get('sn'), x.get('id')))
- def get_display_switchs():
- if "displaySwitchs" in self.device["otherConf"]:
- displaySwitchs = self.device["otherConf"].get('displaySwitchs')
- else:
- displaySwitchs = {'displayCoinsSwitch': False,
- 'displayTimeSwitch': False,
- 'displayPriceSwitch': True,
- "setPulseAble": False,
- "setBasePriceAble": False}
- return displaySwitchs
- ruleList = get_rule_list()
- displaySwitchs = get_display_switchs()
- return {"ruleList": ruleList, 'displaySwitchs': displaySwitchs}
- def custom_push_url(self, order, user, **kw):
- from apps.web.utils import concat_user_center_entry_url
- from apps.web.utils import concat_front_end_url
- return concat_user_center_entry_url(agentId=user.productAgentId, redirect=concat_front_end_url(
- uri='/user/index.html#/user/deviceStatus'))
|