스마트 홈 작업에 로컬 처리 사용 설정

1. 시작하기 전에

스마트 홈 통합을 사용하면 Google 어시스턴트가 사용자 집에 있는 연결된 기기를 제어할 수 있습니다. 스마트 홈 작업을 빌드하려면 스마트 홈 인텐트를 처리할 수 있는 클라우드 웹훅 엔드포인트를 제공해야 합니다. 예를 들어 사용자가 "Hey Google, 조명 켜 줘"라고 말하면 어시스턴트가 클라우드 처리에 명령어를 전송하여 기기의 상태를 업데이트합니다.

Local Home SDK는 스마트 홈 인텐트를 Google Home 기기에 직접 라우팅하는 로컬 경로를 추가하여 스마트 홈 통합을 강화하므로, 신뢰성이 향상되고 사용자의 명령어 처리 지연 시간이 단축됩니다. Local Home SDK를 사용하면 타입스크립트 또는 자바스크립트로 로컬 처리 앱을 작성하고 배포할 수 있으며, 이 앱을 통해 기기를 식별하고 모든 Google Home 스마트 스피커나 Google Nest 스마트 디스플레이에서 명령을 실행할 수 있습니다. 그러면 앱이 기존의 표준 프로토콜을 사용하여 명령을 처리하며 근거리 통신망을 통해 사용자의 기존 스마트 기기와 직접 통신합니다.

72ffb320986092c.png

선행 조건

빌드할 항목

이 Codelab에서는 이전에 빌드한 스마트 홈 통합을 Firebase로 배포한 다음 Actions 콘솔에 스캔 구성을 적용하고 Node.js에서 타입스크립트로 작성된 명령어를 가상의 세탁기로 전송할 로컬 앱을 빌드합니다.

학습할 내용

  • Actions 콘솔에서 로컬 처리를 사용 설정하고 구성하는 방법
  • Local Home SDK를 사용하여 로컬 처리 앱을 작성하는 방법
  • Google Home 스피커 또는 Google Nest 스마트 디스플레이에서 로드된 로컬 처리 앱을 디버그하는 방법

필요한 항목

  • Chrome의 최신 버전
  • Google Home 앱이 설치된 iOS 또는 Android 기기
  • Google Home 스마트 스피커 또는 Google Nest 스마트 디스플레이
  • Node.js 버전 10.16 이상
  • Google 계정
  • Google Cloud 결제 계정

2. 시작하기

활동 제어 사용 설정

Google 어시스턴트를 사용하려면 특정 활동 데이터를 Google과 공유해야 합니다. 이 데이터는 Google 어시스턴트가 제대로 작동하는 데 필요합니다. 하지만 데이터 공유 요구사항은 SDK에만 국한되지 않습니다. 이 데이터를 공유하려면 아직 없는 경우 Google 계정을 만드세요. 모든 Google 계정을 사용할 수 있습니다. 개발자 계정이 아니어도 됩니다.

어시스턴트와 함께 사용하려는 Google 계정의 활동 제어 페이지를 엽니다.

다음 전환 스위치가 사용 설정되어 있는지 확인합니다.

  • 웹 및 앱 활동: Chrome 방문 기록 및 Google 서비스를 사용하는 사이트, 앱, 기기에서 이루어진 활동 포함 체크박스도 선택해야 합니다.
  • 기기 정보
  • 음성 및 오디오 활동

작업 프로젝트 만들기

  1. Actions on Google 개발자 콘솔로 이동합니다.
  2. 새 프로젝트를 클릭하고 프로젝트 이름을 입력한 후 프로젝트 만들기를 클릭합니다.

AWXw5E1m9zVgvVeyeL3uxwCX6DtWOCK6LRSLmOATFzjMbmE5cSWBdSVhJZDFpEFH2azZTK2eMs6OYYdMJYiGb5bKqFEzxaLyRUYuwVGBlSjXzTyy8Z9CvwpXvRwP7xdycklETzFc7Q

