2016년 8월 26일 금요일

라즈베리 파이 제로를 USB 케이블 하나로 사용하기 (Use Raspberry Pi Zero as RNDIS/Ethernet gadget through single USB cable)

라즈베리 파이를 사용할 때 USB 케이블 하나로 전원공급부터 컴퓨터와 네트웍 통신을 해서 ssh로 접속해 제어할 수 있는 방법이 라즈베리 파이 제로를 RNDIS/Ethernet gadget으로 만들어 주는 것이다.



이를 위해서는 먼저 라즈베리 파이 부팅 이미지가 들어있는 sd카드를 PC에 연결해서 내용을 보면 다음과 같은 파일들이 들어 있다.


Raspian SD card 내의 파일
위의 파일들 중에 cmdline.txt와 config.txt 두개의 파일을 수정해야 한다.

먼저 config.txt 파일을 에디터로 열어준다.

config.txt 파일

파일의 맨 마지막 부분에 'dtoverlay=dwc2' 를 추가하고 저장해 준다.

다음은 cmdline.txt 파일을 오픈해서 rootwait 뒷부분에 'modules-load=dwc2,g_ether'를 추가하고 저장해 준다. 여기서 주의할 것은 이 파일에는 엔터키는 사용하지 않는다. 모든 파라미터는 스페이스로 구분된다.

cmdline.txt 수정 전

cmdline.txt 수정 후

이제 모든 변경이 끝났으니 sd 카드를 제거해서 라즈베리 파이 제로에 꼽아주면 된다.

맥의 경우 RNDIS 드라이버를 설치해야 하는데 관련된 내용은 HoRNDIS - 맥용 RNDIS 드라이버 를 참고하면 된다. 단 아쉬운 점은 HoRNDIS가 El Capitan(Mac OS X 10.11)을 지원하지 않아 현재까지는 Yosemite가 설치된 맥에서 까지만 사용할 수 있다.

윈도우의 경우 윈도우 7용 RNDIS 드라이버 설치하기 를 참고해 RNDIS 드라이버를 설치해 주면 된다. 

이제 ssh 클라이언트를 실행해 연결해 보자. 아래 화면은 윈도우용 Tera Term이다. Hostname을 'raspberrypi.local'로 해서 ssh로 연결하면 된다.


첫번째 연결하는 것이면 아래와 같이 security warning이 뜬다. 'Add this machine and its key to the known hosts list'를 체크하고 Continue를 누르면 다음번 부터는 나타나지 않을 것이다.


Username과 Passphrase를 묻는 화면이 나타난다.







디폴트 사용자 이름은 'pi', 암호는 'raspberry' 이다.



로그인이 성공해 프롬프트가 나왔다.


* 'raspberrypi.local' 이름으로 연결이 가능한 건 애플의 Bonjour 기술 덕분이다. 만일 윈도우에서 저 이름으로 접속을 하는데 연결이 안된다면 아이튠즈를 먼저 설치한 다음 다시 시도하면 문제 없이 될 것이다. (아이튠즈를 설치하면 윈도우용 bonjour이 같이 설치되기 때문이다.)

위의 방법으로 하면 편하긴 한데 한가지 문제가 있다.


ifconfig 명령으로 확인해 보면 라즈베리 파이 제로의 네트웍 인터페이스는 usb0인데 그 ip address는 dhcp로 받아오기 때문에 매번 바뀌게 된다.

IP 주소를 고정하려면 /etc/network/interfaces 파일을 수정해 줘야 한다.


에디터로 파일을 열어보면 다음과 같은 내용이 들어 있다.


파일 맨 아래쪽에 빨간색 부분을 추가한 다음 저장해 주면 된다. 아래에서는 라즈베리 파이의 IP주소를 '192.168.10.2'로 지정했다.


이제 라즈베리 파이를 재시동하고 확인해 보면 ip 주소가 바뀐걸 확인할 수 있다.

라즈베리 파이의 설정에 맞춰 pc의 설정도 변경 해 줘야 한다.

윈도우의 경우 먼저 제어판에서 '네트워크 및 공유 센터'를 선택한 다음 '어댑터 설정 변경'을 누른다.


