블루투스 4.0과 안드로이드에서의 통신

2015.07.22 18:29:52

 최근 아이비콘에 대한 관심이 국내외적으로 뜨겁게 일어나고 있다. 아이비콘에 대한 주제를 다루는 세미나들도
자주 열리고 있다. 아이비콘의 기술적인 이슈는 뒤로하더라도 애플이 제시한 하나의 기술에 관심을 많이 갖게 하는 것은 고무적인 현상이라고 생각된다. 


마 스마트폰 모바일 인터넷 환경 제공을 통한 모바일 환경의 변화로 혁신을 추구한 것처럼 접촉이나 근거리 통신을 통해 이루고자 했던 커머스의 변화를 아이비콘을 통해 이루어질 것이라고 예상하는 것이 아닐까 한다. 이번호에서는 블루투스 4.0의 기술적인 부분의 확인을 통해 안드로이드에서의 통신 및 내부 구조에 대해서 좀 더 살펴보고자 한다.



아이비콘과 프락시미티 (Proximity) 프로파일


아이비콘 역시 블루투스 4.0의 스펙을 바탕으로 만들어진 기술이다. 따라서 블루투스에서 제공하는 프로파일, 프락시미티(Proximity) 프로파일을 사용하여 구성되었다. 그림 1은 프락시미티 프로파일의 전체적인 구조를 보여 준다.

그림 1. 프락시미티 프로파일의 구조도


프락시미티 프로파일의 중요한 사용 예는 열쇠나 특정한 물건에 붙여서 물건 분실 방지 기능을 했던 앱세서리와 동일한 구조로 동작한다.


그림 2. 스틱앤파인드 앱세서리 사진.



그림 2는 스틱앤파인드라는 제품으로 리모콘과 같은 제품에 부착하여 제품의 위치를 스마트폰을 통해 찾을 수 있도록 하는 앱세서리 제품이다. 스틱앤파인드라는 제품 역시 프락시미티라는 프로파일을 사용하여 제품의 위치를 찾을 수 있도록 구성하고 있다.


아이비콘은 이 프로파일의 역할을 반대로 사용하여 비콘의 위치를 참조하여 사용자의 위치를 찾거나 매장에서 정보를 전달할 수 있는 구조로 구성한 것이다.


그림 3. 비콘과 스마트폰이 근접했을 때 표시되는 그림


그림 4. 비콘과 스마트폰이 어느 정도 떨어졌을 때 표시되는 그림


그림 5. 비콘과 스마트폰이 통신 가능한 거리 이상일 때 표시되는 그림



따라서 명칭이나 사용방식을 상이하지만 기술적인 배경은 프락시미티라는 블루투스 4.0의 프로파일을 사용하는 것은 동일한 것이다.


프락시미티 프로파일의 특성을 살펴보면 다음과 같은 특징을 확인할 수 있다.


•‌프락시미티 프로파일 장치와 연결 후 연결이 끊어졌을 경우 경보를 보내는 기능
•‌버튼을 눌렀을 때나 기타 상황에 경보를 보내는 기능
•전송 세기를 전달하기 위한 기능.


등이 있다. 아이비콘은 위 기능을 이용하여 비콘과 스마트폰과의 위치를 파악하는데 응용하고 있다.
이제부터 아이비콘에 내장되어 동작되는 소프트웨어의 구조 및 내용에 대해 살펴보도록 하겠다.


다음 소스는 비콘 내부에서 동작하는 소스의 일부분이다. 비콘은 TI의 CC2541이라는 블루투스 칩을 사용하고 있고, 내부에 8051 마이크로 프로세서를 사용한다. 내부 하드웨어를 초기화하고 운용하기 위한 초기 소스다.

________________________________________________________________________________

int main(void)
{
  /* 하드웨어 초기화 */
  HAL_BOARD_INIT();

  // I/O 초기화
  InitBoard( OB_COLD );

  /* HAL 드라이버   초기화 */
HalDriverInit();

  /* NV 시스템   초기화 */
  osal_snv_init();

  /* OS 초기화 */
  osal_init_system();

  /* 인터럽트 활성화 */
  HAL_ENABLE_INTERRUPTS();

  // 보드 초기화
  InitBoard( OB_READY );

  #if defined ( POWER_SAVING )
    osal_pwrmgr_device(   PWRMGR_BATTERY );
  #endif

  /* OSAL 시작 */
  osal_start_system();

  extern void appForceBoot(void);

  appForceBoot();

  return 0;
}

_____________________________________________________________________________

리스트 1. 블루투스 BLE의 내부 소스



비콘의 주요 요소는 비콘을 구성하고 있는 UUID 및 RSSI 정보를 주기적으로 전송하는 것이다. 리스트2는 비콘의 정보를 전달하기 위해서 구성한 내부 정의 내용이다.

