/**
  * Creates a new object for communication to the NXT robot via bluetooth and fetches the
  * corresponding handler.
  */
 private void createBTCommunicator() {
   // interestingly BT adapter needs to be obtained by the UI thread - so we pass it in in the
   // constructor
   myBTCommunicator =
       new BTCommunicator(this, myHandler, BluetoothAdapter.getDefaultAdapter(), getResources());
   btcHandler = myBTCommunicator.getHandler();
 }
  /**
   * Creates and starts the a thread for communication via bluetooth to the NXT robot.
   *
   * @param mac_address The MAC address of the NXT robot.
   */
  private void startBTCommunicator(String mac_address) {
    connected = false;
    connectingProgressDialog =
        ProgressDialog.show(
            this, "", getResources().getString(R.string.connecting_please_wait), true);

    if (myBTCommunicator != null) {
      try {
        myBTCommunicator.destroyNXTconnection();
      } catch (IOException e) {
      }
    }
    createBTCommunicator();
    myBTCommunicator.setMACAddress(mac_address);
    myBTCommunicator.start();
    updateButtonsAndMenu();
  }
 /** Enables/disables the menu items */
 @Override
 public boolean onPrepareOptionsMenu(Menu menu) {
   boolean displayMenu;
   displayMenu = super.onPrepareOptionsMenu(menu);
   if (displayMenu) {
     boolean startEnabled = false;
     if (myBTCommunicator != null) startEnabled = myBTCommunicator.isConnected();
     menu.findItem(MENU_START_SW).setEnabled(startEnabled);
   }
   return displayMenu;
 }
        @Override
        public void handleMessage(Message myMessage) {
          switch (myMessage.getData().getInt("message")) {
            case BTCommunicator.DISPLAY_TOAST:
              showToast(myMessage.getData().getString("toastText"), Toast.LENGTH_SHORT);
              break;
            case BTCommunicator.STATE_CONNECTED:
              connected = true;
              programList = new ArrayList<String>();
              connectingProgressDialog.dismiss();
              updateButtonsAndMenu();
              sendBTCmessage(BTCommunicator.NO_DELAY, BTCommunicator.GET_FIRMWARE_VERSION, 0, 0);
              break;
            case BTCommunicator.MOTOR_STATE:
              if (myBTCommunicator != null) {
                byte[] motorMessage = myBTCommunicator.getReturnMessage();
                int position =
                    byteToInt(motorMessage[21])
                        + (byteToInt(motorMessage[22]) << 8)
                        + (byteToInt(motorMessage[23]) << 16)
                        + (byteToInt(motorMessage[24]) << 24);
                showToast(
                    getResources().getString(R.string.current_position) + position,
                    Toast.LENGTH_SHORT);
              }

              break;

            case BTCommunicator.STATE_CONNECTERROR_PAIRING:
              connectingProgressDialog.dismiss();
              destroyBTCommunicator();
              break;

            case BTCommunicator.STATE_CONNECTERROR:
              connectingProgressDialog.dismiss();
            case BTCommunicator.STATE_RECEIVEERROR:
            case BTCommunicator.STATE_SENDERROR:
              destroyBTCommunicator();
              if (btErrorPending == false) {
                btErrorPending = true;
                // inform the user of the error with an AlertDialog
                AlertDialog.Builder builder = new AlertDialog.Builder(thisActivity);
                builder
                    .setTitle(getResources().getString(R.string.bt_error_dialog_title))
                    .setMessage(getResources().getString(R.string.bt_error_dialog_message))
                    .setCancelable(false)
                    .setPositiveButton(
                        "OK",
                        new DialogInterface.OnClickListener() {
                          @Override
                          public void onClick(DialogInterface dialog, int id) {
                            btErrorPending = false;
                            dialog.cancel();
                            selectNXT();
                          }
                        });
                builder.create().show();
              }

              break;

            case BTCommunicator.FIRMWARE_VERSION:
              if (myBTCommunicator != null) {
                byte[] firmwareMessage = myBTCommunicator.getReturnMessage();
                // check if we know the firmware
                boolean isLejosMindDroid = true;
                for (int pos = 0; pos < 4; pos++) {
                  if (firmwareMessage[pos + 3] != LCPMessage.FIRMWARE_VERSION_LEJOSMINDDROID[pos]) {
                    isLejosMindDroid = false;
                    break;
                  }
                }
                if (isLejosMindDroid) {
                  mRobotType = R.id.robot_type_lejos;
                  setUpByType();
                }
                // afterwards we search for all files on the robot
                sendBTCmessage(BTCommunicator.NO_DELAY, BTCommunicator.FIND_FILES, 0, 0);
              }

              break;

            case BTCommunicator.FIND_FILES:
              if (myBTCommunicator != null) {
                byte[] fileMessage = myBTCommunicator.getReturnMessage();
                String fileName = new String(fileMessage, 4, 20);
                fileName = fileName.replaceAll("\0", "");

                if (mRobotType == R.id.robot_type_lejos
                    || fileName.endsWith(".nxj")
                    || fileName.endsWith(".rxe")) {
                  programList.add(fileName);
                }

                // find next entry with appropriate handle,
                // limit number of programs (in case of error (endless loop))
                if (programList.size() <= MAX_PROGRAMS)
                  sendBTCmessage(
                      BTCommunicator.NO_DELAY,
                      BTCommunicator.FIND_FILES,
                      1,
                      byteToInt(fileMessage[3]));
              }

              break;

            case BTCommunicator.PROGRAM_NAME:
              if (myBTCommunicator != null) {
                byte[] returnMessage = myBTCommunicator.getReturnMessage();
                startRXEprogram(returnMessage[2]);
              }

              break;

            case BTCommunicator.SAY_TEXT:
              if (myBTCommunicator != null) {
                byte[] textMessage = myBTCommunicator.getReturnMessage();
                // evaluate control byte
                byte controlByte = textMessage[2];
                // BIT7: Language
                if ((controlByte & 0x80) == 0x00) mTts.setLanguage(Locale.US);
                else mTts.setLanguage(Locale.getDefault());
                // BIT6: Pitch
                if ((controlByte & 0x40) == 0x00) mTts.setPitch(1.0f);
                else mTts.setPitch(0.75f);
                // BIT0-3: Speech Rate
                switch (controlByte & 0x0f) {
                  case 0x01:
                    mTts.setSpeechRate(1.5f);
                    break;
                  case 0x02:
                    mTts.setSpeechRate(0.75f);
                    break;

                  default:
                    mTts.setSpeechRate(1.0f);
                    break;
                }

                String ttsText = new String(textMessage, 3, 19);
                ttsText = ttsText.replaceAll("\0", "");
                showToast(ttsText, Toast.LENGTH_SHORT);
                mTts.speak(ttsText, TextToSpeech.QUEUE_FLUSH, null);
              }

              break;

            case BTCommunicator.VIBRATE_PHONE:
              if (myBTCommunicator != null) {
                byte[] vibrateMessage = myBTCommunicator.getReturnMessage();
                Vibrator myVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                myVibrator.vibrate(vibrateMessage[2] * 10);
              }

              break;
          }
        }