ConnectedThread.java
Go to the documentation of this file.
00001 package com.riverlab.robotmanager.bluetooth;
00002 
00003 import java.io.IOException;
00004 import java.io.InputStream;
00005 import java.io.OutputStream;
00006 import java.lang.reflect.InvocationTargetException;
00007 import java.lang.reflect.Method;
00008 import java.nio.ByteBuffer;
00009 import java.text.SimpleDateFormat;
00010 import java.util.ArrayList;
00011 import java.util.Arrays;
00012 import java.util.Calendar;
00013 import java.util.Date;
00014 import java.util.List;
00015 import java.util.concurrent.TimeoutException;
00016 
00017 import com.riverlab.robotmanager.MainActivity;
00018 import com.riverlab.robotmanager.RobotManagerApplication;
00019 import com.riverlab.robotmanager.messages.RobotMessage;
00020 import com.riverlab.robotmanager.robot.Robot;
00021 import com.riverlab.robotmanager.voice_recognition.Vocabulary;
00022 import com.riverlab.robotmanager.voice_recognition.VoiceRecognitionThread;
00023 
00024 import android.bluetooth.BluetoothAdapter;
00025 import android.bluetooth.BluetoothDevice;
00026 import android.bluetooth.BluetoothSocket;
00027 import android.graphics.Bitmap;
00028 import android.graphics.BitmapFactory;
00029 import android.os.Bundle;
00030 import android.os.Handler;
00031 import android.os.HandlerThread;
00032 import android.os.Looper;
00033 import android.os.Message;
00034 import android.util.Log;
00035 
00036 public class ConnectedThread extends HandlerThread
00037 {
00038         private BluetoothAdapter mBluetoothAdapter;
00039         private BluetoothSocket mBtSocket;
00040         private InputStream mInStream;
00041         private OutputStream mOutStream;
00042         private RobotManagerApplication mApplication;
00043         private boolean isShutdown = false;
00044         private Object readWriteLock = new Object();
00045 
00046         public static final int CONNECT_MESSAGE = 0;
00047         public static final int DISCONNECT_MESSAGE = 1;
00048         public static final int WRITE_MESSAGE = 2;
00049         public static final int SHUTDOWN_MESSAGE = 3;
00050 
00051 
00052         private Handler mHandler = null;
00053         private Handler mainHandler;
00054         private Handler voiceHandler;
00055 
00056         Thread socketThread;
00057 
00058         public ConnectedThread(Handler mainHandler, RobotManagerApplication app) 
00059         {
00060                 super("Bluetooth Connection Thread");
00061                 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
00062                 mApplication = app;
00063 
00064                 socketThread = new Thread()
00065                 {
00066                         @Override
00067                         public void run()
00068                         {
00069                                 receivePackets();
00070                         }
00071                 };
00072         }
00073 
00074         @Override
00075         public void start()
00076         {
00077                 super.start(); 
00078 
00079                 mHandler = new Handler(getLooper()){
00080                         public void handleMessage(Message msg) 
00081                         {
00082                                 switch (msg.what)
00083                                 {
00084                                 case CONNECT_MESSAGE:
00085                                         String deviceName = (String)msg.obj;
00086                                         connect(deviceName);
00087                                         break;
00088                                 case DISCONNECT_MESSAGE:
00089                                         Log.d("ConnectedThread", "Disconnect request received");
00090                                         disconnect();
00091                                         break;
00092                                 case WRITE_MESSAGE:
00093                                         String msgText = (String)msg.obj;
00094                                         write(msgText.getBytes());
00095                                         break;
00096                                 case SHUTDOWN_MESSAGE:
00097                                         shutdown();
00098                                         break;
00099                                 }
00100                         }
00101                 };              
00102         }
00103 
00104         public synchronized boolean isReady()
00105         {
00106                 return mHandler != null;
00107         }
00108 
00109         public void setHandlers(Handler mainHandler, Handler voiceHandler) 
00110         {
00111                 this.mainHandler = mainHandler;
00112                 this.voiceHandler = voiceHandler;
00113         }
00114 
00115         public Handler getHandler()
00116         {
00117                 return mHandler;
00118         }
00119 
00120         public boolean connect(String deviceName)
00121         {
00122                 for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices())
00123                 {
00124                         if (device.getName().equals(deviceName))
00125                         {                               
00126                                 Log.d("RobotManagerBluetooth", "Attempting to connect to device");
00127                                 // Discovery is resource intensive.  Make sure it isn't going on
00128                                 // when you attempt to connect and pass your message.
00129                                 mBluetoothAdapter.cancelDiscovery();
00130 
00131                                 // Create a Rfcomm Socket between the Server and Glass
00132                                 Log.d("RobotManagerBluetooth", "Attempting to create Rfcomm Socket");
00133                                 Method m;
00134                                 try {
00135                                         m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); 
00136                                         mBtSocket = (BluetoothSocket) m.invoke(device, 1); 
00137                                         Log.d("RobotManagerBluetooth", "Rfcomm Socket created");
00138                                 } 
00139                                 catch (NoSuchMethodException e) {
00140                                         e.printStackTrace();
00141                                         return false;
00142                                 }
00143                                 catch (IllegalArgumentException e) {
00144                                         e.printStackTrace();
00145                                         return false;
00146                                 } catch (IllegalAccessException e) {
00147                                         e.printStackTrace();
00148                                         return false;
00149                                 } catch (InvocationTargetException e) {
00150                                         e.printStackTrace();
00151                                         return false;
00152                                 }
00153 
00154                                 // Establish the connection.  This will block until it connects.
00155                                 Log.d("RobotManagerBluetooth", "Attempting to open socket");
00156                                 try {
00157                                         mBtSocket.connect();
00158                                         Log.d("RobotManagerBluetooth", "Connection established");
00159                                 } catch (IOException e) {
00160                                         e.printStackTrace();
00161                                         return false;
00162                                 }
00163 
00164                                 // Create a data stream so we can talk to server.
00165                                 Log.d("RobotManagerBluetooth", "Sending confirmation message to server");
00166                                 try {
00167                                         mOutStream = mBtSocket.getOutputStream();
00168                                 } catch (IOException e) {
00169                                         e.printStackTrace();
00170                                         return false;
00171                                 }
00172 
00173                                 String message = "Confirm connection\n";
00174                                 byte[] msgBuffer = message.getBytes();
00175                                 try {
00176                                         Log.d("RobotManagerBluetooth", "Writing message");
00177                                         mOutStream.write(msgBuffer);
00178                                         Log.d("RobotManagerBluetooth", "Message written");
00179                                 } catch (IOException e) {
00180                                         e.printStackTrace();   
00181                                         return false;
00182                                 }
00183 
00184                                 // Listen for confirmation from the server.
00185                                 Log.d("RobotManagerBluetooth", "Listening for confirmation message from server");
00186                                 try {
00187                                         mInStream = mBtSocket.getInputStream();
00188                                 } catch (IOException e) {
00189                                         e.printStackTrace();
00190                                         return false;
00191                                 }
00192 
00193                                 String confirmString = "Connection confirmed\n";
00194                                 byte[] receivedBytes = new byte[confirmString.getBytes().length];
00195                                 try
00196                                 {
00197                                         mInStream.read(receivedBytes);
00198                                 } catch (IOException e){
00199                                         e.printStackTrace();
00200                                         return false;
00201                                 }
00202                                 String receivedString = new String(receivedBytes);
00203                                 if (receivedString.equals(confirmString))
00204                                 {
00205                                         Log.d("RobotManagerBluetooth", "Connection confirmed");
00206                                         mApplication.setConnectionStatus(true);
00207 
00208                                         Message connectionMessage = mainHandler.obtainMessage(MainActivity.CONNECTION_MESSAGE, "connected");
00209                                         mainHandler.sendMessageAtFrontOfQueue(connectionMessage);
00210                                         
00211                                         Message voiceConnectionMessage = voiceHandler.obtainMessage(VoiceRecognitionThread.CONNECTION_MESSAGE,
00212                                                         "connected");
00213                                         voiceHandler.sendMessage(voiceConnectionMessage);
00214 
00215                                         socketThread.start();
00216 
00217                                         return true;
00218                                 }
00219                                 else
00220                                 {
00221                                         Log.d("RobotManagerBluetooth", "Confirmation not received");
00222                                         mApplication.setConnectionStatus(false);
00223                                         return false;
00224                                 }
00225                         }
00226                 }
00227                 return false;
00228         }
00229 
00230         public synchronized byte[] read()
00231         {
00232                 try {
00233                         int available = mInStream.available(); 
00234                         if (available > 0) 
00235                         { 
00236                                 byte[] buffer = new byte[available]; 
00237                                 mInStream.read(buffer); 
00238                                 return buffer;
00239                         }
00240                         else
00241                         {
00242                                 return null;
00243                         }
00244                 } catch (IOException e) {
00245                         e.printStackTrace();
00246                         Log.d("ConnectedThread", "Error reading message");
00247                         return null;
00248                 }
00249         }
00250 
00251         public synchronized byte[] read(int length)
00252         {
00253                 byte[] buffer = new byte[length];
00254 
00255                 try {
00256                         buffer = new byte[2048];
00257                         mInStream.read(buffer, 0, length);
00258                         return buffer;
00259                 } catch (IOException e) {
00260                         e.printStackTrace();
00261                         Log.d("ConnectedThread", "Error reading message");
00262                         return null;
00263                 }
00264         }
00265 
00266         /*public void pollSocket() 
00267         {
00268 
00269                 Log.d("ConnectedThread", "Polling socket");
00270 
00271                 while (!isShutdown)
00272                 {
00273                         // Keep listening to the InputStream until an exception occurs  
00274                         String bufferString = "";
00275                         String[] pkts = null;
00276 
00277                         while (mApplication.getConnectionStatus()) 
00278                         {
00279                                 Log.d("ConnectedThread", "Listening for message");
00280 
00281                                 boolean incoming = false;
00282                                 int packetNum = 0;
00283                                 int packetSize = 0;
00284                                 boolean invalid = false;
00285                                 int bufferSlack = 100;
00286 
00287 
00288 
00289                                 byte[] pktBuffer = new byte[packetSize + bufferSlack];
00290                                 pktBuffer = read();
00291 
00292                                 String pktString = new String(pktBuffer);
00293                                 pkts = new String[packetNum];
00294 
00295 
00296                                 String message = "";
00297                                 for (String str : pkts)
00298                                 {
00299                                         message += str;
00300                                 }
00301 
00302 
00303 
00304                         }//While connected loop
00305                 }//While alive
00306 
00307 
00308         }//Function */
00309 
00310         private void receivePackets()
00311         {
00312                 Log.i("ConnectedThread", "Packet listener thread enabled");
00313 
00314                 byte[] buffer = new byte[30];  // buffer store for the stream
00315                 int packetNum = 0;
00316                 int packetSize = 0;
00317                 String message;
00318 
00319                 while(mApplication.getConnectionStatus())
00320                 {
00321                         Log.i("ConnectedThread", "Listening for packet header");
00322 
00323                         String tempString = "";
00324                         while (!hasFullHeader(tempString))
00325                         {       
00326                                 byte[] bytes = read(1);
00327                                 if (bytes != null)
00328                                 {
00329                                         String readString = new String(bytes).trim();
00330                                         tempString += readString;
00331                                 }
00332                         }
00333 
00334                         String headerString = tempString;
00335                         Log.i("ConnectedThread", "Header: " + headerString);
00336 
00337                         if ((headerString.substring(0, 5).equals("<msg>")) && (headerString.indexOf("</msg>") != -1))
00338                         {
00339                                 headerString = headerString.replace("<msg>", "").replace("</msg>", "");
00340                                 String[] parts = headerString.split("_DELIM_");
00341                                 packetNum = Integer.parseInt(parts[0]);
00342                                 packetSize = Integer.parseInt(parts[1]);
00343                         }
00344 
00345                         Log.i("ConnectedThread", "Expecting " + Integer.toString(packetNum)
00346                                         + " packets of size " + Integer.toString(packetSize)
00347                                         + " bytes");
00348 
00349                         message = getPacketData(packetNum, packetSize);
00350                         String[] messageParts = message.split("_DELIM_");
00351                         Log.d("ConnectedThread", "Message type: " + messageParts[0]);
00352 
00353 
00354                         if(messageParts[0].equals("robot_configuration"))
00355                         {
00356                                 parseRobotConfiguration(messageParts[1], messageParts[2], messageParts[3]);
00357                         }
00358                         else if(messageParts[0].equals("text_message"))
00359                         {
00360                                 parseTextMessage(messageParts[1], messageParts[2], messageParts[3]);
00361                         }
00362                         else if(messageParts[0].equals("image_message"))
00363                         {
00364                                 parseImageMessage(messageParts[1], messageParts[2], messageParts[3], messageParts[4]);
00365                         }
00366                 }
00367         }
00368 
00369         private String getPacketData(int numPackets, int pktSize)
00370         {
00371                 Log.i("ConnectedThread", "Getting packet data");
00372 
00373                 int metaSize = 27;
00374                 String pktData = "";
00375                 int deltaT = 3000;
00376                 double stopTime = System.currentTimeMillis() + deltaT;
00377 
00378                 for (int i = 0; i < numPackets && 
00379                                 System.currentTimeMillis() != stopTime; i++)
00380                 {
00381                         Log.i("ConnectedThread", "Listening for packets");
00382                         String tempString = "";
00383                         while (!isShutdown)
00384                         {
00385                                 while (!hasFullPacket(tempString))
00386                                 {       
00387                                         byte[] bytes = read();
00388                                         if (bytes != null)
00389                                         {
00390                                                 String readString = new String(bytes).trim();
00391                                                 tempString += readString;
00392                                         }
00393                                 }
00394                                 Log.i("ConnectedThread", "Packet received");
00395                                 Log.i("ConnectedThread", "Raw: " + tempString);
00396                                 tempString = conditionData(tempString, i+1);
00397                                 Log.i("ConnectedThread", "Conditioned: " + tempString);
00398                                 Log.i("ConnectedThread", "Asking for next packet");
00399                                 write("_NEXT_\n".getBytes());
00400                                 break;
00401                         }
00402                         if (tempString == null)
00403                         {
00404                                 Log.d("ConnectedThread", "Could not read packet #" + Integer.toString(i));
00405                         }
00406                         else
00407                         {
00408                                 pktData += tempString;
00409                         }
00410                 }
00411                 pktData = pktData.replace("_SPACE_", " ");
00412                 return pktData;
00413         }
00414 
00415         private boolean hasFullHeader(String strBuffer)
00416         {
00417                 int start = strBuffer.indexOf("<msg>");
00418                 if (start >= 0)
00419                 {
00420                         int end = strBuffer.indexOf("</msg>", start);
00421                         if (end >= 0)
00422                         {
00423                                 return true;
00424                         }
00425                         else
00426                         {
00427                                 return false;
00428                         }
00429                 }
00430                 else
00431                 {
00432                         return false;
00433                 }
00434         }
00435 
00436         
00437         private boolean hasFullPacket(String strBuffer)
00438         {
00439                 int start = strBuffer.indexOf("<pkt>");
00440                 if (start >= 0)
00441                 {
00442                         int end = strBuffer.indexOf("</pkt>", start);
00443                         if (end >= 0)
00444                         {
00445                                 return true;
00446                         }
00447                         else
00448                         {
00449                                 return false;
00450                         }
00451                 }
00452                 else
00453                 {
00454                         return false;
00455                 }
00456         }
00457 
00458         private String conditionData(String rawString, int expectedIndex)
00459         {
00460                 String conditionedString = "";
00461                 boolean invalid = false;
00462 
00463                 if ((rawString.substring(0, 5).equals("<pkt>")) && (rawString.indexOf("</pkt>") != -1))
00464                 {
00465                         rawString = rawString.replace("<pkt>", "");
00466                         Log.d("ConnectedThread", "Remove pkt tags " + rawString);
00467 
00468                         if ((rawString.substring(0, 7).equals("<index>")) && (rawString.indexOf("</index>") != -1))
00469                         {
00470                                 String pktIndexString = rawString.substring(7, rawString.indexOf("</index>"));
00471                                 int pktIndex = Integer.parseInt(pktIndexString);
00472 
00473                                 String pktBody = rawString.substring(
00474                                                 rawString.indexOf("</index>") + 8);
00475 
00476                                 if (pktBody.indexOf("</pkt>") != -1)
00477                                 {
00478                                         if (expectedIndex == pktIndex)
00479                                         {
00480                                                 conditionedString = pktBody.substring(0,
00481                                                                 pktBody.indexOf("</pkt>"));
00482 
00483                                                 conditionedString = conditionedString.replace("_SPACE_", " ");
00484                                         }
00485                                         else
00486                                         {
00487                                                 invalid = true;
00488                                                 Log.i("ConnectedThread", "Packet index does not match expected index");
00489                                         }
00490                                 }
00491                                 else
00492                                 {
00493                                         invalid = true;
00494                                         Log.i("ConnectedThread", "End of packet not read");
00495                                 }
00496                         }//Check index tags
00497                         else
00498                         {
00499                                 invalid = true;
00500                                 Log.i("ConnectedThread", "Index tags not read");
00501                         }
00502                 }//Check packet tags
00503                 else
00504                 {
00505                         invalid = true;
00506                         Log.i("ConnectedThread", "Begin packet tag not read");
00507                 }
00508 
00509                 if (invalid)
00510                 {
00511                         conditionedString = null;
00512                         Log.i("ConnectedThread", "Invalid packet");
00513                 }
00514 
00515                 return conditionedString;
00516         }
00517 
00518         private void parseRobotConfiguration(String sender, String info, String rawVocab)
00519         {
00520                 Log.d("ConnectedThread", "Configuring Robot");
00521                 Robot newRobot = new Robot();
00522                 newRobot.setName(sender);
00523                 newRobot.setInfo(info);
00524                 newRobot.setVocabulary(new Vocabulary(rawVocab));
00525 
00526                 Message msg = voiceHandler.obtainMessage(VoiceRecognitionThread.ADD_VOCAB_MESSAGE, newRobot.getName());
00527                 voiceHandler.sendMessageAtFrontOfQueue(msg);
00528 
00529                 mApplication.addRobot(newRobot);
00530 
00531                 Log.d("ConnectedThread", "Writing confirmation");
00532                 write("configuration complete\n".getBytes());
00533         }
00534 
00535 
00536         private void parseTextMessage(String sender, String text, String strPriority)
00537         {
00538                 Log.d("ConnectedThread", "Reading text message");
00539                 RobotMessage msg = new RobotMessage();
00540                 msg.setType("Text");
00541                 msg.setSender(sender);
00542                 msg.setText(text);
00543                 msg.setPriority(Integer.parseInt(strPriority));
00544 
00545                 Calendar cal = Calendar.getInstance();
00546                 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
00547                 msg.setTimestamp(sdf.format(cal.getTime()));
00548 
00549                 Log.d("ConnectedThread", "Adding text message to messages");
00550                 mApplication.addMessage(msg);
00551         }
00552 
00553         private void parseImageMessage(String sender, String text, String base64Image, String strPriority)
00554         {
00555                 Log.d("ConnectedThread", "Reading image message");
00556                 RobotMessage msg = new RobotMessage();
00557                 msg.setType("Image");
00558                 msg.setSender(sender);
00559                 msg.setText(text);
00560                 msg.setImage(base64Image);
00561                 msg.setPriority(Integer.parseInt(strPriority));
00562 
00563                 Calendar cal = Calendar.getInstance();
00564                 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
00565                 msg.setTimestamp(sdf.format(cal.getTime()));
00566 
00567                 Log.d("ConnectedThread", "Adding text message to messages");
00568                 mApplication.addMessage(msg);
00569         }
00570 
00571         public void write(byte[] bytes) {
00572                 String sentString = new String(bytes);
00573                 String confirmString = "Copy: " + sentString;
00574 
00575                 Log.d("RobotManagerBluetooth", "Acquiring read/write lock");
00576                 //synchronized (readWriteLock) 
00577                 //{
00578                 try {
00579                         Log.d("RobotManagerBluetooth", "Writing");
00580                         mOutStream.write(bytes);
00581                 } catch (IOException e) { 
00582                         //Something went wrong, end connection
00583 
00584                         e.printStackTrace();
00585                         disconnect();
00586                 }
00587                 /*
00588                         // Listen for confirmation of receipt.
00589                         Log.d("RobotManagerBluetooth", "Listening for confirmation message from server");
00590 
00591                         byte[] receivedBytes = read();
00592 
00593                         String receivedString = new String(receivedBytes).trim();
00594                         if (receivedString.equals(confirmString))
00595                         {
00596                                 Log.d("RobotManagerBluetooth", "Receipt confirmed");
00597 
00598                         }
00599                         else
00600                         {
00601                                 Log.d("RobotManagerBluetooth", "Confirmation of receipt not received, instead: " + receivedString);
00602                                 return;
00603                         }
00604                  */
00605                 //      }
00606         }
00607 
00608         private void sendMainMessage(RobotMessage msg)
00609         {
00610                 Message mainMsg = new Message();
00611 
00612                 if (msg.getType().equals("simple"))
00613                 {
00614                         mainMsg.what = MainActivity.MESSAGE_LIST_MESSAGE;
00615                 }
00616 
00617                 mainMsg.obj = msg;
00618                 mHandler.sendMessageAtFrontOfQueue(mainMsg);
00619         }
00620 
00621         public void disconnect() 
00622         {
00623                 //try 
00624                 //{
00625                         write("end connection\n".getBytes());
00626                         //mBtSocket.close();
00627                         socketThread.interrupt();
00628                         socketThread = null;
00629                         mApplication.setConnectionStatus(false); 
00630                         
00631                         Message connectionMessage = mainHandler.obtainMessage(MainActivity.CONNECTION_MESSAGE, "disconnected");
00632                         mainHandler.sendMessage(connectionMessage);
00633                         
00634                         Message voiceConnectionMessage = voiceHandler.obtainMessage(VoiceRecognitionThread.CONNECTION_MESSAGE, "disconnected");
00635                         voiceHandler.sendMessage(voiceConnectionMessage);
00636                         //}
00637                 /*catch (IOException e) { 
00638                         Log.d("ConnectedThread", "Exception in disconnect");
00639                         e.printStackTrace();
00640                 }*/
00641         }
00642 
00643         public void shutdown()
00644         {
00645                 if (mApplication.getConnectionStatus())
00646                 {
00647                         disconnect();
00648                 }
00649                 isShutdown = true;
00650                 mApplication.setConnectedThreadHandler(null);
00651         }
00652 }


google_glass_driver
Author(s): Nicholas Otero
autogenerated on Fri Aug 28 2015 10:51:44