스마트 홈 앱 선택

Actions 콘솔의 개요 화면에서 스마트 홈을 선택합니다.

36RsBUWBgbgsa5xZ7MJVMm1sIg07nXbfjv0mWCxXViaC5SlbL2gMigw9hgXsZQhNMHLLFOfiKdZsSTNXONFB1i47gksw3SBNpkVYl492WeryOlgxKjpVrLAvg-5cZqu1DI-s5kxM3g

스마트 홈 환경 카드를 선택하면 프로젝트 콘솔로 이동하게 됩니다.

pzgHPsmc2LvLoeUvJfkjKQqD_BvO4v8JOPlcrxsmyptFkkjL4PP6LqrM9r5tNvEIfT9HmK-UKw3GWFPXTjqo4nUrhD2o5shUKHBE31OT8iIA69JZCev7_0_nh-lnL2oJHoxGfqqZ4w

Firebase CLI 설치

Firebase 명령줄 인터페이스(CLI)를 사용하면 로컬에서 웹 앱을 제공하고 웹 앱을 Firebase 호스팅에 배포할 수 있습니다.

CLI를 설치하려면 터미널에서 다음 npm 명령어를 실행하세요.

npm install -g firebase-tools

CLI가 제대로 설치되었는지 확인하려면 다음을 실행합니다.

firebase --version

다음을 실행하여 Google 계정으로 Firebase CLI를 승인합니다.

firebase login

HomeGraph API 사용 설정

HomeGraph API를 사용하면 사용자의 Home Graph 내에서 기기 및 상태를 저장하고 쿼리할 수 있습니다. 이 API를 사용하려면 먼저 Google Cloud Console을 열고 HomeGraph API를 사용 설정해야 합니다.

Google Cloud Console에서 작업 <project-id>.와 일치하는 프로젝트를 선택합니다. 그런 다음 HomeGraph API의 API 라이브러리 화면에서 사용 설정을 클릭합니다.

5SVCzM8IZLi_9DV8M0nEklv16NXkpvM0bIzQK2hSyKyvnFHBxPOz90rbr72ayxzmxd5aNROOqC_Cp4outbdlwJdObDs0DIE_8vYzw6dovoVrP9IZWlWsZxDS7UHOi1jiRbDMG8MqUA

3. 시작 앱 실행

이제 개발 환경을 설정했으므로 시작 프로젝트를 배포하여 모든 것이 올바르게 구성되었는지 확인할 수 있습니다.

소스 코드 가져오기

다음 링크를 클릭하여 개발 머신에 이 Codelab의 샘플을 다운로드합니다.

명령줄에서 GitHub 저장소를 복제할 수도 있습니다.

git clone https://github.com/googlecodelabs/smarthome-local.git

프로젝트 정보

시작 프로젝트에는 다음의 하위 디렉터리가 포함됩니다.

  • public: 스마트 세탁기를 제어하고 모니터링하는 프런트엔드 웹 UI입니다.
  • functions: 스마트 홈 작업에 클라우드 처리를 구현하는 Cloud 함수입니다.
  • local: index.ts에서 스텁된 인텐트 핸들러가 있는 스켈레톤 로컬 처리 앱 프로젝트입니다.

제공되는 클라우드 처리에는 index.js의 다음 함수가 포함됩니다.

  • fakeauth: 계정 연결을 위한 승인 엔드포인트
  • faketoken: 계정 연결을 위한 토큰 엔드포인트
  • smarthome: 스마트 홈 인텐트 처리 엔드포인트
  • reportstate: 기기 상태 변경 시 HomeGraph API 호출
  • updateDevice: 가상 기기에서 보고서 상태를 트리거하는 데 사용하는 엔드포인트

Firebase에 연결

app-start 디렉터리로 이동한 후 작업 프로젝트를 사용해 Firebase CLI를 설정합니다.

cd app-start
firebase use <project-id>

Firebase 프로젝트 구성

