Android-BLE连接参数和将BLE传感器数据存储在SQLite数据库中 [英] Android - BLE connection parameter and Storing BLE sensor data in SQLite Database

查看:144
本文介绍了Android-BLE连接参数和将BLE传感器数据存储在SQLite数据库中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个Android应用,该应用以大约8000字节/秒的速度从BLE传感器接收数据.

I am developing an Android app that receives data from a BLE sensor at a rate of about 8000 bytes per second.

我的应用程序中的连接逻辑基于Google的BluetoothLeGatt示例.有用.我没有做任何更改,也没有明确设置任何连接参数,例如连接事件之间的间隔(我不认为Android 4.4 API支持该功能).

The connection logic in my app is based upon Google's BluetoothLeGatt sample. It works. I haven't changed anything and don't explicitly set any connection parameters like interval between connection events (I don't think the Android 4.4 APIs support that).

我正在使用Android 4.4.2版和TI BLE嗅探器在两台Android手机上进行测试,以监视BLE流量.

I am testing on two Android phones, both using Android version 4.4.2 and am using the TI BLE sniffer to monitor BLE traffic.

一部电话协商一个7.5ms的间隔,并且每个连接事件交换三个20字节的数据包.另一部电话在连接事件之间协商48.75毫秒,并且每个事件交换19个20字节的数据包(每秒的有效数据传输速率大致相同).

One phone negotiates a 7.5ms interval and exchanges three 20-byte packets per connection event. The other phone negotiates 48.75ms between connection events and exchanges nineteen 20-byte packets per event (the effective data transfer rate per second is about the same).

我的问题是我试图记录来自BLE Service活动的数据,这些数据进入SQLite数据库.记录适用于手机,间隔为7.5ms.然而, 该应用程序以48.75ms的时间间隔锁定手机. (通常,该电话的连接不稳定得多).我认为这是因为它正在互相处理19个数据包.

