package com.sunvote.xpadcomm; import android.annotation.SuppressLint; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import com.sunvote.util.ByteUtils; import com.sunvote.util.LogUtil; import com.sunvote.xpadcomm.usb.UsbTransferManager; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; public class XPadApi implements XPadApiInterface { private static String TAG = "XPadApi"; private ComListener m_listener; private static XPadApi m_xpadApi = null; private OutputStream mOutputStream; private InputStream mInputStream; private ReadThread mReadThread; private List sendQueen = Collections.synchronizedList(new ArrayList());//new ArrayList(); private volatile int serialNumber; private int allOkSerialNumber; private int serviceSerialNumber; private boolean isShowLog = true; private boolean isShowOnlineLog = false; private OnLineInfo onLineInfo = new OnLineInfo(); private KeypadInfo info = new KeypadInfo(); private HandlerThread receiverThread = new HandlerThread("rea"); private HandlerThread sendThread = new HandlerThread("send"); private Handler taskHandler = null; private byte[] baseSign ; private byte[] voteSign ; // private boolean hasGetBaseInfo = false; private int writeFrimPageErrCnt = 0; // public SerialPortFinder mSerialPortFinder = new SerialPortFinder(); private XPadApi(){ sendThread.start(); taskHandler = new Handler(sendThread.getLooper()); } public synchronized static XPadApi getInstance() { if (m_xpadApi == null) { m_xpadApi = new XPadApi(); m_xpadApi.init(); } return m_xpadApi; } public void init() { try { LogUtil.d(TAG, "XPadApi.init()"); allOkSerialNumber = -1; serviceSerialNumber = -1; // mSerialPort = getSerialPort(); // module = new UDPModule(); // mOutputStream = module.getOutputStream(); // mInputStream = module.getInputStream(); // mOutputStream = mSerialPort.getOutputStream(); // mInputStream = mSerialPort.getInputStream(); UsbTransferManager.getInstance().setOnUsbConnectListener(new UsbTransferManager.OnUsbConnectListener() { @Override public boolean onConnect(boolean isConnected) { if(isConnected){ byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x03; writeToCom(mBuffer); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x04; writeToCom(mBuffer); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } getWorkMode(); }else{ onLineInfo.onLine = 2 ; m_listener.onOnLineEvent(onLineInfo); } return true; } }); mOutputStream = UsbTransferManager.getInstance().getOutputStream(); mInputStream = UsbTransferManager.getInstance().getInputStream(); Arrays.fill(broadcastData, (byte) 0x0);// 清空多包结果 /* Create a receiving thread */ mReadThread = new ReadThread(); mReadThread.start(); Log.d(TAG, "XPadApi init"); // InitThread initThread = new InitThread(); // initThread.start(); } catch (SecurityException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } private class InitThread extends Thread { @Override public void run() { try { sleep(100); getKeypadParam();// 唤醒 sleep(100); getKeypadParam(); sleep(100); getWorkMode(); } catch (Exception e) { // TODO: handle exception } super.run(); } } public void closeCom() { if (mReadThread != null) mReadThread.interrupt(); // if(module != null){ // module.release(); // } // if (mSerialPort != null) { // mSerialPort.close(); // mSerialPort = null; // } } public static void printDataBuf(byte[] buf, int len, String flag) { String tmpStr = new String(); for (int i = 0; i < len; i++) { tmpStr += String.format("%x ", buf[i]); } LogUtil.d(TAG, flag + ":" + tmpStr); } public static String getDataBufString(byte[] buf, int len, String flag) { String tmpStr = new String(); for (int i = 0; i < len; i++) { tmpStr += String.format("%x ", buf[i]); } return flag + ":" + tmpStr; } public static byte[] intToByteArray1(int i) { byte[] result = new byte[4]; result[0] = (byte) ((i >> 24) & 0xFF); result[1] = (byte) ((i >> 16) & 0xFF); result[2] = (byte) ((i >> 8) & 0xFF); result[3] = (byte) (i & 0xFF); return result; } @Override public void setComListener(ComListener cl) { m_listener = cl; } public class VoteResultItem { public int serialNo; public int status;// 0:未发送 1:已发送 public int ansType; // public int ansCount;// 批次提交的选项数 public int allOK; //1 确认提交 public byte[] data; public boolean sendOk; public int sendTimes = 0; /** * 用于回调标志结果显示 */ public String retBack = "" ; } private Runnable sendTask = new Runnable() { @Override public void run() { // 从队列中取出待发送数据 VoteResultItem voteResultItem = null; boolean send = false; synchronized (sendQueen) { if(sendQueen.size() > 0) { Iterator it = sendQueen.iterator(); while (it.hasNext()) { voteResultItem = it.next(); if ((!voteResultItem.sendOk && !send) || voteResultItem.ansType == AnsType_Select) { // 取出数据发送 if(send){ try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } voteResultItem.status = 1 ; if(voteResultItem.sendTimes < 1){ writeToCom(voteResultItem.data); } voteResultItem.sendTimes++; if(voteResultItem.sendTimes > 6){ voteResultItem.sendTimes = 0 ; } send = true; } } } } // 轮询下一次发送数据 taskHandler.removeCallbacks(this); taskHandler.postDelayed(this,1000); } }; /* * function:addToSendQueen params: 发送内容 功能:添加到发送队列 */ private void addToSendQueen(VoteResultItem item) { boolean isComb = false;// 合并 synchronized (sendQueen) { if (item.ansType == AnsType_BatchSingle && item.allOK != 1) { for (int i = 0; i < sendQueen.size(); i++) { VoteResultItem it = (VoteResultItem) sendQueen.get(i); if (it.status != 1 && it.ansType == AnsType_BatchSingle && it.ansCount < 6) { it.data[9 + it.ansCount * 3] = item.data[9]; it.data[10 + it.ansCount * 3] = item.data[10]; it.data[11 + it.ansCount * 3] = item.data[11]; it.ansCount++; isComb = true; LogUtil.d(TAG, "addToSendQueen isComb=true 合并:" + it.ansCount); break; } } } } if (isComb == false) { sendQueen.add(item); } LogUtil.d(TAG, "addToSendQueen serialNo=" + item.serialNo + " size=" + sendQueen.size()); // 轮询下一次发送数据 taskHandler.removeCallbacks(sendTask); taskHandler.post(sendTask); } private void sendToModalSuccessResponse(int serialNo) { LogUtil.d(TAG,"sendToModalSuccessResponse:" + serialNo); synchronized (sendQueen) { Iterator it = sendQueen.iterator(); while (it.hasNext()) { VoteResultItem voteResultItem = it.next(); if (voteResultItem.status == 1 && serialNo == voteResultItem.serialNo) { voteResultItem.sendOk = true; LogUtil.d(TAG, "set send ok sucess :" + serialNo); break; } } } } /* * function:addToSendQueen params:流水号 功能:根据流水号删除队列已发送成功的项 */ private VoteResultItem removeSentItem(int serialNo) { LogUtil.d(TAG, "send success : " + serialNo); VoteResultItem ret = null; synchronized (sendQueen) { Iterator it = sendQueen.iterator(); while (it.hasNext()) { VoteResultItem voteResultItem = it.next(); if (voteResultItem.status == 1 && voteResultItem.serialNo == serialNo) { voteResultItem.sendOk = true; boolean remove = sendQueen.remove(voteResultItem); LogUtil.d(TAG, "remove success ? " + remove); ret = voteResultItem; break; } } } return ret; } private void clearSentItems() { sendQueen.clear(); } @Override public void getWorkMode() { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x01; writeToCom(mBuffer); } @Override public void setWorkMode(int iMode) { byte[] mBuffer = new byte[0x1F + 4]; // Arrays.fill(mBuffer, (byte) 0x55); Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x02; mBuffer[6] = (byte) iMode; writeToCom(mBuffer); } @Override public void getBaseStatus() { if(baseSign != null){ onBaseInfo(baseSign); } /* byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x03; writeToCom(mBuffer);*/ } @Override public void getVoteStatus() { if(voteSign != null){ onVoteInfo(voteSign); } /*byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x04; writeToCom(mBuffer);*/ } @Override public void getKeypadParam() { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x05; writeToCom(mBuffer); } @Override public void setKeypadParam(int keyId, byte[] KEYSN) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x06; mBuffer[6] = (byte) ((keyId >> 8) & 0xFF);// keyId mBuffer[7] = (byte) (keyId & 0xFF); // mBuffer[8] =(byte) 0xFF; System.arraycopy(KEYSN, 0, mBuffer, 8, 6); byte[] parecode = new byte[4]; Arrays.fill(parecode, (byte) 0xFF); System.arraycopy(KEYSN, 0, mBuffer, 14, 4); writeToCom(mBuffer); } @Override public void checkOnLine(int volt, int keyinStatus) { LogUtil.i(TAG ,"HEART BEAT(S):" + volt + " " + System.currentTimeMillis()); if (isInComCommunicationTest) { return; } byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x07; mBuffer[6] = (byte) volt; mBuffer[7] = (byte) keyinStatus; writeToCom(mBuffer); } @Override public void execKeypadMatch(int iMode, int channal) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x08; mBuffer[6] = (byte) iMode; mBuffer[7] = (byte) channal; writeToCom(mBuffer); } private boolean isInComCommunicationTest = false; @Override public void comCommunicationTest(int sendn, int okn) { isInComCommunicationTest = (sendn != 200); byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x30; mBuffer[5] = 0x0; mBuffer[6] = 0x0; mBuffer[7] = 7; mBuffer[8] = (byte) sendn; mBuffer[9] = (byte) okn; mBuffer[10] = (byte) 0xAA; for (int i = 1; i < 17; i++) { mBuffer[10 + i] = (byte) i; } writeToCom(mBuffer); } @Override public void submitVote(int ansType, String info) {// byte[] ansData LogUtil.i(TAG,"ansType:" + ansType + ",info:" + info); if (ansType == AnsType_Single) {// 单值 byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; int val = Integer.parseInt(info); mBuffer[8] = (byte) val; VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.ansCount = 1; it.serialNo = serialNumber; serialNumberInc(); it.data = mBuffer; addToSendQueen(it); } else if (ansType == AnsType_Select) { String[] ary = info.split(","); String val = ary[0]; int tm = Integer.parseInt(ary[1]); byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; ; mBuffer[8] = (byte) ((tm >> 8) & 0xff); mBuffer[9] = (byte) (tm & 0xff); mBuffer[10] = (byte) ((tm >> 8) & 0xff); mBuffer[11] = (byte) (tm & 0xff); VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.ansCount = 1; it.serialNo = serialNumber; serialNumberInc(); it.data = mBuffer; addToSendQueen(it); // writeToCom(it.data); } else if (ansType == AnsType_Number) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; byte[] val = util_encodeBCD(info.getBytes()); System.arraycopy(val, 0, mBuffer, 8, 8); VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.ansCount = 1; it.serialNo = serialNumber; serialNumberInc(); it.data = mBuffer; addToSendQueen(it); } else if (ansType == AnsType_LoginIn) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 3;//3 签到信息按BCD码格式 byte[] val = util_encodeBCD(info.getBytes()); System.arraycopy(val, 0, mBuffer, 9, 9); VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.ansCount = 1; it.serialNo = serialNumber; serialNumberInc(); it.data = mBuffer; addToSendQueen(it); } else if (ansType == AnsType_BatchSingle) { // String[] ary= info.split(","); byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 0;// ALLOK int pos = 9; String[] item = info.split(":"); if (item.length > 1) { int num = Integer.parseInt(item[0]); int val = Integer.parseInt(item[1]); mBuffer[pos++] = (byte) (num >> 8); mBuffer[pos++] = (byte) (num & 0xff); mBuffer[pos++] = (byte) val; } VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.serialNo = serialNumber; serialNumberInc(); it.ansCount = 1; it.data = mBuffer; addToSendQueen(it); } else if (ansType == AnsType_BatchNumber) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 0;// ALLOK String[] item = info.split(":"); if (item.length > 1) { String[] itIndex = item[0].split("_"); if (itIndex.length == 2) { //综合测评 int personId = Integer.parseInt(itIndex[0]); int projectId = Integer.parseInt(itIndex[1]); mBuffer[9] = (byte) personId; mBuffer[10] = (byte) projectId; } else { int num = Integer.parseInt(item[0]); mBuffer[9] = (byte) (num >> 8); mBuffer[10] = (byte) (num & 0xff); } String strNum = item[1]; byte[] val = util_encodeBCD(strNum.getBytes()); System.arraycopy(val, 0, mBuffer, 11, 4); } VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.serialNo = serialNumber; serialNumberInc(); it.ansCount = 1; it.data = mBuffer; addToSendQueen(it); } else if (ansType == AnsType_SelectOther) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 0;// ALLOK int pos = 9; String[] item = info.split(":"); if (item.length > 1) { int num = Integer.parseInt(item[0]); String val = item[1]; mBuffer[pos++] = (byte) (num >> 8); mBuffer[pos++] = (byte) num; mBuffer[pos++] = 0;// slot try { byte[] name = val.getBytes("GB2312"); System.arraycopy(name, 0, mBuffer, pos, name.length > 16 ? 16 : name.length); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 名字最多16 } VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.serialNo = serialNumber; serialNumberInc(); it.ansCount = 1; it.data = mBuffer; addToSendQueen(it); } else if (ansType == AnsType_Service) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 4; int serv_type = Integer.parseInt(info); mBuffer[9] = (byte) serv_type; mBuffer[10] = (byte) serialNumber; VoteResultItem it = new VoteResultItem(); serviceSerialNumber = serialNumber; it.status = 0; it.ansType = ansType; it.serialNo = serialNumber; serialNumberInc(); it.ansCount = 1; it.data = mBuffer; addToSendQueen(it); } } private int ChoiceValueToInt(String val) { int ret = 0; for (int i = 0; i < val.length(); i++) { char cc = val.charAt(i); if (cc < 'I') { ret |= 1 << (8 + (cc - 'A')); } else { ret |= 1 << (cc - 'I'); } } return ret; } public void submitVoteFource(int ansType, String info) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) serialNumber;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 0;// ALLOK int pos = 9; String[] item = info.split(":"); if (item.length > 1) { int num = Integer.parseInt(item[0]); String val = item[1]; mBuffer[pos++] = (byte) (num >> 8); mBuffer[pos++] = (byte) num; mBuffer[pos++] = 0;// slot try { byte[] name = val.getBytes("GB2312"); System.arraycopy(name, 0, mBuffer, pos, name.length > 16 ? 16 : name.length); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 名字最多16 } VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.serialNo = serialNumber; serialNumberInc(); it.ansCount = 1; it.data = mBuffer; addToSendQueen(it); } @Override public void submitVoteAllOK() { int allokSerialNum = 0xff; byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) allokSerialNum;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) AnsType_BatchSingle; mBuffer[8] = 1;// ALLOK VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = AnsType_BatchSingle; it.serialNo = allokSerialNum; allOkSerialNumber = allokSerialNum; it.ansCount = 1; it.allOK = 1; it.data = mBuffer; addToSendQueen(it); } public void submitVoteAllOKWithValue(int ansType, String info) { LogUtil.i(TAG,"ansType:" + ansType + ",info:" + info); int allokSerialNum = 0xff; byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) allokSerialNum;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) ansType; mBuffer[8] = 1;// ALLOK String[] item = info.split(":"); if (item.length > 1) { String[] itIndex = item[0].split("_"); if (itIndex.length == 2) { //综合测评 int personId = Integer.parseInt(itIndex[0]); int projectId = Integer.parseInt(itIndex[1]); mBuffer[9] = (byte) personId; mBuffer[10] = (byte) projectId; } else { int num = Integer.parseInt(item[0]); mBuffer[9] = (byte) (num >> 8); mBuffer[10] = (byte) (num & 0xff); } String strNum = item[1]; byte[] val = util_encodeBCD(strNum.getBytes()); System.arraycopy(val, 0, mBuffer, 11, 4); } VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = ansType; it.serialNo = allokSerialNum; allOkSerialNumber = allokSerialNum; it.ansCount = 1; it.allOK = 1; it.data = mBuffer; addToSendQueen(it); } @Override public void cancelSubmitVoteAllOK() { int cancelAllokSerialNum = 0xfe; byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) cancelAllokSerialNum;// 流水号 mBuffer[6] = 1;// MSGTYPE 1:ID mode, 2:SN mBuffer[7] = (byte) AnsType_BatchSingle; mBuffer[8] = 0;// ALLOK VoteResultItem it = new VoteResultItem(); it.status = 0; it.ansType = AnsType_BatchSingle; it.serialNo = cancelAllokSerialNum; it.ansCount = 1; it.allOK = 0; it.data = mBuffer; addToSendQueen(it); //serialNumber=0; } private void serialNumberInc() { serialNumber++; if (serialNumber == 0xfe) { serialNumber = 0; } } @Override public void submitSelectOther(String info) { // TODO Auto-generated method stub } @Override public void submitVoteBySn(byte[] keySn, String info) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = 0x08;// 流水号 mBuffer[6] = 2;// MSGTYPE mBuffer[7] = 1;// ANSTYPE System.arraycopy(keySn, 0, mBuffer, 8, 6);// keysn // System.arraycopy(ansData, 0, mBuffer, 8, // ansData.length<=16?ansData.length:16); // info??? writeToCom(mBuffer); } @Override public void sendCmdData(int cmdId, byte[] data) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = (byte) 0xB0;// 0x30 表决器下载单包类指令 mBuffer[5] = 0x0;// keyid 填 0 mBuffer[6] = 0x0;// keyid mBuffer[7] = (byte) cmdId;// KCMD System.arraycopy(data, 0, mBuffer, 8, data.length);// keysn writeToCom(mBuffer); } @Override public void configMode() { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x09; writeToCom(mBuffer); } private byte[] firmFileBuffer; private int firmWritePage; private int firmWritePageMax; @Override public void startFirmUpdate(byte[] fileBuffer) { firmFileBuffer = fileBuffer; compareCount = 0 ; taskHandler.post(updateTask); } private void keepFirmMode() { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 10; mBuffer[4] = 0x78; mBuffer[5] = 0x02; writeToCom(mBuffer); } private void eraseFlash() { int file_len = firmFileBuffer.length; byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 10; mBuffer[4] = 0x78; mBuffer[5] = 0x03; mBuffer[6] = 0; mBuffer[7] = (byte) (file_len / 1024); writeToCom(mBuffer); } private Runnable updateTask = new Runnable() { @Override public void run() { firmWritePage = 0; firmWritePageMax = firmFileBuffer.length / 32; if (firmWritePageMax % 32 > 0) { firmWritePageMax++; } byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 10; mBuffer[4] = 0x78; mBuffer[5] = 0x01; writeToCom(mBuffer); if(compareCount < 20){ compareCount++; taskHandler.postDelayed(this,1000); } } }; private void writeFlash(int page) { byte[] mBuffer = new byte[38 + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 38; mBuffer[4] = 0x78; mBuffer[5] = 0x04; mBuffer[6] = (byte) (page / 256); mBuffer[7] = (byte) (page % 256); int pos = 0; for (int i = 0; i < 32; i++) { pos = page * 32 + i; if (pos == firmFileBuffer.length - 1) { break; } mBuffer[8 + i] = firmFileBuffer[pos]; } LogUtil.d(TAG, "write flash page:" + page); writeToCom(mBuffer); } /* * status 1: success 2 : fail */ private void exitFirmUpdate(int status) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 10; mBuffer[4] = 0x78; mBuffer[5] = 5; mBuffer[6] = (byte) status; writeToCom(mBuffer); } private void writeToCom(byte[] data) { if (mOutputStream != null) { try { int crcValue = Crc16.getUnsignedShort(Crc16.crc16(data, data.length - 4 - 2)); data[data.length - 2] = (byte) (crcValue >> 8); data[data.length - 1] = (byte) (crcValue); if (isShowLog) { if (data[4] == 0x70 && data[5] == 0x07) { // LogUtil.d(TAG, "check online"); if (isShowOnlineLog) { printDataBuf(data, data.length, "send:"); } } else { printDataBuf(data, data.length, "send:"); } } mOutputStream.write(data); } catch (IOException e) { e.printStackTrace(); } m_listener.onSendData(data, data.length); } } private byte[] SerDataRx = new byte[1024]; int iSerRxN = 0; private byte[] comBuffer = new byte[1024]; private class ReadThread extends Thread { @Override public void run() { super.run(); LogUtil.d(TAG, "Xpad ReadThread running "); if (mInputStream != null) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] bytes = new byte[1024]; int tmpLength = -1; while (!isInterrupted()) { try { // tmpLength = mInputStream.read(bytes); bytes = UsbTransferManager.getInstance().receiveUsbRequestData(); if(bytes == null){ continue; } tmpLength = bytes.length; if (tmpLength < 0) { break; } // 1. 先检测读取数据到缓冲区 byteArrayOutputStream.write(bytes, 0, tmpLength); // 2. 判断缓冲区的数据标志是否存在 if (byteArrayOutputStream.size() >= 3) { byte[] temp = byteArrayOutputStream.toByteArray(); int find = ByteUtils.findBytes(temp, new byte[]{(byte) 0xF5, (byte) 0xAA, (byte) 0xAA}, 0); if (find >= 0) { // 3. 标志存在,则继续读取长度 if (byteArrayOutputStream.size() >= find + 4) { int length = ByteUtils.byte1ToInt(byteArrayOutputStream.toByteArray()[find + 3]); if (byteArrayOutputStream.size() >= find + 4 + length) { ByteArrayOutputStream tmp = new ByteArrayOutputStream(); // 4. 根据长度读取包的内容 for (int i = find; i < find + 4 + length; i++) { // 5. 截取包的内容,向外抛出,处理,接着读取下一个包 tmp.write(temp[i]); } //CRC 校验 byte[] datas = tmp.toByteArray(); LogUtil.i(TAG, "RECEIVER DATA:", datas); try { //处理 if(Crc16.checkPack(datas)){ int crc = Crc16.getUnsignedShort(Crc16.crc16(datas,length - 2)); int originCrcValue = 0; originCrcValue |= (datas[length + 2] & 0xff) << 8; originCrcValue |= datas[length + 3] & 0xff; if(crc == originCrcValue){ checkComData(datas, tmp.size()); } } } catch (Exception ex) { LogUtil.i(TAG, "处理命令出错:", ex); } // 7. 剩余数据重新打包处理 // byteArrayOutputStream = new ByteArrayOutputStream(); byteArrayOutputStream.reset(); for (int i = find + 4 + length; i < temp.length; i++) { byteArrayOutputStream.write(temp[i]); } } } } } if (byteArrayOutputStream.size() > 2048) { LogUtil.i(TAG, "被恶意攻击?或者传输数据错误?丢弃处理!", byteArrayOutputStream.toByteArray()); byteArrayOutputStream.reset(); } } catch (Exception e) { LogUtil.e(TAG, e); } } } } @SuppressLint("NewApi") private void checkComData(byte[] data, int size) { m_listener.onComData(data, size); int cmd = data[4] & 0xFF; switch (cmd) { case CMD_CHECK_BASE_STATUS_RESPONSE:// 查询状态类指令应答 int cmd1 = data[5] & 0xFF; if (cmd1 == 1) {// 返回当前工作模式和版本 ModelInfo info = new ModelInfo(); info.mode = data[6]; info.hModel = data[7] & 0xff; info.sVer = data[8] + "." + data[9] + "." + data[10]; m_listener.onModelEvent(info); } else if (cmd1 == 3) { // 查询基础信标 结果 onBaseInfo(data); } else if (cmd1 == 4) { // 查询投票信标 结果 onVoteInfo(data); } else if (cmd1 == 5 || cmd1 == 6) {// 返回当前键盘参数结果 info.ok = data[6]; info.chan = data[7]; info.keyId = ((data[8] & 0xff) << 8) | (data[9] & 0xff); byte[] sn = Arrays.copyOfRange(data, 10, 16); info.keySn = getKeySn(sn); byte[] mc = Arrays.copyOfRange(data, 16, 19); info.matchCode = new String(mc); m_listener.onKeyPadEvent(info); // if(!hasGetBaseInfo){ //第一次启动时取 // hasGetBaseInfo = true; // getBaseStatus(); // } } else if (cmd1 == 7) {// 查询键盘在线状态结果 OnLineInfo info = new OnLineInfo(); info.onLine = data[6]; info.idMode = data[7]; info.chan = data[8] & 0xff; info.rssi = data[9] & 0xff; LogUtil.i(TAG ,"HEART BEAT(R):" + info.chan + " " + System.currentTimeMillis()); info.tx = data[10]; info.rx = data[11]; info.baseId = data[12] & 0xff; info.keyId = ((data[13] & 0xff) << 8) | (data[14] & 0xff); RFFileUploadModule.getInstance().setKeyid(data,13); byte[] sn = Arrays.copyOfRange(data, 15, 21); info.keySn = getKeySn(sn); m_listener.onOnLineEvent(info); onLineInfo = info; } else if (cmd1 == 8 || cmd1 == 9) { info.cmd1 = cmd1; info.ok = data[6]; info.chan = data[7]; info.keyId = ((data[8] & 0xff) << 8) | (data[9] & 0xff); byte[] sn = Arrays.copyOfRange(data, 10, 16); info.keySn = getKeySn(sn); byte[] mc = Arrays.copyOfRange(data, 16, 19); info.matchCode = new String(mc); m_listener.onKeyPadEvent(info); } break; case CMD_BASE_STATUS_CHANGE:// 基础信标变化(主动下发) responseBaseStatusChange(data, size); onBaseInfo(data); break; case CMD_VOTE_STATUS_CHANGE:// 投票信标变化 responseVoteStatusChange(data, size); clearSentItems(); onVoteInfo(data); break; case CMD_UPLOAD_DATA_RESPONSE: // 上传文件指令 onMutilPacketRequest(data, size); break; case CMD_VOTE_RESULT_SEND_RESPONSE: // sendToModalSuccessResponse(data[5] & 0xff); break; case CMD_VOTE_SEND_SUCCESS_RESPONSE: responseVoteSendSuccess(data, size); break; case CMD_KEY_MANAGE:// 表决器管理类指令,单包,透传 CmdDataInfo info = new CmdDataInfo(); info.cmd = data[7]; info.data = Arrays.copyOfRange(data, 8, 28); if (info.cmd == 25) { int keyId = (data[5] << 8) | data[6]; if (keyId != 0) { responseClearKeyboardData(data, size); } } else if (info.cmd == 20) { int keyId = (data[5] << 8) | data[6]; if (keyId == onLineInfo.keyId) { responseAuthrizeKeyboardData(data, size); } else { break; } }else if(info.cmd == 50){ responseAuthrizeKeyboardData(data,size); } m_listener.onCmdData(info); break; case CMD_MULTI_PCKAGE_DOWNLOAD: onMultiPackageInfo(data, size); break; case CMD_COM_COMMUNICATION_TEST_RESPONSE: int sendn = data[8] & 0xff; boolean isOk = true; for (int i = 1; i < 17; i++) { if (data[10 + i] != i) { isOk = false; } } m_listener.onComCommunicationTest(sendn, isOk); break; case CMD_FIRM_UPDATE_RESPONSE: taskHandler.removeCallbacks(updateTask); switch (data[5]) { case 2:// '模块询问是否进入DFU keepFirmMode(); try{ Thread.sleep(1000); }catch (Exception ex){} eraseFlash(); break; case 3:// 擦除应答 if (data[8] != 1) { LogUtil.e(TAG, "eraseFlash fail"); m_listener.onFirmUpdateResult(false, "擦除固件失败!"); break; } LogUtil.e(TAG, "eraseFlash ok"); m_listener.onFirmUpdateInfo("擦除固件完成,开始写入..."); CheckFirmReceveThread checkFirmThread = new CheckFirmReceveThread(); checkFirmThread.start(); writeFrimPageErrCnt = 0; writeFlash(firmWritePage); break; case 4:// 写应答 if (data[8] == 1) { firmWritePage++; writeFrimPageErrCnt = 0; if (firmWritePage < firmWritePageMax) { m_listener.onFirmUpdate(firmWritePage * 100 / firmWritePageMax); LogUtil.d(TAG, "write page ok! " + firmWritePage + "/" + firmWritePageMax + " ==" + firmWritePage * 100 / firmWritePageMax + "%"); //sleep(500); writeFlash(firmWritePage); } else { m_listener.onFirmUpdateInfo("写入完成"); m_listener.onFirmUpdate(100); LogUtil.i(TAG, "write 100%"); sleep(2000); exitFirmUpdate(1); LogUtil.i(TAG, "exitFirmUpdate"); m_listener.onFirmUpdateResult(true, null); } } else { LogUtil.d(TAG, "应答写失败 write page error"); } break; case 5: // 退出升级 LogUtil.d(TAG, "exit update!"); m_listener.onFirmUpdateInfo("退出升级模式成功!"); sleep(3000); LogUtil.d(TAG, "sleep 3s getWorkMode!"); for (int i = 0; i < 5; i++) { getWorkMode(); sleep(1000); } byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x70; mBuffer[5] = 0x03; writeToCom(mBuffer); break; default: break; } default: break; } } private void sleep(int ms) { try { Thread.sleep(ms); } catch (Exception e) { // TODO: handle exception } } //// 回应模块基础信标变化,模块停止重发,否则模块会不断发送 private void responseBaseStatusChange(byte[] data, int size) { byte[] retData = Arrays.copyOf(data, size); retData[4] = (byte) 0xF1; writeToCom(retData); } // 回应模块投票信标变化,模块停止重发,否则模块会不断发送 private void responseVoteStatusChange(byte[] data, int size) { final byte[] retData = Arrays.copyOf(data, size); retData[4] = (byte) 0xF2; writeToCom(retData); } // 回应发送成功通知 private void responseVoteSendSuccess(byte[] data, int size) { byte[] retData = Arrays.copyOf(data, size); retData[4] = (byte) 0xF3; writeToCom(retData); int serialNo = data[5] & 0xff; VoteResultItem ret = removeSentItem(serialNo); if (serialNo == allOkSerialNumber) { m_listener.onVoteSubmitAllOkSuccess(); allOkSerialNumber = -1; } else if (serialNo == serviceSerialNumber) { m_listener.onServiceSubmitSuccess(); serviceSerialNumber = -1; } else { if (ret != null) { m_listener.onVoteSubmitSuccess(ret); } } } //回复清空键盘数据 private void responseClearKeyboardData(byte[] data, int len) { byte[] retData = Arrays.copyOf(data, len); retData[4] = (byte) 0xB0; // retData[8] = 1; 修改原因:肖翔给的表达:人大的表决就是1,评分的是0 writeToCom(retData); } //回复键盘授权数据 private void responseAuthrizeKeyboardData(byte[] data, int len) { byte[] retData = Arrays.copyOf(data, len); retData[4] = (byte) 0xB0; writeToCom(retData); } } // 处理基础信标变化 private void onBaseInfo(byte[] data) { // Arrays.fill(broadcastData, (byte) 0x0);//清空多包结果 if(data != null){ baseSign = new byte[data.length]; System.arraycopy(data,0,baseSign,0,data.length); } BaseInfo info = new BaseInfo(); info.baseId = data[5] & 0xff;// baseID info.idMode = data[6] & 0xff; info.confId = ((data[7] & 0xff) << 8) | (data[8] & 0xff); info.billId = data[9] & 0xff; info.authCode = (data[10] & 0xff) << 8 | (data[11] & 0xff); info.login = data[12] & 0xff; info.report = data[13] & 0xff; info.offTime = data[14] & 0xff; info.attrib = data[15] & 0xff; info.pageNo = (data[16] & 0xff) << 8 | (data[17] & 0xff); byte[] bname = Arrays.copyOfRange(data, 16, 16 + 12); info.baseName = new String(bname); m_listener.onBaseEvent(info); } // 处理投票信标变化 private void onVoteInfo(byte[] data) { if(data != null){ voteSign = new byte[data.length]; System.arraycopy(data,0,voteSign,0,data.length); } byte[] dt = Arrays.copyOfRange(data, 4, data.length - 4 - 1);// 从len开始,和文档下标统一 VoteInfo info = new VoteInfo(); info.baseId = dt[1] & 0xff; info.nowT = dt[2] & 0xff << 8 | dt[3] & 0xff; info.dataPos = dt[4] & 0xff; info.mode = dt[5] & 0xff; info.mode1_msgType = dt[6] & 0xff; // if (info.mode != VoteType_Stop) { // serialNumber = 0; // } if (info.mode == VoteType_Stop) { // 停止 if (info.mode1_msgType == 2) { // 有结果 info.resultInfo.resultType = dt[7] & 0xff; info.resultInfo.bits = dt[8] & 0xff; info.resultInfo.num0 = (dt[9] & 0xff) << 8 | (dt[10] & 0xff); info.resultInfo.num1 = (dt[11] & 0xff) << 8 | (dt[12] & 0xff); info.resultInfo.num2 = (dt[13] & 0xff) << 8 | (dt[14] & 0xff); info.resultInfo.num3 = (dt[15] & 0xff) << 8 | (dt[16] & 0xff); info.resultInfo.num4 = (dt[17] & 0xff) << 8 | (dt[18] & 0xff); info.resultInfo.num5 = (dt[19] & 0xff) << 8 | (dt[20] & 0xff); info.resultInfo.num6 = (dt[21] & 0xff) << 8 | (dt[22] & 0xff); } } else if (info.mode == VoteType_BatchVote) { printDataBuf(data, data.length, "batchvote:"); info.less = dt[11] & 0xff; info.mode3_secret = dt[12] & 0xff; info.fixballot = dt[13] & 0xff ; if(info.fixballot > 0 ){ info.limitFavor = dt[14] & 0xff ; info.limitOppo = dt[15] & 0xff ; info.limitWaiver = dt[16] & 0xff ; }else{ info.limitFavor = 0 ; info.limitOppo = 0 ; info.limitWaiver = 0; } info.mode2_modify = dt[23] & 0xff; info.voteid = dt[21] & 0xff; } else if (info.mode == VoteType_Choice) { info.mode2_modify = dt[7] & 0xff; info.mode3_secret = dt[8] & 0xff; info.mode4 = dt[9] & 0xff; info.mode5 = dt[10] & 0xff; info.mode6 = dt[11] & 0xff; info.mode7 = dt[12] & 0xff; } else if (info.mode == VoteType_BatchElect) {//选举 info.electInfo.type = dt[6] & 0xff; info.electInfo.random = dt[7] & 0xff; info.electInfo.select = dt[8] & 0xff; info.electInfo.other = dt[9] & 0xff; info.electInfo.less = dt[10] & 0xff; info.electInfo.secrecy = dt[11] & 0xff; info.electInfo.modify = dt[12] & 0xff; info.electInfo.start = dt[13] & 0xff; info.electInfo.end = dt[14] & 0xff; info.electInfo.equityMode = dt[15] & 0xff; info.electInfo.minSelect = dt[16] & 0xff; info.electInfo.voteid = dt[21] & 0xff; } else if (info.mode == VoteType_SingleItemEvalue) {//单项评分 info.singleEvalueInfo.mode1 = dt[6] & 0xff; info.singleEvalueInfo.mode2 = dt[7] & 0xff; info.singleEvalueInfo.mode3 = dt[8] & 0xff; info.singleEvalueInfo.mode4 = dt[9] & 0xff; info.singleEvalueInfo.mode5 = dt[10] & 0xff; info.singleEvalueInfo.mode6 = dt[11] & 0xff; info.singleEvalueInfo.mode7 = dt[12] & 0xff; info.singleEvalueInfo.mode8 = dt[13] & 0xff; info.singleEvalueInfo.mode9 = dt[14] & 0xff; info.singleEvalueInfo.mode10 = dt[15] & 0xff; info.singleEvalueInfo.mode11 = dt[16] & 0xff; info.singleEvalueInfo.mode12 = dt[17] & 0xff; info.singleEvalueInfo.title = new byte[12]; System.arraycopy(dt, 12, info.singleEvalueInfo.title, 0, 12); info.voteid = dt[23] & 0xFF ; info.singleEvalueInfo.number = dt[24] & 0xff; } else if (info.mode == VoteType_BatchEvalue) { info.batchEvalueInfo.mode1 = dt[6] & 0xff; info.batchEvalueInfo.startVal = (dt[7] & 0xff) << 8 | (dt[8] & 0xff); info.batchEvalueInfo.endVal = (dt[9] & 0xff) << 8 | (dt[10] & 0xff); info.batchEvalueInfo.autoMove = dt[11] & 0xff; info.batchEvalueInfo.width1 = dt[12] & 0xff; info.batchEvalueInfo.width2 = dt[13] & 0xff; info.batchEvalueInfo.less = dt[14] & 0xff; info.batchEvalueInfo.secrecy = dt[15] & 0xff; info.batchEvalueInfo.modify = dt[16] & 0xff; info.batchEvalueInfo.ruleStart = dt[17] & 0xff; info.batchEvalueInfo.ruleEnd = dt[18] & 0xff; info.batchEvalueInfo.sliderover = dt[19] & 0xff; info.batchEvalueInfo.billNo = dt[20] & 0xff; info.batchEvalueInfo.billSubNo = ((dt[21] & 0xff) << 8) | (dt[22] & 0xff); } else if (info.mode == VoteType_BatchIDEvalue) { info.batchEvalueInfo.mode1 = dt[6] & 0xff; info.batchEvalueInfo.startVal = (dt[7] & 0xff) << 8 | (dt[8] & 0xff); info.batchEvalueInfo.endVal = (dt[9] & 0xff) << 8 | (dt[10] & 0xff); info.batchEvalueInfo.autoMove = dt[11] & 0xff; info.batchEvalueInfo.width1 = dt[12] & 0xff; info.batchEvalueInfo.width2 = dt[13] & 0xff; info.batchEvalueInfo.less = dt[14] & 0xff; info.batchEvalueInfo.secrecy = dt[15] & 0xff; info.batchEvalueInfo.modify = dt[16] & 0xff; info.batchEvalueInfo.ruleStart = dt[17] & 0xff; info.batchEvalueInfo.ruleEnd = dt[18] & 0xff; info.batchEvalueInfo.sliderover = dt[19] & 0xff; info.batchEvalueInfo.billNo = dt[20] & 0xff; info.batchEvalueInfo.billSubNo = ((dt[21] & 0xff) << 8) | (dt[22] & 0xff); } else { info.mode2_modify = dt[7] & 0xff; info.mode3_secret = dt[8] & 0xff; info.mode4 = dt[9] & 0xff; info.voteid = dt[11] & 0xff; info.file = dt[12] & 0xff; info.init = dt[13] & 0xff; } m_listener.onVoteEvent(info); } public void cleanSendQueue() { LogUtil.i(TAG,"cleanSendQueue"); synchronized (sendQueen){ LogUtil.i(TAG,"投票信标变化,清除已发队列"); for(VoteResultItem temp : sendQueen){ LogUtil.i(TAG,"清除数据",temp.data); } sendQueen.clear(); } } private byte[] broadcastData = new byte[4096]; private byte[] fileData; private int fileLen; private int dataLen; private int lastPackH = -1; private short needBits = 0; private int okBits = 0; private int currDownloadMsgId; private int broadMsgId = -1; private long lastOnMultiPackageDataTime; private int maxPackH; //用于计算收到长度 private int maxPachL; //用于计算收到长度 private int downType; private int downId; private boolean isMineDonwload = false ; /** * 字节 标识符 描述 * 1 DOWNCMD 0x40 下载多包类指令 * 2-3 KEYID 表决器编号,2字节,高位在前 * 一般要指定表决器编号使指定键盘进入或退出下载状态 * 但0x0000广播时候,键盘也执行 * FF01到FFFE时候,是用序列号指定键盘 V4.74 * 低位字节01-FE,表示下载次序,由SDK管理,新下载变化一次, * 键盘收到的时候,记录下,同时,此次序也出现在下载数据包中,这样键盘可判断是否是我可以下载的数据,避免上次下载状态没正常退出而错误接受数据 * 4 DOWNCMD 1 进入或退出下载状态 * 5 DOWNTYPE 多包类型 * 6 DOWNID 数据包标识码 * 7 DCMD 模式 1进入下载 0退出下载 * 8-24 FILENAME 在DOWNTYPE=40下载文件模式时候,是下载文件名称,16字符 * 其他模式参数无意义 * SN 序列号模式时候,6字节键盘序列号,用于指定键盘 * 暂不支持文件下载 * * @param data * @param size */ private void onMultiPackageInfo(byte[] data, int size) { byte[] dt = Arrays.copyOfRange(data, 3, data.length);// 从len开始,和文档下标统一 int downCmd = dt[4]; //1 进入或退出下载状态 int dcmd = dt[7];// 1:进入下载 0:退出下载 if (downCmd == 1) { // 1:进入/退出下载 resopnseMultiPackageMode(data, size); if (dcmd == 1) { //模式 1进入下载 int keyId = (data[5] << 8) | data[6]; if (keyId == onLineInfo.keyId || keyId == 0 || keyId == 0xFFFF) { // isMineDonwload = true; downType = dt[5];// 10即时信息 或 11短信 40 下载文件 downId = dt[6]; ////数据包标识码 LogUtil.d(TAG, " 1:进入下载 。。。。。downType = " + downType + " downId:" + downId); lastPackH = -1; if (downType == 40) { //下载文件模式 @Auther Elvis int packH = (dt[8] & 0xff); int packL = (dt[9] & 0xff); fileLen = packH * 256 + packL + 1; int len = 0; for (int i = 10; i < 26; i++) { if (dt[i] == 0) { break; } len++; } String fileName = "test.txt"; try { fileName = new String(dt, 10, len, "GB2312"); } catch (Exception e) { e.printStackTrace(); } dataLen = fileLen + 36; LogUtil.d(TAG, "下载文件,长度:" + fileLen + ", 文件名:" + fileName); if (fileLen > 0) { fileData = new byte[dataLen]; Arrays.fill(fileData, (byte) 0x0); } try { RFFileDownloadModule.getInstance().getDownloadProcess().setFileName(fileName); RFFileDownloadModule.getInstance().getDownloadProcess().setLength(fileLen - 4); RFFileDownloadModule.getInstance().getDownloadProcess().onStartDownload(); } catch (Exception e1) { } } else if (downType >= 1 && downType <= 3) { m_listener.onMultiPackageStartDownload(downType, downId); maxPackH = 0; maxPachL = 0; Arrays.fill(broadcastData, (byte) 0x0); } else { maxPackH = 0; maxPachL = 0; Arrays.fill(broadcastData, (byte) 0x0); } } } else { //0退出下载 int keyId = (data[5] << 8) | data[6]; if (keyId == onLineInfo.keyId || keyId == 0 || keyId == 0xFFFF) { isMineDonwload = false; LogUtil.d(TAG, dcmd + ": 退出下载。。。。。。。。。"); if (downType == 40) { //@Auther Elvis 添加文件下载逻辑 if (System.currentTimeMillis() - lastOnMultiPackageDataTime > 500) { lastOnMultiPackageDataTime = System.currentTimeMillis(); try { if (fileData != null) { File file = RFFileDownloadModule.getInstance().getDownloadProcess().getFile(); FileOutputStream fileOutputStream = new FileOutputStream(file); fileOutputStream.write(fileData, 0, fileLen - 4); fileOutputStream.flush(); fileOutputStream.close(); fileData = null; RFFileDownloadModule.getInstance().getDownloadProcess().onStopDownload(); } } catch (Exception ex) { LogUtil.e(TAG, ex); RFFileDownloadModule.getInstance().getDownloadProcess().onDownloadError(ex); } } } else if (downType >= 1 && downType <= 3) { if (System.currentTimeMillis() - lastOnMultiPackageDataTime > 500) { lastOnMultiPackageDataTime = System.currentTimeMillis(); LogUtil.d(TAG, "maxPackH:" + maxPackH + " maxPachL:" + maxPachL); broadcastData[0] = (byte) 0xF4; broadcastData[1] = (byte) 0xF5; broadcastData[2] = (byte) downType; broadcastData[3] = (byte) downId; m_listener.onMultiPackageData(broadcastData, (maxPackH + 1) * 16 + (maxPachL + 1) * 16 + 4); } } } } } else if (downCmd == 2) { // 2:下载数据 // if(isMineDonwload) { int msgid = (byte) dt[6] & 0xFF; byte packH = dt[7];// 数据段 编号 当前最大15(16片) byte packL = dt[8];// 数据片编号 LogUtil.d(TAG, "下载。。。msgId:" + msgid + " packH:" + packH + " apckL:" + packL); if (downType == 40) { // 文件下载 if (lastPackH != packH) { //新的packH LogUtil.i(TAG, "new packH......."); okBits = 0; lastPackH = packH; } int destPos = ((packH & 0xFF) * 16 + (packL & 0xFF)) * 16; if (destPos + 16 <= fileData.length) { System.arraycopy(dt, 9, fileData, destPos, 16); } if ((okBits & (1 << packL)) == 0) {// 添加文件下载逻辑 进度 RFFileDownloadModule.getInstance().getDownloadProcess().onDownloadAddProcess(16); } okBits |= (1 << packL); LogUtil.d(TAG, "packL:" + packL + " okBits:" + okBits); } else {// 广播 if (broadMsgId != msgid) { Arrays.fill(broadcastData, (byte) 0x0); broadMsgId = msgid; okBits = 0; } if (lastPackH != packH) { LogUtil.i(TAG, "new packH......."); needBits = calcBits(packH); okBits = 0; lastPackH = packH; maxPachL = 0; } if (packH > maxPackH) { maxPackH = packH; } if (packL > maxPachL) { maxPachL = packL; } if (downType >= 1 && downType <= 3) { System.arraycopy(dt, 9, broadcastData, (packH * 16 + packL) * 16 + 4, 16); } else { System.arraycopy(dt, 9, broadcastData, packL * 16, 16);//短信 packH 总共多少片, packL 第几片 } okBits |= (1 << packL); LogUtil.d(TAG, "packL:" + packL + " okBits:" + okBits + " needBits:" + (needBits & 0xffff) + " downType:" + downType); if (downType == 0 || downType > 3) { if (okBits == needBits) { if (broadMsgId != currDownloadMsgId) { m_listener.onMultiPackageData(broadcastData, (packH + 1) * 16); currDownloadMsgId = broadMsgId; } Arrays.fill(broadcastData, (byte) 0x0); broadMsgId = -1; lastPackH = -1; //okBits = 0; } } } // } } else if (downCmd == 3) { // 3:询问 resopnseMultiPackageQuery(data, size); LogUtil.d(TAG, " 3:询问。。。。。。。。。"); } } private short calcBits(byte packh) { short bits = 0; for (int i = 0; i <= packh; i++) { bits |= (1 << i); } return bits; } private void resopnseMultiPackageMode(byte[] data, int size) { byte[] retData = Arrays.copyOf(data, size); retData[4] = (byte) 0xC0; writeToCom(retData); } private void resopnseMultiPackageQuery(byte[] data, int size) { byte[] retData = Arrays.copyOf(data, size); retData[4] = (byte) 0xC0; int tmpOk = ~okBits; retData[11] = (byte) tmpOk; retData[12] = (byte) (tmpOk >> 8); writeToCom(retData); } public static String getVoteType(int mode) { switch (mode) { case VoteType_Stop: return "VoteType_Stop"; case VoteType_Signin: return "VoteType_Signin"; case VoteType_Vote: return "VoteType_Vote"; case VoteType_BatchVote: return "VoteType_BatchVote"; case VoteType_BatchElect: return "VoteType_BatchElect"; default: break; } return "" + mode; } public static String getKeySn(byte[] data) { String sn = ""; String CS = "0123456789ABCDEF"; for (int i = 0; i < 6; i++) { sn += CS.charAt((data[i] >> 4) & 0xF); sn += CS.charAt((data[i] >> 0) & 0xF); } return sn; } private long writeOkPageNo; private int compareCount; private class CheckFirmReceveThread extends Thread { public void run() { while (true) { try { Thread.sleep(2000); if (writeOkPageNo != firmWritePage) { writeOkPageNo = firmWritePage; //sendMessage(keypadID + ":recv"+lastReceveLength+"\n"); //LogUtil.d(TAG,"CheckReceveThread:check ok!"); compareCount = 0; } else { compareCount++; Thread.sleep(2000); if (compareCount <= 20) { LogUtil.d(TAG, "CheckWriteFirmhread:retry ==========="); m_listener.onFirmUpdateInfo("与入页:" + firmWritePage + "失败, 次数:" + compareCount); writeFlash(firmWritePage); } else { compareCount = 0; LogUtil.d(TAG, "CheckWriteFirmhread:fail , exit!"); LogUtil.e(TAG, "写入扇区" + firmWritePage + "失败!"); m_listener.onFirmUpdateResult(false, "写入扇区" + firmWritePage + "失败!"); exitFirmUpdate(2); break; } } if (firmWritePage > 0 && firmWritePage == firmWritePageMax) { LogUtil.d(TAG, "CheckWriteFirmhread:ok : exit!"); break; } } catch (InterruptedException e) { e.printStackTrace(); } } } } ; private static int encodeBCD(byte c) { if (c >= 'a' && c <= 'f') { return 10 + (c - 'a'); } else if (c >= '0' && c <= '9') { return c - '0'; } else if (c >= 'A' && c <= 'F') { return 10 + (c - 'A'); } else if (c == '.') { return 0xE; } return -1; } /** * 把字符串形式转换为字节形式 */ private byte[] util_encodeBCD(byte[] cs) { byte[] rs = new byte[17]; Arrays.fill(rs, (byte) 0xff);// int len = cs.length < 16 ? cs.length : 16; int io = 0; for (int i = 0; i < len; i += 2) { int n = encodeBCD(cs[i]); n <<= 4; if (i + 1 == cs.length) { rs[io++] = (byte) (n | 0xf); break; } n |= encodeBCD(cs[i + 1]); if (n < 0) { break; } rs[io++] = (byte) n; } rs[++io] = 0; return rs; } public static String util_decodeBCD(byte[] cs, int len) { byte[] buf = new byte[8 * 2]; Arrays.fill(buf, (byte) 0); String bcdNum = "0123456789ABCD.F"; String bcdStr = bytesToHexString(cs); for (int i = 0; i < len * 2; i += 2) { byte item = bcdStr.getBytes()[i]; if (item >= '0' && item <= '9') { buf[i] = item; } else if (item == 'E') { buf[i] = '.'; } else if (item == 'F') { buf[i] = 0; break; } item = bcdStr.getBytes()[i + 1]; if (item >= '0' && item <= '9') { buf[i + 1] = item; } else if (item == 'E') { buf[i + 1] = '.'; } else if (item == 'F') { buf[i + 1] = 0; break; } } return new String(buf).trim(); } public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString().toUpperCase(); } /** * @param length 长度 * @param filename 文件名 * @Auther Elvis * 主动发起文件申请 */ public void applyFileUpload(int length, String filename, byte anstype,byte index) { byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = 0x73; mBuffer[5] = (byte) 0XFF;// 流水号 mBuffer[6] = (byte) 0X01;// 流水号 mBuffer[7] = (byte) 15;// MSGTYPE mBuffer[8] = (byte) anstype;// ANSTYPE 添加5 文件上传指令 mBuffer[9] = index;// 高位 // mBuffer[10] = (byte) length;// 低位 // byte[] bytes = new byte[16]; // try { // if (filename != null) { // bytes = filename.getBytes("GB2312"); // } // } catch (UnsupportedEncodingException e) { // e.printStackTrace(); // } // // if (bytes != null) { // for (int i = 0; i < 16 && i < bytes.length; i++) { // mBuffer[11 + i] = bytes[i]; // } // } writeToCom(mBuffer); } /** * @param keyid 键盘id * @param packid 包id * @param packH 段id * @param packL 片id * @param datas 数据 * @Auther Elvis */ public void uploadFileData(byte[] keyid, byte packid, byte packH, byte packL, byte[] datas, byte packtype) { uploadFileData(keyid, packid, packH, packL, datas, 0, datas.length, packtype); } /** * @param keyid 键盘编号 * @param packid 包id * @param packH 数据段id * @param packL 数据片id * @param datas 数据 * @param offset 偏移位置 * @param length 长度 * @Auther Elvis * 上传数据包(多包应答) */ public void uploadFileData(byte[] keyid, byte packid, byte packH, byte packL, byte[] datas, int offset, int length, byte packtype) { LogUtil.i(TAG, "onMutilPacketData packid=" + packid + ",packH=" + packH + ",packL=" + packL + ",offset=" + offset); byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = (byte) 0xA0; if(keyid == null || keyid.length < 2){ if(onLineInfo != null){ keyid[0] = (byte)((onLineInfo.keyId >> 8 ) & 0xFF) ; keyid[1] = (byte)((onLineInfo.keyId ) & 0xFF) ; }else{ keyid = new byte[2]; } } mBuffer[5] = keyid[0]; mBuffer[6] = keyid[1]; mBuffer[7] = 2;//CMD 1 回应多包数据 mBuffer[8] = packtype;//PACKTYPE 多包类型 mBuffer[9] = packid;//数据包标识码 mBuffer[10] = packH;//数据段编号 mBuffer[11] = packL;//数据片编号 for (int i = 0; i < length && i < 16 && i < datas.length - offset; i++) { mBuffer[12 + i] = datas[offset + i]; } writeToCom(mBuffer); } /** * @param packid 包id * @Auther Elvis * 多包接收确认(多包接收应答) */ public void packetConfirmation(byte[] keyid, byte packid, byte packH, byte packL, byte[] names, byte packtype) { LogUtil.i(TAG, "onMutilPacketRespone packid=" + packid + ",packH=" + packH + ",packL=" + packL + ",names=" + names); byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = (byte) 0xA0; if(keyid == null || keyid.length < 2){ if(onLineInfo != null){ keyid[0] = (byte)((onLineInfo.keyId >> 8 ) & 0xFF) ; keyid[1] = (byte)((onLineInfo.keyId ) & 0xFF) ; }else{ keyid = new byte[2]; } } mBuffer[5] = keyid[0]; mBuffer[6] = keyid[1]; mBuffer[7] = 1;//CMD 1 mBuffer[8] = packtype;//PACKTYPE 多包类型 mBuffer[9] = packid;//数据包标识码 mBuffer[10] = packH; mBuffer[11] = packL; if (names != null) { for (int i = 0; i < 14 && i < names.length; i++) { mBuffer[12 + i] = names[i]; } } writeToCom(mBuffer); } /** * @param packid 包id * @param packH 数据段id * @Auther Elvis * 多包接收完毕确认(多包接收完毕确认应答) */ public void packetReceptionConfirmed(byte[] keyid, byte packid, byte packH, byte packtype) { LogUtil.i(TAG, "onMutilPacketRespone packid=" + packid + ",packH=" + packH); byte[] mBuffer = new byte[0x1F + 4]; Arrays.fill(mBuffer, (byte) 0x0); mBuffer[0] = (byte) 0xF5; mBuffer[1] = (byte) 0xAA; mBuffer[2] = (byte) 0xAA; mBuffer[3] = (byte) 0x1F; mBuffer[4] = (byte) 0xA0; if(keyid == null || keyid.length < 2){ if(onLineInfo != null){ keyid[0] = (byte)((onLineInfo.keyId >> 8 ) & 0xFF) ; keyid[1] = (byte)((onLineInfo.keyId ) & 0xFF) ; }else{ keyid = new byte[2]; } } mBuffer[5] = keyid[0]; mBuffer[6] = keyid[1]; mBuffer[7] = 3;//CMD 3 多包接收完毕应答 mBuffer[8] = packtype;//PACKTYPE 多包类型 mBuffer[9] = packid;//数据包标识码 writeToCom(mBuffer); } /** * @param datas 基站传递过来的数据 * @param length 长度 * @Auther Elvis */ public void onMutilPacketRequest(byte[] datas, int length) { LogUtil.i(TAG ,"onMutilPacketRequest",datas); byte[] keyid = new byte[2]; keyid[0] = datas[5]; keyid[1] = datas[6]; byte packid = datas[9]; byte packH = datas[10]; byte[] packLs = new byte[2]; packLs[0] = datas[11]; packLs[1] = datas[12]; int keyId = (keyid[0] << 8) | keyid[1]; if (keyId == onLineInfo.keyId) { if (datas[8] == 5) { RFFileUploadModule.getInstance().onUploadFile(datas[7], keyid, packid, packH, packLs); } if (datas[8] == 3) { RFMessageUploadModule.getInstance().onUploadMessage(datas[7], keyid, packid, packH, packLs); } } } public void openSendData(byte[] datas){ writeToCom(datas); } }