Bluetooth Android SPP, send commands in series to device?

user1324818 picture user1324818 · Apr 10, 2012 · Viewed 10.2k times · Source

----------------------edit--------------------------
A little progress, not a solution though. If I insert the following code in between the commands I want to send, at least the commands are allowed to have time to process on the remote end (however this is still not the right way to do this, the right way would be to wait for response ">" before sending another command)...

android.os.SystemClock.sleep(150);

The listener thread is blocked though during while the systemclock is sleeping, so the input from the modem doesn't get appended to the text view until after the sequence of codes has been sent, which is less than desirable. Again though, sleep is not the right way to do it, and I need to find a better way so I don't send a new command until the ">" result comes back from the device on the other end. When I'm done with this code I will need a way to handle the input either way, so the sleep really isn't progress if I think about it. Example of inserting the sleep:

    sendData("enable");
    android.os.SystemClock.sleep(150);
    sendData("password");        
    android.os.SystemClock.sleep(150); 
    sendData("conf t");        
    android.os.SystemClock.sleep(150);     
    sendData("interface eth0");        
    android.os.SystemClock.sleep(150);    
    //etc...etc...etc... 

----------------------original post below--------------------------

I'm working with this elegantly written piece of code from Matt Bell's blog, located here: http://bellcode.wordpress.com/2012/01/02/android-and-arduino-bluetooth-communication/

source located here: http://project-greengiant.googlecode.com/svn/trunk/Blog/Android%20Arduino%20Bluetooth

Without chopping up the code too badly, I'm trying to fit in a way to elegantly send commands serially to the attached modem, each time waiting until a complete response is received before sending the next command. (I know this is not the Android way of doing things, and I could handle this in a heartbeat using other languages).

Here's what I'm working with so far (you'll see I haven't made it very far, in fact this code works fantastically up until the point where I need to wait for the first command to complete before sending more commands). I omitted as much code as I could that doesn't pertain to this question. Thanks in advance.

    package Android.Arduino.Bluetooth;        

    import java.io.IOException;        
    import java.io.InputStream;        
    import java.io.OutputStream;        
    import java.util.Set;        
    import java.util.UUID;        
    import android.app.Activity;        
    import android.bluetooth.BluetoothAdapter;        
    import android.bluetooth.BluetoothDevice;        
    import android.bluetooth.BluetoothSocket;        
    import android.content.Intent;        
    import android.os.Bundle;        
    import android.os.Handler;        
    import android.widget.TextView;        


    public class BluetoothTest extends Activity        
    {        
        TextView myLabel;        
        BluetoothAdapter mBluetoothAdapter;        
        BluetoothSocket mmSocket;        
        BluetoothDevice mmDevice;        
        OutputStream mmOutputStream;        
        InputStream mmInputStream;        
        int counter;        
        Thread workerThread;        
        byte[] readBuffer;        
        int readBufferPosition;        
        volatile boolean stopWorker;        

        @Override        
        public void onCreate(Bundle savedInstanceState)        
        {        
            super.onCreate(savedInstanceState);        
            setContentView(R.layout.main);        

            myLabel = (TextView)findViewById(R.id.label);        

                        try         
                        {        
                            findBT();        
                            openBT();        
                            sendData("enable");        
                          //insert some code to wait for response before sending (or handle that in the above line, or otherwise)
                            sendData("password");        
                          //insert some code to wait for response before sending (or handle that in the above line, or otherwise)        
                            sendData("conf t");        
                          //insert some code to wait for response before sending (or handle that in the above line, or otherwise)        
                            sendData("interface eth0");        
                          //insert some code to wait for response before sending (or handle that in the above line, or otherwise)        
                          //etc...etc...etc...        
                        }        
                        catch (IOException ex) { }                            

        }        

        }        

        void openBT() throws IOException        
        {        
            UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID        
            mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);                
            mmSocket.connect();        
            mmOutputStream = mmSocket.getOutputStream();        
            mmInputStream = mmSocket.getInputStream();        
            beginListenForData();        
            myLabel.append("Bluetooth Opened" + "\n");        
        }        

        void beginListenForData()        
        {        
            final Handler handler = new Handler();         
            final byte delimiter = 62; //This is the ASCII code for a > character indicating all data received        

            stopWorker = false;        
            readBufferPosition = 0;        
            readBuffer = new byte[1024];              

            workerThread = new Thread(new Runnable()        
            {        
                public void run()        
                {                        

                while(!Thread.currentThread().isInterrupted() && !stopWorker)        
                   {        
                        try         
                        {        
                            int bytesAvailable = mmInputStream.available();                                
                            if(bytesAvailable > 0)        
                            {        
                                byte[] packetBytes = new byte[bytesAvailable];        
                                mmInputStream.read(packetBytes);        
                                for(int i=0;i<bytesAvailable;i++)        
                                {        
                                    byte b = packetBytes[i];        
                                    if(b == delimiter)        
                                    {        
                                        byte[] encodedBytes = new byte[readBufferPosition];        
                                        System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);        
                                        final String data = new String(encodedBytes, "US-ASCII");        
                                        readBufferPosition = 0;        

                                        handler.post(new Runnable()        
                                        {        
                                            public void run()        
                                            {                                                    
                                                myLabel.append(data);                                         
                                            }        
                                        });        
                                    }        
                                    else        
                                    {        
                                        readBuffer[readBufferPosition++] = b;        
                                    }        
                                }        
                            }        
                        }        
                        catch (IOException ex)         
                        {        
                            stopWorker = true;        
                        }        
                   }        

                }        
            });        

            workerThread.start();        
        }        

        void sendData(String msg0) throws IOException        
        {        
            msg0 += "\r";        
            mmOutputStream.write(msg0.getBytes());        
            myLabel.append("Data Sent" + "\n");        
        }        

    }        

Answer

Skye picture Skye · Jan 11, 2013

I recognize that this is a quite old question. However, since I'm developing a similar application, I solved it differently and it might help.

Instead of a delay between the sending you could implement a send/response logic via flags. So at the beginning the connection is initial. You send the enable and set your flag to enableRequested. Then you let your listener wait for the response. Once you have it continue with sending password, set the flag to passwordSent and release the thread again.

So I suggest to not do it in the onCreate but trigger a thread to connect from onCreate. That should work nicely.