My problem is that I am trying to log the data from the BLE Service activity as it comes in to a SQLite database. The logging works for the phone with the 7.5ms interval. However, the app locks up for the phone with the 48.75ms interval. (In general, that phone's connection is a lot less stable). I assume that's because it is getting processing for 19 packets right on top of each other.

我的问题:
1.无论如何,我可以让两部手机(以及以后的任何设备)都使用7.5毫秒的间隔,因为这似乎效果更好?有没有一种方法可以控制 Minimum/Maximum_CE_Length 参数?

My questions:
1. Is there anyway I can make both phones (and any future devices) use the 7.5ms interval since that seems to work better? Is there a way to control the Minimum/Maximum_CE_Length parameters?

  1. 是否有比直接从BLE服务活动中记录数据更好的方法? 这些SQLite Android开发人员页面建议使用ASync任务,但是似乎不合适,因为数据不会进入UI线程.
  1. Is there a better way to log the data than directly from the BLE service activity? These SQLite Android Developer pages suggest using an ASync task but that doesn't seem appropriate since the data isn't going to the UI thread.

我的代码段: 这是我的连接代码

My code snippets: This is my connection code directly from the BluetoothLeGatt sample

  /**
 * Connects to the GATT server hosted on the Bluetooth LE device.
 *
 * @param address The device address of the destination device.
 *
 * @return Return true if the connection is initiated successfully. The connection result
 *         is reported asynchronously through the
 *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
 *         callback.
 */
public boolean connect(final String address) {
    if (mBluetoothAdapter == null || address == null) {
        Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
        return false;
    }
    // Previously connected device.  Try to reconnect.
    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
            && mBluetoothGatt != null) {
        Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
        if (mBluetoothGatt.connect()) {
            mConnectionState = STATE_CONNECTING;
            return true;
        } else {
            return false;
        }
    }
    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
    if (device == null) {
        Log.w(TAG, "Device not found.  Unable to connect.");
        return false;
    }
    // We want to directly connect to the device, so we are setting the autoConnect
    // parameter to false.
    mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
    Log.d(TAG, "Trying to create a new connection.");
    mBluetoothDeviceAddress = address;
    mConnectionState = STATE_CONNECTING;
    return true;
}`

我的日志记录代码在broadcastUpdate函数中:

My logging code is in the broadcastUpdate function:

private void broadcastUpdate(final String action,
                             final BluetoothGattCharacteristic characteristic) {
    final Intent intent = new Intent(action);
    StringBuilder stringBuilder = new StringBuilder();
    StringBuilder descStringBuilder = new StringBuilder();
    byte[]  newData = characteristic.getValue();
    String dataString;

    if (newData != null && newData.length > 0) {
        if (UUID_SENSOR_FFF4.equals(characteristic.getUuid())) {

            totalDataBytes += newData.length;
            // https://stackoverflow.com/questions/8150155/java-gethours-getminutes-and-getseconds
            estimatedTime = System.currentTimeMillis();
            Date timeDiff = new Date(estimatedTime - startTime - 19 * 3600000);
            SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
            descStringBuilder.append("CHAR_FFF4\n");
            descStringBuilder.append("Total Data: " + totalDataBytes + " Bytes\n");
            descStringBuilder.append("Elapsed Time: " + timeFormat.format(timeDiff) + "\n");

            for (int i = 0; i < newData.length; i++){
                byte[] tempArray = { newData[i+1], newData[i] };
                ByteBuffer wrapper = ByteBuffer.wrap(tempArray);
                short tempShort = wrapper.getShort();
                i++;
                stringBuilder.append( tempShort );
                stringBuilder.append( ", ");
            }
            dataString =  stringBuilder.toString();

            values.put(NbmcContract.NmbcDeviceData.COLUMN_TIMESTAMP, estimatedTime );
            values.put(NbmcContract.NmbcDeviceData.COLUMN_DATA_STRING, dataString);

            long newRowId = db.insert(NbmcContract.NmbcDeviceData.TABLE_NAME, null, values);
            descStringBuilder.append("Row ID: " + newRowId + "\n");


        } else {
            descStringBuilder.append(getCharacteristicString(characteristic) + "\nDATA:  ");

            // We expect these characteristics to return ASCII strings
            if (    DEVICE_NAME_CHAR.equals(characteristic.getUuid()) ||
                    MODEL_NUM_CHAR.equals(characteristic.getUuid()) ||
                    SERIAL_NUM_CHAR.equals(characteristic.getUuid()) ||
                    FIRMWARE_REV_CHAR.equals(characteristic.getUuid()) ||
                    HARDWARE_REV_CHAR.equals(characteristic.getUuid()) ||
                    FIRMWARE_REV_CHAR.equals(characteristic.getUuid()) ||
                    SOFTWARE_REV_CHAR.equals(characteristic.getUuid()) ||
                    MANUF_NAME_STRING_CHAR.equals(characteristic.getUuid()))
            {
                for (byte byteChar : newData) {
                    stringBuilder.append(String.format("%c", byteChar));
                }
            }
            else {
                for (byte byteChar : newData) {
                    stringBuilder.append(String.format("%02X", byteChar));
                }
            }
            dataString =  stringBuilder.toString();
        }
        String descString = descStringBuilder.toString();
        intent.putExtra("DESC_STRING", descString);

        UUID uuid = characteristic.getUuid();
        String uuidString = uuid.toString();
        intent.putExtra("CHAR_UUID", uuidString);
        intent.putExtra("EXTRA_DATA", dataString);
    }
    sendBroadcast(intent);
}

推荐答案

1)在API lvl21 +上,您可以尝试bluetoothGatt.requestConnectionPriority(int connectionPriority)
但这就是您所能做的.

1) on API lvl21+ you can try bluetoothGatt.requestConnectionPriority(int connectionPriority)
But that is all you can do.

2) Android上的BTLE堆栈不是最好的,我建议不做任何处理即可获取数据,并在收到所有数据后进行处理. 请注意,该gatt回调发生在不是您的ui线程的随机线程上.两次调用可能来自两个不同的线程,并且如果一个调用写入数据库,而另一个调用同时出现并开始写入,则会造成混乱.

2) The BTLE stack on Android is not the best, i would suggest taking the data without any processing and do the processing after all the data has been received. Please note that the gatt callbacks happen on a random thread that is NOT your ui-thread. Two calls can originate from two different threads and if one writes into a database and the other comes along and starts to write as well you get a mess.

我的建议:

在每个接收事件上,您复制(由于Android可能会将给定的数组重用于将来的数据)并使用Handler将其发送到主线程.在主线程上,将数组收集在列表"或集合"中,一旦收集到一定数量,就启动一个新线程,为其提供列表,然后将其输入数据库中,同时主线程为新线程创建一个新列表数据.

On every receiving event you copy the byte[] array (as Android may reuse the given array for future data) and send it to the main thread with a Handler. On the main thread you collect the arrays in a List or Collection and once a certain amount has been collected you start a new thread, give it the list and let it enter the data into a database while the main thread creates a new list for new data.

这篇关于Android-BLE连接参数和将BLE传感器数据存储在SQLite数据库中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