Firebase 프로젝트를 초기화합니다.

firebase init

데이터베이스, Functions, 호스팅 CLI 기능을 선택합니다.

? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then
 Enter to confirm your choices.
❯◉ Database: Configure Firebase Realtime Database and deploy rules
 ◯ Firestore: Deploy rules and create indexes for Firestore
 ◉ Functions: Configure and deploy Cloud Functions
 ◉ Hosting: Configure and deploy Firebase Hosting sites
 ◯ Storage: Deploy Cloud Storage security rules
 ◯ Emulators: Set up local emulators for Firebase features
 ◯ Remote Config: Get, deploy, and rollback configurations for Remote Config

이렇게 하면 프로젝트에 필요한 API와 기능이 초기화됩니다.

메시지가 표시되면 실시간 데이터베이스를 초기화합니다. 데이터베이스 인스턴스의 기본 위치를 사용할 수 있습니다.

? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up?
Yes

? Please choose the location for your default Realtime Database instance: us-central1

시작 프로젝트 코드를 사용하고 있으므로 보안 규칙의 기본 파일을 선택하고, 기존 데이터베이스 규칙 파일을 덮어쓰지 않도록 해야 합니다.

? What file should be used for Realtime Database Security Rules? Database.rules.json

? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console?
No

마찬가지로 Functions를 구성할 때는 기본 파일을 사용해야 하고, 프로젝트 샘플의 기존 index.js 파일과 package.json 파일을 덮어쓰지 않도록 해야 합니다.

? What language would you like to use to write Cloud Functions?
JavaScript

? File functions/package.json already exists. Overwrite?
No

? File functions/index.js already exists. Overwrite?
No

? Do you want to install dependencies with npm now?
Yes

마지막으로 프로젝트 코드의 public 디렉터리를 사용하도록 호스팅 설정을 구성하고 기존 index.html 파일을 사용합니다.

? What do you want to use as your public directory?
public

? Configure as a single-page app (rewrite all urls to /index.html)?
Yes

? File public/index.html already exists. Overwrite?
 No

Firebase에 배포

functions 폴더로 이동한 다음 npm.을 사용하여 필요한 모든 종속 항목을 설치합니다.

cd functions
npm install

이제 종속 항목을 설치하고 프로젝트를 구성했으므로 앱을 처음으로 실행할 수 있습니다.

firebase deploy

콘솔에 다음과 같은 결과가 표시됩니다.

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.firebaseapp.com

이 명령어는 여러 Firebase용 Cloud Functions와 함께 웹 앱을 배포합니다.