어댑터 중에 RNDIS/Ethernet Gadget을 찾아 선택한 다음 마우스 오른쪽 버튼을 눌러 메뉴에서 '속성'을 선택한다.


Internet Protocol Version 4 (TCP/IPv4)를 선택하고 '속성' 버튼을 누른다.


IP 설정을 넣어주면 된다. 라즈베리 파이가 192.168.10.2를 사용하고 있으므로 윈도우도 192.168.10.x 를 사용해야만 한다. (x는 1~254 사이에서 2를 제외한 임의의 숫자중에 하나)


이제 설정이 끝났으므로 pc에서 라즈베리 파이로 ping을 날려 응답이 오는걸 확인해 보면 된다.



윈도우7용 RNDIS 드라이버 설치하기 (Install RNDIS driver for Windows 7)

RNDIS 장치를 컴퓨터에 연결하면 윈도우가 그에 맞는 디바이스 드라이버를 찾게 된다.



이미 설치되어 있다면 바로 사용할 수 있지만 설치되어 있지 않으면 아래와 같은 메시지가 나오게 된다.



그러면 장치관리자로 가서 보면 RNDIS 가 드라이버가 설치되지 않았다고 장치 이름 앞에 노란색으로 '!' 마크가 붙어 있는걸 볼 수 있다.


장치를 선택한 다음 마우스 오른쪽 버튼을 눌러 '드라이버 소프트웨어 업데이트...'를 선택한 다.


디바이스 드라이버 검색방법을 물으면 '컴퓨터에서 드라이버 소프트웨어 찾아보기'를 선택한다.


그러면 '드라이버 소프트웨어 업데이트' 창이 열리게 된다. 그 창에서 '컴퓨터의 장치 드라이버 목록에서 직접 선택'을 선택해 준다.


그러면 디바이스의 종류를 묻는 창이 나타난다. 여기서 'Network adapters'를 선택하고 'Next'를 눌러준다.


그러면 아래 창이 나오게 된다. 왼쪽의 제조업체에서 'Microsoft Corporation'을 선택하면 오른쪽에 두 종류의 네트워크 어댑터가 보이는데 이 중에 'Remote NDIS Compatible Device'를 선택하고 'Next' 버튼을 눌러준다.


아래와 같은 화면이 나오면 RNDIS 드라이버가 정상 설치된 것이다. 이제부터 USB에 연결한 RNDIS 장치가 네트웍장치로 보일 것이다. 

이제 장치관리자에 가 보면 RNDIS/Ethernet Gadget 드라이버가 정상적으로 설치된 걸 볼 수 있다.




2016년 8월 22일 월요일

라즈베리 파이 3 시리얼/블루투스 문제 (Raspberry Pi 3 UART/Bluetooth problem)

라즈베리 파이에는 디버그 콘솔용 또는 시리얼 통신을 위한 핀이 40핀 커넥터에 나와 있다.

위의 그림에서 처럼 8/10번 핀이 각각 TxD, RxD가 된다.


위의 사진과 같은 USB-to-Serial(TTL level) converter를 사용해 PC와 연결해서 시리얼 통신을 할 수 있다.


이렇게 연결해 주면 된다.

컴퓨터에서 시리얼 에뮬레이터를 실행하고 통신속도를 115200bps로 맞춰 준 다음 라즈베리 파이에 전원을 공급하면 시리얼 에뮬레이터 화면에 이런 내용들이 출력되게 된다.

그런데 라즈베리 파이 2까지는 아무 문제가 없었던 것이 라즈베리 파이 3를 동일하게 연결하면 위와 같은 내용이 나오지 않고 이상하게 깨진 글자가 나오게 된다.

저렇게 깨진 글자가 나오게 되는 이유는 통신 속도가 틀려서이다.

원인을 이해하기 위해 라즈베리 파이의 내부 구조를 살펴보겠다.

라즈베리 파이 1B/B+는 BCM2835, 2는 BCM2836 SoC를 사용하고 있는데 여기에는 각각 2개의 UART가 들어 있는데 UART0는 Full UART, UART1은 mini UART이다. 여기서 UART0는 /dev/ttyAMA0로 사용되고 UART1은 /dev/ttyS0로 사용된다.

위의 그림처럼 mini UART는 몇가지 제약이 있지만, 40핀 커넥터의 8/10번 핀은 full UART의 Tx/Rx로 연결되어 있으므로 아무 문제가 없다.

하지만 라즈베리 파이 3로 오면서 블루투스가 추가되는 바람에 문제가 복잡해졌다.

먼저 하드웨어 구조를 살펴 보자.


위의 사진이 라즈베리 파이 1/2의 구조이다. 시리얼 포트 핀이 UART0에 연결되어 있다.


라즈베리 파이 3로 오면서 무선랜/블루투스 기능 추가를 위해 Broadcom의 BCM43438 칩을 사용하고 있는데 무선랜 기능은 SDIO로 연결하지만 블루투스 기능은 UART0으로 연결을 하고 시리얼 포트 핀은 UART1에 연결되도록 구조가 변경되었다. 그러므로 그 동안 아무 문제 없이 시리얼 포트를 사용하던 프로그램이 라즈베리 파이 3로 오면서 블루투스를 사용하게 되면 제대로 동작을 할 수 없게 되어 버린 것이다.

또한 코드의 /dev/ttyAMA0를 /dev/ttyS0로 변경한다고 해도 문제가 남는다.

UART1의 통신 속도는 다음 공식에 의해 결정된다.


라즈베리 파이 3의 경우 부팅시의 코어 동작 주파수는 400MHz이고 디폴트 baud rate는 115200 bps이다. 즉 위의 공식은...


이 된다. 여기서 baudRateReg는 부팅시에 코어 동작 주파수에 의해 계산된다.

그런데 전력소비를 줄이기 위해 frequency scaling 기능을 사용하고 있기 때문에 시스템 로드가 작은 경우 코어 동작 주파수를 250MHz로 줄일 수 있다. baudRateReg 값은 고정되어 있는데 시스템 클럭 주파수가 변동되기 때문에 결과적으로 baudrate도 따라서 바뀌게 되어 버린다.


즉 코어가 400MHz로 동작할 때는 115200bps로 동작하던 시리얼 포트가 코어 동작 속도가 250MHz가 되면 시리얼 포트 통신속도가 72004 bps로 바뀌어 버리기 때문에 위쪽의 그림처럼 깨진 글자가 나오게 되는 것이다.

그러므로 headless system (모니터 없이 사용하는 경우)에서 시리얼 디버그 콘솔을 사용하거나, UART를 사용하는 RPi shield(GPS/GSM, RS232 등등)를 사용하거나, 시리얼 포트로 다른 프로세서와 통신을 하는 경우 등에는 치명적인 문제가 될 수 있다.

이 문제의 해결책으로는 먼저 부팅시 코어 동작 속도를 고정해 버리는 것이다.

예전 펌웨어를 사용하는 경우 /etc/config.txt 파일에 "core_freq=250" 또는 "force_turbo=1"을 추가해 주는 것이다. 이렇게 하면 코어 동작 속도를 각각 최소 또는 최대(400MHz)로 고정시켜 버리게 된다. 최소로 고정시키면 RPi3의 성능에 영향을 미치게 되고, 최대로 고정시키면 방열대책을 신경 써 줘야 한다. 하지만 최대로 고정시켰다 하더라도 전압이 떨어지거나 코어 온도가 매우 높게 올라가면 250MHz로 쓰로틀링 될 수 있다는걸 주의해야 한다.

새 펌웨어의 경우에는 /boot/config.txt 파일에 "enable_uart=1"을 추가해주면 된다. 앞으로 모든 RPi distribution은 이 옵션을 다 지원하게 될 것이다. 이는 "core_freq=250"과 유사하지만 좀 더 명확한 의도를 표현한다. 이 옵션을 지원하는 distros인 경우 "enable_uart=1"이 활성화 되지 않으면 디버그 콘솔을 비활성화 시켜 놓는다. "enable_uart=1"에 대해 Raspberry Pi Foundation의 엔지니어 Phil Elwell이 상세히 설명 해 놓았다. https://github.com/raspberrypi/firmware/issues/553#issuecomment-199486644

