# -*- coding: utf-8 -*- #!/usr/bin/env python import copy import datetime import time from apps.web.constant import DeviceCmdCode, Const, FAULT_CODE, ErrorCode, MQTT_TIMEOUT from apps.web.core.adapter.base import SmartBox from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device from apps.web.user.models import ConsumeRecord, MyUser, Card from apilib.utils_datetime import to_datetime from apilib.utils_AES import EncryptDate cardKey = 'FR4e1OFCnDdrYA7u' class ChargingWEIFULEBox(SmartBox): def __init__(self, device): super(ChargingWEIFULEBox, self).__init__(device) def translate_funcode(self, fun_code): fun_codeDict = { '01': u'查询所有端口状态', '02': u'查询端口详细信息', '03': u'上报投币充电事件', '04': u'上报刷卡事件', '05': u'上报充电结束事件', '06': u'远程停止充电', '07': u'远程启动充电', '08': u'查询投币总额', '09': u'清除投币总数', '0A': u'查询订单信息', } return fun_codeDict.get(fun_code, '') def translate_event_cmdcode(self, cmdCode): cmdDict = { } return cmdDict.get(cmdCode, '') def test(self, coins): data = {'fun_code':0x07,'order_id':'1111','coins':coins,'port':1,'time':60} devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}) return devInfo def check_feedback_result(self,devInfo): if not devInfo.has_key('rst'): raise ServiceException({'result': 2, 'description': u'报文异常'}) if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'}) if devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'串口通讯失败,您稍候再试,或者联系客服'}) if devInfo['rst'] == 2: raise ServiceException({'result': 2, 'description': u'端口被禁用'}) if devInfo['rst'] == 3: raise ServiceException({'result': 2, 'description': u'端口计量器故障'}) if devInfo['rst'] == 4: raise ServiceException({'result': 2, 'description': u'设备订单已达上限'}) if devInfo['rst'] == 5: raise ServiceException({'result': 2, 'description': u'设备正在自检'}) # result = devInfo['data']['result'] # if result == 0: # return # else:#等待设备的错误码进行细化 # raise ServiceException({'result': 2, 'description': u'充电桩返回了错误,请您重试看看能否解决问题'}) def start_device(self, package, openId, attachParas): if attachParas is None: raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'}) if not attachParas.has_key('chargeIndex'): raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'}) port = int(attachParas['chargeIndex']) unit = package.get('unit', u'分钟') needTime,power = None,None coins = int(float(package['coins'])*100)#单位为分 onPoints = attachParas.get('onPoints') if onPoints: # 远程上分 self.stop_charging_port(port) order_no = ConsumeRecord.make_no() else: order_no = str(attachParas.get("orderNo")) if unit == u'秒': if int(package['time']) < 60: raise ServiceException({'result': 2, 'description': u'套餐的最小时间不能小于60秒'}) needTime = int(float(package['time'])) data = {'fun_code':0x07,'order_id':order_no,'coins':coins,'port':port,'time':needTime} elif unit == u'分钟': needTime = int(package['time'])*60 data = {'fun_code':0x07,'order_id':order_no,'coins':coins,'port':port,'time':needTime} elif unit == u'小时': needTime = int(float(package['time']) * 60 * 60) data = {'fun_code':0x07,'order_id':order_no,'coins':coins,'port':port,'time':needTime} elif unit == u'天': needTime = int(float(package['time']) * 60 * 60 * 24) data = {'fun_code':0x07,'order_id':order_no,'coins':coins,'port':port,'time':needTime} elif unit == u'度': power = int(float(package['time'])*1000000)#微度,需要乘于16个零 data = {'fun_code':0x07,'order_id':order_no,'coins':coins,'port':port,'elec':power} else: needTime = int(package['time']) data = {'fun_code':0x07,'order_id':order_no,'coins':coins,'port':port,'time':needTime} devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}, timeout = MQTT_TIMEOUT.START_DEVICE) self.check_feedback_result(devInfo) data = devInfo['data'] if devInfo['rst'] == 0: # 成功 devInfo['consumeOrderNo'] = data['order']['id'] newValue = { str(port): { 'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') } } else:#TODO result的枚举列出原因 raise ServiceException({'result': 2, 'description': u'充电桩响应异常,请您稍后再试哦'}) if needTime: finishedTime = int(time.time()) + needTime devInfo['needTime'] = needTime/60 if power: finishedTime = int(time.time()) + 60 * 60 * 10#设定10个小时,确实很难知道可以用多久结束 devInfo['needElec'] = float(package['time']) newValue.update({'finishedTime': finishedTime}) Device.update_dev_control_cache(self._device['devNo'], newValue) devInfo['finished_time'] = finishedTime devInfo['consumeOrderNo'] = order_no return devInfo def analyze_event_data(self, data): if data['fun_code'] == '34':#如果是结束事件,需要把reason翻译出来 descDict = { '1':u'开始充电,但是没有接充电器', '2':u'充电过程中,插座脱落', '3':u'用户按下关闭按钮关闭', '4':u'用户刷卡结束充电', '5':u'远程结束充电', '6':u'充电端口故障,为了安全主动关闭', '7':u'订购的时间使用完毕', '8':u'订购的电量使用完毕', '9':u'本端口功率过载,主动关闭', '10':u'整机功率过载,主动关闭', '11':u'其他异常导致的关闭' } order = data['order'] order['reason'] = descDict.get(str(order['closeType']),u'') data['order'] = order return data def get_dev_consume_count(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x08}}) self.check_feedback_result(devInfo) data = devInfo['data'] return {'cardFee': data['total_card']/100.0, 'coinFee': data['total_coin']/100.0}#单位为分 def get_many_port_info(self,portList): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x12}}) self.check_feedback_result(devInfo) resultDict = {} for port,data in devInfo['data']['details'].items(): if port not in portList: continue result = {'index':port} result['status'] = self.__translate_status_from_str(data['status']) result['power'] = data.get('watt',0) result['ampere'] = data.get('ampr',0) / 1000.0 result['voltage'] = data.get('volt') curOrder = None for order in data['orders']: if order['status'] == 'running': curOrder = order break if curOrder: result['elec'] = curOrder['elec'] if curOrder['order_type'] == 'apps_start': result['consumeType'] = 'mobile' try: rcd = ConsumeRecord.objects.get(orderNo = curOrder['id']) if u'虚拟卡' in rcd.remarks: result['consumeType'] = 'mobile_vcard' except Exception,e: pass elif curOrder['order_type'] == 'coin_start': result['consumeType'] = 'coin' elif curOrder['order_type'] == 'card_start': result['consumeType'] = 'card' if curOrder.has_key('amount_time'): result['needTime'] = round(curOrder['amount_time']/60.0,1) if curOrder.has_key('time'): result['duration'] = round(curOrder['time']/60.0,1) result['usedTime'] = round(curOrder['time']/60.0,1) if curOrder.has_key('left_time'): result['leftTime'] = round(curOrder['left_time']/60.0,1) if curOrder.has_key('amount_elec'): result['needElec'] = curOrder['amount_elec']/1000000.0 if curOrder.has_key('elec'): result['elec'] = curOrder.get('elec')/1000000.0 if curOrder.has_key('execute_time'): result['startTime'] = datetime.datetime.fromtimestamp(int(curOrder['execute_time'])).strftime('%m-%d %H:%M:%S') if curOrder.has_key('id') and (curOrder['order_type'] not in ['coin_start','card_charge']) :#card_charge try: rcd = ConsumeRecord.objects.get(orderNo = curOrder['id']) result['openId'] = rcd['openId'] result['coins'] = float(str(rcd['coin']))#都用coins result['money'] = float(str(rcd['money'])) result['orderNo'] = str(curOrder['id']) user = MyUser.objects(openId=result['openId']).first() if user: result['nickName'] = user.nickname except Exception,e:#IC卡,如果没有绑定,不会有consumeRcd,应该直接从订单中拿数据 result['coins'] = float(order['coins']/100.0) result['money'] = float(order['coins']/100.0) pass resultDict[port] = result return resultDict def get_port_info(self, line): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x02, 'port': int(line)}}) self.check_feedback_result(devInfo) #找出当前正在执行的订单 result = {} data = devInfo['data'] result['status'] = self.__translate_status_from_str(data['status']) result['power'] = data.get('watt',0) result['ampere'] = data.get('ampr',0) / 1000.0 result['voltage'] = data.get('volt') curOrder = None for order in data['orders']: if order['status'] == 'running': curOrder = order break if curOrder: result['elec'] = curOrder['elec'] if curOrder['order_type'] == 'apps_start': result['consumeType'] = 'mobile' try: rcd = ConsumeRecord.objects.get(orderNo = curOrder['id']) if u'虚拟卡' in rcd.remarks: result['consumeType'] = 'mobile_vcard' except Exception,e: pass elif curOrder['order_type'] == 'coin_start': result['consumeType'] = 'coin' elif curOrder['order_type'] == 'card_start': result['consumeType'] = 'card' if curOrder.has_key('amount_time'): result['needTime'] = round(curOrder['amount_time']/60.0,1) if curOrder.has_key('time'): result['duration'] = round(curOrder['time']/60.0,1) result['usedTime'] = round(curOrder['time']/60.0,1) if curOrder.has_key('left_time'): result['leftTime'] = round(curOrder['left_time']/60.0,1) if curOrder.has_key('amount_elec'): result['needElec'] = curOrder['amount_elec']/1000000.0 if curOrder.has_key('elec'): result['elec'] = curOrder.get('elec')/1000000.0 if curOrder.has_key('execute_time'): result['startTime'] = datetime.datetime.fromtimestamp(int(curOrder['execute_time'])).strftime('%m-%d %H:%M:%S') if curOrder.has_key('card_no'): result['cardNo'] = str(int(curOrder['card_no'],16)) if curOrder.has_key('id') and (curOrder['order_type'] not in ['coin_start','card_charge']) :#card_charge try: rcd = ConsumeRecord.objects.get(orderNo = curOrder['id']) result['openId'] = rcd['openId'] result['coins'] = float(str(rcd['coin']))#都用coins result['money'] = float(str(rcd['money'])) result['orderNo'] = str(curOrder['id']) except Exception,e: pass return result def __translate_status_from_str(self,status): dictConf = { 'idle':Const.DEV_WORK_STATUS_IDLE, 'busy':Const.DEV_WORK_STATUS_WORKING, 'forbid':Const.DEV_WORK_STATUS_FORBIDDEN, 'fault':Const.DEV_WORK_STATUS_FAULT, 'running':Const.DEV_WORK_STATUS_WORKING } return dictConf.get(status,Const.DEV_WORK_STATUS_IDLE) # 访问设备,获取设备端口信息 def get_port_status_from_dev(self): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x01}}) self.check_feedback_result(devInfo) data = devInfo['data'] result = {} portNum = data.get('total',10) ii = 0 while ii < portNum: ii += 1 result[str(ii)] = {'status':self.__translate_status_from_str(data['status'].get(str(ii)))} allPorts, usedPorts, usePorts = self.get_port_static_info(result) Device.update_dev_control_cache(self._device['devNo'], {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts}) # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存 ctrInfo = Device.get_dev_control_cache(self._device['devNo']) for strPort, info in result.items(): if ctrInfo.has_key(strPort): ctrInfo[strPort].update({'status': info['status']}) else: ctrInfo[strPort] = info Device.update_dev_control_cache(self._device['devNo'], ctrInfo) return result def get_port_status(self, force = False): if force: return self.get_port_status_from_dev() ctrInfo = Device.get_dev_control_cache(self._device['devNo']) if not ctrInfo.has_key('allPorts'): self.get_port_status_from_dev() ctrInfo = Device.get_dev_control_cache(self._device['devNo']) allPorts = ctrInfo.get('allPorts', 10) statusDict = {} for ii in range(allPorts): tempDict = ctrInfo.get(str(ii + 1), {}) if tempDict.has_key('status'): statusDict[str(ii + 1)] = {'status': tempDict.get('status')} elif tempDict.has_key('isStart'): if tempDict['isStart']: statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING} else: statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE} else: statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE} allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict) Device.update_dev_control_cache(self._device['devNo'], {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts}) return statusDict def lock_unlock_port(self, port, lock = True): portInfo = self.get_port_info(port) if portInfo and portInfo['status'] == Const.DEV_WORK_STATUS_WORKING and lock: raise ServiceException({'result': 2, 'description': u'端口正忙,请先关闭端口后,再禁止端口'}) typeStr = 'deactive' if lock else 'active' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'port':int(port),'type':typeStr,'fun_code':0x0D}}) self.check_feedback_result(devInfo) if devInfo['rst'] == 0: if lock: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_FORBIDDEN}}) else: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}}) else: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}}) def active_deactive_port(self, port, active): if active: raise ServiceException({'result': 2, 'description': u'该设备不支持直接打开端口'}) return self.stop_charging_port(port) #停止该端口下的所有任务 def stop_charging_port(self, port): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x06, 'port': port}}) self.check_feedback_result(devInfo) if devInfo['rst'] == 0: Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}}) return True if devInfo['rst'] == 0 else False def get_order(self,order_no): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x0A, 'order_id': order_no}}) self.check_feedback_result(devInfo) curOrder = devInfo['data'].get('order',None) result = {} if not curOrder.has_key('order_type'):#有可能没有订单,应该返回空 return result result['status'] = curOrder['status'] result['elec'] = curOrder['elec'] if curOrder['order_type'] == 'apps_start': result['consumeType'] = 'mobile' try: rcd = ConsumeRecord.objects.get(orderNo = curOrder['id']) if u'虚拟卡' in rcd.remarks: result['consumeType'] = 'mobile_vcard' except Exception,e: pass elif curOrder['order_type'] == 'coin_start': result['consumeType'] = 'coin' elif curOrder['order_type'] == 'card_start': result['consumeType'] = 'card' if curOrder.has_key('amount_time'): result['needTime'] = round(curOrder['amount_time']/60.0,1) if curOrder.has_key('time'): result['duration'] = round(curOrder['time']/60.0,1) result['usedTime'] = round(curOrder['time']/60.0,1) if curOrder.has_key('left_time'): result['leftTime'] = round(curOrder['left_time']/60.0,1) if curOrder.has_key('amount_elec'): result['needElec'] = curOrder['amount_elec']/1000000.0 if curOrder.has_key('elec'): result['elec'] = curOrder.get('elec')/1000000.0 if curOrder.has_key('execute_time'): result['startTime'] = datetime.datetime.fromtimestamp(int(curOrder['execute_time'])).strftime('%m-%d %H:%M:%S') if curOrder.has_key('card_no'): result['cardNo'] = str(int(curOrder['card_no'],16)) if curOrder.has_key('id') and (curOrder['order_type'] not in ['coin_start','card_charge']) :#card_charge try: rcd = ConsumeRecord.objects.get(orderNo = curOrder['id']) result['openId'] = rcd['openId'] result['coins'] = float(str(rcd['coin']))#都用coins result['money'] = float(str(rcd['money'])) result['orderNo'] = str(curOrder['id']) except Exception,e: return None return result def response_card_balance(self, cardNo,balance,result): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code':35,'card_no':cardNo,'balance':int(100*float(balance)),'result':result}}) self.check_feedback_result(devInfo) # 获取设备配置参数 def get_dev_setting(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x0C}}) self.check_feedback_result(devInfo) result = devInfo['data'] result.update({ 'fcharge_watt':result['fcharge']['watt'], 'fcharge_time':result['fcharge']['time'], 'fcharge_check':result['fcharge'].get('check',10), }) packageElec,packageTime = [],[] for name,conf in result['package'].items(): if name == 'TIME': for k,v in conf.items(): packageTime.append({'price':int(k)/100,'time':v/60})#单位从秒转为分钟 else: for k,v in conf.items(): packageElec.append({'price':int(k)/100,'time':v/1000000})#单位从微度转为度 result['package_elec'] = packageElec result['package_time'] = packageTime powerRate = [] for k,v in result['power_rate'].items(): powerRate.append(v) def cmp_power(x,y): if x['max'] < y['max']: return -1 elif x['max'] > y['max']: return 1 return 0 powerRate = sorted(powerRate,cmp_power) result['power_rate'] = powerRate defaultVolume = 0 volumeList = [] for k,v in result['volume'].items(): if k == 'default': defaultVolume = v else: tempList = k.split('-') volumeList.append({'start':tempList[0],'end':tempList[1],'volume':v}) result.pop('volume') result['volume'] = defaultVolume result['volume_list'] = volumeList result['once_card'] = result['once_card'] / 100.0 result['once_coin'] = result['once_coin'] / 100.0 state = self.get_dev_consume_count() result.update(state) return result # 获取设备配置参数 def set_dev_setting(self, setConf): #如果是卡密码,直接进行修改 if setConf.has_key('card_pwd'): return self.set_card_pwd(setConf['card_pwd']) #时间套餐不能为空 if setConf.has_key('package_time') and len(setConf['package_time']) == 0: raise ServiceException({'result': 2, 'description': u'按时间计费的套餐不能为空'}) #检查数据 if not (int(setConf['fcharge_time']) >= 1 and int(setConf['fcharge_time']) <= 300): raise ServiceException({'result': 2, 'description': u'浮充时间必须大于等于1分钟,小于等于300分钟'}) if not (int(setConf['fcharge_check']) >= 2 and int(setConf['fcharge_check']) <= 30): raise ServiceException({'result': 2, 'description': u'浮充检测时间必须大于等于2分钟,小于等于30分钟'}) if not (int(setConf['fcharge_watt']) >= 20 and int(setConf['fcharge_watt']) <= 100): raise ServiceException({'result': 2, 'description': u'浮充功率必须大于等于20瓦,小于等于100瓦'}) if not (int(setConf['volume']) >= 0 and int(setConf['volume']) <= 7): raise ServiceException({'result': 2, 'description': u'音量必须大于等于0,小于等于7'}) volumeDict = {'default':int(setConf['volume'])} for vl in setConf['volume_list']: startTime = to_datetime('2020-01-01 %s:00' % vl['start']) endTime = to_datetime('2020-01-01 %s:00' % vl['end']) if endTime <= startTime: raise ServiceException({'result': 2, 'description': u'结束时间一定要大于起始时间。比如起始时间为07:00,结束时间为23:59'}) volumeDict['%s-%s' % (vl['start'],vl['end'])] = int(vl['volume']) setConf.pop('volume') setConf.pop('volume_list') setConf['volume'] = volumeDict setConf['once_card'] = int(float(setConf['once_card'])*100) setConf['once_coin'] = int(float(setConf['once_coin'])*100) setConf['max_watt'] = int(setConf['max_watt']) if not (int(setConf['max_watt']) >= 50 and int(setConf['max_watt']) <= 1000): raise ServiceException({'result': 2, 'description': u'最大功率必须大于等于100瓦,小于等于1000瓦'}) setConf.update({'fun_code':0x0B}) setConf['fcharge'] = { 'watt':int(setConf['fcharge_watt']), 'time':int(setConf['fcharge_time']), 'check':int(setConf['fcharge_check']), } setConf.pop('fcharge_watt') setConf.pop('fcharge_time') setConf.pop('fcharge_check') packageElec,packageTime = {},{} isHaveOneCoinForElec,isHaveOneCoinForTime = False,False for pConf in setConf['package_time']: if pConf['price'] == 1: isHaveOneCoinForTime = True packageTime[str(int(float(pConf['price'])*100))] = int(float(pConf['time'])*60) for pConf in setConf['package_elec']: if pConf['price'] == 1: isHaveOneCoinForElec = True packageElec[str(int(float(pConf['price'])*100))] = int(float(pConf['time'])*1000000) if (setConf['chrmt']=='ELEC' and not isHaveOneCoinForElec) or (setConf['chrmt']=='TIME' and not isHaveOneCoinForTime): raise ServiceException({'result': 2, 'description': u'刷卡投币收费模式中,至少需要包含1元的使用套餐'}) if ( len(packageElec) != len(setConf['package_elec']) ) or ( len(packageTime) != len(setConf['package_time']) ): raise ServiceException({'result': 2, 'description': u'套餐价格不允许出现重复'}) setConf.pop('package_time') setConf.pop('package_elec') setConf['package'] = {'ELEC':packageElec,'TIME':packageTime} powerRate = {} powerList = [] for pConf in setConf['power_rate']: powerRate[str(pConf['max'])] = pConf powerList.append(int(pConf['max'])) powerList = sorted(powerList) powerSetDict = {} ii = 0 prePw = 0 for pw in powerList: ii += 1 if ii == 1: powerSetDict[str(ii)] = {'min':0,'max':pw,'rate':int(powerRate[str(pw)]['rate'])} else: if int(powerRate[str(pw)]['rate']) < int(powerRate[str(prePw)]['rate']): raise ServiceException({'result': 2, 'description': u'功率越大,比例应该越高,这样用户的时间才消耗快一些,您才不会亏哦'}) powerSetDict[str(ii)] = {'min':prePw,'max':pw,'rate':int(powerRate[str(pw)]['rate'])} prePw = pw setConf.pop('power_rate') setConf['power_rate'] = powerSetDict devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': setConf}) self.check_feedback_result(devInfo) def ack_event(self,orderNo,funCode): devInfo = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], 'data': {'fun_code':funCode,'order_id':orderNo}}) self.check_feedback_result(devInfo) def clear_dev_feecount(self): devInfo = MessageSender.send(self.device, self.make_random_cmdcode(), {'IMEI': self._device['devNo'], 'data': {'fun_code':0x09,'total_coin':True,'total_card':True}}) self.check_feedback_result(devInfo) def response_card_charge_result(self,cardNo,result): MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SERVER_ASYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code':37,'card_no':cardNo,'result':result}}) def reboot_device(self): data = {'fun_code':0x0B,'reset_mcu':True} MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': data}) MessageSender.async_send(self.device, DeviceCmdCode.SET_DEVINFO, {'IMEI': self._device['devNo'], 'restart': True}) def set_device_function(self, request, lastSetConf): if request.POST.has_key('clearSum'): self.clear_dev_feecount() elif request.POST.has_key('reboot'): self.reboot_device() def set_device_function_param(self, request, lastSetConf): newConf = copy.deepcopy(request.POST) newConf.pop('logicalCode', None) self.set_dev_setting(newConf) # if request.POST.has_key('maxPower') and request.POST.has_key('icMoney'): # lastSetConf.update({'maxPower': int(request.POST.get('maxPower', 0))}) # lastSetConf.update({'icMoney': int(request.POST.get('icMoney', 0))}) # self.set_IC_coin_power_config(lastSetConf) # # if request.POST.has_key('time1') and request.POST.has_key('time2') and request.POST.has_key('time3'): # lastSetConf.update({'time1': int(request.POST.get('time1', 0))}) # lastSetConf.update({'time2': int(request.POST.get('time2', 0))}) # lastSetConf.update({'time3': int(request.POST.get('time3', 0))}) # self.set_IC_coin_power_config(lastSetConf) # # if request.POST.has_key('power1') and request.POST.has_key('power1ratio'): # lastSetConf.update({'power1': int(request.POST.get('power1', 0))}) # lastSetConf.update({'power1ratio': int(request.POST.get('power1ratio', 0))}) # lastSetConf.update({'power2': int(request.POST.get('power2', 0))}) # lastSetConf.update({'power2ratio': int(request.POST.get('power2ratio', 0))}) # lastSetConf.update({'power3': int(request.POST.get('power3', 0))}) # lastSetConf.update({'power3ratio': int(request.POST.get('power3ratio', 0))}) # lastSetConf.update({'power4': int(request.POST.get('power4', 0))}) # lastSetConf.update({'power4ratio': int(request.POST.get('power4ratio', 0))}) # lastSetConf.update({'power5': int(request.POST.get('power5', 0))}) # lastSetConf.update({'power5ratio': int(request.POST.get('power5ratio', 0))}) # self.set_gear_conf(lastSetConf) # # if request.POST.has_key('card1Time') and request.POST.has_key('card2Time') and request.POST.has_key( # 'card3Time'): # lastSetConf.update({'card1Time': int(request.POST.get('card1Time', 0))}) # lastSetConf.update({'card2Time': int(request.POST.get('card2Time', 0))}) # lastSetConf.update({'card3Time': int(request.POST.get('card3Time', 0))}) # self.set_card_time_config(lastSetConf) # # if request.POST.has_key('fuchongPower') and request.POST.has_key('fuChongTime'): # lastSetConf.update({'fuchongPower': int(request.POST.get('fuchongPower', 0))}) # lastSetConf.update({'fuChongTime': int(request.POST.get('fuChongTime', 0))}) # self.set_fuchong_config(lastSetConf) def get_card_pwd(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x11}}) self.check_feedback_result(devInfo) result = devInfo['data'] enObj = EncryptDate(cardKey) cardPwd = enObj.decrypt(result['card_pwd']) if not cardPwd: cardPwd = '' return {'card_pwd':cardPwd} def translante_card_no(self,hexCardNo): return int(hexCardNo,16) def check_pwd(self,pwd): if len(pwd) != 6: raise ServiceException({'result': 2, 'description': u'密码必须是6位纯数字密码'}) for char in pwd: if not (char>='0' and char<='9'): raise ServiceException({'result': 2, 'description': u'密码必须是6位纯数字密码'}) return def set_card_pwd(self,pwd): self.check_pwd(pwd) enObj = EncryptDate(cardKey) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code':0x0B,'card_pwd':enObj.encrypt(pwd)}}) self.check_feedback_result(devInfo) def set_card_mode(self,setConf): cardMode = int(setConf.get('card_mode')) valueDict = {'fun_code':0x10} if cardMode == 0: valueDict.update({'mode':cardMode}) elif cardMode == 1:#格式化为离线卡 self.check_pwd(setConf['new_pwd']) newPwd = setConf['new_pwd'] if not str(setConf['balance']).isdigit(): raise ServiceException({'result': 2, 'description': u'余额必须是数字'}) balance = int(setConf['balance']) if not (balance >=0 and balance <= 5000): raise ServiceException({'result': 2, 'description': u'余额必须在0和5000元之间'}) balance = balance * 10#硬件模块记录的单位是角 enObj = EncryptDate(cardKey) valueDict.update({'mode':1,'new_pwd':enObj.encrypt(str(newPwd)),'balance':balance}) elif cardMode == 2: self.check_pwd(setConf['old_pwd']) self.check_pwd(setConf['new_pwd']) newPwd = setConf['new_pwd'] oldPwd = setConf['old_pwd'] enObj = EncryptDate(cardKey) valueDict.update({'mode':2,'old_pwd':enObj.encrypt(str(oldPwd)),'new_pwd':enObj.encrypt(str(newPwd))}) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': valueDict}) self.check_feedback_result(devInfo) def get_card_mode(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x11}}) self.check_feedback_result(devInfo) cardMode = devInfo['data']['card_mode'] return {'card_mode':cardMode} def check_alarm(self,alarm): if alarm.faultCode == FAULT_CODE.MCU_REBOOT: return u'此告警,建议您多观察,如果比较频繁不停上报单台设备的告警,可能会运行不稳定。需要您联系技术支持确认。' elif alarm.faultCode == FAULT_CODE.COUNTER_FAULT: portInfo = self.get_port_info(alarm.portNo) if portInfo['status'] == Const.DEV_WORK_STATUS_FAULT: return u'此端口目前已经为故障状态,继电器可能运行不稳定,建议您联系技术支持,以确认设备运行情况。' else: return u'端口状态检查正常,继电器或存偶尔无法获取数据。暂不影响使用。' elif alarm.faultCode == FAULT_CODE.RELAY_FAULT: return u'无法进行远程诊断,建议您到现场,直接插上插座,然后检查是否不用付款,就能够充电。如果是的,就属于继电器粘连。' elif alarm.faultCode == FAULT_CODE.DEV_OVERLOAD: return u'整机功率最大限定为7500瓦,接入的负载超过此负载,为了安全,将强行关闭所有充电端口。' elif alarm.faultCode == FAULT_CODE.COPY_CARD: return u'出现一模一样的卡,可能是用户复制了另外一张离线卡,然后使用,会给您造成经济上的损失,建议冻结。' return '' def get_part_info(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'data': {'fun_code': 0x05}}) self.check_feedback_result(devInfo) partInfo = devInfo['data'] result = {} nameDesc = {'networkBoard':u'网络板','chargeBoard':u'充电板','cardBoard':u'刷卡板'} for k,v in partInfo.items(): if k not in nameDesc: continue result[nameDesc.get(k)] = {'SN':v} return result def recharge_card(self, cardNo, money, orderNo=None): hex_cardNo = hex(int(cardNo))[2::].replace('L', '').upper() result = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SERVER_ASYNC, {'IMEI': self.device['devNo'], 'data': {'fun_code': 37, 'result': 1, 'card_no': hex_cardNo, 'charge': int(money * 100), 'order_id': orderNo}}) # 返回验证 self.check_feedback_result(result) card = Card.objects.filter(cardNo=cardNo,dealerId=self.device.ownerId).first() balance = card.balance + money return { 'result': ErrorCode.SUCCESS, 'description': '' }, balance def get_customize_score_unit(self): return u'元' def get_customize_package_unit(self): chrmt = self.device['otherConf'].get('chrmt') if not chrmt: chrmt = self.get_dev_setting().get('chrmt') # 按时间计费 if chrmt == 'TIME' or chrmt == 'POWER': return u'分钟' # 按电量计费 elif chrmt == 'ELEC': return u'度' return u'元' def start_customize_point(self,pointNum,openId,port): unit = self.get_customize_package_unit() package = {'name':'customizePoint','price':pointNum,'coins':pointNum,'unit':unit,'time':999} # 如果是时间,就用时间作为兜底的控制,钱填大一些; attachParas = {'chargeIndex':port,'onPoints':True} return self.start_device(package, openId, attachParas)