브라우저(https://<project-id>.firebaseapp.com)에서 호스팅 URL을 열어 웹 앱을 확인합니다. 다음과 같은 인터페이스가 표시됩니다.

L60eA7MOnPmbBMl2XMipT9MdnP-RaVjyjf0Y93Y1b7mEyIsqZrrwczE7D3RQISRs-iusL1g4XbNmGhuA6-5sLcWefnczwNJEPfNLtwBsO4Tb9YvcAZBI6_rX19z8rxbik9Vq8F2fwg

이 웹 UI는 기기 상태를 보거나 수정할 수 있는 타사 플랫폼을 나타냅니다. 데이터베이스에 기기 정보를 입력하기 시작하려면 업데이트를 클릭하세요. 페이지에는 변경사항이 표시되지 않지만 세탁기의 현재 상태는 데이터베이스에 저장됩니다.

이제 Actions 콘솔을 사용하여 Google 어시스턴트에 배포한 클라우드 서비스를 연결할 차례입니다.

Actions 콘솔 프로젝트 구성

개요 > 작업 빌드에서 작업 추가를 선택합니다. 스마트 홈 인텐트를 처리하는 클라우드 함수의 URL을 입력하고 저장을 클릭합니다.

https://us-central1-<project-id>.cloudfunctions.net/smarthome

Uso-o00XQXBHvOR9vQq9tmpYDYQJKsFEstsgRFnxPAJf7zJ2FxwhISiodo3dB1Tz49Okd6ivi66fjpo7rarS_GZelglGWCT1r9FzDGUl1r67ddIcIbQrxqN8jG9F9GAKOpk0Ckc-eA

개발 > 호출 탭에서 작업의 표시 이름을 추가하고 저장을 클릭합니다. 이 이름이 Google Home 앱에 표시됩니다.

gvC-TvmKDy-D-xjwkeCjNt__9ErA7DL8hZWa1oH1yPJ9SpYOepDYjxx6WnJ56IG-t37fJ65kmHISQdh72Ot2G-0tu6Flxf4gom5kvx_3hlvFeMqYuFgXr_85pfWWn7VLFHtS55p1zw

s4yc1kOW4XtKUQN1EYegiDLU5oTqmxQ2PNbeaujm26OQmYKKpjug7j5FYmutLSAZ1zBd-ZkcZlL7zyTZqw4bge3_oOeWvJTsqJ-A08vfZwImYQrKiquLskLuTpmMqXEZD1xchhCWGQ

작업 연결을 사용하려면 왼쪽 탐색 메뉴에서 개발 > 계정 연결 옵션을 선택합니다. 다음 계정 연결 설정을 사용하세요.

클라이언트 ID

ABC123

클라이언트 비밀번호

DEF456

인증 URL

https://us-central1-.cloudfunctions.net/fakeauth

토큰 URL

https://us-central1-.cloudfunctions.net/faketoken

rRyZTiBSTuPk3YtJtXjDK1pPftUxsaEhs9jzpvFtbHTD6bEwYxM8jV4MWxiljKA1bKVZrIRoO9O3jtBefLKf_OyMpukPjwIj8zGvyU3UwASzMrnRskl-hVAfAmQVi4sC_zAwgYwRXw

저장을 클릭하여 계정 연결 구성을 저장한 후 테스트를 클릭하여 프로젝트에서 테스트를 사용 설정합니다.

OgUvpQfXioygkRwPcaJpzjyNQDZy6enidUC8YMPaCOrZi0YeWCFsCJV9Gqg-_UfsqTnn4KEg--uE3Ymr0QuamDonF4RyYHtRKcULXABDuaEnj2hq8i20LYj1SrGP_1lQ_UsUB90pGw

시뮬레이터로 리디렉션됩니다. 기기에서 테스트(soCeBB1CkSIEqsBmDc8Cth6EjgcXUnrOHeOpLNlvMiiXM73Rmh8iBK1ZFLFd47kycYqIMq3Fm49ryAGUt79BXVPDyEB1IU3W0fgiL49iqTAVrpRszL10mmxzq_AQTJZVrXor-vne2w) 아이콘 위로 마우스를 이동하여 프로젝트의 테스트가 사용 설정되었는지 확인합니다.

2zbfeYpG-wEd2SFP07Wc4mJzHakLX7YvrNw3IV0_0Kd-TonfsKIvvjKWlwvrmTm5jLj3XPWqCtcDd5J2z6gwn9fnchpYVraw1j_mE4M0LVppAl5WY5cK7g0uZyhZ3VFFS25yPmyksg

스마트 홈 작업을 테스트하려면 프로젝트를 Google 계정에 연결해야 합니다. 이렇게 하면 동일한 계정에 로그인된 Google 어시스턴트 표시 경로와 Google Home 앱을 통해 테스트할 수 있습니다.

  1. 휴대전화에서 Google 어시스턴트 설정을 엽니다. 콘솔에서와 동일한 계정으로 로그인해야 합니다.
  2. 어시스턴트에서 Google 어시스턴트 > 설정 > 홈 컨트롤로 이동합니다.
  3. 오른쪽 하단에서 더하기(+) 아이콘을 클릭합니다.
  4. 테스트 앱이 [test] 접두사 및 설정한 표시 이름으로 표시됩니다.
  5. 항목을 선택합니다. 그러면 Google 어시스턴트가 서비스를 인증하고 SYNC 요청을 보내 서비스에 사용자의 기기 목록을 제공하도록 요청합니다.

Google Home 앱을 열고 세탁기 기기가 표시되는지 확인합니다.

XcWmBVamBZtPfOFqtsr5I38stPWTqDcMfQwbBjetBgxt0FCjEs285pa9K3QXSASptw0KYN2G8yfkT0-xg664V4PjqMreDDs-HPegHjOc4EVtReYPu-WKZyygq9Xmkf8X8z9177nBjQ

Google Home 앱에서 음성 명령을 사용하여 세탁기를 제어할 수 있는지 확인합니다. 클라우드 처리의 프런트엔드 웹 UI에서 기기 상태 변경도 확인할 수 있어야 합니다.

이제 작업에 로컬 처리를 추가할 수 있습니다.

4. 클라우드 처리 업데이트

로컬 처리를 지원하려면 otherDeviceIds라는 새로운 기기별 필드를 클라우드 SYNC 응답에 추가해야 하며, 이 응답에는 기기의 고유 로컬 식별자가 포함됩니다. 이 필드는 기기를 로컬로 제어하는 기능도 나타냅니다.

다음 코드 스니펫과 같이 otherDeviceIds 필드를 SYNC 응답에 추가하세요.

functions/index.js

app.onSync((body) => {
  return {
    requestId: body.requestId,
    payload: {
      agentUserId: '123',
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [ ... ],
        name: { ... },
        deviceInfo: { ... },
        willReportState: true,
        attributes: {
          pausable: true,
        },
        otherDeviceIds: [{
          deviceId: 'deviceid123',
        }],
      }],
    },
  };
});

업데이트된 프로젝트를 Firebase에 배포합니다.

firebase deploy --only functions

배포가 완료되면 웹 UI로 이동하여 툴바에서 새로고침 ae8d3b25777a5e30.png 버튼을 클릭합니다. 이렇게 하면 요청 동기화 작업이 트리거되기 때문에 어시스턴트가 업데이트된 SYNC 응답 데이터를 수신합니다.

bf4f6a866160a982.png

5. 로컬 처리 구성

이 섹션에서는 로컬 처리에 필요한 구성 옵션을 스마트 홈 작업에 추가합니다. 개발 중에 Google Home 기기가 액세스하여 다운로드할 수 있는 로컬 처리 앱을 Firebase 호스팅에 게시합니다.

Actions 콘솔에서 개발 > 작업을 선택하고 Local Home SDK 구성 섹션을 찾습니다. 테스트 URL 필드에 다음 URL을 입력하고 프로젝트 ID를 입력한 후 저장을 클릭합니다.

https://<project-id>.firebaseapp.com/local-home/index.html

7d59b31f8d2a988.png

다음으로 Google Home 기기가 로컬 스마트 기기를 검색하는 방법을 정의해야 합니다. Local Home 플랫폼은 mDNS, UPnP, UDP 브로드캐스트 등 기기 검색을 위한 몇 가지 프로토콜을 지원합니다. UDP 브로드캐스트를 사용하여 스마트 세탁기를 찾습니다.

기기 스캔 구성에서 새 스캔 구성을 클릭하여 새 스캔 구성을 추가합니다. UDP를 프로토콜로 선택하고 다음 속성을 입력합니다.

필드

설명

제안 값

브로드캐스트 주소

UDP 브로드캐스트 주소

255.255.255.255

브로드캐스트 포트

Google Home이 UDP 브로드캐스트를 전송하는 포트

3311

수신 포트

Google Home이 응답을 수신하는 포트

3312

검색 패킷

UDP 브로드캐스트 데이터 페이로드

48656c6c6f4c6f63616c486f6d6553444b

4777bf63c53b6858.png

마지막으로 창 상단에 있는 저장을 클릭하여 변경사항을 게시합니다.

6. 로컬 처리 구현