두번째 방법으로는 디바이스 트리 오버레이로 40핀 헤더의 핀 매핑을 바꿔 Full UART를 사용하게 해 주는 것이다.

원래는 위의 사진에서 왼쪽같이 되어 있는데 오른쪽같이 되도록 변경하는 것이다. 이를 위해서는 '/boot/config.txt'에 'dtoverlay=pi3-disable-bt'를 추가해 주거나, '/boot/config.txt'에 'dtoverlay=pi3-miniuart-bt'를 추가해 주면 된다.

'dtoverlay=pi3-disable-bt'를 추가해주면 UART1을 사용하지 않는걸로 해서 블루투스를 비활성화 시킨다. 이 경우 라즈비안에서는 "sudo systemctl disable hciuart" 명령을 추가로 실행해 줘야 한다.

'dtoverlay=pi3-miniuart-bt'를 추가해 주는 경우는 블루투스가 mini-UART를 사용한다. 이를 위해 '/boot/config.txt'에 'core_freq=250' 또는 'force_turbo=1'이 들어가 있어야 한다. 또한 라즈비안의 경우 '/lib/systemd/system/hciuart.service'의 ttyAMA0를 ttyS0로 수정해 줘야 한다. 그리고 이 때는 블루투스의 성능에 제한이 생길 수 있기 때문에 저속 BLE만 실질적으로 사용하는데 문제가 없다.

위의 어떤 옵션을 사용하건 'enable_uart=0'을 넣어주지 않는 한 시리얼 콘솔은 활성화 되어 있다.

즉 위의 설명을 요약하자면 다음과 같다.

* 시리얼 콘솔과 일반적인 블루투스를 사용하고 싶은 경우 (/boot/config.txt 파일을 수정)
  - 코어 주파수를 고정
  - "core_freq=250" 또는 "force_turbo=1"을 추가 (old 펌웨어인 경우)
  - "enable_uart=1" (만일 동작 주파수를 고속으로 고정하고 싶으면 "force_turbo=1"을 추가)

* 고속 시리얼을 사용하고 싶은 경우
  - UART0와 UART1 핀을 교체
  - 블루투스를 사용할 수 없는 경우
    + "dtoverlay=pi3-disable-bt"
    + (라즈비안) "sudo systemctl disable hciuart"를 실행
  - 저속 블루투스 클래식 또는 BLE
    + "dtoverlay=pi3-miniuart-bt" 와 "core_freq=250" 또는 "force_turbo=1"중의 하나를 추가
    + (라즈비안) "/lib/systemd/system/hciuart.service" 파일의 "ttyAMA0"를 "ttyS0"로 수정
  - 디버그 콘솔을 비활성화 시키려면 "disable_uart=0" 추가
* Mini UART를 사용하려면 항상 코어 주파수를 고정할 필요가 있음


2016년 8월 16일 화요일

라즈베리 파이를 에디스톤 URL 비콘으로 사용하기 (Use Raspberry Pi as an Eddystone URL beacon)

이전 포스트인 라즈베리 파이를 비콘으로 사용하기를 먼저 보기를 권한다.

Eddystone beacon


Eddystone은 구글이 만든 프로토콜로 BLE 디바이스가 URL을 메시지로 브로드캐스트 할 수 있게 해 준다. Eddystone에 관한 자세한 내용은 github를 보면 된다. 현재 스펙은 3가지 타입(UID, URL, telemetry)의 브로드캐스트 메시지를 정의하고 있다.

Eddystone 비콘의 마법은 스마트폰 쪽에서 이 브로드캐스트 메시지를 기다리고 있다가 메시지를 받으면경고 메시지를 표시하거나 특정 동작을 수행할 수 있다.

이 튜토리어에서는 라즈베리 파이를 eddystone beacon으로 사용하는 방법을 보여준다.

Setting up the Pi


