@Override
  public void run() {
    try {
      communicator = NXTCommFactory.createNXTComm(NXTCommFactory.BLUETOOTH);
      synchronized (listeners) {
        for (LinkListener listener : listeners) {
          listener.bluetoothInitialized(this);
        }
      }
    } catch (Throwable t) {
      t.printStackTrace();
      synchronized (listeners) {
        for (LinkListener listener : listeners) {
          listener.bluetoothFailed(this);
        }
      }
    }

    long lastSearchTime = 0;
    while (!stopRequest) {

      long currentTime = System.currentTimeMillis();

      if (!isConnected()
          && (availableRovers == null
              || (availableRovers.length == 0 && currentTime - lastSearchTime > 5000))) {
        try {
          synchronized (listeners) {
            for (LinkListener listener : listeners) {
              listener.searchStarted(this);
            }
          }
          availableRovers = communicator.search(null, NXTCommFactory.BLUETOOTH);
          synchronized (listeners) {
            for (LinkListener listener : listeners) {
              listener.searchCompleted(this);
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
          synchronized (listeners) {
            for (LinkListener listener : listeners) {
              listener.searchFailed(this);
            }
          }
        }
        lastSearchTime = System.currentTimeMillis();
      }

      if (transmitter != null && !transmitter.isConnected()) {
        transmitter = null;
        synchronized (messagesToSend) {
          messagesToSend.clear();
        }
        synchronized (listeners) {
          for (LinkListener listener : listeners) {
            listener.disconnected(this);
          }
        }
      }

      if (isConnected()) {
        transmitter.encodeMessage(new KeepaliveMessage());

        while (messagesToSend.size() > 0) {
          Message message = null;
          synchronized (messagesToSend) {
            message = (Message) messagesToSend.remove(0);
          }
          transmitter.encodeMessage(message);
        }

        // Check for connection timeout.
        if (transmitter.getLastReceiveTime() != 0
            && System.currentTimeMillis() - transmitter.getLastReceiveTime() > 5000) {
          transmitter.disconnect();
        }
      }

      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
 public boolean isConnected() {
   return transmitter != null && transmitter.isConnected();
 }
 public void disconnect() {
   if (transmitter != null && transmitter.isConnected()) {
     transmitter.disconnect();
   }
 }