• 0
chaplin.u@gmail.com

баг в компоненте TBluetoothLE

Вопрос

Нашёл баг в компоненте TBluetoothLE. По каким-то причинам длина передаваемого массива ограничена 20 байтами. Если посылаешь больше - ничего не передаётся.

Причём в компоненте данные хранятся ( запускаю отсылку - потом читаю = всё есть)  а на устройство не посылается вообще. 

К кому обращаться ? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

50 ответов на этот вопрос

  • 0
15 минут назад, Pax Beach сказал:

Не знаю почему, но у меня компонент BluetoothLE вообще не находит ни одно устройство, ни на ноуте, ни на телефоне.

Трудно что-то тестировать без этого.

 

У меня находит браслеты Xiaomi Miband, но далеко не всегда и не все (из трех - только два находил)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
2 часа назад, Rusland сказал:

У меня находит браслеты Xiaomi Miband, но далеко не всегда и не все (из трех - только два находил)

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

Не знаю, как еще проверить компонент. Может быть BLE можно эмулировать на ноуте?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Потому что это не всякая железка а спец. девайс.

Поэтому я и прошу дать код( компоненту) и я её проверю. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Я не проверял код, но попробуйте.

копируем себе в проект файлик System.android.Bluetooth.pas, он расположен по пути source\rtl\net\

далее находим constructor TAndroidBluetoothGattListener.Create(const ALEDevice: TAndroidBluetoothLEDevice); 

и заменяем на это

constructor TAndroidBluetoothGattListener.Create(const ALEDevice: TAndroidBluetoothLEDevice);
var
  retry: Integer;
  status: Boolean;
begin
  inherited Create;
  FGatt := ALEDevice;

  // вставляем наш код
  retry := 5;
  status := False;
  while (not status) or (retry > 0) do
  begin
    status = FGatt.FJGatt.requestMtu(тут значение);
    dec(retry);
  end;
end;

если в этот момент уже есть доступ к интерфейсу JBluetoothGatt, то все получится.

проверять не на чем, так что дальше сами

Pax Beach понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
54 минуты назад, ZuBy сказал:

Я не проверял код, но попробуйте.

копируем себе в проект файлик System.android.Bluetooth.pas, он расположен по пути source\rtl\net\

далее находим constructor TAndroidBluetoothGattListener.Create(const ALEDevice: TAndroidBluetoothLEDevice); 

и заменяем на это


constructor TAndroidBluetoothGattListener.Create(const ALEDevice: TAndroidBluetoothLEDevice);
var
  retry: Integer;
  status: Boolean;
begin
  inherited Create;
  FGatt := ALEDevice;

  // вставляем наш код
  retry := 5;
  status := False;
  while (not status) or (retry > 0) do
  begin
    status = FGatt.FJGatt.requestMtu(тут значение);
    dec(retry);
  end;
end;

если в этот момент уже есть доступ к интерфейсу JBluetoothGatt, то все получится.

проверять не на чем, так что дальше сами

Я бы согласование все-таки делал в отдельном потоке и проверил на наличие менеджера, а так отлично, должно заработать.

Вот что у меня получилось:

constructor TAndroidBluetoothGattListener.Create(const ALEDevice
  : TAndroidBluetoothLEDevice);
begin
  inherited Create;
  FGatt := ALEDevice;
  // ADDED to increase MTU size - BEGIN
  if FGatt <> nil then
    if (FGatt.FConnectionStatus = TBluetoothDeviceState.Connected) then
      TThread.CreateAnonymousThread(
        procedure
        var
          MTU: Integer;
          status: Boolean;
        begin
          MTU := 525;
          while MTU > 100 do
          begin
            TThread.Synchronize(nil,
              procedure
              begin
                status := FGatt.FJGatt.requestMtu(MTU);
              end);
            if not status then
            begin
              dec(MTU, 100);
            end
            else
            begin
              // FRememberMTUasInteger := MTU; // I think, you need to implement this filed in private section to use in a furure
              break; // all good bro, it needs to exit from the thread
            end;
          end;
        end).Start;
  // ADDED to increase MTU size - END
end;

На счет необходимости синхронизации не уверен, надо пробовать.

Изменено пользователем Pax Beach

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

извиняюсь за ламерство но как этот файл подключить к проекту -_-

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

я вижу что это добавлено в Create а по описанию запрос подаётся после OnConnect

http://stackoverflow.com/questions/36435575/bluetoothgatt-negotiating-new-mtu-succeeds-but-new-size-cannot-be-used-3-bytes

 

Capture.JPG

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

ну ок, держите (в том же файле)

