# -*- coding: utf-8 -*- from apps.web.core.adapter.base import * from apps.web.device.models import Cell, Device # 0A:修改从机地址;0B 回读从机状态 0C 按时间充电 0D 按电量充电 0E 停止充电 class JinzeBox(SmartBox): def __init__(self, device): super(JinzeBox, self).__init__(device) def get_port_status_from_dev(self): return def test(self, coins): data = 'A500' +'0010050000000001' + '0001' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], "funCode": '0C', 'data': data}) return devInfo def analyze_event_data(self, data): port = int(data[2:4]) voltage = int(data[10:12],16) + int(data[12:14],16)/10.0 current = int(data[14:16],16) + int(data[16:18],16)/10.0 duration = int(data[18:20],16)*60 + int(data[20:22],16) elec = round((int(data[22:24],16) + int(data[24:26],16)/10.0)/4.55,2) mode = data[26:28] battery = data[28:30] statusDesc = '' if mode == '00': statusDesc = u'待机' elif mode == '01': statusDesc = u'充电' elif mode == '02': statusDesc = u'识别' elif mode == '03': statusDesc = u'维护' elif mode == '04': statusDesc = u'浮充' elif mode == '05': statusDesc = u'完成' elif mode == '06': statusDesc = u'异常' elif mode == '90': statusDesc = u'额度用完结束' elif mode == '91': statusDesc = u'电池脱落' elif mode == '92': statusDesc = u'远程断电' elif mode == '93': statusDesc = u'无法充入' elif mode == '94': statusDesc = u'电池异常' return {'port':port,'voltage':voltage,'current':current,'duration':duration,'inputElec':elec,'mode':mode,'battery':battery,'statusDesc':statusDesc} #回读数据 A5 00 00 10 02 00 B7 #回应A5 00 01 60 0B 1C 06 00 00 00 00 00 00 00 00 9E D1 def read_port(self,port): hexPort = fill_2_hexByte(hex(int(port)), 2) data = 'A5' + hexPort + '00100200' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '0B', 'data': data}) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'电池没有接上或者充电站从机无响应,建议您检查是否接上了电池,或者是否从机地址错误','flag':1}) data = devInfo['data'] portInfo = self.analyze_event_data(data) return portInfo def get_port_list(self): devObj = Device.objects.get(devNo = self._device['devNo']) portDict = devObj.otherConf.get('portDict',{}) return portDict.keys() def add_address(self,new): hexNew = fill_2_hexByte(hex(int(new)), 2) try: self.read_port(new) raise ServiceException({'result': 2, 'description': u'您编辑的新从机地址已经被占用,请您换一个没有被使用的新从机地址'}) except ServiceException,e: if not e.result.get('flag',0): raise e #A5 0A(旧地址) 00 10 B2 0B CD(新地址) 00 data = 'A500' + '0010B20B' + hexNew + '00' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], "funCode": '0A', 'data': data}) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'充电站正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) #再次检查修改后的从机地址是否能够回读上来 try: self.read_port(new) except ServiceException,e: if e.result.get('flag',0): raise ServiceException({'result': 2, 'description': u'修改之后的地址,访问没有响应,可能设置失败了,请您再次检查设备'}) else: raise e #登记记录到数据库中 devObj = Device.objects.get(devNo = self._device['devNo']) portDict = devObj.otherConf.get('portDict',{}) portDict.update({str(new):Const.DEV_WORK_STATUS_IDLE}) devObj.otherConf['portDict'] = portDict devObj.save() return devObj def edit_address(self,old,new): hexOld = fill_2_hexByte(hex(int(old)), 2) hexNew = fill_2_hexByte(hex(int(new)), 2) # 首先回读,检查从机地址是正确。如果回读地址无响应,会报错 self.read_port(old) # 检查新地址是否被占用 try: self.read_port(new) raise ServiceException({'result': 2, 'description': u'您编辑的新从机地址已经被占用,请您换一个没有被使用的新从机地址'}) except ServiceException,e: if not e.result.get('flag',0): raise e #A5 0A(旧地址) 00 10 B2 0B CD(新地址) 00 data = 'A5' + hexOld + '0010B20B' + hexNew + '00' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], "funCode": '0A', 'data': data}) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'充电站正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) #再次检查修改后的从机地址是否能够回读上来 try: self.read_port(new) except ServiceException,e: if e.result.get('flag',0): raise ServiceException({'result': 2, 'description': u'修改之后的地址,访问没有响应,可能设置失败了,请您再次检查设备'}) #登记记录到数据库中 devObj = Device.objects.get(devNo = self._device['devNo']) portDict = devObj.otherConf.get('portDict',{}) portDict.pop(str(old)) portDict.update({str(new):Const.DEV_WORK_STATUS_IDLE}) devObj.otherConf['portDict'] = portDict devObj.save() return devInfo def stop(self,port): # 首先回读,检查从机地址是正确。如果回读地址无响应,会报错 self.read_port(port) hexPort = fill_2_hexByte(hex(int(port)),2) data = 'A5' + hexPort + '0010050000000001' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], "funCode": '0E', 'data': data}) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'充电站正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) spendTime = devInfo['duration']/60 ctrInfo = Device.get_dev_control_cache(self._device['devNo']) try: needTime = ctrInfo['needTime'] devInfo['remainder_time'] = needTime - spendTime return devInfo except Exception,e: devInfo['remainder_time'] = 0 return devInfo def get_port_info(self,line): try: portInfo = self.read_port(line) except Exception,e: portInfo = {'status':Const.DEV_WORK_STATUS_IDLE} return portInfo def get_port_status(self, force = False): devObj = Device.objects.get(devNo = self._device['devNo']) portDict = devObj.otherConf.get('portDict',{}) ctrInfo = Device.get_dev_control_cache(self._device['devNo']) statusDict = {} for port,status in portDict.items(): tempDict = ctrInfo.get(str(port),{}) if tempDict.has_key('status'): statusDict[str(port)] = {'status':tempDict.get('status')} elif tempDict.has_key('isStart'): if tempDict['isStart']: statusDict[str(port)] = {'status':Const.DEV_WORK_STATUS_WORKING} else: statusDict[str(port)] = {'status':Const.DEV_WORK_STATUS_IDLE} elif status == Const.DEV_WORK_STATUS_FORBIDDEN: statusDict[str(port)] = {'status':Const.DEV_WORK_STATUS_FORBIDDEN} else: statusDict[str(port)] = {'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): devObj = Device.objects.get(devNo = self._device['devNo']) if lock: Device.update_dev_control_cache(self._device['devNo'], {str(port):{'status':Const.DEV_WORK_STATUS_FORBIDDEN}}) devObj.otherConf['portDict'].update({str(port):Const.DEV_WORK_STATUS_FORBIDDEN}) else: Device.update_dev_control_cache(self._device['devNo'], {str(port):{'status':Const.DEV_WORK_STATUS_IDLE}}) devObj.otherConf['portDict'].update({str(port):Const.DEV_WORK_STATUS_IDLE}) devObj.save() #只支持按时间充电 #A5 00 00 10 05 00 00 00 00 01 BB 启动慢充 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']) # 首先回读,检查从机地址是正确。如果回读地址无响应,会报错 self.read_port(port) hexPort = fill_2_hexByte(hex(port),2) needTime = int(package['time']) needCoins = int(package['coins']) unit = package.get('unit', u'分钟') if unit == u'小时': needTime = int(package['time']) * 60 elif unit == u'天': needTime = int(package['time']) * 1440 hexTime = fill_2_hexByte(hex(needTime)) data = 'A5' + hexPort + '0010050100000001' + hexTime devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], "funCode": '0C', 'data': data}, timeout = MQTT_TIMEOUT.START_DEVICE) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'充电站正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) start_timestamp = int(time.time()) devInfo['finishedTime'] = start_timestamp + needTime * 60 portValue = { 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'), 'status': Const.DEV_WORK_STATUS_WORKING, 'finishedTime': devInfo['finishedTime'], 'needTime': needTime, 'isStart': True, 'openId': openId, 'refunded': False, 'coins': needCoins, 'vCardId': self._vcard_id } ctrInfo = Device.get_dev_control_cache(self._device['devNo']) if ctrInfo.has_key(str(port)) and ctrInfo.has_key('needTime'): portValue = ctrInfo[str(port)] portValue.update({'needTime':portValue['needTime']+needTime}) Device.update_dev_control_cache(self._device['devNo'],{str(port): portValue}) return devInfo #注意格子锁的状态,只用读取全部的这个命令,单个锁的不要用了。 def get_board_lock_status(self,boardNo): hexBoardNo = fill_2_hexByte(hex(int(boardNo)), 2) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '80', 'data': '80' + hexBoardNo + '0033'}) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'充电站正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) #1:表示开。0:表示关。 lockData = hexbyte_2_bin(devInfo['data'][4:6]) + hexbyte_2_bin(devInfo['data'][6:8]) + hexbyte_2_bin(devInfo['data'][8:10]) result = {} ii = 1 for data in lockData[::-1]: if data == '0': result[str(ii)] ='close' else: result[str(ii)] = 'open' ii += 1 return result def get_all_lock_status(self): cells = Cell.objects.filter(logicalCode = self._device['logicalCode']) boardList = list(set([cell.boardNo for cell in cells])) devLockDict = {} for boardNo in boardList: lockDict = self.get_board_lock_status(boardNo) devLockDict[str(boardNo)] = lockDict resultDict = {} for cell in cells: resultDict[str(cell.cellNo)] = devLockDict[str(cell.boardNo)][str(cell.lockNo)] return resultDict def open_many_locks(self,boardNo,lockNos): lockNoDict = {'0':8,'1':7,'2':6,'3':5,'4':4,'5':3,'6':2,'7':1,'8':16,'9':15,'10':14,'11':13,'12':12,'13':11,'14':10,'15':9, '16':24,'17':23,'18':22,'19':21,'20':20,'21':19,'22':18,'23':17} binData = "" for ii in range(24): lockNo = lockNoDict.get(str(ii)) if lockNo in lockNos: binData += '1' else: binData += '0' hexData1 = fill_2_hexByte(hex(int(binData[0:8],2)),2) hexData2 = fill_2_hexByte(hex(int(binData[8:16],2)),2) hexData3 = fill_2_hexByte(hex(int(binData[16:24],2)),2) hexBoardNo = fill_2_hexByte(hex(int(boardNo)), 2) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {'IMEI': self._device['devNo'], "funCode": '90', 'data': '90' + hexBoardNo + hexData1 + hexData2 + hexData3}) if devInfo.has_key('rst') and devInfo['rst'] != 0: if devInfo['rst'] == -1: raise ServiceException({'result': 2, 'description': u'充电站正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif devInfo['rst'] == 1: raise ServiceException({'result': 2, 'description': u'充电站正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) return devInfo @property def isHaveStopEvent(self): return True