本地首頁偵錯

1. 事前準備

智慧型住宅整合功能可讓 Google 助理控制使用者住家中的已連結裝置。如要建構雲端到雲端整合,您必須提供可處理智慧型住宅意圖的雲端 Webhook 端點。舉例來說,當使用者說出「Ok Google,開燈」,Google 助理就會將指令傳送至雲端執行服務,以便更新裝置狀態。

Local Home SDK 可新增本機路徑,直接將智慧型住宅意圖轉送至 Google Home 裝置,藉此提升可靠性,並縮短處理使用者指令的延遲時間,進而提升智慧型住宅整合程度。您可以使用這個 API 在 TypeScript 或 JavaScript 中編寫及部署本機服務應用程式,以便在任何 Google Home 智慧音箱或 Google Nest 智慧螢幕上識別裝置並執行指令。接著,應用程式會透過區域網路,使用現有的標準通訊協定來執行指令,直接與使用者的現有智慧型裝置通訊。

72ffb320986092c.png

除錯雲端到雲端整合是建構正式品質整合作業的關鍵步驟,但如果沒有實用且易於使用的疑難排解和測試工具,這項作業將會相當耗時且費力。為方便排解雲端到雲端整合問題,Google Cloud Platform (GCP) 的MetricsLogging智慧型住宅測試套件可協助您找出並解決整合問題。

必要條件

建構項目

在本程式碼研究室中,您將為雲端對雲端整合建構本機執行要求,並將其連結至 Google 助理,然後透過智慧型住宅與 Google Cloud Platform (GCP) 指標和記錄的測試套件,對本機 Home 應用程式進行偵錯。

課程內容

  • 如何使用 GCP 指標和記錄功能,找出並解決實際工作環境問題。
  • 如何使用測試套件找出功能和 API 問題。
  • 如何在開發 Local Home 應用程式時使用 Chrome 開發人員工具。

軟硬體需求

2. 執行洗衣機應用程式

取得原始碼

按一下下方連結,即可在開發機器上下載這個程式碼研究室的範例:

...或者,您也可以從指令列複製 GitHub 存放區:

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

關於專案

這個入門應用程式包含的子目錄和雲端函式與 啟用雲端至雲端整合的本機訂單處理功能程式碼研究室相似。但這裡使用的是 app-faulty,而非 app-start。我們將從本機的 Home 應用程式開始,該應用程式雖然可運作,但效能不佳。

連結至 Firebase

我們會使用您在啟用雲端到雲端整合功能的本機訂單履行程式碼研究室中建立的專案,但我們會部署在本程式碼研究室中下載的檔案。

前往 app-faulty 目錄,然後在「啟用雲端至雲端整合功能的本機訂單履行」程式碼研究室中建立的整合專案中設定 Firebase CLI:

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

部署至 Firebase

前往 app-faulty/functions 資料夾,然後使用 npm 安裝所有必要的依附元件:

$ cd functions
$ npm install

注意:如果您看到下列訊息,可以忽略並繼續操作。這項警告是因為一些較舊的依附元件,詳情請參閱這篇文章

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

前往 app-faulty/local/ 目錄,然後執行下列指令,下載 TypeScript 編譯器並編譯應用程式:

$ cd ../local
$ npm install
$ npm run build

這會編譯 index.ts (TypeScript) 來源,並將下列內容放入 app-faulty/public/local-home/ 目錄:

  • bundle.js:包含本機應用程式和依附元件的編譯 JavaScript 輸出內容。
  • index.html:本機代管頁面,用於提供應用程式,以便在裝置上進行測試。

您已安裝依附元件並設定專案,現在可以首次執行應用程式了。

$ firebase deploy

您應該會看到下列控制台輸出內容:

...

✔ Deploy complete!

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

這個指令會部署網頁應用程式,以及幾個 Cloud Functions for Firebase

更新 HomeGraph

