웹에서 블루투스를 통해 직렬

François Beaufort
François Beaufort

Web Bluetooth APIWeb Serial API를 사용하면 웹 앱이 각각 저전력 블루투스 (BLE) 기기 및 직렬 기기와 통신할 수 있습니다. 많은 웹 개발자가 이미 이러한 API를 사용하여 큰 성공을 거두고 있지만 블루투스 클래식 기기 지원에 대한 요구도 점점 커지고 있습니다.

이제 Web Serial API는 데스크톱용 Chrome 117의 Serial Port Profile (SPP)을 비롯하여 페어링된 블루투스 클래식 기기에서 RFCOMM 서비스와의 통신을 지원합니다. 이를 통해 웹 개발자와 사용자 모두에게 새로운 가능성이 열립니다. 다음은 이 기능을 활용할 수 있는 실제 기기입니다.

  • Pixel Buds Pro 및 기타 무선 이어폰은 RFCOMM을 사용하여 오디오 설정과 펌웨어 업데이트를 관리합니다.
  • 모바일 POS 시스템은 블루투스 SPP를 사용하여 영수증 프린터와 통신합니다.
  • 가축 RFID 태그 판독기는 블루투스 SPP를 사용하여 동물의 움직임을 기록합니다.

블루투스 RFCOMM 프로토콜

90년대 후반으로 돌아가 보세요. Palm Pilot을 크레이들에 넣기만 하면 다음 날 캘린더가 동기화됩니다. 무선으로 할 수 있다면 얼마나 좋을까요? 이 새로운 '블루투스' 기술을 사용하면 더 이상 복잡한 전선에 시달리지 않아도 됩니다. 무선이 미래입니다. 단 하나의 문제가 있습니다. 기존에 있는 모든 것이 RS-232 케이블로 연결되도록 설계되었습니다. 따라서 블루투스는 무선 주파수 통신 (RFCOMM) 프로토콜을 사용하여 기존의 모든 소프트웨어와 하드웨어에 이 인터페이스를 제공합니다.

오늘날에도 RFCOMM 서비스는 신규 및 기존 하드웨어에서 널리 사용되고 있습니다. 이를 통해 지금까지 저전력 블루투스에서 충족하지 못했던 특정 지연 시간 및 대역폭 요구사항을 충족할 수 있습니다. 이러한 이유로 제조업체가 궁극적으로 블루투스 저에너지로 이전하고 개발자가 대신 웹 블루투스 API를 사용할 수 있기 전에 이러한 기존 RFCOMM 서비스에 액세스할 수 있도록 직렬 기기에 연결하기 위한 API인 웹 직렬과 블루투스 간의 통합을 개발했습니다.

Web Serial API 변경사항

이제 데스크톱용 Chrome 117부터 웹 개발자는 Web Serial API를 사용하여 RFCOMM 서비스를 통해 페어링된 블루투스 클래식 기기와 안정적으로 통신할 수 있습니다. 이는 Web Serial API의 다음 업데이트로 인해 가능해졌습니다.

  • 이제 Chrome은 표준화된 블루투스 클래식 직렬 포트 프로필을 사용하여 직렬 인터페이스를 노출하는 페어링된 블루투스 기기를 열거합니다.
  • 이제 Chrome은 운영체제가 에뮬레이션된 직렬 포트를 통해 기기 노드를 만들지 않은 경우에도 직렬 인터페이스와 통신할 수 있습니다.
  • 이제 Chrome은 RFCOMM 직렬 인터페이스를 노출하는 비직렬 포트 서비스와 통신할 수 있습니다 (비표준 서비스 클래스 ID 참고).

Web Serial API를 사용하는 방법은 직렬 포트에서 읽고 쓰기 도움말을 참고하세요. 이 도움말에서는 블루투스에 대한 기본 지식이 있다고 가정하며 블루투스를 통한 직렬 변경사항에 중점을 둡니다.