Local Home SDK 입력 패키지를 사용하여 TypeScript로 로컬 처리 앱을 개발해 봅니다. 시작 프로젝트에서 제공된 스켈레톤을 살펴보세요.

local/index.ts

/// <reference types="@google/local-home-sdk" />

import App = smarthome.App;
import Constants = smarthome.Constants;
import DataFlow = smarthome.DataFlow;
import Execute = smarthome.Execute;
import Intents = smarthome.Intents;
import IntentFlow = smarthome.IntentFlow;

...

class LocalExecutionApp {

  constructor(private readonly app: App) { }

  identifyHandler(request: IntentFlow.IdentifyRequest):
      Promise<IntentFlow.IdentifyResponse> {
    // TODO: Implement device identification
  }

  executeHandler(request: IntentFlow.ExecuteRequest):
      Promise<IntentFlow.ExecuteResponse> {
    // TODO: Implement local fulfillment
  }

  ...
}

const localHomeSdk = new App('1.0.0');
const localApp = new LocalExecutionApp(localHomeSdk);
localHomeSdk
  .onIdentify(localApp.identifyHandler.bind(localApp))
  .onExecute(localApp.executeHandler.bind(localApp))
  .listen()
  .then(() => console.log('Ready'))
  .catch((e: Error) => console.error(e));

로컬 처리의 핵심 구성요소는 smarthome.App 클래스입니다. 시작 프로젝트는 IDENTIFYEXECUTE 인텐트의 핸들러를 연결한 다음 listen() 메서드를 호출하여 앱이 준비되었음을 Local Home SDK에 알립니다.

IDENTIFY 핸들러 추가

Google Home 기기가 Actions 콘솔에서 제공한 스캔 구성을 기반으로 로컬 네트워크에서 인증되지 않은 기기를 발견하면 Local Home SDK가 IDENTIFY 핸들러를 트리거합니다.

한편 Google에서 일치하는 기기를 검색하면 플랫폼에서 결과 스캔 데이터를 사용해 identifyHandler를 호출합니다. 앱 스캔은 UDP 브로드캐스트를 사용하며 IDENTIFY 핸들러에 제공된 스캔 데이터에는 로컬 기기에서 보낸 응답 페이로드가 포함됩니다.

핸들러는 로컬 기기의 고유 식별자가 포함된 IdentifyResponse 인스턴스를 반환합니다. identifyHandler 메서드에 다음 코드를 추가하여 로컬 기기에서 오는 UDP 응답을 처리하고 적절한 로컬 기기 ID를 결정합니다.

local/index .ts

identifyHandler(request: IntentFlow.IdentifyRequest):
    Promise<IntentFlow.IdentifyResponse> {
  console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));

  const scanData = request.inputs[0].payload.device.udpScanData;
  if (!scanData) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_request', 'Invalid scan data');
    return Promise.reject(err);
  }

  // In this codelab, the scan data contains only local device id.
  const localDeviceId = Buffer.from(scanData.data, 'hex');

  const response: IntentFlow.IdentifyResponse = {
    intent: Intents.IDENTIFY,
    requestId: request.requestId,
    payload: {
      device: {
        id: 'washer',
        verificationId: localDeviceId.toString(),
      }
    }
  };
  console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));

  return Promise.resolve(response);
}

verificationId 필드는 SYNC 응답의 otherDeviceIds 값 중 하나와 일치해야 합니다. 이 필드는 사용자의 Home Graph에서 로컬 처리에 사용할 수 있는 기기를 표시합니다. Google에서 일치하는 항목을 찾으면 해당 기기는 인증된 것으로 간주되며 로컬 처리를 진행할 수 있습니다.

EXECUTE 핸들러 추가

로컬 처리를 지원하는 기기가 명령어를 수신하면 Local Home SDK가 EXECUTE 핸들러를 트리거합니다. 로컬 인텐트의 콘텐츠는 클라우드 처리로 전송된 EXECUTE 인텐트와 같습니다. 따라서 인텐트를 로컬에서 처리하는 로직은 클라우드에서 인텐트를 처리하는 방식과 유사합니다.

