[XE8] 모바일 앱에서 클래식 블루투스를 이용해 데이터 전송하기

2015.07.27 18:16

지난 7월 24일 사물인터넷 앱 개발 with RAD Studio 교육을 진행했습니다.

교육이 끝나고 한 교육생분이  "클래식 블루투스로 데이터 전송이 잘되지 않아요."라는 질문을 받고 테스트한 내용 공유합니다.


클래식 블루투스 기능 테스트는 RAD Studio 기본 샘플 중 "Classic Bluetooth Basic app"으로 진행했습니다.

Classic Bluetooth Basic app

RAD Studio XE8 사용자는 다음 경로에서 샘플을 확인할 수 있습니다.

C:\Users\Public\Documents\Embarcadero\Studio\16.0\Samples\Object Pascal\Mobile Samples\Device Sensors and Services\Bluetooth\Classic Bluetooth Basic app


이 샘플은 다음 기능을 포함하고 있습니다.

  • 하나의 앱에서 서버(서비스 생성)와 클라이언트 역할을 모두 제공합니다.
  • 장비를 탐색하고, 페어링하고, 서비스를 탐색합니다.
  • 연결된 서비스로 데이터를 전송하고, 서비스는 데이터를 수신합니다.

❑ 다른 서비스에 접속 시 주의할 점과 처리방법

이 샘플은 문자열 전송 서비스를 목적으로 구현되어 있습니다.(클라이언트 소켁 생성 시 문자열 전송 서비스의 GUID(상수)를 이용해서 클라이언트 소켓을 생성합니다.)

다른 서비스와 접속하도록 하려면 선택한 서비스의 GUID를 이용해 클라이언트 소켓을 생성하도록 수정해야 합니다..


위 내용을 적용하기 위해 아래와 같이 샘플 코드를 변경했습니다.


1, 선택한 서비스의 GUID를 보관하기 위한 변수 선언

서비스 콤보박스(ComboBoxService)에서 선택한 서비스의 GUID를 보관하기 위해 private 영역에 변수를 선언

FServiceGUID: string;


2, 서비스 콤보박스 변경 시 변수에 서비스 GUID 할당

ComboBoxService의 OnChange 이벤트에 선택한 서비스의 GUID를 변수에 할당하도록 구현

procedure TForm1.ComboBoxServicesChange(Sender: TObject);
var
  itemText: string;
begin
  if ComboBoxServices.ItemIndex >= 0 then
  begin
    itemText := ComboBoxServices.Items[ComboBoxServices.ItemIndex];
    FServiceGUID := Copy(itemText,
                          Pos('--> ', itemText) + Length('--> '),
                          Length(itemText));
  end;
end;


3, 선택한 서비스의 GUID로 클라이언트 소켓 생성하도록 수정

상수(ServiceGUI)로 선언된 문자열 전송 서비스 GUID 대신 선택한 서비스의 GUID로 클라이언트 소켓을 생성하도록 아래와 같이 수정

procedure TForm1.SendData;
var
  ToSend: TBytes;
  LDevice: TBluetoothDevice;
begin
  if (FSocket = nil) or (ItemIndex <> ComboboxPaired.ItemIndex) then
  begin
    if ComboboxPaired.ItemIndex > -1 then
    begin
      LDevice := FPairedDevices[ComboboxPaired.ItemIndex] as TBluetoothDevice;
      // [데브기어] 상수로 정의된 서비스 GUID 대신 ComboServices의 GUID 값으로 변경
//      DisplayR.Lines.Add(GetServiceName(ServiceGUI));
      DisplayR.Lines.Add(GetServiceName(FServiceGUID));
      DisplayR.GoToTextEnd;
      // [데브기어] 상수로 정의된 서비스 GUID 대신 ComboServices의 GUID 값으로 변경
//      FSocket := LDevice.CreateClientSocket(StringToGUID(ServiceGUI), False);
      FSocket := LDevice.CreateClientSocket(StringToGUID(FServiceGUID), False);
      if FSocket <> nil then
      begin
// 생략


테스트 환경과 결과

❑ 테스트 환경

테스트는 아래 그림과 같이 블루투스 모듈과 블루투스 모듈을 USB로 연결할 수 있는 USB-TTL 모듈을 이용해 블루투스 데이터를 ComPort로 읽어 오도록 구성했습니다.(관련 장비는 다모아 시스템(www.dma.kr)의 최낙구 대표님께서 제공해 주셨습니다.)


테스트에 사용한 모듈은 아래와 같습니다.

❑ 모바일 앱 - 블루투스 장비와 연결, 데이터 전송


블루투스 장비와 페어링

블루투스 장비와 연결하기 위해서는 페어링 과정이 필요합니다.

[Discover devices] 버튼으로 주변의 장비를 탐색하고, 탐색한 장비 선택 후 [Pair] 버튼으로 페어링 시도합니다.


이미 페어링 되어 있는 장비라면 위 과정을 생략할 수 있습니다.(위 페어링 과정은 OS에서 제공하는 페어링 기능을 이용할 수도 있습니다.)

블루투스 장비로 데이터 전송

