시작하기
nRF52 DK에 있는 NFC 기능을 이용하여 안드로이드 스마트폰의 애플리케이션을 자동으로 실행시키는 예제에 대해서 알아보도록 하자.
Android Application Record (AAR)이라고 불리는 메시지에 스마트폰에 설치되어 있는 애플리케이션의 패키지 이름을 포함시켜 실행시킬 수 있다. iOS는 지원하지 않으므로 참고하시기 바랍니다.
record_launch_app 예제는 nRF52 DK의 NFC 안테나와 스마트폰을 태그 하면 LED1이 켜지고 nRF Toolbox 애플리케이션이 실행된다.
\examples\nfc\record_launch_app\pca10040\blank\ses 폴더에서 프로젝트를 열어보자.
/** @snippet [NFC Launch App usage_0] */
/* nRF Toolbox Android application package name */
static const uint8_t m_android_package_name[] = {'n', 'o', '.', 'n', 'o', 'r', 'd', 'i', 'c', 's',
'e', 'm', 'i', '.', 'a', 'n', 'd', 'r', 'o', 'i',
'd', '.', 'n', 'r', 'f', 't', 'o', 'o', 'l', 'b',
'o', 'x'};
uint8_t m_ndef_msg_buf[256];
/** @snippet [NFC Launch App usage_0] */
/**
* @brief Function for application main entry.
*/
int main(void)
{
/** @snippet [NFC Launch App usage_1] */
uint32_t len;
uint32_t err_code;
/** @snippet [NFC Launch App usage_1] */
log_init();
/* Configure LED-pins as outputs */
bsp_board_init(BSP_INIT_LEDS);
/* Set up NFC */
err_code = nfc_t2t_setup(nfc_callback, NULL);
APP_ERROR_CHECK(err_code);
/** @snippet [NFC Launch App usage_2] */
/* Provide information about available buffer size to encoding function. */
len = sizeof(m_ndef_msg_buf);
/* Encode launchapp message into buffer */
err_code = nfc_launchapp_msg_encode(m_android_package_name, sizeof(m_android_package_name),
NULL, NULL,
m_ndef_msg_buf, &len);
APP_ERROR_CHECK(err_code);
/** @snippet [NFC Launch App usage_2] */
/* Set created message as the NFC payload */
err_code = nfc_t2t_payload_set(m_ndef_msg_buf, len);
APP_ERROR_CHECK(err_code);
/* Start sensing NFC field */
err_code = nfc_t2t_emulation_start();
APP_ERROR_CHECK(err_code);
while (1)
{
NRF_LOG_FLUSH();
__WFE();
}
}
main 함수를 살펴보면 nfc_t2t_setup, nfc_launchapp_msg_encode, nfc_t2t_payload_set, nfc_t2t_emulation_start 함수를 호출해 NFC를 사용할 수 있다.
먼저 nfc_t2t_setup 함수를 호출해 Type 2 Tag 라이브러리를 통해 NFC를 사용할 수 있도록 설정하고 nfc_callback 함수를 이벤트 핸들러로 등록한다.
ret_code_t nfc_launchapp_msg_encode(uint8_t const * p_android_package_name,
uint8_t android_package_name_length,
uint8_t const * p_win_app_id,
uint8_t win_app_id_length,
uint8_t * p_buf,
uint32_t * p_len)
{
ret_code_t err_code;
/* Create NFC NDEF message description, capacity - 2 records */
NFC_NDEF_MSG_DEF(nfc_launchapp_msg, 1);
/* Create NFC NDEF Windows Phone LaunchApp Record description */
NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC_DEF(nfc_win_launchapp_rec,
p_win_app_id,
win_app_id_length);
/* Create NFC NDEF Android Application Record description */
NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC_DEF(nfc_and_launchapp_rec,
p_android_package_name,
android_package_name_length);
if (p_win_app_id != NULL)
{
/* Add Windows Phone LaunchApp Record as first record to message */
err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_launchapp_msg),
&NFC_NDEF_WINDOWS_LAUNCHAPP_RECORD_DESC(nfc_win_launchapp_rec));
VERIFY_SUCCESS(err_code);
}
if (p_android_package_name != NULL)
{
/* Add Android Application Record as second record to message */
err_code = nfc_ndef_msg_record_add(&NFC_NDEF_MSG(nfc_launchapp_msg),
&NFC_NDEF_ANDROID_LAUNCHAPP_RECORD_DESC(nfc_and_launchapp_rec));
VERIFY_SUCCESS(err_code);
}
VERIFY_FALSE(NFC_NDEF_MSG(nfc_launchapp_msg).record_count == 0,
NRF_ERROR_INVALID_PARAM);
/* Encode whole message into buffer */
err_code = nfc_ndef_msg_encode(&NFC_NDEF_MSG(nfc_launchapp_msg),
p_buf,
p_len);
return err_code;
}
nfc_launchapp_msg_encode 함수의 전달 인자로 안드로이드 애플리케이션 패키지 이름과 크기, 윈도우 애플리케이션 아이디와 크기, 사용할 버퍼와 크기를 넘겨주면 NFC 애플리케이션 실행 메시지로 사용할 버퍼에 인코딩 된다.
여기서는 예제와 다르게 윈도우 애플리케이션 인코딩을 제외하고 진행하도록 하겠다.
NFC 태그 데이터를 설정해줘야 하는데 NDEF 메시지 또는 TLV 구조 중 선택할 수 있으며 여기서는 NDEF 메시지 방식을 사용한다.
nfc_t2t_payload_set 함수의 전달 인자로 인코딩 된 메시지와 크기를 넘겨주면 NFC 페이로드로 설정이 완료된다.
nfc_t2t_emulation_start 함수를 호출해 NFC 태그를 활성화하여 NFC 필드가 감지되면 반응하도록 한다.
예제를 실행하고 스마트폰을 NFC 기본 모드로 설정하고 nRF52 DK의 NFC 안테나에 태그해 보자.
예제가 잘 동작하는 것을 알았으니 이제 NDEF 메시지에 대해서 알아보도록 하자.
NFC Data Exchange Format (NDEF)은 NFC를 통한 데이터 교환에 사용되는 바이너리 포맷으로 이 데이터 포맷은 일반적으로 NFC 장치 및 NFC 태그에 사용된다.
NDEF는 메시지 형태이며 레코드 헤더와 레코드 페이로드로 구성되어 있다.
레코드 헤더에는 다음과 같은 필드로 구성되어 있다.
필드 | 길이 | 필수 | 설명 |
Flags & TNF | 1 byte | Y | 하단에 별도 설명 |
Type Length | 1 byte | Y | 타입 길이 설정 |
Payload Length | 1 또는 4 byte | Y | 페이로드 길이 설정 SR 플래그에 따라 1 또는 4 byte 길이 |
ID Length | 1 byte | N | 페이로드 ID 길이 IL 플래그가 설정된 경우만 필요 |
Payload Type | 가변 | N | NDEF 레코드 페이로드 타입 설정 Type Length가 0인 경우 필수 |
Payload ID | 가변 | N | NDEF 레코드 페이로드 ID 설정, IL 플래그가 설정되고 ID Length가 0인 경우 필수 |
Flag & TNF 필드는 다음과 같이 1 byte로 구성되어 있다.
MB | ME | CF | SR | IL | TNF |
1 bit | 1 bit | 1 bit | 1 bit | 1 bit | 3 bit |
-
MB (Message Begin), ME (Message End) : MB 플래그는 NDEF 레코드의 시작, ME 플래그는 NDEF 레코드의 끝을 설정하는 것으로 레코드가 하나인 경우엔 두 플래그 모두 설정한다.
-
CF (Chunk Flag) : 청크 페이로드(여러 레코드로 분할된 페이로드)를 설정하는 것으로 마지막 레코드를 제외하고 모두 설정한다. 이 라이브러리에서는 지원하지 않는 기능이다.
-
SR (Short Record) : Payload Length의 길이를 결정하는 플래그로 설정된 경우 Payload Length는 1 byte가 되고 설정하지 않은 경우 4 byte가 된다. NDEF 생성기는 현재 4 byte Payload Length만 지원한다.
-
IL (ID Length Present) : 레코드 헤더에 ID Length 설정에 필요한 플래그이다.
-
TNF (Type Name Format) : Payload Type의 구조를 설정하는 플래그로 다음과 같이 정의되어 있다.
값 | Type Name Format |
0x00 | 비어있음 (페이로드 없음) |
0x01 | NFC 포럼에 정의된 타입 (NFC RTD) |
0x02 | 미디어 타입 (RFC 2046) |
0x03 | 절대 URI (RFC 3986) |
0x04 | NFC 포럼에 정의된 규칙에 따른 임의 타입 (NFC RTD) |
0x05 | 정의되지 않은 타입으로 byte 형식 |
0x06 | 청크 페이로드인 경우 사용 |
0x07 | Reserved (사용하지 않음) |
레코드 페이로드는 구현하는 애플리케이션별로 다르며 TNF와 관련이 있다.
record_launch_app 예제를 통해 NDEF 메시지를 자세히 알아보도록 하자.
먼저 스마트폰에 NFC Tools 애플리케이션을 설치를 한다.
NFC Tools 애플리케이션을 실행하고 OTHER 탭에서 Read memory를 선택한 후 nRF52 DK의 NFC 안테나를 태그 하면 안드로이드 애플리케이션에 대한 1개의 레코드를 포함한 NDEF 메시지를 송신하고 있다.
수신된 메모리는 언뜻 봐서는 어떤 데이터인지 감이 오지 않으므로 NDEF 구조에 맞춰 구분을 해보자.
5F | 10 | 57 | 90 | 55 | 04 | D7 | 63 | E5 | 03 |
UID0 | UID1 | UID2 | BCC0 | UID3 | UID4 | UID5 | UID6 | BCC1 | INT |
FF | FF | E1 | 10 | 7C | 0F |
LOCK0 | LOCK1 | OTP0 | OTP1 | OTP2 | OTP3 |
수신된 데이터는 Type 2 Tag 타입이며 위 데이터 구조에 대한 자세한 내용은 NFC 포럼에서 확인할 수 있다.
이후부터의 내용이 NDEF 메시지로 어떤 데이터가 들어있는지 확인해보자.
03 | 35 | C4 | 0F | 00 | 00 | 00 | 20 |
NDEF Message | NDEF Length |
Flag & TNF MB, ME = 1 TNF = 0x04 |
Type Length = 15 |
Payload Length = 32 | |||
TLV Tag |
레코드 헤더 |
61 6E 64 72 6F 69 64 2E 63 6F 6D 3A 70 6B 67 |
android.com:pkg |
타입 |
6E 6F 2E 6E 6F 72 64 69 63 73 65 6D 69 2E 61 6E 64 72 6F 69 64 2E 6E 72 66 74 6F 6F 6C 62 6F 78 | FE |
no.nordicsemi.android.nrftoolbox | Terminator |
페이로드 | TLV Tag |
이러한 구조의 NDEF 메시지를 통해 안드로이드 애플리케이션을 실행할 수 있게 되는 것이다.
이제 NFC 태그를 하면 카카오톡이 실행되도록 소스코드를 수정해보도록 하자.
안드로이드 애플리케이션의 패키지 이름을 알아내는 방법은 다양하지만 여기서는 간단하게 알 수 있는 방법을 소개하겠다.
컴퓨터에서 구글 플레이 스토어에 들어가 카카오톡을 검색해서 들어가면 URL에 패키지 이름을 표기한다.
https://play.google.com/store/apps/details?id 다음에 나오는 com.kakao.talk이 카카오톡의 패키지 이름이다.
static const uint8_t m_kakaotalk_package_name[] = {'c', 'o', 'm', '.', 'k', 'a', 'k', 'a', 'o', '.', 't', 'a', 'l', 'k'};
이렇게 알아낸 패키지 이름을 소스코드에 적용해서 변경하면 NFC 태그를 하면 카카오톡이 실행되는 것을 확인할 수 있다.
'Embedded > nRF52 BLE 개발 안내서' 카테고리의 다른 글
nRF52 BLE 개발하기 - nfc/record_url (1) | 2021.02.24 |
---|---|
nRF 52 BLE 개발하기 - nfc/record_text (0) | 2021.02.24 |
nRF52 BLE 개발하기 - saadc (0) | 2021.02.17 |
nRF52 BLE 개발하기 - pwm_driver (4) | 2021.02.07 |
nRF52 BLE 개발하기 - low_power_pwm (0) | 2021.02.04 |
댓글