Android / Windows之间的蓝牙通信,缺少消息

时间:2019-07-11 06:43:32

标签: android windows multithreading delphi bluetooth

我正在尝试编写一个小的蓝牙协议,用于从Android设备向Windows设备发送B64编码的消息,反之亦然。 为此,我使用封装在一个类中的3个线程。

  TBluetooth = class
  private
    FBTReceiveThread: TBTReceiveThread;
    FBTSendThread: TBTSendThread;
    FBTMsgHandlerThread: TBTMsgHandlerThread;
    FBluetoothManager: TBluetoothManager;
    FServiceName: String;
    FServiceGUID: String;
    function ManagerConnected(): Boolean;
  public
    constructor create(const AServicename: STring; const aGuid: String; const AValue: TBluetoothOnMsgReady);
    destructor Destroy(); override;
    function ListPairedDevices: TBluetoothDeviceList;
    function getDeviceFromAdress(const Aadress: String): TBluetoothDevice;
    function sendMessage(const aData: STring; const aIdentifier: STring; const Aadress: String;
      const HighPriority: Boolean): TGuid;
    procedure startListening;
    // procedure stopListening;
    procedure SetBluetoothOnError(const AValue: TBluetoothOnError);
    procedure SetBluetoothOnMSGReady(const AValue: TBluetoothOnMsgReady);
    procedure SetBluetoothSendStatus(const AValue: TBLuetoothSendStatus);
    property BluetoothOnMSGReady: TBluetoothOnMsgReady write SetBluetoothOnMSGReady;
    property BluetoothOnError: TBluetoothOnError write SetBluetoothOnError;
    property BluetoothSendStatus: TBLuetoothSendStatus write SetBluetoothSendStatus;
  end;

一种用于发送消息,一种用于接收消息,一种用于组合消息的各个部分。

SendThread

手动拆分消息,以更好地控制它们的发送时间,并在重新审视端轻松组合它们。 我正在将消息部分添加到队列中,并且“ sendthread”正在将它们一一发送。

procedure TBTSendThread.Execute;
var
  msgToSend: TBtMsgRec;
  msgHeader, statusstr: String;
  fData: TBytes;
begin
  inherited;
  while not terminated do
    try
      if (FQueue.Count > 0) then
      begin
        TMonitor.Enter(FLock);
        try
          msgToSend := FQueue.First;
          FQueue.Delete(0);
          FSocket := msgToSend.targetDevice.CreateClientSocket(StringToGuid(FServiceGUID), True);
          FSocket.Connect;

          msgHeader := msgToSend.Identifier + '|' + GUIDToString(msgToSend.FGuid) + '|' + inttoStr(msgToSend.Length) +
            '|' + inttoStr(msgToSend.part) + '/' + inttoStr(msgToSend.max) + '|';
          fData := TEncoding.UTF8.GetBytes(msgHeader + msgToSend.Data);
          FSocket.SendData(fData);
          if (msgToSend.part = msgToSend.max) then
            dec(fQueueCount);
          if assigned(FGetSendStatus) then
            Synchronize(
              procedure
              begin
                FGetSendStatus(msgToSend.FGuid, msgToSend.Length, msgToSend.part, msgToSend.max, fQueueCount);
              end);
          Sleep(50);
        finally
          TMonitor.Exit(FLock);
          FSocket.close;
        end;
      end;
    except
      on e: Exception do
      begin
        Synchronize(
          procedure
          begin
            if assigned(FBLuetoothOnError) then
              FBLuetoothOnError(e);
          end);
      end;
    end;
end;

接收线程

接收线程读取Socket的缓冲区,并将原始字符串传递给msghandler线程。

procedure TBTReceiveThread.Execute;
var
  FSocket: TBluetoothSocket;
  ok: Boolean;
  LData: TBytes;
begin
  inherited;
  while not terminated do
    try
      FSocket := FServerSocket.Accept(500);
      if FSocket <> nil then
      begin
        ok := True;
        while ok do
          try
            LData := FSocket.ReceiveData;
            if (Length(LData) > 0) and assigned(FMsgHandlerThread) then
              FMsgHandlerThread.addRawMsg(TEncoding.UTF8.GetString(LData));
          except
            ok := false;
          end;
        SetLength(LData, 0);
        //sleep(50);
      end;
    except
      on e: Exception do
      begin
        Synchronize(
          procedure
          begin
            if assigned(FBLuetoothOnError) then
              FBLuetoothOnError(e);
          end);
      end;
    end;
end;

MSGHandler线程

MSGHandler线程获取原始字符串并将其组合成完整的消息。当它收到消息的最后一部分时,会将已完成的消息移交。

  procedure TBTMsgHandlerThread.Execute();
var
  msg: TBtMsgRec;
  NewMsg: Boolean;
  i: Integer;
begin
  inherited;
  while not terminated do
  begin
    if (FRawMsgList.Count > 0) then
    begin
      msg := parseMsg(FRawMsgList.First);
      FRawMsgList.Delete(0);
      NewMsg := True;

      for i := 0 to FParsedMsgList.Count - 1 do
        if (msg.FGuid = FParsedMsgList[i].FGuid) then
        begin
          NewMsg := false;
          msg.Data := FParsedMsgList[i].Data + msg.Data;
          FParsedMsgList.Delete(i);
          if (msg.part = msg.max) then
            Synchronize(
              procedure
              begin
                if assigned(FBluetoothOnMsgReady) then
                  FBluetoothOnMsgReady(msg);
              end)
          else
            FParsedMsgList.add(msg);
          break;
        end;
      if NewMsg then
        if msg.max = 1 then
          Synchronize(
            procedure
            begin
              if assigned(FBluetoothOnMsgReady) then
                FBluetoothOnMsgReady(msg);
            end)
        else
          FParsedMsgList.add(msg);
    end;
  end;
end;

问题摘要:

发送(通过回调通知我有关发送消息的状态进行监视)和合并部分工作正常,但某些消息未达到其目标。我看不到模式,可惜没有错误消息。

我认为问题出在我对线程的使用上。我的理论是,接收方线程以某种方式错过了一些消息。 因此,我尝试提高接收线程的优先级,并更改线程的睡眠时间。即使我认为在线程中使用睡眠不是一个好主意。但这是我第一次使用线程,并且大多数用于蓝牙通信的代码示例都使用它。

编辑:

procedure TBTMsgHandlerThread.addRawMsg(ARawMsg: String);
begin
  Synchronize(
    procedure
    begin
      FRawMsgList.add(ARawMsg);
    end);
end;

0 个答案:

没有答案