procedure TAndroidBluetoothGattListener.onConnectionStateChange(gatt: JBluetoothGatt; status, newState: Integer);
begin
  FGatt.FConnectionStatus := TBluetoothDeviceState(newState);
  FGatt.FServicesEvent.SetEvent;
  case FGatt.FConnectionStatus of
    TBluetoothDeviceState.None:
      if Assigned(FGatt.OnDisconnect) then
        FGatt.OnDisconnect(FGatt);
    TBluetoothDeviceState.Connected:
      if (not FGatt.FConnecting) and Assigned(FGatt.OnConnect) then
      begin
        if TJBuild_VERSION.JavaClass.SDK_INT >= TJBuild_VERSION_CODES.JavaClass.LOLLIPOP then
          FGatt.FJGatt.requestMtu(64);
        FGatt.OnConnect(FGatt);
      end;
    // TBluetoothDeviceState.Paired:;
  end;
  FGatt.FConnecting := False;
end;

В следующий раз подготовьте как можно больше материала, никому не охото копаться в проблеме тем более не имея на руках нужного девайса.

Если есть код на Java и место куда его вставить, так мы переведём на делфи (по возможности)

Надеюсь ваша проблема решится

Pax Beach понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

добавил в проект. скомпилировал. запустил но наличие этого файла никак не меняет программу. типа ему по-барабану что он есть что нет.

никакого запроса не происходит...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

может не туда вставили ? там кроме TAndroidBluetoothGattListener есть ещё TBluetoothLEAdapter TAndroidBluetoothLEDevice TAndroidBluetoothGattServerListener

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
1 час назад, chaplin.u@gmail.com сказал:

добавил в проект. скомпилировал. запустил но наличие этого файла никак не меняет программу. типа ему по-барабану что он есть что нет.

никакого запроса не происходит...

А точно используется измененный модуль, а не системный?

DCU  файл в каталоге проекта создался?

В режиме отладки в этот метод вообще не заходит отладчик?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Важно, ещё уточнить, на какой версии Андроида пробуете.

Метод введен в API 21, соответственно работать будет на Android 5.0 и выше.

Pax Beach и Равиль Зарипов (ZuBy) понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

файл есть ...\Android\Debug\System.Android.Bluetooth.dcu но я вижу что нужно как сказал ZuBy ещё раз всё уточнить.

1. Устройства я понятно предоставить не могу но и можно без него т.к. речь идёт о добавлении функции/метода к готовой компоненте.

2. Как я понял мульти-платформенность в студии работает перенаправлением вызовов функций в студии к нативным функциям платформы. поэтому в директории c:\Program Files (x86)\Embarcadero\Studio\18.0\source\rtl\net\

есть System.Android.Bluetooth.pas,System.Mac.Bluetooth.pas,System.Win.Bluetooth.pas.

3. В компоненте BluetoothLE есть TBluetoothLEDevice у которого есть  функции/методы  http://docwiki.embarcadero.com/Libraries/Berlin/en/System.Bluetooth.TBluetoothLEDevice.

В этом списке отсутствует function requestMtu(mtu: Integer): Boolean; cdecl; и procedure onMtuChanged(gatt: JBluetoothGatt; mtu: Integer; status: Integer); cdecl;
которые присутсвуют в c:\Program Files (x86)\Embarcadero\Studio\18.0\source\rtl\android\Androidapi.JNI.Bluetooth.pas 

задача в том чтобы подключить их к компоненте. т.е чтобы они появились в меню доступных функций ( см. катинку) и компилятор не матюкнулся когда я напишу FBLEDevice->requestMtu(200)

т.е. ты можешь положить компоненту на форму и проверить что такая функция присутствует. задача выполнена.

 

 

ble.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

в таком случае добро пожаловать на багтрекер, оставьте заявку на включение этого метода в компонент и будет Вам счастье (а может и нет)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Я не считаю себя гуру, но за себя скажу. Что для меня это не нужно и копаться в тонне кода только чтобы вынести один метод наружу. Оформите платную заявку, может кто нить и возьмется

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
3 часа назад, chaplin.u@gmail.com сказал:

файл есть ...\Android\Debug\System.Android.Bluetooth.dcu но я вижу что нужно как сказал ZuBy ещё раз всё уточнить.

1. Устройства я понятно предоставить не могу но и можно без него т.к. речь идёт о добавлении функции/метода к готовой компоненте.

2. Как я понял мульти-платформенность в студии работает перенаправлением вызовов функций в студии к нативным функциям платформы. поэтому в директории c:\Program Files (x86)\Embarcadero\Studio\18.0\source\rtl\net\

есть System.Android.Bluetooth.pas,System.Mac.Bluetooth.pas,System.Win.Bluetooth.pas.

3. В компоненте BluetoothLE есть TBluetoothLEDevice у которого есть  функции/методы  http://docwiki.embarcadero.com/Libraries/Berlin/en/System.Bluetooth.TBluetoothLEDevice.