_____________________________________________________________________________

#define   IBEACON_CHAR1       0   // UUID
#define   IBEACON_CHAR2       1   // Marjor
#define   IBEACON_CHAR3       2   // Minor
#define   IBEACON_CHAR4       3   // 파워 레벨
#define   IBEACON_CHAR5       4   // LED 상태
#define   IBEACON_CHAR6       5   // 전송 간격
#define   IBEACON_CHAR7       6   // BLE 송신 파워
#define   IBEACON_CHAR8       7   // 소프트웨어 버전

// 아이비콘 서비스 UUID
#define   IBEACON_SERV_UUID             0x2880

#define   UUID_BASE_HEAD                0x70,0xB0
#define   UUID_BASE_TAIL
                  0xDE,0x12,0xA5,0x98,0x1A,0x03,0x34,0xF7,0xAB,0xA8,0x95,0xA2

#define IBEACON_UUID
 0xAA,0xBB,0x11,0x22,0xDF,0xFB,0x48,0xD2,0xB0,0x60,0xD0,0xF5,0xA7,0x10,0x96,0xE0

// UUID
#define   IBEACON_CHAR1_UUID            0x2881
#define   IBEACON_CHAR2_UUID            0x2882
#define   IBEACON_CHAR3_UUID            0x2883
#define   IBEACON_CHAR4_UUID            0x2884
#define   IBEACON_CHAR5_UUID            0x2885
#define   IBEACON_CHAR6_UUID            0x2886
#define   IBEACON_CHAR7_UUID            0x2887
#define   IBEACON_CHAR8_UUID            0x2888

// 아이비콘 서비스 비트 필드
#define   IBEACON_SERVICE                 0x00000001

// 크기
#define   IBEACON_CHAR1_LEN           16
#define   IBEACON_CHAR2_LEN           2
#define   IBEACON_CHAR3_LEN           2 
#define   IBEACON_CHAR4_LEN           1
#define   IBEACON_CHAR5_LEN           1 
#define   IBEACON_CHAR6_LEN           2
#define   IBEACON_CHAR7_LEN           1
#define   IBEACON_CHAR8_LEN           20

____________________________________________________________________________

리스트 2. 아이비콘 프로파일의 내부 구조 소스


아이비콘에서 정보를 구성하는 소스 부분이다. 실재 내부에 있는 구조체에 정보를 할당하고 주기적인 전송시에 정보를 전달하는 역할을 한다.


_______________________________________________________________________________

static gattAttribute_t   iBeaconAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
  // 아이비콘 서비스
  {
    {   ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
      GATT_PERMIT_READ,                         /* permissions */
    0,                                        /*   handle */
    (uint8   *)&iBeaconService            /*   pValue */
  },

    // 속성 정의
    {
      {   ATT_BT_UUID_SIZE, characterUUID },
        GATT_PERMIT_READ,
      0,
        &iBeaconChar1Props
    },

      // 속성 정의 1
      {
        {   ATT_UUID_SIZE, iBeaconChar1UUID },
          GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
          iBeaconChar1
      },
 
      // 중략
 
      // 속성 정의8
      {
        {   ATT_UUID_SIZE, iBeaconChar8UUID },
          GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
          iBeaconChar8
      },
     
      // 사용자 정의 속성
      {
        {   ATT_BT_UUID_SIZE, charUserDescUUID },
          GATT_PERMIT_READ,
        0,
          iBeaconChar8UserDesp
      }
};

______________________________________________________________________________

리스트 3. 아이비콘의 프로파일 내부 소스



 ‌비콘 프로그래밍



그림 6. 스마트폰의 노티피케이션 표시 화면


그림 7. 노티피케이션으로 전달된 상품 정보 화면


그림 8. 프락시미티의 동작 그림



비콘을 이용한 프로그래밍 구조는 비콘에서 송신하는 전파의 정보를 이용하여 비콘과 스마트폰과의 거리를 측정하는 방식이다. 다음 그림은 비콘과 스마트폰의 거리에 따라 위치를 표시해 주는 그림이다. 비콘은 주기적으로 스마트폰으로 정보를 전달하고 이 정보를 이용하여 스마트폰은 위치 정보를 산출하여 표시해 주는 것이다.


물론 아직까지는 비콘에서 전달된 정보가 GPS와 같은 정확한 위치 정보가 아니라 단순한 무선상의 감도(RSSI) 정보이기 때문에 위치를 정확하게 판단하거나 추측하기에는 다소 무리가 있다. 실제 거리를 산출하기 위해서는 많은 테스트 및 알고리즘적인 보완이 필요하다. 이러한 점이 비콘의 문제점이기는 하지만 기술적인 보완을 통해 저렴하게 이용할 수 있는 솔루션이 될 수 있다.


 ‌노티피케이션


