BLE на Android не может вызвать onCharacteristicChanged()

Вопрос или проблема

Я пытаюсь разработать демон BLE связи. Сервер BLE работает на плате с Linux и модулем Bluetooth, сервер разработан с использованием python-dbus, а часть характеристик показана ниже

class DapUsrInfoCharacteristic(bluetooth_gatt.Characteristic):
    bonded = False
    def __init__(self, bus, index, service):
        bluetooth_gatt.Characteristic.__init__(
                self, bus, index,
                bluetooth_constants.DAP_CHR_UUID,
                ['read', 'write', 'notify'],
                service)
                # ['encrypt-authenticated-read', 'encrypt-authenticated-write', 
                #  'notify'],
                # service)

    def ReadValue(self, options):
        # Замените это на фактическое значение для чтения
        show_log(LOG_LEVEL.INFO, "Чтение значения от клиента")
        return dbus.ByteArray([0x01])

    def WriteValue(self, value, options):
        # self.do_notify(value)
        self.callback(CallbackType.BLE_RECVD_MSG, value)
        # self.parse_msg_from_client(value)

    def StartNotify(self):
        show_log(LOG_LEVEL.INFO, "начало уведомлений")
        self.notifying = True

    def StopNotify(self):
        show_log(LOG_LEVEL.INFO, "остановка уведомлений")
        self.notifying = False

    def register_callback(self, callback):
        self.callback = callback

    def do_notify(self, value):
        self.StartNotify()
        if not self.notifying:
            show_log(LOG_LEVEL.INFO, "Нет уведомлений")
            return
        show_log(LOG_LEVEL.INFO, f"Отправка сообщения клиенту: {value}")

        self.PropertiesChanged(bluetooth_constants.GATT_CHARACTERISTIC_INTERFACE, {'Value': value}, [])
        show_log(LOG_LEVEL.INFO, f"Сообщение отправлено клиенту: {value}")

    def parse_msg_from_client(self, value):
        msg_type = int(value[0])
        if msg_type == BLE_MSG_TYPE.BONDED.value:
            self.bonded = bool(value[1])
            show_log(LOG_LEVEL.INFO, f"Статус связи: {self.bonded}")
            self.callback(CallbackType.BLE_BONDED, None)
        else:
            show_log(LOG_LEVEL.INFO, f"Неизвестный тип сообщения: {value}")

BLE клиент — это телефон на Android, я могу читать и записывать значение характеристики на сервере BLE. Однако это не работает, когда я хочу подписаться на уведомления для характеристики, самый связанный участок кода Android показан ниже:

/* Обратный вызов Gatt */
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        ...

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            Log.d(TAG, "Статус записи дескриптора: " + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "Дескриптор записан");
                mainHandler.post(() ->  eventSink.success("Дескриптор записан"));
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            Log.d(TAG, "------------------");
            byte[] value = characteristic.getValue();
            Log.d(TAG, "Характеристика изменена: " + Arrays.toString(value));
            mainHandler.post(() ->  eventSink.success("Характеристика изменена: " + Arrays.toString(value) + "\n"));
        }
    };

/*Включить уведомление характеристики*/
boolean isEnableNotification =  bluetoothGatt.setCharacteristicNotification(targetCharacteristic, true);
if (!isEnableNotification) {
                    Log.e(TAG, "Не удалось включить уведомление");
                    return;
                }
                Log.d(TAG, "Уведомление характеристики включено");

                List<BluetoothGattDescriptor> descriptors = targetCharacteristic.getDescriptors();
                Log.d(TAG,"Всего дескрипторов: " + descriptors.size());
                for (BluetoothGattDescriptor descriptor : descriptors) {
                    Log.d(TAG, "Дескриптор: " + descriptor.getUuid().toString());
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    boolean isWriteDesp = bluetoothGatt.writeDescriptor(descriptor);
                    Log.d(TAG, "Статус записи дескриптора: " + isWriteDesp);
                }
                Log.d(TAG, "Завершена запись дескрипторов");        

Не могли бы вы дать несколько советов? Большое спасибо!

Не могли бы вы дать несколько советов? Большое спасибо!

Ответ или решение

Здравствуйте!

Проблема, с которой вы сталкиваетесь, связана с тем, что метод onCharacteristicChanged() в вашем клиенте Android не вызывается, несмотря на успешную запись дескриптора и настройку уведомлений для характеристик. Давайте рассмотрим несколько моментов, которые могут помочь вам решить эту проблему.

  1. Проверка UUID характеристики: Убедитесь, что вы используете правильный UUID характеристики как в Android клиенте, так и на сервере. Этот UUID должен совпадать с тем, который вы определили на сервере.

  2. Запись дескриптора уведомлений: Убедитесь, что вы правильно записываете дескриптор уведомлений. В вашей реализации вы устанавливаете ENABLE_NOTIFICATION_VALUE и ENABLE_INDICATION_VALUE, что может вызвать путаницу. Попробуйте использовать только одно из значений:

    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    // или
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
  3. Проверка состояния уведомлений: Убедитесь, что метод StartNotify() на сервере успешно выполняет свою задачу. Вы можете добавить дополнительную отладочную информацию внутри этого метода, чтобы удостовериться, что уведомления действительно начинаются.

  4. Проверка логики обратного вызова: Убедитесь, что ваш сервер правильно вызывает метод do_notify(value), когда нужно отправить уведомление. Возможно, стоит временно добавить больше отладочных логов, чтобы увидеть, фактически ли вызывается этот метод и что он передает клиенту.

  5. Асинхронность и потоки: Так как взаимодействие с Bluetooth может быть асинхронным, убедитесь, что ваша логика обработки данных (например, как вы обрабатываете данные, полученные из метода onCharacteristicChanged) выполняется в подходящем потоке. Возможно, стоит добавить дополнительную обработку ошибок, чтобы увидеть, не происходит ли каких-либо исключений.

  6. Проблемы с совместимостью: Некоторые устройства могут иметь ограничения на уровне BLE стеков. Если проблема сохраняется, попробуйте протестировать на другом устройстве с Android.

  7. Тестирование с помощью сторонних приложений: Попробуйте использовать сторонние приложения для BLE, такие как nRF Connect или LightBlue Explorer. Это позволит проверить, работает ли уведомление на более низком уровне, что может помочь вам определить, является ли проблема в вашем коде или на сервере.

  8. Перезапуск соединения: В некоторых случаях проблема может быть связана с самим соединением. Попробуйте сбросить соединение и снова подключиться к устройству, когда вы включили уведомления.

Если после выполнения всех этих шагов проблема останется, пожалуйста, предоставьте дополнительные логи или информацию, чтобы мы могли помочь более детально. Удачи в вашем проекте!

Оцените материал
Добавить комментарий

Капча загружается...