В этом списке отсутствует function requestMtu(mtu: Integer): Boolean; cdecl; и procedure onMtuChanged(gatt: JBluetoothGatt; mtu: Integer; status: Integer); cdecl;
которые присутсвуют в c:\Program Files (x86)\Embarcadero\Studio\18.0\source\rtl\android\Androidapi.JNI.Bluetooth.pas 

задача в том чтобы подключить их к компоненте. т.е чтобы они появились в меню доступных функций ( см. катинку) и компилятор не матюкнулся когда я напишу FBLEDevice->requestMtu(200)

т.е. ты можешь положить компоненту на форму и проверить что такая функция присутствует. задача выполнена.

ble.png

1. Сейчас не могу найти ссылку, но сам читал, что проблема с согласованием MTU есть только у Android. iOS делает согласование автоматически, Windows начинает согласование с половины октет — 500+ байт. Мне не на чем это проверить, нет под рукой BLE (маячки почему-то компонентом не распознаются как BLE), так что этот момент проверяй сам.

2. Тебе привели правильный код изменения компоненты. Неумение провести своими руками простую отладку сильно усложняет дело, трудно тебе помочь, когда ты не даешь понятную обратную связь.

Поэтому, как сказал Zuby, либо ждать от Идеры изменений в следующем релизе, либо платное задание разместить где-нить.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
44 минуты назад, chaplin.u@gmail.com сказал:

если дело в оплате то можно договориться.

Не уверен, что для кого-то здесь дело в этом.

Просто мы пытаемся разобраться с FMX, и так как устройство только у тебя, а обратная связь скупая, то дальше только пустая трата времени.

Надо искать человека, у которого есть подходящее устройство  БЛЕ и желание копаться с  MTU.

Andrey Efimov понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

устройство тут не причём. я повторюсь что речь идёт о доступе к функции которая описана в Androidapi.JNI.Bluetooth.pas. Должны быть стандартные способы обратиться к этой функции.

Кстати для проверки можно обратиться к любой другой функции (которую ты можешь проверить ) описаной в этом или другом файле в этой-же директории.  

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
10 минут назад, chaplin.u@gmail.com сказал:

устройство тут не причём. я повторюсь что речь идёт о доступе к функции которая описана в Androidapi.JNI.Bluetooth.pas. Должны быть стандартные способы обратиться к этой функции.

Кстати для проверки можно обратиться к любой другой функции (которую ты можешь проверить ) описаной в этом или другом файле в этой-же директории.  

Если бы мы здесь писали в Android Studio или любой другой IDE на JAVA для Android, можно было бы через Android менеджер GATT устройств обратиться к JAVA интерфейсу конкретного устройства BLE и вызвать нужный нам метод.

Но ты ставишь задачу, сделать вызов, работая с устройствами через компонент TBluetoothLE. В Delphi работа с модулем Androidapi.JNI.Bluetooth.pas не явная, этот файл всего лишь обертка для внешней Android библиотеки, вызовы к ее методам осуществляются через патч, работу внесенных изменений можно проверить в процессе отладки на устройстве. Участники написали, что нужно сделать, осталось только протестировать, делается ли вызов метода requestMTU(), проходит ли согласование корректно. Может быть у тебя метод вызывается, но твое BLE не дает согласие на изменение размера пакета.

Хорошая мысль, сделать параметр "MTU_Size" в компоненте, чтобы компонент на любой платформе при сопряжении с устройствами выполнял принудительное согласование MTU. Для этого нужно написать разработчикам, как сказал ранее ZuBy.

 

Равиль Зарипов (ZuBy) понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
В 09.12.2016 в 19:10, ZuBy сказал:

копируем себе в проект файлик System.android.Bluetooth.pas, он расположен по пути source\rtl\net\

далее находим constructor TAndroidBluetoothGattListener.Create(const ALEDevice: TAndroidBluetoothLEDevice); 

и заменяем на это


constructor TAndroidBluetoothGattListener.Create(const ALEDevice: TAndroidBluetoothLEDevice);
var
  retry: Integer;
  status: Boolean;
begin
  inherited Create;
  FGatt := ALEDevice;

  // вставляем наш код
  retry := 5;
  status := False;
  while (not status) or (retry > 0) do
  begin
    status = FGatt.FJGatt.requestMtu(тут значение);
    dec(retry);
  end;
end;

 

Правильно ли я понял что нужно проделать все что выше, бросить компонент BluetoothLE и работать с ним?

Поставил breakpoint на строке FGatt := ALEDevice;

В какой момент должен сработать breakpoint? Когда найдет устройство или когда подконнектиться к нему?

Изменено пользователем Rusland

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу