스마트 홈 디버깅

1. 시작하기 전에

사물 인터넷 (IoT) 개발자는 사용자가 Google Home 앱의 터치 컨트롤 및 Google 어시스턴트의 음성 명령을 통해 기기를 제어할 수 있는 클라우드 간 통합을 빌드할 수 있습니다.

a4657871181b5ad2.gif

클라우드 간 통합을 위한 디버깅 도구를 학습하는 것은 Google 어시스턴트와 프로덕션 품질 통합을 빌드하는 데 중요한 단계입니다. 간편한 모니터링 및 디버깅을 위해 Google Cloud Platform (GCP) 측정항목, 로깅, 스마트 홈용 테스트 모음을 사용하여 통합 문제를 식별하고 해결할 수 있습니다.

기본 요건

빌드할 항목

이 Codelab에서는 결함이 2개인 클라우드 간 통합을 배포하고 어시스턴트에 연결한 후 스마트 홈 및 Google Cloud Platform (GCP) 측정항목 및 로깅을 위한 테스트 모음을 통해 통합의 결함을 디버그합니다.

학습할 내용

  • GCP 측정항목 및 로깅을 사용하여 프로덕션 문제를 식별하고 해결하는 방법
  • 스마트 홈용 테스트 모음을 사용하여 기능 및 API 문제를 식별하는 방법

필요한 항목

2. 결함이 있는 앱 실행

소스 코드 가져오기

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

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

$ git clone https://github.com/google-home/smarthome-debug.git

프로젝트 정보

세탁기 앱에는 다음과 같은 하위 디렉터리가 포함됩니다.

Firebase에 연결

개발 머신에서 터미널을 엽니다. washer-faulty 디렉터리로 이동한 후 스마트 홈 기기를 Google 어시스턴트에 연결하기 Codelab에 빌드된 통합 프로젝트를 사용하여 Firebase CLI를 설정합니다.

$ cd washer-faulty
$ firebase use <firebase-project-id>

Firebase에 배포하기

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

$ cd functions
$ npm install

참고: 아래 메시지가 표시되면 무시하고 계속 진행할 수 있습니다. 이 경고는 일부 이전 종속 항목으로 인해 발생하며 자세한 내용은 여기를 참고하세요.

found 5 high severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details

이제 종속 항목을 설치하고 프로젝트를 구성했으므로 결함이 있는 세탁기 앱을 배포할 수 있습니다.

$ firebase deploy

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

...

✔ Deploy complete!

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

HomeGraph 업데이트

