@Override
  public synchronized void onDataAvailable(BluetoothGattCharacteristic characteristic) {
    // UART RX
    if (characteristic.getService().getUuid().toString().equalsIgnoreCase(UUID_SERVICE)) {
      if (characteristic.getUuid().toString().equalsIgnoreCase(UUID_RX)) {
        final byte[] bytes = characteristic.getValue();
        final String data = new String(bytes, Charset.forName("UTF-8"));

        mReceivedBytes += bytes.length;

        final UartDataChunk dataChunk =
            new UartDataChunk(System.currentTimeMillis(), UartDataChunk.TRANSFERMODE_RX, data);
        mDataBuffer.add(dataChunk);
        final String formattedData = mShowDataInHexFormat ? asciiToHex(data) : data;

        runOnUiThread(
            new Runnable() {
              @Override
              public void run() {
                if (mIsTimestampDisplayMode) {
                  final String currentDateTimeString =
                      DateFormat.getTimeInstance().format(new Date(dataChunk.getTimestamp()));

                  mBufferListAdapter.add(
                      new TimestampData(
                          "[" + currentDateTimeString + "] TX: " + formattedData, mRxColor));
                  // mBufferListAdapter.add("[" + currentDateTimeString + "] RX: " + formattedData);
                  // mBufferListView.smoothScrollToPosition(mBufferListAdapter.getCount() - 1);
                  mBufferListView.setSelection(mBufferListAdapter.getCount());
                }
                updateUI();
              }
            });

        // MQTT publish to RX
        MqttSettings settings = MqttSettings.getInstance(UartActivity.this);
        if (settings.isPublishEnabled()) {
          String topic = settings.getPublishTopic(MqttUartSettingsActivity.kPublishFeed_RX);
          final int qos = settings.getPublishQos(MqttUartSettingsActivity.kPublishFeed_RX);
          mMqttManager.publish(topic, data, qos);
        }
      }
    }
  }
  private void uartSendData(String data, boolean wasReceivedFromMqtt) {
    // MQTT publish to TX
    MqttSettings settings = MqttSettings.getInstance(UartActivity.this);
    if (!wasReceivedFromMqtt) {
      if (settings.isPublishEnabled()) {
        String topic = settings.getPublishTopic(MqttUartSettingsActivity.kPublishFeed_TX);
        final int qos = settings.getPublishQos(MqttUartSettingsActivity.kPublishFeed_TX);
        mMqttManager.publish(topic, data, qos);
      }
    }

    // Add eol
    if (mIsEolEnabled) {
      // Add newline character if checked
      data += "\n";
    }

    // Send to uart
    if (!wasReceivedFromMqtt
        || settings.getSubscribeBehaviour() == MqttSettings.kSubscribeBehaviour_Transmit) {
      sendData(data);
      mSentBytes += data.length();
    }

    // Add to current buffer
    UartDataChunk dataChunk =
        new UartDataChunk(System.currentTimeMillis(), UartDataChunk.TRANSFERMODE_TX, data);
    mDataBuffer.add(dataChunk);

    final String formattedData = mShowDataInHexFormat ? asciiToHex(data) : data;
    if (mIsTimestampDisplayMode) {
      final String currentDateTimeString =
          DateFormat.getTimeInstance().format(new Date(dataChunk.getTimestamp()));
      mBufferListAdapter.add(
          new TimestampData("[" + currentDateTimeString + "] TX: " + formattedData, mTxColor));
      mBufferListView.setSelection(mBufferListAdapter.getCount());
    }

    // Update UI
    updateUI();
  }