Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android可恢复写入特性锁定onCharacteristicWrite/onCharacteristicChange_Java_Android_Bluetooth Lowenergy_Bluetooth Gatt - Fatal编程技术网

Java Android可恢复写入特性锁定onCharacteristicWrite/onCharacteristicChange

Java Android可恢复写入特性锁定onCharacteristicWrite/onCharacteristicChange,java,android,bluetooth-lowenergy,bluetooth-gatt,Java,Android,Bluetooth Lowenergy,Bluetooth Gatt,我有一个发送消息缓冲区的消息线程。在特征写入下一条消息之前,每条消息排队发送一次onCharacteristicWrite成功。characteristic也被设置为WRITE\u TYPE\u NO\u RESPONSE,因此消息缓冲队列在特征写调用之间非常快(大约0-7ms) 主要问题:“堵塞”特征 在大多数情况下,这非常有效。当存在大量消息时,问题似乎会出现(可能发生在消息较少的情况下,但在发送大量消息时更为明显)。发生的情况是,writeCharacteristic将被调用,并且该特性似

我有一个发送消息缓冲区的消息线程。在特征写入下一条消息之前,每条消息排队发送一次
onCharacteristicWrite
成功。characteristic也被设置为
WRITE\u TYPE\u NO\u RESPONSE
,因此消息缓冲队列在特征写调用之间非常快(大约0-7ms)

主要问题:“堵塞”特征

在大多数情况下,这非常有效。当存在大量消息时,问题似乎会出现(可能发生在消息较少的情况下,但在发送大量消息时更为明显)。发生的情况是,
writeCharacteristic
将被调用,并且该特性似乎被锁定,因为
onCharacteristicChanged
不再读取任何新数据,并且无法访问
onCharacteristicWrite