$ hciconfig
$ sudo hciconfig hci0 up
$ sudo hciconfig hci0 leadv 3
$ sudo hcitool -i hci0 cmd 0x08 0x0008 17 02 01 06 03 03 aa fe 0f 16 aa fe 10 00 02 77 65 62 67 61 7a 65 72 08 00 00 00 00 00 00 00 00

 바로 위의 명령 payload를 상세히 보면 다음과 같다.

0x08 - OGF (Operaton Group Field) -> Bluetooth Command Group (0x08)
0x0008 - OCF (Operation Command Field) -> HCI_LE_Set_Advertising_Data (0x0008)
17 - Length (23 bytes)
  02 - Length
    01 - Flags Data type value
    06 - Flags Data
  03 - Length
    03 - Complete list  of 16-bit Service UUID data type value
    aa - 16-bit Eddystone UUID
    fe - 16-bit Eddystone UUID
  0f - Length
    16 - Service Data data type value
    aa - 16-bit Eddystone UUID
    fe - 16-bit Eddystone UUID
    10 - Frame type -> URL
    00 - TX Power (calibrated)
    02 - URL Scheme 02 -> http://
    77 - 'w'
    65 - 'e'
    62 - 'b'
    67 - 'g'
    61 - 'a'
    7a - 'z'
    65 - 'e'
    72 - 'r'
    08 - 08 -> '.org'
  00 - 
  00 - 
  00 - 
  00 - 
  00 - 
  00 - 
  00 - 
  00 - 

위의 명령은 URL 'http://webgazer.org' 를 브로드캐스트 한다.
만일 다른 URL을 advertise하고 싶으면 아래 박스에 원하는 URL을 입력하면 그에 해당하는 명령을 자동으로 만들어 준다.


 
위의 명령을 라즈베리 파이에 입력해 주면 이제부터 라즈베리 파이가 Eddystone URL beacon으로 동작하게 된다. 아이폰에서 PhyWeb이나 안드로이드에서 크롬을 사용해 보면 링크가 뜨는걸 확인할 수 있다.

* 모든 설정이 끝났는데 안드로이드에서 비콘이 보이지 않는 경우 원인은 거의 99.9% 이상이 URL주소가 https:// 로 시작하지 않아서이다. 어떤 이유로...아마도 man in the middle attack에 대해 방어하기 위해 안드로이드의 크롬은 URL이 secure하기를 요구한다. 그러지 않으면 비콘이 발견되어도 트리거 되지 않는다.

LoRaWAN 네트웍 소개 - 암스텔담의 경우


“그것을 만들면 그가 올 것이다” 1989년 영화인 “Field of Dreams”에서 허공에서 속삭이는 소리였다. 케빈 코스트너 캐릭터는 자라서 “그”가 누군지는 미스터리일지라도 “그것”이 야구장이라는걸 확신하게 된다. 그래서 코스트너는 옥수수밭을 쟁기질해서 야구장을 만들어 다음에 무엇이 올 때 까지 고집스럽게 기다린다.

TTN(The Thins Network)의 창립자는 비슷한 게임을 하고 있다. 하지만 여기서 “그것”은 가입이 필요 없는 커뮤니티 기반의 LoRaWAN 네트웍으로 암스텔담을 커버해서 “그”는 도시에 설치될 상상할 수도 없이 많은 배터리로 동작하는 와이어리스 디바이스를 사용한 수없이 무수한 솔루션이 될 수 있다.





LoRaWAN(Long Range Wide-Area Network)은 저소비전력, 장거리, 저대역폭 네트웍 솔루션으로 스마트 시티에 이상적이다. LoRaWAN의 핵심에는 Semtech이 만든 작은 칩이 있는데 대량인 경우 $1 정도에 구매가 가능하다. 이 칩은 433MHz, 868MHz (대부분의 유럽), 915MHz(USA) 주파수 대역에서 0.3Kbps~50Kbps 정도의 양방향 통신이 가능하다. IoT에 있어 LoRaWAN은 스마트폰에 있어 3G/4G와 같은 역할을 한다.

