我有一个带有蓝牙低能耗芯片的定制硬件。我用一个500 u32s的数组来设置它,这样数组[n]==n。我正在开发一个android应用程序,它可以连接到设备,请求数组的长度,然后一次一个地请求数组中的数据点。
android应用程序似乎基本上运行良好。它连接到设备,请求长度,并在收到上一条数据后继续请求下一条数据。但是,在数组的中途(从-2到450个元素中的任何一个元素看起来不一致),它将编写另一个命令,并使其一直指向onCharacteristicWrite(),但它从未收到响应。我的BLE外设连接到CoolTerm,它甚至从来没有收到命令。以下是我的代码和日志片段:
BLEService:

 private final BluetoothGattCallback bleGattCallback = new BluetoothGattCallback() {

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicRead(gatt, characteristic, status);
        Log.d("onCharacteristicRead", byteArrToHex(characteristic.getValue()));
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        if(status != BluetoothGatt.GATT_SUCCESS){
            Log.d("onCharacteristicWrite", "Failed write, retrying");
            gatt.writeCharacteristic(characteristic);
        }
        Log.d("onCharacteristicWrite", byteArrToHex(characteristic.getValue()));
        super.onCharacteristicWrite(gatt, characteristic, status);
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
        Log.d("onCharacteristicChanged", byteArrToHex(characteristic.getValue()));
        broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
    }

};

我省略了回调中与描述符写入、连接状态更改等相关的不必要部分。当数据广播时,它将在mainActivity的这一部分中接收:
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String receivedUUID = intent.getStringExtra("uuid");
        byte[] data = intent.getByteArrayExtra("data");
        Log.d("messageReceiver", "received intent in mainActivity with uuid " + receivedUUID.toString());
        if(receivedUUID.equals(READ_LEN_UUID.toString()) && currentlyReading) {
            datapoints = new ArrayList<Long>();
            numberOfDatapoints = 0;
            numberOfDatapoints |= (data[0] & 0xff);
            numberOfDatapoints |= (data[1] & 0xff) << 8;
            numberOfDatapoints |= (data[2] & 0xff) << 16;
            numberOfDatapoints |= (data[3] & 0xff) << 24;
            Log.d("RECEIVER TEST:", "number of datapoints = " + numberOfDatapoints);

            if(numberOfDatapoints > 0) {
                bleService.requestDatapoint(0);
            }
        } else if (receivedUUID.equals(READ_DATAPOINT_UUID.toString()) && currentlyReading){
            long message = 0;
            message |= (data[0] & 0xff);
            message |= (data[1] & 0xff) << 8;
            message |= (data[2] & 0xff) << 16;
            message |= (data[3] & 0xff) << 24;

            Log.d("Datapoint Recieved", "Index " + datapoints.size() + " = " + message);
            datapoints.add(message);

            if(datapoints.size() < numberOfDatapoints){
                bleService.requestDatapoint(datapoints.size());
            }
        }
    }
};

调用writeCharacteristic的代码:
public void requestDatapoint(int index){
    Log.d("requestDatapoint", "Requested datapoint at " + index);

    BluetoothGattCharacteristic commandChar = this.gattService.getCharacteristic(WRITE_UUID);
    byte[] request = new byte[3];

    // command - 2 = get index
    request[0] = (byte) (2 & 0xff);

    // index
    request[1] = (byte) ((index) & 0xff);
    request[2] = (byte) ((index >> 8) & 0xff);
    commandChar.setValue(request);
    bleGatt.writeCharacteristic(commandChar);
}

我很确定发送命令太快不会有问题。它实际上是难以置信的慢,这是我故意做的,这样我可以更容易地测试东西,然后再继续我的项目的下一部分。
我的调试日志中的一个片段:
08-23 12:08:18.470 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 49
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 31 00
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 31 00 00 00
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 49 = 49
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 50
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 32 00
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 32 00 00 00
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.585 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.590 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 50 = 50
08-23 12:05:55.590 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 51
08-23 12:05:55.680 16753-16845/sethp.datalogcollector D/onCharacteristicWrite: 02 33 00
08-23 12:05:55.685 16753-16764/sethp.datalogcollector D/onCharacteristicChanged: 33 00 00 00
08-23 12:05:55.685 16753-16764/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 51 = 51
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 52
08-23 12:05:55.785 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 34 00 00 00
08-23 12:05:55.785 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 52 = 52
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 53
08-23 12:05:55.790 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 35 00

以及我相应的CoolTerm日志片段:
command: 02
index: 0031
command = 2
datapoint at 49 = 49
attempting to send 49

command: 02
index: 0032
command = 2
datapoint at 50 = 50
attempting to send 50

command: 02
index: 0033
command = 2
datapoint at 51 = 51
attempting to send 51

command: 02
index: 0034
command = 2
datapoint at 52 = 52
attempting to send 52

注意,在我的外设日志中,它似乎没有接收到对数据点53的请求。
作为参考,oncharacteristicwrite调试中的第一个十六进制字节是命令。命令02只是意味着我正在请求一个索引处的数据点,不管接下来的2个字节包含什么。
我注意到在android日志中,没有用于请求datapoint 51的oncharacteristicwrite日志。这种情况似乎每次都发生在它停止获取数据之前,但我不确定这是否重要,或者这是否只是日志缓冲区的问题。
我运行了很多测试,试图注意到任何模式,我注意到,当设备没有连接到调试电缆时,它似乎获得了更多的数据点。在这一点上,我唯一的想法是,也许我有一个异步中断回调的问题,但我不知道该怎么做。有没有人想过为什么在调用oncharacteristicwrite之后它似乎没有真正写入数据?
谢谢
编辑:
我听从了埃米尔的建议,打开了蓝牙日志。我和Wireshark玩了一圈,弄清楚了发生了什么事。我再次尝试我的应用程序,它运行到索引102,直到它停止,在这一点上,我断开了设备。我在wireshark中搜索数据包,发现我的设备确实收到了大约102个数据包,但它没有发送103个请求。我再次检查了我的android日志,oncharacteristicwrite内部的一条日志语句说它发送了命令026700,这是一个103的请求。因此,oncharacteristicwrite似乎正在被调用,但实际上并没有被编写。
经过更多的凝视和思考,我非常确定,要么1)oncharacteristicwrite被不正确地调用,因为数据从未被写入,要么2)不知何故,某种异步的东西正在中断它并阻止它传输。我不知道会做什么。
最后编辑:
尽管,据我从规范中了解,oncharacteristicwrite只应在进行可靠、成功的写入时调用,但我还是决定检查writecharacteristic的返回值。我几个小时前就该检查的。你知道吗,在最后一次请求时它返回了false。
我认为调用oncharacteristicwrite的事实(即使返回值为false)是一个错误。我已经读到使用onCharacteristicWrite调用来写入下一个数据块是安全的。不是他们错了,就是这里发生了什么怪事。不管怎样,我想检查那些函数调用返回值是个不错的主意。

最佳答案

现在我想我看到了。有时通知会在onwritecharacteristic回调之前到达。由于您在通知回调中发出了下一次写入,上一次写入仍处于挂起状态。在发出下一个write之前,必须确保已调用onwritecharacteristic。

关于android - onCharacteristicWrite()被调用,但并不总是写,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39109178/

10-09 03:34