앱은 TCP/UDP 소켓 또는 HTTP(S) 요청을 사용하여 로컬 기기와 통신할 수 있습니다. 이 Codelab에서는 HTTP가 가상 기기를 제어하는 데 사용되는 프로토콜 역할을 합니다. 포트 번호는 index.ts에서 SERVER_PORT 변수로 정의됩니다.

다음 코드를 executeHandler 메서드에 추가하여 들어오는 명령어를 처리하고 HTTP를 통해 로컬 기기로 전송하세요.

local/index.ts

executeHandler(request: IntentFlow.ExecuteRequest):
    Promise<IntentFlow.ExecuteResponse> {
  console.log("EXECUTE intent: " + JSON.stringify(request, null, 2));

  const command = request.inputs[0].payload.commands[0];
  const execution = command.execution[0];
  const response = new Execute.Response.Builder()
    .setRequestId(request.requestId);

  const promises: Array<Promise<void>> = command.devices.map((device) => {
    console.log("Handling EXECUTE intent for device: " + JSON.stringify(device));

    // Convert execution params to a string for the local device
    const params = execution.params as IWasherParams;
    const payload = this.getDataForCommand(execution.command, params);

    // Create a command to send over the local network
    const radioCommand = new DataFlow.HttpRequestData();
    radioCommand.requestId = request.requestId;
    radioCommand.deviceId = device.id;
    radioCommand.data = JSON.stringify(payload);
    radioCommand.dataType = 'application/json';
    radioCommand.port = SERVER_PORT;
    radioCommand.method = Constants.HttpOperation.POST;
    radioCommand.isSecure = false;

    console.log("Sending request to the smart home device:", payload);

    return this.app.getDeviceManager()
      .send(radioCommand)
      .then(() => {
        const state = {online: true};
        response.setSuccessState(device.id, Object.assign(state, params));
        console.log(`Command successfully sent to ${device.id}`);
      })
      .catch((e: IntentFlow.HandlerError) => {
        e.errorCode = e.errorCode || 'invalid_request';
        response.setErrorState(device.id, e.errorCode);
        console.error('An error occurred sending the command', e.errorCode);
      });
  });

  return Promise.all(promises)
    .then(() => {
      return response.build();
    })
    .catch((e) => {
      const err = new IntentFlow.HandlerError(request.requestId,
          'invalid_request', e.message);
      return Promise.reject(err);
    });
}

TypeScript 컴파일

local/ 디렉터리로 이동하고 다음 명령어를 실행하여 타입스크립트 컴파일러를 다운로드하고 앱을 컴파일합니다.

cd local
npm install
npm run build

그러면 index.ts(타입스크립트) 소스가 컴파일되고 다음 콘텐츠가 public/local-home/ 디렉터리에 배치됩니다.

  • bundle.js: 로컬 앱과 종속 항목을 포함하는 컴파일된 자바스크립트 출력입니다.
  • index.html: 기기 내 테스트를 위한 앱을 제공하는 데 사용되는 로컬 호스팅 페이지입니다.

테스트 프로젝트 배포

업데이트된 프로젝트 파일을 Google Home 기기에서 액세스할 수 있도록 Firebase 호스팅에 배포합니다.

firebase deploy --only hosting

7. 스마트 세탁기 시작

이제 로컬 처리 앱과 스마트 세탁기 사이의 통신을 테스트해 볼 차례입니다. Codelab 시작 프로젝트에는 가상의 세탁기가 포함되어 있습니다. 가상 세탁기는 Node.js로 작성되었으며 사용자가 로컬에서 제어할 수 있는 스마트 세탁기를 시뮬레이션합니다.

기기 구성

