Einzelnen Beitrag anzeigen

toenne

Registriert seit: 13. Jan 2011
14 Beiträge
 
#1

XE5 + Android + Bluetooth = Problem

  Alt 24. Sep 2015, 22:30
Ich möchte eine BT-Kommunikation zwischen einem Android-Smartphone und einem Atmel µC realisieren.
Aktueller Versuchsaufbau: Ein HC05 Bluetoothmodul hängt über einen USB/TTL-Wandler am Rechner, auf selbigen läuft HTerm als Terminalprogramm. Starte ich auf dem Smartphone ein BT-Terminalprogramm aus dem Playstore so kann ich Daten hin- und herschicken.
Aus einem etwas umfangreicheren Code (https://www.youtube.com/watch?v=vesPd5WvykA ; Code ist in den Kommentaren verlinkt) und diesen Units http://www.pclviewer.com/android/ habe ich ein Testprojekt gebaut, bei dem auf einer Form ein Label liegt auf dem Text ausgegeben werden soll, der vorher vom PC über den HC05 gesendet und vom Smartphone über BT empfangen wurde. Ferner wird dieser Text direkt wieder retour geschickt und dann in HTerm angezeigt.
Unit und Form habe ich mal angehängt, hier auch nochmal zum direkten Lesen der Code:

Code:
unit BTUnit3;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  Androidapi.JNI.BluetoothAdapter,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNIBridge,
  Android.JNI.Toast,
  FMX.ListBox, FMX.Layouts, FMX.Memo, FMX.Edit, FMX.Objects, FMX.ListView.Types,
  FMX.ListView, System.Rtti, FMX.Grid, Data.Bind.GenData,
  System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.EngExt,
  Fmx.Bind.DBEngExt, Data.Bind.Components, Data.Bind.ObjectScope;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    OutLabel2: TLabel;
    procedure FormShow(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    targetMAC:string;                     // remote MAC address of the selected
    targetName: string;
    ostream:JOutputStream;
    istream:JInputstream;
    uid:JUUID;                            // UUID for SPP traffic
    Sock:JBluetoothSocket;
    Adapter:JBluetoothAdapter;            // Local BLUETOOTH adapter
    remoteDevice:JBluetoothDevice;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormShow(Sender: TObject);
var
  s:string;
  i:integer;
  list:TStringList;
begin
  list:=TStringList.Create;
  s:=checkBluetooth;                      // Make sure bluetooth is enabled
  Toast(s);
  if pos('disabled',s)<>0 then exit;

  // This is the well known SPP UUID for connection to a Bluetooth serial device
  uid:=TJUUID.JavaClass.fromString(stringtojstring('00001101-0000-1000-8000-00805F9B34FB'));

  list.Clear;
  list.AddStrings(getbonded);   // produce a list of bonded/paired devices

  for i := 0 to list.Count-1 do
  begin
   targetName := list[i].Split(['='])[0];
   targetMAC := list[i].Split(['='])[1];
   if targetName = 'HC05' then
    begin
     Adapter:=TJBluetoothAdapter.JavaClass.getDefaultAdapter;
     remoteDevice:=Adapter.getRemoteDevice(stringtojstring(targetMAC));
     Toast('Connecting to ' + targetName +' (' + targetMAC + ')');
     sock:=remoteDevice.createRfcommSocketToServiceRecord(UID);
     try sock.connect;
      except Toast('Could not create service record!');
     end;
     if not sock.isConnected then
      begin
       Toast('Failed to connect to '+targetMAC+'! Try again...');
       exit;
      end;
     Toast('Connected!');

     ostream:=sock.getOutputStream;          // record io streams
     istream:=sock.getInputStream;

     Application.ProcessMessages;
     sleep(200);

     timer1.Enabled:=True;
    exit;
    end;
   end;

end;


procedure TForm1.Timer1Timer(Sender: TObject);
var
  len,i:integer;
  s:string;
  buffer:TJavaArray<byte>;
begin
  len:=istream.available;
  if len=0 then exit;
  timer1.Enabled := false;
  buffer:=TJavaArray<byte>.create(len);
  istream.read(buffer,0,len);

  s:='';
  for i:=0 to len-1 do
  begin
   s := s + chr(buffer[i]);
   ostream.write(buffer[i]);
  end;
  OutLabel2.text := s;
  FillChar(buffer, SizeOf(buffer), 0);
  timer1.Enabled:=True;

end;

end.
Eigentlich ganz simpel: Es wird eine Devicelist erstellt, geprüft ob das HC05 drin vorkommt und dann direkt mit selbigen verbunden.
Über einen Timer - hier mit 0.5s Preset, Wert spielt aber letztlich keine Rolle - wird geprüft ob ein InputStream vorliegt,selbiger im Label ausgegeben und danach wieder zurück geschickt.
Generell funktioniert das, aber mit einer Merkwürdigkeit: Es wird immer erst nur ein Zeichen ausgegeben, dann jeweils Pakete von 9-11 Zeichen der übrigen Zeichen und zuletzt die noch überzähligen Zeichen. Die Pausen dazwischen entsprechen dem Timerpreset.
Beispiel: Gebe ich '0123456789abcdefghijklmnopqrstuvwxyz' in HTerm ein so ist die Ausgabe auf dem Label nacheinander
0
(0.5s Pause)
123456789
(0.5s Pause)
abcdefghij
(0.5s Pause)
klmnopqrs
(0.5s Pause)
tuvwxyz
Die zurückgesendeten Daten erscheinen in HTerm in genau den gleichen Paketen, allerdings in einer Zeile (also ohne CRLF), aber ebenso mit den Pausen dazwischen.
Hat irgend jemand eine Idee woraus dieses merkwürdige Verhalten resultiert? Vor allem merkwürdig dass generell zu Beginn nur ein Zeichen erscheint, in den Paketen danach dann aber die Länge (ohne nachvollziehbare Logik) zwischen 9 und 11 Zeichen schwankt? Wieso wird es überhaupt un Pakete zerlegt?
Ich stehe komplett auf dem Schlauch...

Danke!
Angehängte Dateien
Dateityp: zip bt.zip (2,1 KB, 34x aufgerufen)
  Mit Zitat antworten Zitat