# -*- 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 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 WeiFuLe21KW(SmartBox): def __init__(self, device): super(WeiFuLe21KW, self).__init__(device) 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 _get_all_info(self): data = { 'funCode': 2, 'all': True } data = self.send_mqtt(data) return data 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) def _get_device_configs(self): return Device.objects.get(devNo=self.device.devNo).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() + 24 * 60 * 60), consumeOrder=consumeOrder if consumeOrder else {}, weifuleOrderNo=weifuleOrderNo, expireAt=datetime.datetime.now() + datetime.timedelta(days=91) ).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, 'port': int(port) } data = self.send_mqtt(data) exec_task = data.get('exec_task', []) 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) 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('card_disable') == True or request.POST.get('card_disable') == False: update_dict.update({'card_disable': request.POST.get('card_disable')}) if request.POST.get('scan_disable') == True or request.POST.get('scan_disable') == False: update_dict.update({'scan_disable': request.POST.get('scan_disable')}) if request.POST.get('sys_pwd') == True or request.POST.get('sys_pwd') == False: update_dict.update({'sys_pwd': request.POST.get('sys_pwd')}) # if request.POST.get('card_refund') == True or request.POST.get('card_refund') == False: # update_dict.update({'card_refund': request.POST.get('card_refund')}) if request.POST.get('reboot') == True: self._reboot_device() return if request.POST.get('restart') == True: self._restart_device() return if request.POST.get('factory_set') == True: self._factory_set_device() return if request.POST.get('czskze') == True: self._reset_total_card() return self.send_mqtt(update_dict) 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('one_card'): update_dict.update({'one_card': int(float(request.POST.get('one_card')) * 100)}) if request.POST.get('max_watt'): update_dict.update({'max_watt': int(request.POST.get('max_watt'))}) if request.POST.get('max_volt'): update_dict.update({'max_volt': int(request.POST.get('max_volt'))}) if request.POST.get('max_ampr'): update_dict.update({'max_ampr': int(request.POST.get('max_ampr'))}) if request.POST.get('card_timeout'): update_dict.update({'card_timeout': int(request.POST.get('card_timeout'))}) if request.POST.get('max_time'): update_dict.update({'max_time': int(request.POST.get('max_time'))}) if request.POST.get('price1'): prices = self._transform_prices(request.POST) update_dict.update({'prices': prices}) if request.POST.get('sys_old_pwd'): password = serviceCache.get(self.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_pwd = request.POST.get('sys_pwd') sys_pwd2 = request.POST.get('sys_pwd2') if sys_pwd != sys_pwd2: raise ServiceException({'result': 2, 'description': u'两次新密码输入不一致'}) if not sys_pwd: raise ServiceException({'result': 2, 'description': u'请输入新密码'}) if sys_old_pwd == sys_pwd: raise ServiceException({'result': 2, 'description': u'新旧密码不能为一致'}) if password != sys_old_pwd: raise ServiceException({'result': 2, 'description': u'旧密码输入错误'}) result = re.findall(r'[a-zA-Z0-9]{6,10}', sys_pwd) if not result or len(result[0]) != len(sys_pwd) or len(result[0]) < 6 or len(result[0]) > 10: raise ServiceException({'result': 2, 'description': u'新密码只能是6-10位,由字母或者数字'}) update_dict.update({'sys_pwd': enObj.encrypt(sys_pwd)}) self.send_mqtt(update_dict) serviceCache.set(self.cache_key(), enObj.encrypt(sys_pwd), 600) if request.POST.get('card_oncefee'): update_dict.update({'card_oncefee': int(float(request.POST.get('card_oncefee')) * 100)}) if request.POST.get('card_dft_pwd'): card_dft_pwd = str(request.POST.get('card_dft_pwd')) result = re.findall(r'[a-zA-Z0-9]{6}', card_dft_pwd) if not result or len(result[0]) != len(card_dft_pwd): raise ServiceException({'result': 2, 'description': u'卡片密码只能是6位,由字母或者数字组成'}) update_dict.update({'card_dft_pwd': card_dft_pwd}) if request.POST.get('card_dft_mny'): update_dict.update({'card_dft_mny': int(float(request.POST.get('card_dft_mny')) * 100)}) if request.POST.get('card_token'): card_token = str(request.POST.get('card_token')) result = re.findall(r'[a-zA-Z0-9]{6}', card_token) if not result or len(result[0]) != len(card_token): raise ServiceException({'result': 2, 'description': u'设备刷卡标签只能是6位,由字母或者数字组成'}) update_dict.update({'card_token': card_token}) if request.POST.get('max_temp'): update_dict.update({'max_temp': int(request.POST.get('max_temp'))}) if request.POST.get('csh_tel'): update_dict.update({'csh_tel': request.POST.get('csh_tel')}) if len(update_dict) > 1: self.send_mqtt(update_dict) def get_dev_setting(self): data = { 'fun_code': 12, 'all': True, } data = self.send_mqtt(data) data['card_oncefee'] = data.get('card_oncefee', 0) / 100.0 data['card_dft_mny'] = data.get('card_dft_mny', 0) / 100.0 price = data.pop('prices') price_dict = self._transform_prices(price, 'get') sys_pwd = data.pop('sys_pwd') serviceCache.set(self.cache_key(), sys_pwd, 600) data.update(price_dict) total_card = self._get_total_card() data.update(total_card) return data def get_port_status_from_dev(self): data = { 'fun_code': 1, 'all': True } data = self.send_mqtt(data) port_stat = data.get('port_stat', {}) result = [] for port, status in port_stat.items(): item = { 'index': port, 'power': 0, 'devTemp': round(data.get('mach_temp', 0), 2), } if status == 'busy' or status == 'ready': running = item running.update({'status': status}) _info = self.get_port_info(int(port)) exec_task = _info.get('exec_task', []) waittingOrder = [] for task in exec_task: # 启动方式 个人信息 consumeOrder = ConsumeRecord.objects.filter(devNo=self.device.devNo, orderNo=task['id']).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['power'] = _info.get('power', 0) # 电量 item['elec'] = task['elec'] # 时间 item['usedTime'] = task['time'] # 金额 item['consumeMoney'] = '{}{}'.format(task['money'], self.show_pay_unit) item['leftMoney'] = '{}{}'.format(task['left_money'], self.show_pay_unit) item['coins'] = '{}{}'.format(task['amount'], self.show_pay_unit) # 开始时间 start_time = task.get('create_time') start_time = datetime.datetime.fromtimestamp(start_time) item['start_time'] = 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(orderNo=task['id']).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 cache_key(self): return 'sys_pwd_{}'.format(self.device.devNo) def _get_port_status(self): data = { 'fun_code': 1, 'port_stat': True } data = self.send_mqtt(data) port_stat = data.get('port_stat') result = {} for port, status in port_stat.items(): if status == 'fault': result[str(port)] = {'status': Const.DEV_WORK_STATUS_FAULT, 'port': str(port)} elif status == 'idle': result[str(port)] = {'status': Const.DEV_WORK_STATUS_IDLE, 'port': str(port)} elif status == 'link': result[str(port)] = {'status': Const.DEV_WORK_STATUS_CONNECTED, 'port': str(port)} elif status == 'estop': result[str(port)] = {'status': Const.DEV_WORK_STATUS_ESTOP, 'port': str(port)} elif status == 'ready': result[str(port)] = {'status': Const.DEV_WORK_STATUS_READY, 'port': str(port)} elif status == 'busy': result[str(port)] = {'status': Const.DEV_WORK_STATUS_WORKING, 'port': str(port)} elif status == 'forbiden': result[str(port)] = {'status': Const.DEV_WORK_STATUS_FORBIDDEN, 'port': str(port)} else: result[str(port)] = {'status': Const.DEV_WORK_STATUS_FAULT, 'port': str(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_task', []) 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['power'] = _info.get('power', 0) # 时间 item['elec'] = task['elec'] # 电量 item['usedTime'] = task['time'] # 金额 item['consumeMoney'] = '{}{}'.format(task['money'], self.show_pay_unit) item['leftMoney'] = '{}{}'.format(task['left_money'], 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 = { 'fun_code': 12, 'all': True, } data = self.send_mqtt(data) prices = data.get('prices') # 用默认时间填满缝隙 defaultPrice = 1.5 priceList = [] for price in prices: if price[0] == 'default': defaultPrice = price[1] else: priceList.append(price) fillList = [] for ii in range(len(priceList)-1): price = priceList[ii] if price[0] == 'default': continue endTime= price[0].split('-')[1] nextPrice = priceList[ii+1] nextStartTime = nextPrice[0].split('-')[0] if nextStartTime>endTime: fillList.append(('%s-%s' % (endTime,nextStartTime),defaultPrice)) # 头尾加上时间 firstTime = priceList[0][0].split('-')[0] if firstTime != '00:00': priceList.insert(0, ('00:00-%s'% firstTime,defaultPrice)) tailTime = priceList[-1][0].split('-')[1] if tailTime != '24:00': priceList.append(('%s-24:00'% tailTime,defaultPrice)) # 合并价格一样的时间区间 startTime = priceList[0][0].split('-')[0] elecPrice = priceList[0][1] resultList = [{'startTime':startTime,'elecPrice':elecPrice}] for ii in range(len(priceList)-1): nextPrice = priceList[ii+1] if nextPrice[1] == resultList[-1]['elecPrice']: continue resultList.append({'startTime':nextPrice[0].split('-')[0],'elecPrice':nextPrice[1],'sevicePrice':0}) 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)