在瀏覽器 (https://<project-id>.web.app) 中開啟主機網址,即可查看網頁應用程式。在網頁 UI 中,按一下「Refresh」ae8d3b25777a5e30.png 按鈕,透過「Request Sync」更新 HomeGraph,並使用來自故障洗衣機應用程式的最新裝置中繼資料:

fa3c47f293cfe0b7.png

開啟 Google Home 應用程式,確認洗衣機裝置的新名稱「Faulty Washer」是否顯示在應用程式中。請務必將裝置指派到有 Nest 裝置的房間。

2a082ee11d47ad1a.png

3. 啟動智慧型洗衣機

如果您已執行「啟用雲端至雲端整合功能的本機訂單處理程序」程式碼研究室,應該已啟動虛擬智慧型洗衣機。如果已停止,請務必重新啟動虛擬裝置。

啟動裝置

前往 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

4. 測試本機 Google Home 應用程式

透過 Google Home 裝置向裝置發送語音指令,例如:

「Ok Google,開啟洗衣機」。

「Ok Google,啟動洗衣機」。

「Ok Google,強制使用本機」

「Ok Google,停止洗衣機運作」。

在「強制本地」後,如果嘗試控制洗衣機,Google 助理會回應「抱歉,目前無法使用故障的洗衣機」。

這表示無法透過本機路徑存取裝置。在發出「Hey Google,強制使用本機」指令之前,這項功能會正常運作,因為如果無法透過本機路徑存取裝置,系統會改用雲端路徑。不過,在「強制使用本機」後,系統會停用回復至雲端路徑的選項。

為了找出問題所在,我們將使用 Google Cloud Platform (GCP) 的MetricsLogging 和 Chrome 開發人員工具。

5. 對本機 Google Home 應用程式進行偵錯

在下一個章節中,您將使用 Google 提供的工具,找出無法透過本機路徑存取裝置的原因。您可以使用 Google Chrome 開發人員工具連線至 Google Home 裝置、查看主控台記錄檔,以及對 Local Home 應用程式進行偵錯。您也可以將自訂記錄檔傳送至 Cloud Logging,以便瞭解使用者在 Local Home 應用程式中發現的主要錯誤。

連結 Chrome 開發人員工具

如要將偵錯工具連結至本機執行要求應用程式,請按照下列步驟操作:

  1. 請確認你已將 Google Home 裝置連結至具備 開發人員控制台專案存取權的使用者。
  2. 重新啟動 Google Home 裝置,讓裝置取得 HTML 網址,以及你在開發人員控制台中放置的掃描設定。
  3. 在開發機器上啟動 Chrome。
  4. 開啟新的 Chrome 分頁,然後在網址欄中輸入 chrome://inspect,即可啟動檢查器。

頁面上會顯示裝置清單,應用程式網址則會顯示在 Google Home 裝置名稱下方。

567f97789a7d8846.png

啟動檢查器

按一下應用程式網址下方的「Inspect」,即可啟動 Chrome 開發人員工具。選取「控制台」分頁,確認您可以看到 TypeScript 應用程式列印的 IDENTIFY 意圖內容。

774c460c59f9f84a.png

這項輸出內容表示 IDENTIFY 處理常式已成功觸發,但 IdentifyResponse 中傳回的 verificationId 與 HomeGraph 中的任何裝置都不相符。讓我們新增一些自訂記錄,找出原因。

新增自訂記錄

雖然 Local Home SDK 會顯示 DEVICE_VERIFICATION_FAILED 錯誤,但這並無法協助找出根本原因。我們來新增一些自訂記錄,確保能正確讀取及處理掃描資料。請注意,如果我們拒絕含有錯誤的承諾,系統實際上也會將錯誤訊息傳送至 Cloud Logging

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.
  // Is there something wrong here?
  const localDeviceId = Buffer.from(scanData.data);
  console.log(`IDENTIFY handler: received local device id
      ${localDeviceId}`);

  // Add custom logs
  if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_device', 'Invalid device id from scan data ' +
        localDeviceId);
    return Promise.reject(err);
  }

  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);
}

此外,請變更本機 Google Home 應用程式版本,以便我們判斷是否使用正確的版本。

local/index.ts

const localHomeSdk = new App('1.0.1');

新增自訂記錄後,您必須再次編譯應用程式,並重新部署至 Firebase。

$ cd ../app-faulty/local
$ npm run build
$ firebase deploy --only hosting

請重新啟動 Google Home 裝置,以便載入更新過的本機居家應用程式。如要查看 Google Home 裝置是否使用預期的版本,請在 Chrome 開發人員工具中查看主控台記錄。

ecc56508ebcf9ab.png

存取 Cloud Logging

讓我們來看看如何使用 Cloud Logging 找出錯誤。如要存取專案的 Cloud Logging,請按照下列步驟操作:

  1. 前往 Cloud Platform 主控台的「專案」頁面。
  2. 選取智慧型住宅專案。
  3. 在「操作」下方,依序選取「記錄」 >「記錄檔探索工具」

整合專案使用者的記錄資料存取權,會透過身分與存取權管理 (IAM) 進行管理。如要進一步瞭解記錄資料的角色和權限,請參閱 Cloud Logging 的存取權控管

使用進階篩選條件

我們知道 IDENTIFY 意圖發生錯誤,因為本機裝置無法辨識,因此本機路徑無法運作。不過,我們想確切瞭解問題所在,因此請先篩除 IDENTIFY 處理常式中發生的錯誤。

點選「顯示查詢」切換鈕,該按鈕應會變成「查詢建構工具」方塊。在「查詢建立工具」方塊中輸入 jsonPayload.intent="IDENTIFY",然後按一下「執行查詢」按鈕。

4c0b9d2828ee2447.png

因此,您會取得 IDENTIFY 處理常式中擲回的所有錯誤記錄。接著,展開上次的錯誤。您會在 IDENTIFY 處理常式中拒絕承諾時,找到剛設定的 errorCodedebugString

71f2f156c6887496.png

debugString 中,我們可以得知本機裝置 ID 並未採用預期格式。Local Home 應用程式預期取得的本機裝置 ID 應為字串,開頭為 deviceid,後面接 3 個數字,但本機裝置 ID 是十六進制字串。

修正錯誤

回到我們從掃描資料剖析本機裝置 ID 的原始碼,我們發現在將字串轉換為位元組時,並未提供編碼。系統會以十六進位字串的形式接收掃描資料,因此在呼叫 Buffer.from() 時,請將 hex 做為字元編碼傳遞。

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');
  console.log(`IDENTIFY handler: received local device id
      ${localDeviceId}`);

  if (!localDeviceId.toString().match(/^deviceid[0-9]{3}$/gi)) {
    const err = new IntentFlow.HandlerError(request.requestId,
      'invalid_device', 'Invalid device id from scan data ' +
      localDeviceId);
    return Promise.reject(err);
  }

  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);
}

此外,請變更本機 Google Home 應用程式版本,以便我們判斷是否使用正確的版本。

local/index.ts

const localHomeSdk = new App('1.0.2');

修正錯誤後,請編譯應用程式並重新部署至 Firebase。在 app-faulty/local 中執行:

$ npm run build
$ firebase deploy --only hosting

測試修正結果

部署完成後,請重新啟動 Google Home 裝置,以便載入更新的本機 Home 應用程式。請確認本機 Home 應用程式版本為 1.0.2,這次應該不會在 Chrome 開發人員工具主控台中看到任何錯誤。

c8456f7b5f77f894.png

你現在可以再次嘗試將指令傳送到裝置。

「Ok Google,強制使用本機」。

「Ok Google,停止洗衣機運作」。

「Ok Google,開啟洗衣機」。

...

「Ok Google,強制使用預設設定」。

6. 執行智慧型住宅的測試套件

使用 Google Home 應用程式中的觸控設定或語音指令驗證裝置後,您可以使用自動化的智慧型家居測試套件,根據與整合相關聯的裝置類型和特徵驗證用途。測試套件會執行一系列測試,偵測整合作業中的問題,並針對失敗的測試案例顯示資訊性訊息,以便您在深入研究事件記錄之前,加快偵錯作業。

執行智慧型住宅的測試套件