我注意到的其他事情:

    private boolean stopMessageThread = false;
    private boolean characteristicWriteSuccessful = true;
    private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
    private Thread messageThread =  new Thread( new Runnable() {
        private long lastTime = 0;
        private int count = 0;
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted() && !stopMessageThread) {
                if(messageQueue.size() != 0 && characteristicWriteSuccessful) {

                    Log.i(TAG, ""+(System.currentTimeMillis()-lastTime));
                    Log.i(TAG, "Queue count: "+messageQueue.size());

                    characteristicWriteSuccessful = false;
                    byte[] message = messageQueue.remove(0);
                    customCharacteristic.setValue(message);
                    boolean status = bluetoothGatt.writeCharacteristic(customCharacteristic);

                    Log.i(TAG, "write characteristic status "+status);

                    lastTime = System.currentTimeMillis();
                    //sleep(10); // this kinda helps but can still throw the error
                }
            }
        }
    });
  • 在每次
    characteristicWrite
    之后添加5-10ms的睡眠延迟似乎是可行的 帮助,但我不明白当
    onCharacteristicWrite
    返回成功时,Bluetooth GATT对象为什么需要延迟

  • 有时我会在
    onConnectionStateChange
    中收到一个回调,状态为8,设备超出范围。但这种情况并不总是发生

  • 有时
    characteristicWrite
    返回false;然而,它也可以在进入上述“阻塞特性”状态之前返回true
  • 消息线程代码:

        private boolean stopMessageThread = false;
        private boolean characteristicWriteSuccessful = true;
        private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
        private Thread messageThread =  new Thread( new Runnable() {
            private long lastTime = 0;
            private int count = 0;
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted() && !stopMessageThread) {
                    if(messageQueue.size() != 0 && characteristicWriteSuccessful) {
    
                        Log.i(TAG, ""+(System.currentTimeMillis()-lastTime));
                        Log.i(TAG, "Queue count: "+messageQueue.size());
    
                        characteristicWriteSuccessful = false;
                        byte[] message = messageQueue.remove(0);
                        customCharacteristic.setValue(message);
                        boolean status = bluetoothGatt.writeCharacteristic(customCharacteristic);
    
                        Log.i(TAG, "write characteristic status "+status);
    
                        lastTime = System.currentTimeMillis();
                        //sleep(10); // this kinda helps but can still throw the error
                    }
                }
            }
        });
    
    private boolean stopMessageThread=false;
    私有布尔特征WriteSuccessful=true;
    private ArrayList messageQueue=new ArrayList();
    私有线程messageThread=newthread(newrunnable()){
    私有长lastTime=0;
    私有整数计数=0;
    @凌驾
    公开募捐{
    而(!Thread.currentThread().isInterrupted()&&!stopMessageThread){
    if(messageQueue.size()!=0&&characteristicWriteSuccessful){
    Log.i(标记“+(System.currentTimeMillis()-lastTime));
    Log.i(标记,“队列计数:”+messageQueue.size());
    characteristicWriteSuccessful=假;
    字节[]消息=消息队列。删除(0);
    customCharacteristic.setValue(消息);
    布尔状态=bluetoothGatt.writeCharacteristic(customCharacteristic);
    Log.i(标签,“写入特征状态”+状态);
    lastTime=System.currentTimeMillis();
    //sleep(10);//这有点帮助,但仍然会抛出错误
    }
    }
    }
    });
    
    除了繁忙的等待(可能会阻塞整个CPU并迅速耗尽电池)之外,我看不到任何同步。存在共享数据结构(可能是
    stopMessageThread
    characteristicWriteSuccessful
    messageQueue
    )和多个线程访问它们。如果没有同步,竞争条件将发生,阻塞可能就是这种情况的一种表现

    因此,我建议采用一种更简单的设计,特别是没有发送消息的线程:

    private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
    private boolean isSending = false;
    
    void sendMessage(byte[] message) {
        synchronized (this) {
            if (isSending) {
                messageQueue.add(message);
                return;
            }
            isSending = true;
        }
        customCharacteristic.setValue(message);
        bluetoothGatt.writeCharacteristic(customCharacteristic);
    }
    
    public void onCharacteristicWrite (BluetoothGatt gatt, 
                    BluetoothGattCharacteristic characteristic, 
                    int status) {
        byte[] message;
        synchronized (this) {
            if (messageQueue.size() == 0) {
                isSending = false;
                return;
            }
            message = messageQueue.remove(0);
        }
        customCharacteristic.setValue(message);
        bluetoothGatt.writeCharacteristic(customCharacteristic); 
    }
    
    private ArrayList messageQueue=new ArrayList();
    私有布尔isSending=false;
    无效发送消息(字节[]消息){
    已同步(此){
    如果(正在结束){
    messageQueue.add(message);
    回来
    }
    isSending=true;
    }
    customCharacteristic.setValue(消息);
    bluetoothGatt.书面特征(客户特征);
    }
    关于特征的公共无效写入(蓝牙gatt,
    蓝牙特征,
    int状态){
    字节[]消息;
    已同步(此){
    if(messageQueue.size()==0){
    isSending=false;
    回来
    }
    message=messageQueue.remove(0);
    }
    customCharacteristic.setValue(消息);
    bluetoothGatt.书面特征(客户特征);
    }
    
    此解决方案中的假设是
    writeCharacteristic
    不会阻塞并且速度很快。这是一个安全的假设,因为该方法在设计上是异步的:它有一个回调,当操作完成时将调用该回调

    因此,回调
    onCharacteristicWrite
    用于发送缓冲区中的下一条消息。因此,对线程的需求消失了——相关的复杂性也消失了


    在从后台线程调用回调时,仍涉及多个线程。因此,对共享数据的访问是同步的。

    除了繁忙的等待(这会阻塞整个CPU并迅速耗尽电池)之外,我看不到任何同步。存在共享数据结构(可能是
    stopMessageThread
    characteristicWriteSuccessful
    messageQueue
    )和多个线程访问它们。如果没有同步,竞争条件将发生,阻塞可能就是这种情况的一种表现

    因此,我建议采用一种更简单的设计,特别是没有发送消息的线程:

    private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
    private boolean isSending = false;
    
    void sendMessage(byte[] message) {
        synchronized (this) {
            if (isSending) {
                messageQueue.add(message);
                return;
            }
            isSending = true;
        }
        customCharacteristic.setValue(message);
        bluetoothGatt.writeCharacteristic(customCharacteristic);
    }
    
    public void onCharacteristicWrite (BluetoothGatt gatt, 
                    BluetoothGattCharacteristic characteristic, 
                    int status) {
        byte[] message;
        synchronized (this) {
            if (messageQueue.size() == 0) {
                isSending = false;
                return;
            }
            message = messageQueue.remove(0);
        }
        customCharacteristic.setValue(message);
        bluetoothGatt.writeCharacteristic(customCharacteristic); 
    }
    
    private ArrayList messageQueue=new ArrayList();
    私有布尔isSending=false;
    无效发送消息(字节[]消息){
    已同步(此){
    如果(正在结束){
    messageQueue.add(message);
    回来
    }
    isSending=true;
    }
    customCharacteristic.setValue(消息);
    bluetoothGatt.书面特征(客户特征);
    }
    关于特征的公共无效写入(蓝牙gatt,
    蓝牙特征,
    int状态){
    字节[]消息;
    已同步(此){
    if(messageQueue.size()==0){
    isSending=false;
    回来
    }
    message=messageQueue.remove(0