주차장 공간이 비어 있으면 통보를 해 주거나, 주변의 전기차 충전기가 사용중이 아니면 알려주는 동네에 살고 있다고 상상해 보자. 쓰레기통이 거의 차면 도로에 쓰레기가 흘러넘치기 전에 미화원에게 통보해주는 걸 상상해보자. 집 안의 일산화탄소나 흡연이 감지되면 알림을 보내주는 그림을 그려보자. 또는 창문이 열려 있어 비가 들이치는걸 알려주는걸 상상해보자. 도시가 스마트하면 해외 여행중에도 지갑, 열쇠, 또는 우산을 잃어버렸을 때 찾는걸 도와줄 수 있을 것이다. 이런 것이 모든 디바이스에 3G, WiFi, Bluetooth를 요구하지 않고도  TTN이 암스텔담에서 그리고 있는 미래이다.





LoRaWAN 게이트웨이는 매우 작고 배터리로 동작하는 LoRaWAN 센서 또는 디바이스들과 LoS가 확보되면 15 Km 이상, 건물로 막혀 있어도 몇 Km 내에서 통신을 할 수 있다. LoRaWAN 디바이스는 얼마나 자주 통신을 해야 하는가에 달려있기는 해도 일반적으로 배터리 교환 없이 수년간 동작할 수 있다. 고정 센서의 경우는 작은 태양광 패널을 사용해 실질적으로 반영구적으로 전원 공급이 가능하다.

암스텔담은 작년 8월 개당 $1200인 10개의 게이트웨이를 사용해 LoRaWAN 망이 구축되었다. 겨우 6주만에 커뮤니트 소유의 네트웍이 펀딩되어 특정 통신사의 지원 없이 자원봉사자에 의해 구축되었다. 이 네트웍은 도시 내의 누구건 완전히 무료로 사용할 수 있다. 별도의 가입이나 로그인이 전혀 필요 없다. 그리고 이 비용은 7월에 TTN이 200유로의 LoRaWAN 게이트웨이를 킥스타터 후원자에게 발송하기 시작하면서 극적으로 떨어졌다.



암스텔담의 LoRaWAN 네트웍은 통신 트래픽이 폭증하기 전인 90년대 초반의 인터넷과 닮아 있다. 학생, 호비스트, 벤쳐사업가가 LoRaWAN의 한계를 테스트하고 use case를 식별하기 시작하는 장소이다.

TTN의 창업자 중의 한명인 Wienke Giezeman은 “현재 개발자는 어떤 어플리케이션이 동작할 수 있는가 확인하기 위해 기술을 탐험하고 있다”고 말했다. “이런 실험들을 통해 대규모로 구현될 비즈니스를 지원할 수 있는지 결정하게 될 것이다” Giezeman과 Stokking은 LoRaWAN 기반의 스마트 시티 솔루션이 2017년부터 나오기 시작할 것이라고 기대한다. “우리는 개발자들이 2016년에 훌륭한 어플리케이션을 만들어 2017년에 상용화 할 수 있게 돕는데 초점을 맞추고 있다”

Giezeman과 Stokking은 첫번째 LoRaWAN 솔루션은 도시 서비스를 향상시키기를 원하는 정부에 의해 만들어 질 것이라고 믿는다. 여기에는 쓰레기, 상하수도 관리, 항만 및 공항 트래픽 관리, 도로 정체 관리까지 모든 것을 포함한다. 당장 모든 것이 가능하다.

“그것을 만들면 그가 올 것이다” LoRaWAN 네트웍이 Sao Paulo, Boston, Buenos Aires, Kochi, Sydney를 기반으로 전 세계에 울려퍼지는 목소리이다.  현재 TTN의 커뮤니티 기반 캠패인은 전 세계적으로 36개 도시가 참여하고 있다. LoRaWAN이 90년대 중반 이후의 인터넷에서 본 것 처럼 폭발적으로 증가할지 말하는건 아직 이르다. 하지만 내년 스마트 시티의 23억개로 추정되는 IoT디바이스를 연결할 필요가 있고 이것이 바로 거기에 사용될 수 있는 기술이라는건 명백하다.

2016년 8월 14일 일요일

mbed OS상에서의 physical web과 web bluetooth (Physical Web and Web Bluetooth on mbed OS)