請按照下列操作說明,透過 Test Suite 測試雲端到雲端整合:

  1. 在網路瀏覽器中開啟智慧住宅測試套件
  2. 使用右上角的按鈕登入 Google。這樣一來,測試套件就能直接將指令傳送至 Google 助理。
  3. 在「Project ID」欄位中,輸入雲端到雲端整合項目的專案 ID。然後點選「下一步」繼續。
  4. 在「測試設定」步驟中,您應該會在「裝置和測試」部分中看到「Faulty Washer」裝置。
  5. 由於範例洗衣機應用程式沒有用於新增 / 移除 / 重新命名洗衣機的 UI,因此請停用「Test Request Sync」選項。在實際運作系統中,只要使用者新增 / 移除 / 重新命名裝置,就必須觸發「Request Sync」
  6. 請保留啟用的 Local Home SDK 選項,因為我們將測試本機和雲端路徑。
  7. 按一下「下一步:測試環境」,即可開始執行測試。

67433d9190fa770e.png

測試完成後,您會發現本機路徑中的暫停/繼續測試失敗,而雲端路徑中的暫停/繼續測試則通過。

d1ebd5cfae2a2a47.png

分析錯誤訊息

請仔細查看失敗測試案例中的錯誤訊息。這些資訊會告訴您該測試的預期狀態和實際狀態。在本例中,「Pause the Washer」的預期狀態為 isPaused: true,但實際狀態為 isPaused: false。同樣地,對於「暫停洗衣機」來說,預期狀態是 isPaused: true,但實際狀態是 isPaused: false

6bfd3acef9c16b84.png

根據錯誤訊息,在本機路徑中,我們似乎反向設定 isPaused 狀態。

找出並修正錯誤

讓我們找出 Local Home 應用程式將執行指令傳送至裝置的來源程式碼。getDataCommand()executeHandler() 呼叫的函式,用於在傳送至裝置的執行指令中設定 payload

local/index.ts

getDataForCommand(command: string, params: IWasherParams): unknown {
    switch (command) {
        case 'action.devices.commands.OnOff':
            return {
                on: params.on ? true : false
            };
        case 'action.devices.commands.StartStop':
            return {
                isRunning: params.start ? true : false
            };
        case 'action.devices.commands.PauseUnpause':
            return {
                // Is there something wrong here?
                isPaused: params.pause ? false : true
            };
        default:
            console.error('Unknown command', command);
            return {};
    }
}

我們確實將 isPause 設為反向狀態,因此應在 params.pausetrue 時設為 true,在其他情況下則設為 false。那麼,讓我們來解決這個問題。

local/index.ts

getDataForCommand(command: string, params: IWasherParams): unknown {
    switch (command) {
        case 'action.devices.commands.OnOff':
            return {
                on: params.on ? true : false
            };
        case 'action.devices.commands.StartStop':
            return {
                isRunning: params.start ? true : false
            };
        case 'action.devices.commands.PauseUnpause':
            return {
                isPaused: params.pause ? true : false
            };
        default:
            console.error('Unknown command', command);
            return {};
    }
}

變更本機 Google Home 應用程式版本,以便我們判斷是否使用正確的版本。

local/index.ts

const localHomeSdk = new App('1.0.3');

請務必再次編譯應用程式,並重新部署至 Firebase。在 app-faulty/local 中執行:

$ npm run build
$ firebase deploy --only hosting

請重新啟動 Google Home 裝置,以便載入更新的本機 Home 應用程式。請確認本機 Home 應用程式版本為 1.0.3。

測試修正結果

現在,請使用相同的設定重新執行智慧型家居測試套件,您會發現所有測試案例都通過測試。

b7fc8c5d3c727d8d.png

7. 恭喜

764dbc83b95782a.png

恭喜!您已成功瞭解如何透過智慧住宅測試套件和 Cloud Logging 排解本機 Home 應用程式的問題。

瞭解詳情

以下提供其他可嘗試的做法:

您也可以進一步瞭解如何測試及提交整合項目供審查,包括向使用者發布整合項目的認證程序。