本地首頁偵錯

1. 事前準備

智慧型住宅整合功能可讓 Google 助理控管使用者的智慧聯網裝置住家如要建立智慧型住宅動作,您必須提供能夠處理智慧型住宅意圖的 Cloud Webhook 端點。例如,使用者說出:「Ok Google,開燈」時Google 助理會將指令傳送至雲端執行要求,藉此更新裝置狀態。

Local Home SDK 可讓您新增本機路徑,將智慧型住宅意圖直接轉送至 Google Home 裝置,藉此強化智慧型住宅的整合作業,進而提升穩定性並減少處理使用者處理作業的延遲時間指令。可讓你使用 TypeScript 或 JavaScript 編寫及部署本機執行要求應用程式,藉此識別裝置,並在任何 Google Home 智慧音箱或 Google Nest 智慧螢幕上執行指令。這樣一來,您的應用程式就能直接與使用者現有的標準通訊協定來執行指令。

72ffb320986092c.png

對智慧型住宅動作偵錯是建構動作品質的重要步驟,但如果沒有資訊豐富的疑難排解和測試工具,則複雜且耗時。為協助智慧住宅動作偵錯,Google Cloud Platform (GCP) 的指標記錄智慧型住宅測試套件可協助您找出並解決動作問題。

必要條件

建構項目

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

課程內容

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

軟硬體需求

2. 執行洗衣機應用程式

取得原始碼

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

...或者從指令列複製 GitHub 存放區:

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

關於專案

範例應用程式包含類似的子目錄和雲端功能,與「為智慧型住宅動作啟用本機執行要求」程式碼研究室所述。不過,這裡是 app-faulty,而不是 app-start。我們會先從可以正常運作但無法正常運作的本地家庭應用程式開始著手。

連結至 Firebase

我們會使用您在「為智慧住宅動作啟用本機執行要求」程式碼研究室中建立的專案,但我們會部署在這個程式碼研究室中下載的檔案。

前往 app-faulty 目錄,然後使用「為智慧型住宅動作啟用本機執行要求」程式碼研究室中建立的 Actions 專案,設定 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

在瀏覽器中開啟「Hosting URL」(代管網址) (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 助理回覆「很抱歉,目前似乎無法使用故障洗衣機」等您嘗試控制洗衣機時。

表示無法透過本機路徑連上裝置。這項設定在發出「Ok Google,強制當地」按鈕前運作因為無法透過本機路徑連上裝置時,我們會改用雲端路徑。不過,一旦「強製本機」執行這項設定,即無法選擇改回使用雲端路徑。

為了找出問題所在,不妨利用 Google Cloud Platform (GCP) 中的指標Logging 和 Chrome 開發人員工具。

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

在下一節中,您將使用 Google 提供的工具,瞭解無法透過本機路徑連上裝置的原因。您可以使用 Google Chrome 開發人員工具連線至 Google Home 裝置、查看控制台記錄,以及為本機 Google Home 應用程式偵錯。您也可以將自訂記錄傳送至 Cloud Logging,以便掌握使用者在本機 Google Home 應用程式中發現的重大錯誤。

連結 Chrome 開發人員工具

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

  1. 確認已將 Google Home 裝置連結至有權存取 Actions 主控台專案的使用者。
  2. 重新啟動您的 Google Home 裝置,該裝置才能取得 HTML 網址,以及您在 Actions 主控台執行的掃描設定。
  3. 在開發機器上啟動 Chrome。
  4. 開啟新的 Chrome 分頁,並在網址欄位中輸入 chrome://inspect 即可啟動檢查器。

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

567f97789a7d8846.png

啟動檢查器

按一下應用程式網址下方的「檢查」,啟動 Chrome 開發人員工具。選取「Console」分頁標籤,並確認您可看到 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 應用程式。如要確認 Google Home 裝置是否使用預期的版本,請查看 Chrome 開發人員工具的控制台記錄。

ecc56508ebcf9ab.png

存取 Cloud Logging

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

  1. 在 Cloud Platform 控制台中,前往「Projects」(專案) 頁面。
  2. 選取智慧型住宅專案。
  3. 在「作業」下方,選取「記錄」>記錄檔探索工具

系統會透過 Identity and Access Management (IAM) 為 Actions 專案的使用者管理記錄資料存取權。如要進一步瞭解記錄資料的角色和權限,請參閱 Cloud Logging 存取權控管一文。

使用進階篩選器

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

按一下「Show query」切換按鈕,清單應會變成「Query Builder」方塊。在「Query Builder」(查詢產生器) 方塊中輸入 jsonPayload.intent="IDENTIFY",然後按一下「Run query」按鈕。

4c0b9d2828ee2447.png

因此,您會收到 IDENTIFY 處理常式擲回的所有錯誤記錄。接著,展開最後一個錯誤。拒絕 IDENTIFY 處理常式中的承諾時,您會找到剛剛設定的 errorCodedebugString

71f2f156c6887496.png

透過 debugString,我們可以判斷本機裝置 ID 格式不符合預期。本機 Google 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 裝置,以便載入更新後的本機應用程式。請確認本機主畫面應用程式為 1.0.2 版,而 Chrome 開發人員工具控制台中應該不會出現任何錯誤。

c8456f7b5f77f894.png

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

「Ok Google,強制當地。」

「Ok Google,把洗衣機關掉。」

「Ok Google,打開洗衣機。」

...

「Ok Google,強制預設。」

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

使用 Google Home 應用程式中的觸控設定或語音指令驗證裝置後,你可以使用自動化的針對智慧型住宅測試套件,根據與動作相關聯的裝置類型和特徵驗證用途。測試套件會執行一系列的測試來偵測動作中的問題,並針對失敗的測試案例顯示實用資訊,有助於加快偵錯速度,再深入分析事件記錄。

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

如要測試您的智慧型住宅動作 by Test Suite,請按照下列操作說明:

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

67433d9190fa770e.png

測試完成後,您會發現雲端路徑中的暫停/恢復測試在通過時,本機路徑中的暫停/繼續執行測試會失敗。

d1ebd5cfae2a2a47.png

分析錯誤訊息

請進一步瞭解測試失敗案例的錯誤訊息。可讓您瞭解測試的預期狀態和實際狀態。在這個案例中,「Pause the Washer」的預期狀態為 isPaused: true,但實際狀態我們得到 isPaused: false。同樣地,「Pause the Washer」的預期狀態為 isPaused: true,但實際狀態我們得到 isPaused: false

6bfd3acef9c16b84.png

從錯誤訊息中,這個情況看起來像本機路徑,我們要反向設定 isPaused 狀態。

找出並修正錯誤

請找出本機 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 裝置,以便載入更新後的本機 Google Home 應用程式。確認本機主畫面應用程式為 1.0.3 版。

測試修正結果

現在,以相同設定重新執行適用於智慧型住宅的測試套件,您會發現所有測試案例都已通過。

b7fc8c5d3c727d8d.png

7. 恭喜

764dbc83b95782a.png

恭喜!您已順利學會如何透過智慧型住宅的測試套件,排解本機 Google Home 應用程式的問題Cloud Logging

瞭解詳情

您還可以試試以下其他功能:

您也可以進一步瞭解如何測試並提交動作送審,包括向使用者發布動作應用程式的認證程序。