필터를 지정하지 않고 navigator.serial.requestPort()를 호출하면 사용자가 블루투스가 아닌 직렬 포트, 이미 매핑된 블루투스 직렬 포트, 표준화된 블루투스 클래식 직렬 포트 프로필에서 제공하는 매핑되지 않은 직렬 포트를 선택할 수 있습니다.

// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();

대부분의 기기는 표준화된 블루투스 기존 직렬 포트 프로필을 통해 SPP 기반 통신을 노출하지만 일부 기기는 맞춤 RFCOMM 기반 서비스를 사용합니다. 이러한 기기에는 표준 블루투스 UUID 범위에 속하지 않는 서비스 클래스 ID가 있습니다.

아래 예와 같이 이러한 맞춤 RFCOMM 기반 서비스에 액세스하려면 allowedBluetoothServiceClassIds 목록을 navigator.serial.requestPort()에 전달해야 합니다.

const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef";

// Prompt user to select any serial port.
// Access to the custom Bluetooth RFCOMM service above will be allowed.
const port = await navigator.serial.requestPort({
  allowedBluetoothServiceClassIds: [myBluetoothServiceUuid],
});

Chrome은 오디오 및 동영상과 같은 블루투스 클래식 서비스를 지원하지 않으므로 Bluetooth SIG Base UUID를 사용하는 모든 서비스 클래스 ID (즉, '-0000-1000-8000-00805f9b34fb'로 끝나는 모든 UUID)는 직렬 포트 프로필 ID를 제외하고 차단됩니다.

navigator.serial.requestPort()를 호출할 때 bluetoothServiceClassId 필터 키를 사용하여 서비스 클래스 ID로 식별된 필터링된 블루투스 직렬 포트 목록을 사용자에게 표시할 수도 있습니다. 아래 예를 참조하세요.

const myBluetoothServiceUuid = "01234567-89ab-cdef-0123-456789abcdef";

// Prompt the user to select Bluetooth serial ports with
// the custom Bluetooth RFCOMM service above.
const port = await navigator.serial.requestPort({
  allowedBluetoothServiceClassIds: [myBluetoothServiceUuid],
  filters: [{ bluetoothServiceClassId: myBluetoothServiceUuid }],
});

직렬 포트가 블루투스 기기의 일부인 경우 포트가 연결된 RFCOMM 채널과 연결된 서비스 클래스 ID가 포함된 새 bluetoothServiceClassId 키는 port.getInfo()를 호출하여 반환된 직렬 포트 정보에서 사용할 수 있습니다. 직렬 포트가 매핑되면 '00001101-0000-1000-8000-00805f9b34fb' 또는 0x1101(줄여서)을 반환합니다.

const { bluetoothServiceClassId } = port.getInfo();

사용 사례 예시: Pixel Buds Pro 제어

Pixel Buds Pro 웹 호환 앱은 사용자가 웹브라우저가 있는 모든 기기에서 Pixel Buds Pro를 제어할 수 있는 새로운 웹 앱입니다. 즉시 로드 환경을 위해 프로그레시브 웹 앱 기술을 사용하여 빌드되며 원하는 경우 다른 운영체제 앱과 함께 설치할 수 있습니다.

앱은 Web Serial API를 사용하여 Pixel Buds Pro와 통신합니다. 이를 통해 사용자는 액티브 노이즈 제어, 이퀄라이저, 인이어 감지, 펌웨어 업데이트 등 Pixel Buds Pro의 다양한 설정을 제어할 수 있습니다.

Pixel Buds Pro 웹 호환 앱을 사용해 보려면 ChromeOS 기기에서 mypixelbuds.google.com으로 이동하세요 (다른 플랫폼은 곧 제공될 예정).

Pixel Buds Pro 웹 호환 앱의 스크린샷
Pixel Buds Pro 웹 호환 앱

리소스

감사의 말

리뷰를 제공해 주신 레이리 그랜트, 토마스 슈타이너, 벤 모스, 빈센트 셰이브님께 감사드립니다.