BLE CallBack onCharacteristicChanged не является обратным вызовом - PullRequest
0 голосов
/ 04 августа 2020

Я студент, работающий с BLE, и я не очень хорошо владею английским sh, поэтому, пожалуйста, разберитесь с этим с помощью переводчика Google. Поскольку уведомление BLE не работает во время работы, трудно прикрепить источник, поэтому, пожалуйста, помогите.

boolean success4 = mBluetoothGatt.writeDescriptor(descriptor); ложно, но я не знаю почему.

        // Debugging
        private static final String TAG = "BleManager";

        // Constants that indicate the current connection state
        public static final int STATE_ERROR = -1;
        public static final int STATE_NONE = 0;        // Initialized
        public static final int STATE_IDLE = 1;        // Not connected
        public static final int STATE_SCANNING = 2;    // Scanning
        public static final int STATE_CONNECTING = 13;    // Connecting
        public static final int STATE_CONNECTED = 16;    // Connected

        // Message types sent from the BluetoothManager to Handler
        public static final int MESSAGE_STATE_CHANGE = 1;
        public static final int MESSAGE_READ = 2;
        public static final int MESSAGE_WRITE = 3;
        public static final int MESSAGE_DEVICE_NAME = 4;
        public static final int MESSAGE_TOAST = 5;

        public static final long SCAN_PERIOD = 10000;    // Stops scanning after a pre-defined scan period.
        public static final long SCAN_INTERVAL = 5 * 60 * 1000;

        // System, Management
        private static Context mContext = null;
        Handler mHandler;
        private boolean connect = false;

        // Bluetooth
        private BluetoothAdapter mBluetoothAdapter;
        private BluetoothManager mBluetoothManager;
        private BluetoothGattCharacteristic mcharacteristic;

        private ArrayList<BluetoothDevice> mDeviceList = new ArrayList<BluetoothDevice>();
        private BluetoothDevice mDefaultDevice = null;

        private BluetoothGatt mBluetoothGatt = null;

        private ArrayList<BluetoothGattService> mGattServices
                = new ArrayList<BluetoothGattService>();
        private BluetoothGattService mDefaultService = null;
        private ArrayList<BluetoothGattCharacteristic> mGattCharacteristics
                = new ArrayList<BluetoothGattCharacteristic>();
        private ArrayList<BluetoothGattCharacteristic> mWritableCharacteristics
                = new ArrayList<BluetoothGattCharacteristic>();
        private BluetoothGattCharacteristic mDefaultChar = null;


        // Parameters
        private int mState = -1;

        private void BleManager() {

            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            mState = STATE_NONE;
            mContext = this;
            if (mContext == null) {return;}
            else
            {
                scanLeDevice(true);
            }

        }

        public synchronized void finalize() {
            // Make sure we're not doing discovery anymore
            if (mBluetoothAdapter != null) {
                mState = STATE_IDLE;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                disconnect();
            }

            mDefaultDevice = null;
            mBluetoothGatt = null;
            mDefaultService = null;
            mGattServices.clear();
            mGattCharacteristics.clear();
            mWritableCharacteristics.clear();

            if (mContext == null)
                return;

            // Don't forget this!!
            // Unregister broadcast listeners
            // mContext.unregisterReceiver(mReceiver);
        }

        /*****************************************************
         *  Private methods
         ******************************************************/

        /**
         * This method extracts UUIDs from advertised data
         * Because Android native code has bugs in parsing 128bit UUID
         * use this method instead.
         */

        private void stopScanning() {
            if (mState < STATE_CONNECTING) {
                mState = STATE_IDLE;
            }
            scanLeDevice(false);
            //mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }

        /**
         * Check services and looking for writable characteristics
         */
        private int checkGattServices(List<BluetoothGattService> gattServices) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.e("# BluetoothAdapter", " not initialized");
                return -1;
            }

            for (BluetoothGattService gattService : gattServices) {
                // Default service info

                Log.e("# GATT Service:", " " + gattService.getUuid().toString());

                // Remember service
                mGattServices.add(gattService);

                // Extract characteristics
                List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
                for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {

                    // Remember characteristic
                    mGattCharacteristics.add(gattCharacteristic);
                    for (BluetoothGattDescriptor descriptor:gattCharacteristic.getDescriptors()){
                        Log.e("# GATT Char:", gattCharacteristic.getUuid().toString());
                        Log.e(TAG, "BluetoothGattDescriptor: " + descriptor.getUuid().toString());
                    }

                    boolean isWritable = isWritableCharacteristic(gattCharacteristic);
                    if (isWritable) {
                        mWritableCharacteristics.add(gattCharacteristic);
                    }

                    boolean isReadable = isReadableCharacteristic(gattCharacteristic);
                    if (isReadable) {
                        readCharacteristic(gattCharacteristic);
                    }

                    if (isNotificationCharacteristic(gattCharacteristic) && gattCharacteristic.getUuid().toString().equals("0000ffe1-0000-1000-8000-00805f9b34fb")) {

                        setCharacteristicNotification(gattCharacteristic, true);

                        if (gattCharacteristic.getUuid().toString().equals("0000ffe1-0000-1000-8000-00805f9b34fb")) {
                            Log.e("default", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                            mDefaultChar = gattCharacteristic;
                            Log.e("default", "////////////////////////////////////////////// " + mDefaultChar.getUuid().toString());
                            //break;
                        }
                    }
                }
            }

            return mWritableCharacteristics.size();
        }

        private boolean isWritableCharacteristic(BluetoothGattCharacteristic chr) {
            if (chr == null) return false;

            final int charaProp = chr.getProperties();
            if (((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) |
                    (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) {
                Log.e("# Found writable", " characteristic");
                return true;
            } else {
                Log.e("# Not writable", " characteristic");
                return false;
            }
        }

        private boolean isReadableCharacteristic(BluetoothGattCharacteristic chr) {
            if (chr == null) return false;

            final int charaProp = chr.getProperties();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                Log.e("# Found readable", " characteristic");
                return true;
            } else {
                Log.e("# Not readable", " characteristic");
                return false;
            }
        }

        private boolean isNotificationCharacteristic(BluetoothGattCharacteristic chr) {
            if (chr == null) return false;

            final int charaProp = chr.getProperties();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                Log.e("# Found notification", " characteristic");
                return true;
            } else {
                Log.e("# Not notification", " characteristic");
                return false;
            }
        }

        /**
         * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
         * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
         * callback.
         *
         * @param characteristic The characteristic to read from.
         */
        public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.e("# BluetoothAdapter", " not initialized");
                return;
            }
            mBluetoothGatt.readCharacteristic(characteristic);
        }

        /**
         * Enables or disables notification on a give characteristic.
         *
         * @param characteristic Characteristic to act on.
         * @param enabled        If true, enable notification.  False otherwise.
         */
        public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                                  boolean enabled) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.e("# BluetoothAdapter ", "not initialized");
                return;
            }
            characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);

            boolean success1 = mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
            //00002902-0000-1000-8000-00805f9b34fb
            //public static String CLIENT_CHARACTERISTIC_CONFIG = "0000ffe1-0000-1000-8000-00805f9b34fb";
            Log.e("info1",characteristic.getUuid().toString() + " // " + characteristic.getValue() + " // " + enabled + " // " + success1);
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
            Log.e("info2",characteristic.getUuid().toString() + " // " + characteristic.getValue() + " // " + enabled);
            boolean success3 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            boolean success2 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
            Log.e("info3",characteristic.getUuid().toString() + " // " + characteristic.getValue() + " // " + enabled + " // " + success3 + " // " + success2);
            //boolean success5 = mBluetoothGatt.writeCharacteristic(characteristic);
            boolean success4 = mBluetoothGatt.writeDescriptor(descriptor);
            Log.e("info4",descriptor.getCharacteristic() + " // " + descriptor.getValue() + " // " + descriptor.getPermissions() + " // " + descriptor.getUuid() + " // " + enabled + " // " + success4);

            //mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        }


        /*****************************************************
         *  Public methods
         ******************************************************/

        public int getState() {
            return mState;
        }

    private void scanLeDevice(final boolean enable) {
        mHandler = new Handler();
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                }
            }, SCAN_PERIOD);

            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

        private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if(device.getName() != null && device.getName().equals("AINTEL_MFD") && connect == false){
                                connect = true;
                                scanLeDevice(false);
                                Log.e("ScanDevice",device.getName() + " // " + device.getUuids() + " // " + device.getAddress() + " // " + rssi + " // " + scanRecord[0] + " // " + scanRecord[1]);
                                connectGatt(Vars.mContext,false, device);
                            }
                        }
                    });
                }
            };

        public boolean scanLeDevice(final boolean enable, UUID[] uuid) {
            boolean isScanStarted = false;
            if (enable) {
                if (mState == STATE_SCANNING)
                    return false;

                if (mBluetoothAdapter.startLeScan(uuid, mLeScanCallback)) {
                    mState = STATE_SCANNING;
                    mDeviceList.clear();

                    // If you want to scan for only specific types of peripherals
                    // call below function instead
                    //startLeScan(UUID[], BluetoothAdapter.LeScanCallback);

                    // Stops scanning after a pre-defined scan period.
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            stopScanning();
                        }
                    }, SCAN_PERIOD);

                    isScanStarted = true;
                }
            } else {
                if (mState < STATE_CONNECTING) {
                    mState = STATE_IDLE;
                }
                stopScanning();
            }

            return isScanStarted;
        }

        public boolean connectGatt(Context c, boolean bAutoReconnect, BluetoothDevice device) {
            if (c == null || device == null)
                return false;

            mGattServices.clear();
            mGattCharacteristics.clear();
            mWritableCharacteristics.clear();

            mBluetoothGatt = device.connectGatt(c, bAutoReconnect, mGattCallback);
            mDefaultDevice = device;

            mState = STATE_CONNECTING;
            return true;
        }

        public boolean connectGatt(Context c, boolean bAutoReconnect, String address) {
            if (c == null || address == null)
                return false;

            if (mBluetoothGatt != null && mDefaultDevice != null
                    && address.equals(mDefaultDevice.getAddress())) {
                if (mBluetoothGatt.connect()) {
                    mState = STATE_CONNECTING;
                    return true;
                }
            }

            BluetoothDevice device =
                    BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
            if (device == null) {
                Log.e("# Device not found. ", "Unable to connect.");
                return false;
            }

            mGattServices.clear();
            mGattCharacteristics.clear();
            mWritableCharacteristics.clear();

            mBluetoothGatt = device.connectGatt(c, bAutoReconnect, mGattCallback);
            mDefaultDevice = device;

            mState = STATE_CONNECTING;
            return true;
        }

        /**
         * Disconnects an existing connection or cancel a pending connection. The disconnection result
         * is reported asynchronously through the
         * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
         * callback.
         */
        public void disconnect() {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.e("# BluetoothAdapter", " not initialized");
                return;
            }
            mBluetoothGatt.disconnect();
        }

        public boolean write(BluetoothGattCharacteristic chr, byte[] data) {
            if (mBluetoothGatt == null) {
                Log.e(TAG, "# BluetoothGatt not initialized");
                return false;
            }

            BluetoothGattCharacteristic writableChar = null;

            if (chr == null) {
                if (mDefaultChar == null) {
                    for (BluetoothGattCharacteristic bgc : mWritableCharacteristics) {
                        if (isWritableCharacteristic(bgc)) {
                            writableChar = bgc;
                        }
                    }
                    if (writableChar == null) {
                        Log.e(TAG, "# Write failed - No available characteristic");
                        return false;
                    }
                } else {
                    if (isWritableCharacteristic(mDefaultChar)) {
                        Log.e("# Default", "is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
                        writableChar = mDefaultChar;
                    } else {
                        Log.e("# De ", "is not writable");
                        mDefaultChar = null;
                        return false;
                    }
                }
            } else {
                if (isWritableCharacteristic(chr)) {
                    Log.e("# user ", "GattCharacteristic is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
                    writableChar = chr;
                } else {
                    Log.e("# user ", "GattCharacteristic is not writable");
                    return false;
                }
            }

            writableChar.setValue(data);
            writableChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
            mBluetoothGatt.writeCharacteristic(writableChar);
            mDefaultChar = writableChar;
            return true;
        }

        public void setWritableCharacteristic(BluetoothGattCharacteristic chr) {
            mDefaultChar = chr;
        }

        public ArrayList<BluetoothGattService> getServices() {
            return mGattServices;
        }

        public ArrayList<BluetoothGattCharacteristic> getCharacteristics() {
            return mGattCharacteristics;
        }

        public ArrayList<BluetoothGattCharacteristic> getWritableCharacteristics() {
            return mWritableCharacteristics;
        }


        /*****************************************************
         *  Handler, Listener, Timer, Sub classes
         ******************************************************/

        // Various callback methods defined by the BLE API.
        private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    mState = STATE_CONNECTED;
                    Log.e(TAG, "# Connected to GATT server.");

                    gatt.discoverServices();

                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    mState = STATE_IDLE;
                    Log.e(TAG, "# Disconnected from GATT server.");
                    mBluetoothGatt = null;
                    mGattServices.clear();
                    mDefaultService = null;
                    mGattCharacteristics.clear();
                    mWritableCharacteristics.clear();
                    mDefaultChar = null;
                    mDefaultDevice = null;
                }
            }

            @Override
            // New services discovered
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.e(TAG, "# New GATT service discovered.");
                    checkGattServices(gatt.getServices());
                } else {
                    Log.e(TAG, "# onServicesDiscovered received: " + status);
                }
            }

            @Override
            // Result of a characteristic read operation
            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    // We've received data from remote
                    Log.e(TAG, "# Read characteristic11111: " + String.format("%02X",characteristic.getValue()));

                /*
                 * onCharacteristicChanged callback receives same message
                 *
                final byte[] data = characteristic.getValue();
                if (data != null && data.length > 0) {
                    final StringBuilder stringBuilder = new StringBuilder(data.length);
                    //for(byte byteChar : data)
                    //  stringBuilder.append(String.format("%02X ", byteChar));
                    stringBuilder.append(data);
                    Log.e(TAG, stringBuilder.toString());

                    mHandler.obtainMessage(MESSAGE_READ, new String(data)).sendToTarget();
                }

                if(mDefaultChar == null && isWritableCharacteristic(characteristic)) {
                    mDefaultChar = characteristic;
                }
                */
                }
            }

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                // We've received data from remote
                byte[] newValue = characteristic.getValue();
                Log.e(TAG, "# onCharacteristicChanged: " + String.format("%02X",newValue));

                final byte[] data = characteristic.getValue();
                if (data != null && data.length > 0) {
                    final StringBuilder stringBuilder = new StringBuilder(data.length);
                    //for(byte byteChar : data)
                    //  stringBuilder.append(String.format("%02X ", byteChar));
                    stringBuilder.append(data);
                    Log.e(TAG, stringBuilder.toString());
                }

                if (mDefaultChar == null && isWritableCharacteristic(characteristic)) {
                    mDefaultChar = characteristic;
                }
            }
        };
    }

1 Ответ

0 голосов
/ 04 августа 2020

3 вещи:

  • Сначала убедитесь, что у вас есть разрешения. Требуется Manifest.permission.BLUETOOTH permission.
  • Убедитесь, что ваша характеристика c верна.
  • Замените onDescriptorWrite и проверьте, что вы сделали с writeDescriptor оттуда. Если есть проблема, onDescriptorWrite сообщит вам.

Документы Google о BLE не так хороши. Поэтому эта замечательная статья поможет вам решить любую проблему с BLE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...