IoT 개발자로서 마주치게 되는 가장 큰 의문은 '사용자가 어떻게 우리 디바이스를 사용할 수 있게 하지?' 이다. 최근 몇년간 이 문제를 해결하는 가장 일반적이고 표준적인 방법은 디바이스 전용 앱을 만드는 것이었다. 하지만 주변에 디바이스가 점점 많아지기 시작하면서 사용자들에게 '또 다른 전용 앱'을 설치하라고 하는게 점점 힘들어지고 있다. 물론 이건 사용자가 그곳에 당신의 디바이스가 있다는걸 알고 있다는 전제 하에서의 이야기이다...디바이스가 있는지 모른다면 저 질문 자체가 성립하지 않을것이다.

그러므로 주변에 있는 IoT 디바이스를 사용하게 하기 위한 더 편한 방법이 필요하게 된다. 단순히 디바이스를 조작하는 것 뿐 아니라 디바이스를 발견할 수 있어야만 한다. 이 두가지 문제를 해결하기 위해 구글은 안드로이드용 크롬 48부터 브라우져에 추가한 두가지 기능은 매우 흥미롭다.

먼저 Physical Web을 추가했는데 이 기능은 운영체제에 통합되어 주변의 블루투스 비콘을 보여준다. Eddystone-URL 프로토콜을 사용해 저가형 BLE 비콘을 가지고 URL을 브로드캐스트하는데 사용할 수 있게 해 주어 주변 디바이스와 상호작용을 할 수 있게 해 준다. 이것은 주차 미터의 결제 포털부터 새로운 장난감을 제어하는 웹 어플리케이션까지 다양한 곳에 적용할 수 있다. 이것만으로도 충분히 흥미롭지만 구글은 Web Bluetooth 지원도 추가해 웹 어플리케이션이 BLE 디바이스와 통신을 할 수 있게 해 주었다.

이 두 기능은 각각 그 자체로도 훌륭하지만, 두 기능을 통합하면 IoT 개발자에게 매우 유용한 기능을 제공해 준다.

1. 디바이스가 URL을 브로드캐스트 해서 주변에 있는 사용자가 디바이스를 발견할 수 있게 해 줌
2. 이 URL이 가르키는 곳에는 사용자가 디바이스를 컨트롤 할 수 있는 웹 앱이 있음

BOOM~! 이제 디바이스 발견 문제와 전용 앱 설치 문제를 해결했다. Physical world에서 디바이스를 발견하는것 부터 발견한 디바이스를 제어하는데 까지 몇초 내로 가능하다. 다음은 이 기능의 데모로 Parrot 드론을 발견하고 그것을 제어하는 비디오이다.



Eddystone beacons are non-connectable


하지만 임베디드 개발자 관점에서 코드를 작성하려고 하면 마주치게 되는 문제는 Eddystone 비콘도 '비콘'이라는 것이다. 비콘의 역할은 특정 위치에서 advertisement 패킷을 브로드캐스트 하는 것이다. 비콘 디바이스는 브로드캐스트만 수행하지 다른 디바이스가 비콘에 연결하는걸 허용하지 않는다. 그러므로 그 디바이스와 통신을 하기 위해 GATT로 연결할 수 없다. 문제를 더 복잡하게 만드는건 Eddystone 프로토콜에는 GATT 서비스 UUID 목록을  보내기 위한 공간이 없기 때문에 다른 어플리케이션이 디바이스가 가지고 있는 기능을 발견할 수 없다는 것이다. 이렇게 되면 사용성이 매우 제한되게 된다. 하지만 개발자로서 이 문제를 해결해 보자.

BLE examples repository에는 mbed OS에서 실행되는 훌륭한 Eddystone 라이브러리가 포함되어 있다. 최근 동료인 Andres Amaya Garcia가 이 라이브러리에 frame scheduling을 위한 몇가지 새로운 기능을 추가했다. 이 기능은 비콘이 URL과 telemetry 데이터를 둘 다 브로드캐스트 할 수 있도록 허용한다. 이는 한 비콘에서 서로 다른 advertisement 패키지를 보냄으로서 가능해졌다.