페어링된 장비를 선택 후 [Services] 버튼을 누르면 장비에서 제공하는 서비스를 가져올 수 있고, 서비스를 선택 후 [Service Demo] 탭에서 [Send text to] 버튼으로 서비스로 문자열을 전송할 수 있습니다.

COM Port 소프트웨어

위 과정을 통해 모바일에서 전송한 데이터는 블루투스 모듈을 통해 ComPort로 데이터를 수신할 수 있습니다.




저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

험프리.김현수 험프리.김현수 Firemonkey/기능제어 XE8, 블루투스, 클래식 블루투스

  1. 베를린 기준 샘플 컴파일 시 Permission Denied.
    pm에서 블루투스 권한이 하나 안들어가 있어서 다시 부여하고..
    컴파일해서 페어링, 서비스 탐색까지 확인되나
    시리얼 전송 시 Java.IOException 나옵니다.
    해당 샘플에 문제가 있어 보입니다.

    다른 아두이노, 라즈베리, AVR 같은 임베디드 단말이나 마켓에 있는 다른 앱으로는 BT와 시리얼 통신이 잘 이루어집니다.

    테스트 환경은 안드로이드 4.4.2 6.0.1 두가지 입니다.

  2. 글쎄요. 샘플에 문제가 있다고 단정지으면 답이 없어질것 같습니다.(단, 어느 지점이 문제가 있다고 정확한 지적은 발전될 수 있습니다^^)

    저도 처음 시도할때 시행착오를 많이 겪었는데요. 결과적으로 보면 페어링과 연결(GUID)이 잘못된 부분을 찾아내서 해결하니 정상 연결 및 데이터 송수신을 확인할 수 있었습니다.

    문제가 있으시다고 보시면 디버그 모드로 실행하셔서 문제를 확인하고, 문제를 해결하거나 피해가는 형태로 개발해 보시면 반드시 해결할 수 있을 겁니다.

[XE7] 안드로이드 블루투스 활성화 조회와 설정하기

2015.02.12 09:39

일본인 개발자인 山本隆(야마모토 타카시)의 글을 참고해 안드로이드에서 블루투스 활성여부 조회와 설정하는 내용을 공유합니다.

블루투스 활성여부 조회

uses
  Androidapi.JNI.Bluetooth;

procedure TForm2.Button1Click(Sender: TObject);
var
  Adapter: JBluetoothAdapter;
begin
  Adapter := TJBluetoothAdapter.JavaClass.getDefaultAdapter;
  if Adapter.isEnabled then
    ShowMessage('Bluetooth가 활성화 되어있습니다.')
  else
    ShowMessage('Bluetooth가 활성화 되지 않았습니다.');
end;

블루투스 활성화 설정

uses
  Androidapi.JNI.Bluetooth;

procedure TForm2.Button2Click(Sender: TObject);
var
  Adapter: JBluetoothAdapter;
begin
  Adapter := TJBluetoothAdapter.JavaClass.getDefaultAdapter;
  if Adapter.enable then
    ShowMessage('Bluetooth를 활성화합니다.')
  else
    ShowMessage('사용할 수 없습니다.');
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  Adapter: JBluetoothAdapter;
begin
  Adapter := TJBluetoothAdapter.JavaClass.getDefaultAdapter;
  if Adapter.disable then
    ShowMessage('Bluetooth를 비활성화합니다.')
  else
    ShowMessage('사용할 수 없습니다.');
end;

블루투스 권한이 있는지 확인

uses
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText;

procedure TForm2.Button3Click(Sender: TObject);
  function HasPermission(const Permission: string): Boolean;
  begin
    Result := SharedActivityContext.checkCallingOrSelfPermission(StringToJString(Permission)) = TJPackageManager.JavaClass.PERMISSION_GRANTED
  end;

begin
  if HasPermission('android.permission.BLUETOOTH') then
    ShowMessage('Bluetooth 통신 권한이 있습니다.')
  else
    ShowMessage('Bluetooth 통신 권한이 없습니다');

  if HasPermission('android.permission.BLUETOOTH_ADMIN') then
    ShowMessage('Bluetooth 설정 수정 권한이 있습니다.')
  else
    ShowMessage('Bluetooth 설정 수정 권한이 없습니다.');
end;

  • 블루투스 관련 권한(Project Options > Uses Permissions)이 필요합니다.
    • Bluetooth
    • Bluetooth admin

샘플프로그램 다운로드

ProjectSetBluetooth.zip

참고 글


저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

험프리.김현수 험프리.김현수 Firemonkey/기능제어 XE7, 블루투스, 안드로이드

블루투스LE(Bluetooth Low Energy)의 이해

2014.12.05 09:42

RAD Studio XE7에서는 블루투스 라이브러와 컴포넌트를 통해 클래식 블루투스와 블루투스LE(BLE) 통신이 편리해 졌습니다.


컴포넌트가 있더라고 기술의 이해가 있어야 사용하고, 프로젝트에 적용을 할 수 있는데요.

마침 델파이 개발자인 곰순이(장정환)님이 블루투스 LE 관련해 이해하기 쉽게 작성한 글이 있어 공유합니다.

앞으로도 좋은 글 많이 기대하겠습니다.

저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

험프리.김현수 험프리.김현수 Delphi/C++Builder ble, XE7, 블루투스, 블루투스LE