无法通过USB-OTG

时间:2017-07-23 17:21:32

标签: java android arduino apdu usbserial

我想创建一个项目/安卓应用程序,可以将命令传输到arduino并通过USB-OTG接收响应。规格如下:

  1. android app将命令(以字节数组形式)发送到arduino,
  2. arduino收到,命令提示arduino向应用程序发送响应(也以字节数组形式),
  3. 应用程序收到响应,提示它发送另一个命令,
  4. 反复执行此操作,直到arduino发送最终响应,其中包含我希望Android应用程序显示的数据(例如余额,交易金额等)
  5. 用户只需按一下按钮(在应用程序上),就需要自动完成整个过程。

    这个项目基本上是一个智能卡读卡器模拟器(它是一个模拟器,因为APDU响应被硬编码到arduino代码中,因此整个系统不需要实际的智能卡和读卡器。)

    问题的描述如下,其后是问题。这很长,所以请耐心等待。

    我修改的java代码是:

     UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
        @Override
        public void onReceivedData(byte[] arg0) {
    
            //the part that I modified :
            String balance = "";
            try{
                if ((arg0[0] == (byte) 0x50) && (arg0[1] == (byte) 0x33)) {
                    byte[] CMD2 = {0x00,(byte)0xA2,0x00,0x00,0x05,0x41,0x00};
                    serialPort.write(CMD2);
                }
                else if ((arg0[0] == (byte) 0x50) && (arg0[1] == (byte) 0x44)) {
                    byte[] CMD3 = {0x00,(byte)0xA2,0x00,0x00,0x05,0x41,0x11};
                    serialPort.write(CMD3);
                }
                else if ((arg0[0] == (byte) 0x50) && (arg0[1] == (byte) 0x1C)) {
                    byte[] CMD4 = {0x00,(byte)0xD1,0x00,0x00,0x10};
                    serialPort.write(CMD4);
                }
                else if (arg0[0] == (byte) 0xC5) {
    
                    byte[] bufferData = PickData(arg0, 8);
                    balanceData = bytesToLong(bufferData);
                    balance = Long.toString(balanceData);
                    balanceView.setText(balance);
                }
                else{
                    balanceView.setText("Balance Check Failed! Click Refresh");
                }
            }catch (Exception e) {
                e.printStackTrace();}
    
    
        }
    
    };
    /* The part that I added */
    //Picks the balance data from the final response.
    public static byte[] PickData(byte[] bytes, int lengthb) {
        byte[] buffer= new byte [lengthb];
        for (int i = 0; i < lengthb; i++) {
            if((bytes[i+1]==0xB0)||(bytes[i+1]==0x90))
                buffer[i] = 0;
            else
                buffer[i] = bytes[1+i];
        }
        return buffer;
    }
    
    
    //converts array of byte into long. 
    public static long bytesToLong(byte[] Data) {
        long value=0;
        for (int i = 0; i < Data.length; i++)
        {
            value = (value << 8) + (Data[i] & 0xff);
        }
        return value;
    }
    

    这是arduino代码:

    #include <SoftwareSerial.h>
    #define RX 3
    #define TX 5
    int c;
    SoftwareSerial usbdevice=SoftwareSerial(RX,TX);
    byte command[11];
    
    //Hard-coded responses
    byte response1[] = {0x50,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    byte response2[] = {0x50,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    byte response3[] = {0x50,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    //0x2710 is the balance data. It will be translated to long then to string, which is 10000.
    byte response4[] = {0xC5,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x10,0x90,0x00}; 
    
    String str; //only for serial monitor viewing
    byte response[11];  // to be printed on Serial Monitor
    
    void setup() {
      pinMode(RX,INPUT);
      pinMode(TX,OUTPUT);
      Serial.begin(115200);
      usbdevice.begin(9600);
      Serial.println("Arduino Reader Simulation Start: ");
    }
    
    void loop() 
    {
      //Reads the command from android
      if(usbdevice.available()>0)
      {
        c=0;
        delay(15);
        while(1)
        {
          if(usbdevice.available()>0)
          {
            command[c] = usbdevice.read();
            c++;
          }
          else
            break;
        }
     //Checks the command byte-per-byte then sends the response 
     for(c=0;c<11;c++)
        {
          if((command[0] == 0x00)&&(command[1] == 0xA2)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x05)&&(command[5] == 0x4e)&&(command[6] == 0x00)){
            usbdevice.write(response1[c]);
            response[c] = response1[c];
          }
          else if((command[0] == 0x00)&&(command[1] == 0xA2)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x05)&&(command[5] == 0x41)&&(command[6] == 0x00)){
            usbdevice.write(response2[c]);
            response[c] = response2[c];
          }
          else if ((command[0] == 0x00)&&(command[1] == 0xA2)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x05)&&(command[5] == 0x41)&&(command[6] == 0x11)){
            usbdevice.write(response3[c]);
            response[c] = response3[c];
          }
          else if((command[0] == 0x00)&&(command[1] == 0xD1)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x10)){
            usbdevice.write(response4[c]);
            response[c] = response4[c];
          }
        }
        //Prints each command and it's response.
        printAll();
      }
    }
    

    在测试这些代码时,我遇到了一些问题:

    1. 起初我没有使用try-catch。经过测试,每当我尝试发送第一个命令时,应用程序都会崩溃。当我尝试使用try-catch时,应用程序不再崩溃,但第二个问题出现了(我从未使用过try-catch,所以我不知道它的目的以及如何正确使用它。)
    2. 有时,应用程序成功显示了余额,但大部分时间都失败了。成功的过程:

          Command: 
      0 a2 0 0 5 4e 0 0 0 0 0 
      Response: 
      50 33 0 0 0 0 0 0 0 0 0 
      Command: 
      0 a2 0 0 5 41 0 0 0 0 0 
      Response: 
      50 44 0 0 0 0 0 0 0 0 0 
      Command: 
      0 a2 0 0 5 41 11 0 0 0 0 
      Response: 
      50 1c 0 0 0 0 0 0 0 0 0 
      Command: 
      0 d1 0 0 10 41 11 0 0 0 0 
      Response: 
      c5 0 0 0 0 0 0 27 10 90 0 
      

      失败的过程:

      //First attempt
      Command: 
      0 a2 0 0 5 4e 0 0 0 0 0 
      Response: 
      50 33 0 0 0 0 0 0 0 0 0 
      Command: 
      48 10 50 e0 5 4e 0 0 0 0 0 
      Response: 
      50 33 0 0 0 0 0 0 0 0 0 
      
      //Second attempt
      Command: 
      0 a2 0 0 5 4e 0 0 0 0 0 
      Response: 
      50 33 0 0 0 0 0 0 0 0 0 
      Command: 
      0 a2 0 0 5 41 0 0 0 0 0 
      Response: 
      50 44 0 0 0 0 0 0 0 0 0 
      Command: 
      0 a2 0 0 5 41 11 0 0 0 0 
      Response: 
      50 1c 0 0 0 0 0 0 0 0 0 
      Command: 
      0 d1 0 20 5 41 11 0 0 0 0 
      Response: 
      50 1c 0 0 0 0 0 0 0 0 0 
      
    3. 从失败的过程中可以看出,从android发送到arduino的命令字节与java代码中的硬编码字节不同。不知何故,android会随机发送随机字节作为命令,从而停止进程并显示“失败”消息。我不知道为什么会发生这种情况。我的理解是,如果我不使用try-catch,这可能是导致崩溃的原因。

      根据上述问题的详细信息,我的问题是:

      1。如何解决崩溃问题以及“随机更改命令数据”问题?

      2。有没有其他方法像这样顺序传输数据但实际上有效吗?

      提前谢谢你。

      P.S。 我怀疑其中一个问题是由java代码中的函数PickData引起的,因为当我禁用它时,应用程序几乎从未失败过显示某些东西,尽管它总会显示一些随机数(如果我很幸运,应用程序可能会显示余额数据)。这个随机改变的字节数据是我非常困惑的。

      我正在使用本教程作为参考: https://www.allaboutcircuits.com/projects/communicate-with-your-arduino-through-android/

      我还使用Github用户felHR85的USB串行库(如上面的教程中所使用的)。链接:https://github.com/felHR85/UsbSerial/

0 个答案:

没有答案