이 기능은 비콘이 Physical Web/Eddystone URL 비콘과, 연결할 수 있는(connectable) 블루투스 디바이스가 되길 바라는 우리들에게 딱 맞는 기능이다. 매 500ms마다 URL을 브로드캐스트 하고 그 500ms후에 일반 블루투스 프레임을 브로드캐스트 할 수 있다. 이 기능이 다음 라이브러리에 훌륭하게 포함되었다. 'eddystone' 폴더를 자신의 mbed OS 프로젝트 내의 source 폴더에 추가하고 나서 다음과 같이 라이브러리를 초기화 하면 된다.


#include "mbed-drivers/mbed.h"
#include "minar/minar.h"
#include "core-util/FunctionPointer.h"
#include "ble/BLE.h"
#include "eddystone/EddystoneService.h"

using namespace mbed::util;

// Eddystone URL
static const char defaultUrl[] = "https://control.me";
// Normal Beacon name
static char beaconName[] = "I'm a beacon!";
// Service UUIDs for the beacon
static uint16_t uuid16_list[] = { 0x8765 };

static const PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13};
static const PowerLevels_t radioPowerLevels      = {-30, -16, -4, 4};

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    BLE::Instance().gap().startAdvertising(); // restart advertising
}

void onBleInitError(BLE &ble, ble_error_t error)
{
    (void)ble;
    (void)error;
   /* Initialization error handling should go here */
}

void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(ble, error);
        return;
    }

    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);

    // Set up Eddystone
    auto eddyServicePtr = new EddystoneService(ble, defaultAdvPowerLevels, radioPowerLevels, 0);
    eddyServicePtr->setURLData(defaultUrl);
    // The name of the beacon and the service list
    eddyServicePtr->setNormalFrameData(beaconName, strlen(beaconName), uuid16_list, sizeof(uuid16_list));

    // Every 500 ms. Eddystone URL, then Normal frame
    eddyServicePtr->setUIDFrameAdvertisingInterval(0);
    eddyServicePtr->setTLMFrameAdvertisingInterval(0);
    eddyServicePtr->setURLFrameAdvertisingInterval(500);
    eddyServicePtr->setNormalFrameAdvertisingInterval(500);

    eddyServicePtr->startBeaconService();
}

void app_start(int, char**) {
    BLE::Instance().init(bleInitComplete);
}

Seeing it all come together


모든것이 동작하는지 확인하려면 안드로이드 6 버젼 이상을 사용하는 안드로이드 폰이 필요하고 그 폰에 Chrome Dev를 설치해야 한다. 설치한 후에 chrome://flags#enable-physical-web 과 chrome://flags#enable-web-bluetooth 두가지 기능을 활성화 시켜야 한다.


주소창에 'chrome://flags#enable-physical-web'  을 입력한다.


Enable the Physical Web 항목을 선택한다.


Enable the Physical Web 항목을 'Enabled'로 바꿔주면 된다.


주소창에 'chrome://flags#enable-web-bluetooth' 를 입력한다.



Web Bluetooth 항목을 'Enabled'로 바꿔주면 된다. 





 두 항목을 활성화 시켰으면 아래쪽의 'Relaunch Now'버튼을 눌러 크롬을 재시작 해 준다.

이제 drawer를 아래로 내리면 주변의 Physical Web 비콘과 URL 목록을 보여준다.


'Pair'를 터치하면 커넥션이 연결되고 characteristic을 읽거나 쓸 수 있게 된다.


Physical Web URL을 통해 연결할 때는 페어링 스탭은 더 이상 필요하지 않다고 생각하지만 아직까지는 이 스탭이 필요하다.

Conclusion


이제 가능성은 무한하다. 디바이스와의 적절한 BLE 커넥션을 가지고 있으니 네이티브 안드로이드 앱에서처럼 characteristic을 원하는 대로 읽고 쓸 수 있다. 다음 단계로 넘어갈 준비가 된 사람들을 위해 가속도 센서값을 블루투스를 통해 전송하고 복수의 BLE 디바이스에서의 움직임을 그래프로 그리는 웹 앱 코드를 준비 해 놓았다. 소스코드는 github에서 찾아볼 수 있다.