Перейти к содержанию
Fire Monkey от А до Я
  • 0

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


chaplin.u@gmail.com

Вопрос

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

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

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

Ссылка на комментарий

Рекомендуемые сообщения

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

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

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

 

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

Ссылка на комментарий
  • 0
2 часа назад, Rusland сказал:

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

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

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

 

Ссылка на комментарий
  • 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, то все получится.

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

Ссылка на комментарий
  • 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

я вижу что это добавлено в 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 и место куда его вставить, так мы переведём на делфи (по возможности)

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

Ссылка на комментарий
  • 0

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

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

Ссылка на комментарий
  • 0
1 час назад, chaplin.u@gmail.com сказал:

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

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

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

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

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

Ссылка на комментарий
  • 0
  • Модераторы

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

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

Ссылка на комментарий
  • 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.

Ссылка на комментарий
  • 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.

 

Ссылка на комментарий
  • 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
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...