노티피케이션 기능은 스마트폰을 가지고 상점 근처에 갔을 때 통보를 해주는 기능을 구현하는 것이다. 사용자의 별도의 동작이 없더라도 상품에 대한 정보나 이벤트 정보를 전달할 수 있기 때문에 유용한 기능이라고 하겠다. 그림 6과 그림 7은 노티피케이션을 통해 스마트폰에 전달된 정보를 보여준다.


노티피케이션의 중요한 기능은 사용자가 스마트폰 화면을 보고 있지 않을 때 사용자에게 관련 정보를 전달해 주는데 있다. 사용자가 스마트폰을 들고 비콘이 설치된 매장 근처를 갈 때 매장의 홍보 정보를 전달해 주는 기능이다. 앞에서 소개한 기능들은 비콘의 기술적인 구현이라고 보면 노티피케이션은 실제 홍보나 상품소개에 유용한 기능이라고 하겠다.


프락시미티는 비콘과 스마트폰과의 실제 위치를 구하는 것이 아니라 근처에 접근했을 때 필요한 정보를 표시해 주는 기능을 한다. 아이비콘 설명에서 보여주는 것처럼 스마트폰이 물건 근처에 왔을 때 제품에 대한 정보를 표시해 주는 기능을 한다. 앞에서 거리를 구하는 기능이 실제 거리와는 오차가 심하기 때문에 실질적으로는 프락시미티 기능을 사용하는 것이 더 유용할 것이라고 생각한다. 그림 8은 프락시미티 기능을 사용해서 상점 근처에 왔을 때 상점에 대한 정보를 표시해 주는 금이다.


 ‌안드로이드 비콘 프로그래밍


안드로이드에서 비콘과의 거리를 계산하는 소스이다. 비콘과의 거리는 상대적인 거리를 계산해 내며 비콘에서 수신 받은 RSSI 정보를 산출하여 계산하게 된다. 또한 여러 개의 비콘을 처리할 수 있도록 하여, 각 비콘과의 거리 정보를 산출하여 이용할 수 있게 구성할 수 있다.


_______________________________________________________________________________

public class DistanceBeaconActivity   extends Activity {

  private static final String TAG =   DistanceBeaconActivity.class.getSimpleName();

  // 위치 계상 상수
  private static final double   RELATIVE_START_POS = 320.0 / 1110.0;
  private static final double   RELATIVE_STOP_POS = 885.0 / 1110.0;

  private BeaconManager beaconManager;
  private Beacon beacon;
  private Region region;

  private View dotView;
  private int startY = -1;
  private int segmentLength = -1;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

      getActionBar().setDisplayHomeAsUpEnabled(true);
    setContentView(R.layout.distance_view);
    dotView = findViewById(R.id.dot);

    beacon = getIntent().getParcelableExtra(ListBeaconsActivity.EXTRAS_BEACON);
    region = new Region("regionid",   beacon.getProximityUUID(), beacon.getMajor(), beacon.getMinor());
    if (beacon == null) {
      Toast.makeText(this, "비콘이 검색되지 않음", Toast.LENGTH_LONG).show();
      finish();
    }

    beaconManager = new BeaconManager(this);
    beaconManager.setRangingListener(new   BeaconManager.RangingListener() {
      @Override
      public void onBeaconsDiscovered(Region   region, final List<Beacon> rangedBeacons) {
        runOnUiThread(new Runnable() {
          @Override
          public void run() {
            // 여러 개의 비콘 처리
            Beacon foundBeacon = null;
            for (Beacon rangedBeacon :   rangedBeacons) {
              if   (rangedBeacon.getMacAddress().equals(beacon.getMacAddress())) {
                foundBeacon = rangedBeacon;
              }
            }
            if (foundBeacon != null) {
                updateDistanceView(foundBeacon);
            }
          }
        });
      }
    });

_____________________________________________________________________________

리스트 4. 비콘 처리 안드로이드 앱 소스



다음 소스는 실제 비콘과의 거리를 계산하는데 사용되는 소스이다. 검색된 비콘과 스마트폰과의 RSSI 정보를 바탕으로 computeDotPosY 함수를 통해 실제 거리를 계산하게 된다.

_____________________________________________________________________________

private void   updateDistanceView(Beacon foundBeacon) {
    if (segmentLength == -1) {
      return;
    }

      dotView.animate().translationY(computeDotPosY(foundBeacon)).start();
  }

  private int computeDotPosY(Beacon beacon) {
    // 비콘과 스마트폰의 위치 계산
    double distance =   Math.min(Utils.computeAccuracy(beacon), 6.0);
    return startY + (int) (segmentLength *   (distance / 6.0));
  }

