# -*- coding: utf-8 -*- # !/usr/bin/env python import logging import time import random from apilib.utils_datetime import timestamp_to_dt from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, hexbyte_2_bin from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device logger = logging.getLogger(__name__) class LanguangBox(SmartBox): def __init__(self, device): super(LanguangBox, self).__init__(device) def test(self, coins): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '00', 'data': '<020002>'}) return devInfo #主要是处理设备状态发生变化的事件,直接把设备状态报文上报 #(0D0300010000000001B901F70041) def analyze_event_data(self,data): status = data[5:9] if status == '0001': return {'status':Const.DEV_WORK_STATUS_IDLE,'statusInfo':u'空闲'} elif status == '0002': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'等待卡消费'} elif status == '0004': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'卡消费'} elif status == '0008': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'卡消费结束'} elif status == '0010': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'投币后等待按键消费'} elif status == '0020': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'投币消费'} elif status == '0040': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'投币消费结束'} elif status == '0080': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'虚拟消费'} elif status == '0100': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'虚拟消费结束'} elif status == '0200': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'卡值操作状态'} elif status == '0400': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'等待取卡'} elif status == '0800': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'存在消费卡'} elif status == '1000': return {'status':Const.DEV_WORK_STATUS_WORKING,'statusInfo':u'低水位'} else: return {'status':Const.DEV_WORK_STATUS_IDLE,'statusInfo':u'空闲'} def get_dev_config(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '01', 'data': '<03015153>'}) 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'当前机器正在忙,无响应,请稍后再试哦'}) #(2301 01 02BC00000000000A000A06500690000A000A00005460000000080014012C00144C) data = devInfo['data'][5::] result = data[0:2] if result == '00': raise ServiceException({'result': 2, 'description': u'当前机器返回错误,建议您请稍后再试哦'}) g_g_mid = int(data[2:6],16) g_g_work_tmr = int(data[6:14],16) g_g_chk_on_tmr = int(data[14:18],16) g_g_chk_off_tmr = int(data[18:22],16) # j_w_down = int(data[22:26],16)/16 - 100 # j_w_up = int(data[26:30],16)/16 - 100 j_w_down = int(data[22:26],16) j_w_up = int(data[26:30],16) j_w_chk_on_tmr = int(data[30:34],16) j_w_chk_off_tmr = int(data[34:38],16) c_y_wait_tmr = int(data[38:46],16) c_y_work_tmr = int(data[46:54],16) z_s_chk_on_tmr = int(data[54:58],16) z_s_chk_off_tmr = int(data[58:62],16) c_s_delay = int(data[62:66],16) return { 'g_g_mid':g_g_mid,'g_g_work_tmr':g_g_work_tmr,'g_g_chk_on_tmr':g_g_chk_on_tmr,'g_g_chk_off_tmr':g_g_chk_off_tmr, 'j_w_down':j_w_down,'j_w_up':j_w_up,'j_w_chk_on_tmr':j_w_chk_on_tmr,'j_w_chk_off_tmr':j_w_chk_off_tmr, 'c_y_wait_tmr':c_y_wait_tmr,'c_y_work_tmr':c_y_work_tmr,'z_s_chk_on_tmr':z_s_chk_on_tmr,'z_s_chk_off_tmr':z_s_chk_off_tmr, 'c_s_delay':c_s_delay } def calc_crc(self,data): checkSum = 0 for ii in range(len(data)/2): hexByte = int(data[2*ii:2*ii + 2],16) checkSum = checkSum ^ hexByte checkSum = fill_2_hexByte(hex(checkSum), 2) return str(checkSum) def set_dev_config(self,conf): data = '230101' data += fill_2_hexByte(hex(int(conf['g_g_mid'])), 4) data += fill_2_hexByte(hex(int(conf['g_g_work_tmr'])), 8) data += fill_2_hexByte(hex(int(conf['g_g_chk_on_tmr'])), 4) data += fill_2_hexByte(hex(int(conf['g_g_chk_off_tmr'])), 4) # downT = (int(conf['j_w_down']) + 100) * 16 # data += fill_2_hexByte(hex(int(downT)), 4) # upT = (int(conf['j_w_up']) + 100) * 16 # data += fill_2_hexByte(hex(int(upT)), 4) downT = (int(conf['j_w_down'])) data += fill_2_hexByte(hex(int(downT)), 4) upT = (int(conf['j_w_up'])) data += fill_2_hexByte(hex(int(upT)), 4) data += fill_2_hexByte(hex(int(conf['j_w_chk_on_tmr'])), 4) data += fill_2_hexByte(hex(int(conf['j_w_chk_off_tmr'])), 4) data += fill_2_hexByte(hex(int(conf['c_y_wait_tmr'])), 8) data += fill_2_hexByte(hex(int(conf['c_y_work_tmr'])), 8) data += fill_2_hexByte(hex(int(conf['z_s_chk_on_tmr'])), 4) data += fill_2_hexByte(hex(int(conf['z_s_chk_off_tmr'])), 4) data += fill_2_hexByte(hex(int(conf['c_s_delay'])), 4) crc = self.calc_crc(data) data += crc data = '<' + data + '>' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '01', '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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][6::] result = data[0:2] if result == '00': raise ServiceException({'result': 2, 'description': u'当前机器返回错误,建议您请稍后再试哦'}) return devInfo def get_usr_pwd_fee(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '02', 'data': '<03025150>'}) 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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][5::] result = data[0:2] if result == '00': raise ServiceException({'result': 2, 'description': u'当前机器返回错误,建议您请稍后再试哦'}) tempPwd = data[2:14] usr_pwd = '' if tempPwd != 'FFFFFFFFFFFF': for ii in range(6): index = (ii + 1) * 2 -1 num = str(int(tempPwd[index])) usr_pwd += num f_l_1_litres = int(data[14:18],16) f_l_1_cents = int(data[18:22],16) f_l_2_litre = int(data[22:26],16) f_l_2_cents = int(data[26:30],16) f_l_3_litre = int(data[30:34],16) f_l_3_cents = int(data[34:38],16) f_l_4_litre = int(data[38:42],16) f_l_4_cents = int(data[42:46],16) return { 'usr_pwd':usr_pwd, 'f_l_1_litres':f_l_1_litres,'f_l_1_cents':f_l_1_cents, 'f_l_2_litres':f_l_2_litre,'f_l_2_cents':f_l_2_cents, 'f_l_3_litres':f_l_3_litre,'f_l_3_cents':f_l_3_cents, 'f_l_4_litres':f_l_4_litre,'f_l_4_cents':f_l_4_cents } def set_usr_pwd_fee(self,conf): data = '190201' if len(conf['usr_pwd']) == 0: data += 'FFFFFFFFFFFF' elif len(conf['usr_pwd']) != 6: raise ServiceException({'result': 2, 'description': u'密码必须是6位数字或者空密码'}) else: strPwd = conf['usr_pwd'] for num in strPwd: if num < '0' or num > '9': raise ServiceException({'result': 2, 'description': u'密码必须是6位数字或者空密码'}) data += '0%s' % num data += fill_2_hexByte(hex(int(conf['f_l_1_litres'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_1_cents'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_2_litres'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_2_cents'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_3_litres'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_3_cents'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_4_litres'])), 4) data += fill_2_hexByte(hex(int(conf['f_l_4_cents'])), 4) crc = self.calc_crc(data) data +=crc data = '<' + data + '>' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '01', '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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][6::] result = data[0:2] if result == '00': raise ServiceException({'result': 2, 'description': u'当前机器返回错误,建议您请稍后再试哦'}) return devInfo def get_dev_status(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '03', 'data': '<020301>'}) 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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][5::] xf_status = '0x' + data[0:4] io_jdq = data[4:6] io_fmq = int(data[6:8],16) io_sw = data[8:10] io_aj = data[10:12] hBin = hexbyte_2_bin(data[12:14]) lBin = hexbyte_2_bin(data[14:16]) if hBin[0] == '1': temp = '' for ch in hBin + lBin: if ch == '1': temp += '0' else: temp += '1' io_wd = round(-(int(temp[0:4],2)*4096+int(temp[4:8],2)*256+int(temp[8:12],2)*16 + int(temp[12:16],2) + 1)/16.0,2) else: io_wd = round(int(data[12:16],16)/16.0,2) io_hd = int(data[16:20],16) io_llj = int(data[20:22],16) return {'xf_status':xf_status,'io_jdq':io_jdq,'io_fmq':io_fmq,'io_sw':io_sw, 'io_aj':io_aj,'io_wd':io_wd,'io_hd':io_hd,'io_llj':io_llj} def get_consume_info(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '04', 'data': '<020406>'}) 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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][9::] c_id = data[0:8] c_ye = int(data[8:16],16) tbq_ye = int(data[16:20],16) xn_ye = int(data[20:28],16) end_ye = int(data[28:36],16) return {'c_id':c_id,'c_ye':c_ye,'tbq_ye':tbq_ye,'xn_ye':xn_ye,'end_ye':end_ye} def get_consume_stats(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '09', 'data': '<0309515B>'}) 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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][5::] sum_all = int(data[0:8],16)/100.0 sum_card = int(data[8:16],16)/100.0 sum_xn_xf = int(data[16:24],16)/100.0 sum_tbq = int(data[24:32],16)/100.0 return {'sum_all':sum_all,'sum_card':sum_card,'sum_xn_xf':sum_xn_xf,'sum_tbq':sum_tbq} def clear_consume_info(self): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '09', 'data': '<0309000A>'}) 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 def stop(self,port): devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '08', 'data': '<0708FF0000006494>'}) 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'当前机器正在忙,无响应,或者请稍后再试哦'}) data = devInfo['data'][6::] result = data[0:2] if result == '00': raise ServiceException({'result': 2, 'description': u'当前机器返回错误,建议您请稍后再试哦'}) devInfo['remainder_time'] = 0 return devInfo def start_device(self, package, openId, attachParas): needCoins = int(float(package['coins'])*100) data = '070801' data += fill_2_hexByte(hex(needCoins),8) crc = self.calc_crc(data) data += crc data = '<' + data + '>' devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = { 'IMEI': self._device['devNo'], "funCode": '08', '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 + 60 * 60 Device.update_dev_control_cache( self._device['devNo'], { 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'), 'status': Const.DEV_WORK_STATUS_WORKING, 'finishedTime': devInfo['finishedTime'], 'isStart': True, 'openId': openId, 'refunded': False, 'coins': needCoins, 'vCardId': self._vcard_id }) return devInfo def remote_charge_card(self, money, rechargeRecord=None): result = self.get_dev_status() if result['xf_status'] != u"0x0001": raise ServiceException({'result': 2, 'description': u'设备正忙,请稍后再试'}) data = '0D0701' logger.info('i have money ooooo,money=%s' % money) orderNo = fill_2_hexByte(hex(random.randint(0, 0xFFFF)),4) data += orderNo data += '00000000' data += fill_2_hexByte(hex(int(money*100)),8) crc = self.calc_crc(data) data += crc data = '<' + data + '>' devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '07', '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'设备正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) # todo 不能带状态判断,因为第一时间的主板返回一定是失败 # if devInfo['data'] != '(020701)': # raise ServiceException({'result': 2, 'description': u'设备返回实体卡失败'}) def get_dev_setting(self): conf = self.get_dev_config() conf2 = self.get_usr_pwd_fee() conf.update(conf2) return conf def get_device_function_by_key(self,keyName): devInfo = {} if 'g_g_mid' in keyName: devInfo = self.get_dev_config() elif 'f_l_1_litres' in keyName: devInfo = self.get_usr_pwd_fee() elif 'io_fmq' in keyName or 'io_llj' in keyName: devInfo = self.get_dev_status() elif 'c_id' in keyName: devInfo = self.get_consume_info() elif 'sum_all' in keyName: devInfo = self.get_consume_stats() elif 'io_kzq1' in keyName: devInfo = self.get_dev_status() jdqInfo = devInfo['io_jdq'] kzqBin = hexbyte_2_bin(jdqInfo) devInfo['io_kzq1'] = kzqBin[7] devInfo['io_kzq2'] = kzqBin[6] devInfo['io_kzq3'] = kzqBin[5] devInfo['io_kzq4'] = kzqBin[4] devInfo['io_kzq5'] = kzqBin[3] devInfo['io_kzq6'] = kzqBin[2] devInfo['io_kzq7'] = kzqBin[1] devInfo['io_kzq8'] = kzqBin[0] elif 'io_sw1' in keyName: devInfo = self.get_dev_status() swInfo = devInfo['io_sw'] swBin = hexbyte_2_bin(swInfo) devInfo['io_sw1'] = swBin[7] devInfo['io_sw2'] = swBin[6] devInfo['io_sw3'] = swBin[5] devInfo['io_sw4'] = swBin[4] elif 'io_aj1' in keyName: devInfo = self.get_dev_status() swInfo = devInfo['io_aj'] swBin = hexbyte_2_bin(swInfo) devInfo['io_aj1'] = swBin[7] devInfo['io_aj2'] = swBin[6] devInfo['io_aj3'] = swBin[5] elif 'xf_status' in keyName: devInfo = self.get_dev_status() return devInfo def set_device_function_param(self,request,lastSetConf): if request.POST.has_key('g_g_mid'): lastSetConf.update({'g_g_mid': int(request.POST.get('g_g_mid', 0))}) lastSetConf.update({'g_g_work_tmr': int(request.POST.get('g_g_work_tmr', 0))}) lastSetConf.update({'g_g_chk_on_tmr': int(request.POST.get('g_g_chk_on_tmr', 0))}) lastSetConf.update({'g_g_chk_off_tmr': int(request.POST.get('g_g_chk_off_tmr', 0))}) lastSetConf.update({'j_w_down': int(request.POST.get('j_w_down', 0))}) lastSetConf.update({'j_w_up': int(request.POST.get('j_w_up', 0))}) lastSetConf.update({'j_w_chk_on_tmr': int(request.POST.get('j_w_chk_on_tmr', 0))}) lastSetConf.update({'j_w_chk_off_tmr': int(request.POST.get('j_w_chk_off_tmr', 0))}) lastSetConf.update({'c_y_wait_tmr': int(request.POST.get('c_y_wait_tmr', 0))}) lastSetConf.update({'c_y_work_tmr': int(request.POST.get('c_y_work_tmr', 0))}) lastSetConf.update({'z_s_chk_on_tmr': int(request.POST.get('z_s_chk_on_tmr', 0))}) lastSetConf.update({'z_s_chk_off_tmr': int(request.POST.get('z_s_chk_off_tmr', 0))}) lastSetConf.update({'c_s_delay': int(request.POST.get('c_s_delay', 0))}) self.set_dev_config(lastSetConf) if request.POST.has_key('f_l_1_litres') and request.POST.has_key('f_l_1_litres'): lastSetConf.update({'usr_pwd': str(request.POST.get('usr_pwd', ''))}) lastSetConf.update({'f_l_1_litres': int(request.POST.get('f_l_1_litres', 0))}) lastSetConf.update({'f_l_1_cents': int(request.POST.get('f_l_1_cents', 0))}) lastSetConf.update({'f_l_2_litres': int(request.POST.get('f_l_2_litres', 0))}) lastSetConf.update({'f_l_2_cents': int(request.POST.get('f_l_2_cents', 0))}) lastSetConf.update({'f_l_3_litres': int(request.POST.get('f_l_3_litres', 0))}) lastSetConf.update({'f_l_3_cents': int(request.POST.get('f_l_3_cents', 0))}) lastSetConf.update({'f_l_4_litres': int(request.POST.get('f_l_4_litres', 0))}) lastSetConf.update({'f_l_4_cents': int(request.POST.get('f_l_4_cents', 0))}) self.set_usr_pwd_fee(lastSetConf) def set_device_function(self,request,lastSetConf): # if request.POST.has_key('clearSum') and request.POST.get('clearSum') == 'true': if request.POST.get('clearSum', False): self.clear_consume_info() def check_dev_status(self, attachParas = None): info = self.get_dev_status() if info['xf_status'] != '0x0001': raise ServiceException({'result': 2, 'description': u'当前设备正忙,需要设备空闲,您才可以操作哦'})