正在调用onCharacteristicWrite(),但它并不总是写

时间:2016-08-23 19:22:27

标签: android bluetooth bluetooth-lowenergy android-bluetooth android-ble

我有一个带有蓝牙低能耗芯片的定制硬件。我用一个500 u32s的数组设置它,使得array [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日志中,没有onCharacteristicWrite日志来请求数据点51.这似乎每次都在它停止获取数据之前发生,但我不确定这是否是重要的,或者它只是日志缓冲区的一个问题。

我已经运行了很多试图注意任何模式的测试,并且我注意到当设备未连接到调试电缆时似乎获得了更多的数据点。我在这一点上唯一的想法是,我可能遇到异步中断回调的问题,但我不知道会做什么。在调用onCharacteristicWrite之后,有没有人想过为什么它似乎没有实际写入数据?

由于

编辑:

我遵循了Emil的建议并开启了蓝牙记录功能。我和wireshark一起玩,想出发生了什么事。我再次尝试了我的应用程序,它跑到索引102直到它停止,此时我断开了设备。我挖掘了Wireshark中的数据包,发现我的设备DID收到了大约102的数据,但它没有发送103的请求。我仔细检查了我的android日志,并且来自onCharacteristicWrite里面的一条Log语句说它发送了命令02 67 00,这是103的请求。因此,似乎正在调用onCharacteristicWrite,但实际上并未写入该特性。

经过一些更多的凝视和思考后,我非常肯定1)onCharacteristicWrite被正确调用,因为数据永远不会被写入,或者2)某种程度上异步正在中断它并阻止它发送。我不知道会做什么。

最终编辑:

即使我从规范中理解,onCharacteristicWrite只应在可靠,成功的写入进行时调用,我决定检查writeCharacteristic的返回值。几小时前我应该检查一下。而且你知道什么,它在最后一次请求时返回false。

我认为onCharacteristicWrite被调用的事实即使返回为假也是一个错误。我已经读过使用onCharacteristicWrite调用来编写下一个数据块是安全的。他们错了,或者在这里发生了什么事情。无论哪种方式,我认为检查这些函数调用返回值是个不错的主意。

1 个答案:

答案 0 :(得分:2)

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