브라우저 (https://<firebase-project-id>.firebaseapp.com)에서 호스팅 URL을 열어 웹 앱을 확인합니다. 웹 UI에서 새로고침 ae8d3b25777a5e30.png 버튼을 클릭하여 동기화 요청을 통해 결함이 있는 세탁기 앱의 최신 기기 메타데이터로 HomeGraph를 업데이트합니다.

6f2b1344179977cf.png

Google Home 앱을 열고 Faulty Washer라는 이름의 세탁기 기기가 표시되는지 확인합니다.

e357de6a7faff925.png

3. 통합 테스트

프로젝트를 배포한 후 통합이 세탁기를 제어하는지 테스트합니다.

세탁기 테스트하기

휴대전화를 통해 다음 음성 명령을 시도하면 값이 변경된 것을 확인할 수 있습니다.

"Hey Google, 세탁기 켜 줘."

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

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

"Hey Google, 세탁기 재개해 줘."

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

세탁기를 일시중지 / 재개하면 어시스턴트가 음성으로 문제가 있다고 응답합니다.

"죄송합니다. <프로젝트 표시 이름>에 연락할 수 없습니다."

이 문제를 디버그하려면 먼저 오류에 관한 추가 정보를 사용하여 근본 원인을 파악하고 이를 좁혀야 합니다.

스마트홈 분석 대시보드

오류를 검사하기에 좋은 위치는 클라우드 처리의 사용량 및 상태 측정항목 차트를 집계하는 스마트홈 분석 대시보드입니다.

  • 사용량 측정항목은 일일 활성 사용자 수 및 처리의 총 요청 수를 비롯하여 클라우드 간 통합의 사용량 추세를 반영합니다.
  • 상태 측정항목을 사용하면 요청 지연 시간, 성공률, 오류 분류를 포함하여 Cloud-to-Cloud 통합에서 이상치 발생을 모니터링할 수 있습니다.

오류의 원인을 파악하려면 아래 단계에 따라 프로젝트 대시보드에 액세스하세요.

  1. Developer Console에서 프로젝트 페이지로 이동합니다.
  2. 스마트 홈 프로젝트를 선택합니다.
  3. 왼쪽 메뉴에서 애널리틱스 탭을 클릭합니다.

b1735bbe11a7aff8.png

  1. 그러면 Google Cloud의 프로젝트 대시보드 목록이 표시됩니다. Google Home 분석 - 클라우드 통합 대시보드를 선택합니다.

5edd3751323176dd.png

  1. Cloud Fulfillment Errors - Status Breakdown(Cloud Fulfillment 오류 - 상태 분석) 차트 아래로 스크롤하여 강조 표시된 기간의 오류 코드를 확인합니다.

c468743c20a11c15.png

PARTNER_RESPONSE_MISSING_DEVICE 오류 코드는 근본 원인에 관한 힌트를 제공합니다. 그런 다음 오류 코드를 기반으로 이벤트 로그를 검색하여 자세한 내용을 확인합니다.

이벤트 로그 액세스

오류에 관한 자세한 내용을 확인하려면 Cloud Logging을 통해 클라우드 간 통합의 이벤트 로그에 액세스하세요.

Google Cloud Platform에서 탐색 메뉴를 열고 작업에서 로깅 > 로그 탐색기를 선택하여 프로젝트의 이벤트 로그에 액세스합니다. 또는 검색창에서 로그 탐색기를 검색할 수도 있습니다.

모든 필드 검색 입력란에 쿼리 PARTNER_RESPONSE_MISSING_DEVICE를 입력하고 쿼리 실행을 클릭합니다. 쿼리와 일치하는 로그가 결과 섹션에 표시됩니다.

747cca0f1249a5a.png

오류 로그에는 다음을 나타내는 오류 세부정보가 포함된 스마트 홈 이벤트가 표시됩니다.

  • 사용자가 취한 작업은 '세탁기 재개' (actionType: 'STARTSTOP_UNPAUSE')로, 최근 실패한 음성 명령에 해당합니다.
  • 연결된 디버깅 메시지는 'JSON response does not include device.'입니다.

디버깅 메시지를 토대로 세탁기 앱이 EXECUTE 응답에 올바른 기기를 포함하지 않는 이유를 확인해야 합니다.

오류의 근본 원인 파악하기

functions/index.js에서 각 명령어의 상태와 새 기기 상태를 반환하는 EXECUTE 핸들러 (onExecute 배열)를 찾습니다. EXECUTE 응답에 기기 ID를 삽입하는 것은 updateDevice 함수의 확인에 따라 다릅니다.

index.js

app.onExecute(async (body) => {
 ...

 for (const command of intent.payload.commands) {
   for (const device of command.devices) {
     for (const execution of command.execution) {
       executePromises.push(
           updateDevice(execution, device.id)
               .then((data) => {
                 result.ids.push(device.id);
                 Object.assign(result.states, data);
               })
               .catch((e) =>
                 functions.logger.error('EXECUTE',
                     device.id, e.message)));
     }
   }
 }

updateDevice 함수가 세탁기에서 일시중지 / 재개를 처리하는 방식을 자세히 확인하면 일시중지 / 재개 명령어와 일치하는 문자열이 잘못된 것을 알 수 있습니다.

index.js

const updateDevice = async (execution, deviceId) => {
 const {params, command} = execution;
 let state; let ref;
 switch (command) {
   ...
   case 'action.devices.commands.PauseUnpausePause':
     state = {isPaused: params.pause};
     if (params.pause) state.isRunning = false;
     ref = firebaseRef.child(deviceId).child('StartStop');
     break;
 }

 return ref.update(state)
     .then(() => state);
};

오류 수정

이제 오류의 근본 원인을 파악했으므로 일시중지 / 재개 명령어의 문자열을 수정할 수 있습니다.

index.js

const updateDevice = async (execution, deviceId) => {
 const {params, command} = execution;
 let state; let ref;
 switch (command) {
   ...
   case 'action.devices.commands.PauseUnpause':
     state = {isPaused: params.pause};
     if (params.pause) state.isRunning = false;
     ref = firebaseRef.child(deviceId).child('StartStop');
     break;
 }

 return ref.update(state)
     .then(() => state);
};

수정사항 테스트하기

Firebase CLI를 사용하여 업데이트된 코드를 배포합니다.

firebase deploy --only functions

다음 음성 명령을 다시 시도해 보세요. 이제 세탁기를 일시중지 / 재개할 때 어시스턴트가 올바르게 응답합니다.

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

=>

"알겠습니다. 세탁기 일시중지합니다."

"Hey Google, 세탁기 재개해 줘."

=>

"확인했습니다. 세탁기를 재개합니다."

또한 질문을 통해 세탁기의 현재 상태를 테스트할 수 있습니다.

"Hey Google, 세탁기 켜져 있어?"

"Hey Google, 내 세탁기 돌아가고 있어?"

"Hey Google, 세탁기가 지금 무슨 모드야?"

4. 테스트 모음으로 통합 테스트

수동 테스트 외에도 자동화된 스마트 홈용 테스트 모음을 사용하여 통합과 연결된 기기 유형 및 트레잇을 기반으로 사용 사례를 검증할 수 있습니다. 테스트 모음은 일련의 테스트를 실행하여 통합의 문제를 감지하고, 이벤트 로그를 살펴보기 전에 디버깅을 신속하게 진행할 수 있도록 실패한 테스트 사례에 관한 유용한 메시지를 표시합니다.

스마트 홈용 테스트 모음 실행

다음 안내에 따라 테스트 모음으로 클라우드 간 통합을 테스트합니다.

  1. 웹브라우저에서 스마트 홈용 테스트 모음을 엽니다.
  2. 오른쪽 상단의 버튼을 사용하여 Google에 로그인합니다. 이렇게 하면 테스트 모음이 명령어를 Google 어시스턴트로 직접 전송할 수 있습니다.
  3. 프로젝트 ID 필드에 클라우드 간 통합의 프로젝트 ID를 입력합니다. 그런 다음 다음을 클릭하여 계속합니다.
  4. 테스트 설정 단계에서 테스트 모음에 세탁기의 기기 유형과 트레잇이 표시됩니다.

78ed6a1ebdb581bf.png

  1. 샘플 세탁기 앱에는 세탁기를 추가 / 삭제 / 이름을 바꾸는 UI가 없으므로 테스트 요청 동기화 옵션을 사용 중지합니다. 프로덕션 시스템에서는 사용자가 기기를 추가 / 삭제 / 이름을 바꿀 때마다 동기화 요청을 트리거해야 합니다.
  2. 다음을 클릭하여 테스트 실행을 시작합니다.

테스트 모음 실행이 완료되면 테스트 사례의 결과를 확인합니다. 각각의 오류 메시지와 함께 두 개의 실패한 테스트 사례가 포착된 것을 확인할 수 있습니다.

5838d10631c98ed2.png

Cloud-to-Cloud 통합 실패를 디버그하려면 먼저 오류 메시지를 분석하여 오류의 근본 원인을 파악해야 합니다.

오류 메시지 분석하기

개발자가 근본 원인을 파악할 수 있도록 테스트 모음에는 실패한 각 테스트 사례에 대한 오류 메시지가 표시되어 실패 이유를 나타냅니다.

위의 첫 번째 실패한 테스트 사례의 경우

99e4e5d06965a8a7.png

오류 메시지는 테스트 모음에서 클라우드 간 통합에서 보고된 상태에 "isPause": true가 예상되지만 실제 상태에는 "isPause": false만 포함되어 있음을 나타냅니다.

또한 두 번째 실패한 테스트 사례의 오류 메시지는 클라우드 간 통합의 QUERY 응답에 "isPause": true가 포함되어 있음을 나타냅니다. 이는 클라우드 간 통합에서 보고된 상태의 "isPause": false와 다릅니다.

fdb5124102e3a37.png

두 오류 메시지에 따라 통합 보고서에 올바른 값으로 isPaused가 표시되는지 확인해야 합니다.

오류의 근본 원인 파악하기

보고서 상태를 통해 Home Graph에 상태 변경사항을 게시하는 reportstate 함수가 포함된 functions/index.js를 엽니다. Report State 페이로드를 검사하면 페이로드에 isPaused 상태가 누락된 것을 확인할 수 있습니다. 이는 테스트 모음이 실패한 테스트 사례에서 확인한 것과 정확히 일치합니다.

index.js

exports.reportstate = functions.database.ref('{deviceId}').onWrite(
    async (change, context) => {
      ...

      const requestBody = {
        requestId: 'ff36a3cc', /* Any unique ID */
        agentUserId: USER_ID,
        payload: {
          devices: {
            states: {
              /* Report the current state of our washer */
             [context.params.deviceId]: {
                online: true,
                on: snapshot.OnOff.on,
                isRunning: snapshot.StartStop.isRunning,
                currentRunCycle: [{
                  currentCycle: 'rinse',
                  nextCycle: 'spin',
                  lang: 'en',
                }],
                currentTotalRemainingTime: 1212,
                currentCycleRemainingTime: 301,
              },
            },
          },
        },
      };

      const res = await homegraph.devices.reportStateAndNotification({
        requestBody,
      });
      ...
    });

오류 수정

이제 오류의 근본 원인을 파악했으므로 Report State 페이로드에 isPaused 상태를 추가하여 functions/index.js를 수정합니다.

index.js

exports.reportstate = functions.database.ref('{deviceId}').onWrite(
    async (change, context) => {
      ...

      const requestBody = {
        requestId: 'ff36a3cc', /* Any unique ID */
        agentUserId: USER_ID,
        payload: {
          devices: {
            states: {
              /* Report the current state of our washer */
             [context.params.deviceId]: {
                online: true,
                on: snapshot.OnOff.on,
                isPaused: snapshot.StartStop.isPaused,
                isRunning: snapshot.StartStop.isRunning,
                currentRunCycle: [{
                  currentCycle: 'rinse',
                  nextCycle: 'spin',
                  lang: 'en',
                }],
                currentTotalRemainingTime: 1212,
                currentCycleRemainingTime: 301,
              },
            },
          },
        },
      };
      ...
    });

수정사항 테스트하기

Firebase CLI를 사용하여 업데이트된 코드를 배포합니다.

$ firebase deploy --only functions

스마트 홈용 테스트 모음을 다시 실행하면 모든 테스트 사례가 통과한 것을 확인할 수 있습니다.

148837f85d377dd6.png

5. 축하합니다

17d485868a6771bc.png

축하합니다. 스마트 홈 및 GCP 측정항목 및 로깅을 위한 테스트 모음을 통해 클라우드 간 통합 문제를 해결하는 방법을 알아봤습니다.

자세히 알아보기

이 Codelab을 기반으로 다음 실습을 해 보고 추가 리소스를 살펴보세요.

또한 사용자에게 통합을 게시하기 위한 인증 프로세스 등 통합을 테스트 및 제출하는 과정도 자세히 알아볼 수 있습니다.