Actions 콘솔에서 기기 검색을 위해 스캔 구성에 적용한 것과 동일한 UDP 매개변수를 사용하도록 가상 기기를 구성해야 합니다. 또한 가상 기기에 보고할 로컬 기기 ID와 기기 상태가 변경될 때 상태 보고 이벤트에 사용할 작업 프로젝트 ID를 가상 기기에 알려야 합니다.

매개변수

제안 값

deviceId

deviceid123

discoveryPortOut

3311

discoveryPacket

HelloLocalHomeSDK

projectId

작업 프로젝트 ID

기기 시작

virtual-device/ 디렉터리로 이동한 다음 기기 스크립트를 실행하여 구성 매개변수를 인수로 전달합니다.

cd virtual-device
npm install
npm start -- \
  --deviceId=deviceid123 --projectId=<project-id> \
  --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK

기기 스크립트가 예측한 매개변수를 통해 실행되는지 확인합니다.

(...): UDP Server listening on 3311
(...): Device listening on port 3388
(...): Report State successful

8. TypeScript 앱 디버그

다음 섹션에서는 Google Home 기기가 로컬 네트워크를 통해 가상 스마트 세탁기에 명령어를 제대로 스캔, 식별, 전송할 수 있는지 확인합니다. Chrome 개발자 도구를 사용하여 Google Home 기기에 연결하고 콘솔 로그를 보고 TypeScript 앱을 디버그할 수 있습니다.

Chrome 개발자 도구 연결

디버거를 로컬 처리 앱에 연결하려면 다음 단계를 따르세요.

  1. Google Home 기기를 Actions 콘솔 프로젝트에 액세스할 수 있는 사용자에게 연결했는지 확인합니다.
  2. Google Home 기기를 재부팅합니다. 그러면 Google Home HTML URL 및 개발자가 Actions 콘솔에 입력한 스캔 구성을 가져올 수 있습니다.
  3. 개발 머신에서 Chrome을 시작합니다.
  4. 새 Chrome 탭을 열고 주소 입력란에 chrome://inspect를 입력하여 검사기를 실행합니다.

페이지에 기기 목록이 표시되고 앱 URL이 Google Home 기기 이름 아래에 표시되어야 합니다.

567f97789a7d8846.png

검사기 실행

앱 URL에서 검사를 클릭하여 Chrome 개발자 도구를 실행합니다. 콘솔 탭을 선택하고 TypeScript 앱에서 출력된 IDENTIFY 인텐트의 콘텐츠를 볼 수 있는지 확인합니다.

6b67ded470a4c8be.png

이 출력은 로컬 처리 앱이 가상 기기를 성공적으로 검색하고 식별했음을 의미합니다.

로컬 처리 테스트

Google Home 앱의 터치 컨트롤을 사용해 기기에 명령어를 전송하거나 다음의 음성 명령을 통해 Google Home 기기에 전송합니다.

"Hey Google, 세탁기 켜 줘."

"Hey Google, 세탁기 시작해 줘."

"Hey Google, 세탁기 중지해 줘."

이렇게 하면 플랫폼이 트리거되어 EXECUTE 인텐트를 TypeScript 앱으로 전송합니다.

bc030517dacc3ac9.png

각 명령어로 로컬 스마트 세탁기 상태 변화를 볼 수 있는지 확인합니다.

...
***** The washer is RUNNING *****
...
***** The washer is STOPPED *****

9. 수고하셨습니다

764dbc83b95782a.png

축하합니다. Local Home SDK를 사용하여 로컬 처리를 스마트 홈 작업에 통합했습니다.

자세히 알아보기

다음과 같은 작업을 해볼 수 있습니다.

  • 스캔 구성을 변경하고 구성이 실행되도록 합니다. 예를 들어 다른 UDP 포트나 검색 패킷을 사용해 보세요.
  • Raspberry Pi와 같은 임베디드 기기에서 실행되도록 가상 스마트 기기 코드베이스를 수정하고 LED 또는 디스플레이를 사용하여 현재 상태를 시각적으로 나타냅니다.