이 프로젝트는 embedded101.com의 "Win 10 IoT-Core: Bluetooth Universal Windows Serial App"에서 자세히 다룹니다.
개요
이 프로젝트는 라즈베리 파이 2 같은 IoT Core 장치를 범용 블루투스 USB 동글을 통해 임베디드 블루투스 장치와 블루투스 시리얼 프로파일(SPP)로 연결하는 유니버설 윈도우 앱(UWP)입니다.
배경
블루투스는 근거리 피어투피어 네트워킹을 지원합니다. 와이파이와 달리 1:1 연결이며, 두 장치가 연결되어 데이터를 주고받습니다. 대칭적 연결(시리얼 프로파일로 원시 데이터 교환)도 가능하지만, 보통 비대칭적입니다(한쪽이 특정 데이터 포맷을 생성해 다른 쪽이 소비). 예: 휴대폰이 A2DP 프로파일로 오디오를 헤드셋(HSP 프로파일)로 스트리밍. OBEX(Object Exchange)는 양쪽이 데이터를 교환하는 대칭 연결입니다.
마이크로소프트 IoT Core 블루투스 샘플은 GATT(Generic Attribute Profile)를 사용해 블루투스 저에너지(BLE) 프로토콜의 프로파일 검색·기술 서비스를 제공합니다. 저전력 심플 기기가 데이터를 생성하면 복잡한 프로세서가 소비하는 구조죠.
이 프로젝트는 훨씬 단순합니다. 오직 SPP(Serial Port Profile)만 다루며, RFCOMM 프로파일 기반입니다. 아주 오래된 USB 블루투스 동글로 개발되어 어떤 동글이든 작동할 것입니다.
IoT 앱
간단한 블루투스 시리얼 UWP(윈도우 10) 테스트 앱입니다. 앱 실행 시 장치와 페어링된 모든 블루투스 장치를 리스트로 열거합니다. 하나를 더블클릭하면 연결을 시도합니다. 텍스트박스에 보낼 텍스트를 입력하고 버튼을 누르면 전송. 수신된 텍스트는 자동으로 수신란에 표시됩니다. 따라서 상대측(아두이노)이 받은 문자를 그대로 에코백하면 보낸 텍스트가 수신란에 다시 나타납니다.
엔드포인트(아두이노 측)
테스트용으로 블루투스 어댑터를 장착한 아두이노 우노를 사용합니다. 블루투스 연결로 수신한 문자를 그대로 에코백하는 간단한 실드 코드입니다.
실드 설정(Setup):
// 시리얼 루프백 앱
// 설정 단계
// 연결된 시스템에 의해 시작됨
// 블루투스에서 사용할 수 있음: BT 장치의 RxTx를 아두이노 TxRx에 연결
// 프로그래밍 전에는 BT 어댑터를 분리해야 함
void setup() {
// 내 어댑터 보드레이트 115200
// 아두이노-BT 어댑터 포트 속도
// BT 어댑터가 커맨드 모드일 때 설정
// 이건 BT 무선 속도가 아님(설정 불가)
Serial.begin(115200);
delay(333);
while (!Serial) ;
delay(1000);
Serial.println("The quick brown fox jumps over the lazy dog!");
}
블루투스는 P2P이므로 연결 전 페어링이 필수입니다. 앱 내에서 하지 않습니다. 패스키 페어링은 임베디드 기기 간에 까다로울 수 있습니다(헤드리스, 팝업 미지원 등). IoT Core 웹 포털이나 SSH 쉘에서 실행하는 명령줄 유틸리티로 페어링합니다. 최신 OS 웹 포털은 패스키 페어링을 지원합니다(윈도우 10 RTM 당시엔 없었음). 자세한 내용은 위 링크의 글 참조.
프로젝트 시작
Visual Studio 2015에서 유니버설 윈도우 앱 템플릿으로 프로젝트 생성:
New Project → Visual C# → Windows → Blank App (Universal Windows)
앱 UI 만들기 (XAML)
위 레이아웃과 비슷하게 UI 구성:
모든 텍스트 요소는 TextBlock, 단 SendText만 TextBox
SendText는 캐리지 리턴 허용(Multiline)
Recvd 텍스트는 텍스트 랩핑 활성화(Multiline)
UI 요소를 가로 방향 StackPanel로 행 구성, 이들을 세로 방향 StackPanel과 ListBox로 다시 쌓음
원하면 RelativePanel이나 Grid 행/열로 레이아웃해도 무방
ConnectDevices는 ListBox로, ItemsSource를 PairedDevices(나중에 설명)에 바인딩, ItemTemplate로 TextBlock을 PairedDeviceInfo의 Name 속성에 바인딩. 더블탭 이벤트(ConnectDevices_DoubleTapped)로 연결 시작.