  @Override
  public boolean   onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() ==   android.R.id.home) {
      finish();
      return true;
    }
    return super.onOptionsItemSelected(item);
  }

____________________________________________________________________________

리스트 5. 비콘과의 거리 계산 소스



다음은 비콘 관리 및 노티피케이션을 처리하는 소스이다. beconManager에서는 비콘에 대한 연결, 정보 관리 등을 처리할 수 있도록 구성되었다. 아이폰과 달리 안드로이드에서는 백그라운드로 비콘에 대한 정보를 검색하고 관리할 수 있는 형태가 되어야 한다. 따라서 비콘에 대한 주기적인 검색은 백그라운드 서비스 형태로 구현되어 동작된다. 또한 노티피케이션 역시 백그라운드로 처리하여 영역에 대한 접근 시 백그라운드에서 이벤트를 발생시키는 구조로 구성된다.

_____________________________________________________________________________

private   BeaconManager beaconManager;
  private NotificationManager   notificationManager;
  private Region region;

  @Override
  protected void onCreate(Bundle   savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.notify_demo);
      getActionBar().setDisplayHomeAsUpEnabled(true);

    Beacon beacon =   getIntent().getParcelableExtra(ListBeaconsActivity.EXTRAS_BEACON);
    region = new Region("regionId",   beacon.getProximityUUID(), beacon.getMajor(), beacon.getMinor());
    notificationManager =   (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    beaconManager = new BeaconManager(this);

    // 백그라운드로 비콘 검색 시간 지정
      beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1),   0);

    beaconManager.setMonitoringListener(new   MonitoringListener() {
      @Override
      public void onEnteredRegion(Region   region, List<Beacon> beacons) {
        postNotification("Entered   region");
      }

      @Override
      public void onExitedRegion(Region   region) {
        postNotification("Exited   region");
      }
    });
  }

_____________________________________________________________________________

리스트6. 노티피케이션 소스



 ‌블루투스 4.0에 대한 관리 소스


_____________________________________________________________________________

public class   LeDeviceListAdapter extends BaseAdapter {

  private ArrayList<Beacon> beacons;
  private LayoutInflater inflater;

  public LeDeviceListAdapter(Context context)   {
    this.inflater =   LayoutInflater.from(context);
    this.beacons = new   ArrayList<Beacon>();
  }

  public void replaceWith(Collection<Beacon>   newBeacons) {
    this.beacons.clear();
    this.beacons.addAll(newBeacons);
    notifyDataSetChanged();
  }

  @Override
  public int getCount() {
    return beacons.size();
  }

  @Override
  public Beacon getItem(int position) {
    return beacons.get(position);
  }

  @Override
  public long getItemId(int position) {
    return position;
  }

  @Override
  public View getView(int position, View   view, ViewGroup parent) {
    view = inflateIfRequired(view, position,   parent);
    bind(getItem(position), view);
    return view;
  }

  private void bind(Beacon beacon, View view)   {
    ViewHolder holder = (ViewHolder)   view.getTag();
      holder.macTextView.setText(String.format("MAC: %s (%.2fm)",   beacon.getMacAddress(), Utils.computeAccuracy(beacon)));
    holder.majorTextView.setText("Major:   " + beacon.getMajor());
    holder.minorTextView.setText("Minor:   " + beacon.getMinor());
      holder.measuredPowerTextView.setText("MPower: " +   beacon.getMeasuredPower());
    holder.rssiTextView.setText("RSSI:   " + beacon.getRssi());
  }

_______________________________________________________________________________

리스트 7. 비콘 관리 소스


 ‌끝으로


지금까지 안드로이드에서 블루투스 처리 및 블루투스 4.0에 대한 정보에 대해서 살펴봤다. 다음호에서부터는 블루투스 4.0을 이용하여 다양한 장치를 이용하는 방법에 대해 살펴보도록 하겠다.



라영호 대표 주식회사 테뷸라


Copyright ⓒ 첨단 & automationasia.net



상호명(명칭) : ㈜첨단 | 등록번호 : 서울,아54000 | 등록일자 : 2021년 11월 1일 | 제호 : 오토메이션월드 | 발행인 : 이종춘 | 편집인 : 임근난 | 본점 : 서울시 마포구 양화로 127, 3층, 지점 : 경기도 파주시 심학산로 10, 3층 | 발행일자 : 2021년 00월00일 | 청소년보호책임자 : 김유활 | 대표이사 : 이준원 | 사업자등록번호 : 118-81-03520 | 전화 : 02-3142-4151 | 팩스 : 02-338-3453 | 통신판매번호 : 제 2013-서울마포-1032호 copyright(c)오토메이션월드 all right reserved