Я задавал ряд развивающихся вопросов, касающихся моего проекта Android, который постоянно отображает данные Bluetooth в режиме реального времени. И я не очень хорошо задавал вопросы.
Итак, что мне нужно сделать, это отредактировать этот вопрос, очистить его, добавить важные детали, и, самое главное, мне нужно добавить фрагменты кода соответствующих разделов кода, особенно разделов, которые я взломал довольно часто, и предоставить объяснение об этих разделах кода. Таким образом, возможно, я мог бы получить ответ на мой вопрос / проблемы, а именно: Является ли мое текущее решение приемлемым? Собирается ли это, пока я добавляю новые функции?
По сути, я уже создал первую версию своего приложения, собрав воедино некоторый открытый исходный код Blueterm и OrientationSensor .
Было предложено добавить поток, обработчик, службу, или использовать асинхронную задачу, или AIDL и т. Д. Но я решил, что не хочу изменять или заменять существующее решение, если мне это не нужно. В основном я хочу знать, достаточно ли это, чтобы двигаться вперед и расширить , чтобы добавить другие функции.
Кстати, то, что я ранее называл BluetoothData, это просто данные Bluetooth: это 16-битные данные, полученные с удаленного устройства Bluetooth со скоростью от 2 до 10 выборок в секунду. Мое приложение в основном представляет собой систему сбора данных, которая получает / получает данные Bluetooth и строит их на графике.
Вот описание открытого исходного кода Blueterm, с которого я начал (см. Ссылку выше). Blueterm - это в основном программа-эмулятор терминала, которая общается через Bluetooth. Он состоит из нескольких видов деятельности, причем Blueterm является наиболее важным. Он обнаруживает, связывает и соединяется с удаленным устройством Bluetooth, которое поддерживает SPP / RfComm. После подключения я могу использовать Blueterm для настройки удаленного устройства, посылая ему команды для включения выборки, изменения количества каналов для выборки (на один канал), изменения формата входных данных (мне нравятся данные, разделенные запятыми) и т. Д.
Вот описание открытого исходного кода OrientationSensorExample, с которого я начал (см. Ссылку выше). Это в основном пример приложения библиотеки AnroidPlot. Деятельность OrientationSensor реализует SensorEventListener. Это включает переопределение onSenorChanged (), которое вызывается всякий раз, когда берутся новые данные датчика ориентации, и перерисовывает график.
Объединив эти два проекта с открытым исходным кодом (Blueterm и OrientationSensorExample) в одно приложение (Blueterm), вот описание того, как работает все приложение (Blueterm). Когда я запускаю Blueterm, весь экран эмулирует красивый синий терминал. В открывшемся меню «Параметры» выполните сопряжение, подключитесь и настройте удаленное устройство Bluetooth, как описано выше. После того, как я настроил удаленное устройство, я снова захожу в меню параметров и выбираю «Данные графика», который запускает действие «График». Эмулятор терминала исчезает, и появляется хороший прокручиваемый график в реальном времени из действия Plot.
Вот как я это сделал. В onOptionsItemSelected () я добавил случай для запуска действия Plot следующим образом:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.connect:
if (getConnectionState() == BluetoothSerialService.STATE_NONE) {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
else
if (getConnectionState() == BluetoothSerialService.STATE_CONNECTED) {
mSerialService.stop();
mSerialService.start();
}
return true;
case R.id.preferences:
doPreferences();
return true;
case R.id.menu_special_keys:
doDocumentKeys();
return true;
case R.id.plot_data:
doPlotData();
return true;
}
return false;
}
private void doPlotData() {
Intent plot_data = new Intent(this, com.vtrandal.bluesentry.Plot.class);
startActivity(plot_data);
}
Затем в фоновом потоке bluetooth я добавил вызов update () для вызова plotData () следующим образом:
/**
* Look for new input from the ptty, send it to the terminal emulator.
*/
private void update() {
int bytesAvailable = mByteQueue.getBytesAvailable();
int bytesToRead = Math.min(bytesAvailable, mReceiveBuffer.length);
try {
int bytesRead = mByteQueue.read(mReceiveBuffer, 0, bytesToRead);
append(mReceiveBuffer, 0, bytesRead);
//VTR use existing handler that calls update() to get data into plotting activity
//OrientationSensor orientationSensor = new OrientationSensor();
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
Затем в упражнении «Заговор» я в основном убрал дом, удалил «Implements SensorEventListener» и некоторые связанные с ним методы и переменные и записал функцию plotData (), как показано выше. Вот как plotData () и его вспомогательные методы splitData () и nowPlotData () в настоящее время выглядят так:
private static StringBuffer strData = new StringBuffer("");
public static void plotData(byte[] buffer, int base, int length) {
Log.i("Entering: ", "plotData()");
/*
byte[] buffer = (byte[]) msg.obj;
int base = msg.arg1;
int length = msg.arg2;
*/
for (int i = 0; i < length; i++) {
byte b = buffer[base + i];
try {
if (true) {
char printableB = (char) b;
if (b < 32 || b > 126) {
printableB = ' ';
}
Log.w("Log_plotData", "'" + Character.toString(printableB)
+ "' (" + Integer.toString(b) + ")");
strData.append(Character.toString(printableB));
if (b == 10)
{
Log.i("End of line: ", "processBlueData()");
Log.i("strData", strData.toString());
splitData(strData);
strData = new StringBuffer("");
}
}
} catch (Exception e) {
Log.e("Log_plotData_exception", "Exception while processing character "
+ Integer.toString(i) + " code "
+ Integer.toString(b), e);
}
}
Log.i("Leaving: ", "plotData()");
}
private static void splitData(StringBuffer strBuf) {
String strDash = strBuf.toString().trim();
String[] strDashSplit = strDash.split("-");
for (int ndx = 0; ndx < strDashSplit.length; ndx++)
{
if (strDashSplit[ndx].length() > 0)
Log.i("strDashSplit", ndx + ":" + strDashSplit[ndx]);
String strComma = strDashSplit[ndx].trim();
String[] strCommaSplit = strComma.split(",");
for (int mdx = 0; mdx < strCommaSplit.length; mdx++)
{
if (strCommaSplit[mdx].length() > 0)
Log.i("strCommaSplit", mdx + ":" + strCommaSplit[mdx]);
if (mdx == 1)
{
int raw = Integer.parseInt(strCommaSplit[1],16);
Log.i("raw", Integer.toString(raw));
float rawFloat = raw;
Log.i("rawFloat", Float.toString(rawFloat));
float ratio = (float) (rawFloat/65535.0);
Log.i("ratio", Float.toString(ratio));
float voltage = (float) (5.0*ratio);
Log.i("voltage", Float.toString(voltage));
nowPlotData(voltage);
}
}
}
}
public static void nowPlotData(float data) {
// get rid the oldest sample in history:
if (plotHistory.size() > HISTORY_SIZE) {
plotHistory.removeFirst();
}
// add the latest history sample:
plotHistory.addLast(data);
// update the plot with the updated history Lists:
plotHistorySeries.setModel(plotHistory, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
//VTR null pointer exception?
if (plotHistoryPlot == null)
Log.i("aprHistoryPlot", "null pointer exception");
// redraw the Plots:
plotHistoryPlot.redraw();
}
Время для сводки: я в основном нашел метод update () в фоновом потоке, который был создан действием Blueterm. Метод update () по существу добавляет вновь полученные данные Bluetooth в экранный буфер с помощью метода append (). Таким образом, метод update () фонового потока выглядит как хорошее место для вызова plotPlot (). Поэтому я разработал plotData () для отображения данных, передаваемых в append (). Это работает, так как plotData () является статическим методом. Я был бы признателен за объяснение того, почему plotData (), по-видимому, должен быть статическим, чтобы работать.
И снова мой общий вопрос / проблемы: мое текущее решение в порядке? Собирается ли это, пока я добавляю новые функции?