歡迎來到 Google Home 開發人員中心,你可以在這裡學習如何學習智慧型住宅動作。注意事項:您將在 Actions 主控台建構動作。

偵錯本機首頁

1. 事前準備

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

Local Home SDK 新增了本機路徑,將智慧型住宅意圖直接導向 Google Home 裝置,藉此改善智慧型住宅的整合速度,藉此提升可靠性並減少處理使用者指令時的延遲時間。這可讓你在 TypeScript 或 JavaScript 中編寫及部署本機執行應用程式,藉此辨識裝置,並在任何 Google Home 智慧型揚聲器或 Google Nest 智慧螢幕上執行指令。之後,您的應用程式會使用現有的標準通訊協定來完成指令,並透過區域網路與使用者的現有智慧型裝置直接通訊。

72ffb320986092c.png

建立「智慧型住宅動作」是製作正式版動作的重要步驟,但這並不容易且十分耗時,而且沒有資訊豐富且易於使用的疑難排解和測試工具。您可以利用 Google Cloud Platform (GCP) 指標Logging智慧型住宅測試套件,找出並解決動作相關問題,以便對智慧型住宅動作進行偵錯。

必要條件

建構項目

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

課程內容

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

軟硬體需求

2. 執行洗衣機應用程式

取得原始碼

點選下列連結,在開發機器下載本程式碼研究室的範例:

...您也可以透過指令列複製 GitHub 存放區:

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

計畫資訊

範例應用程式包含為智慧型住宅動作啟用本機執行程式碼研究室的類似子目錄和雲端功能。不過,我們可以用 app-faulty 取代 app-start。我們會先介紹一款可以正常運作的本機主畫面應用程式。

連結至 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

在瀏覽器中開啟 Hosting URL (檢視網址,https://<project-id>.web.app) 以查看網路應用程式。在網頁 UI 中,按一下 [Refresh] (重新整理) 按鈕 ae8d3b25777a5e30.png,即可透過 Request Sync 更新錯誤 - 以執行錯誤洗衣機應用程式的最新裝置中繼資料:

fa3c47f293cfe0b7.png

請開啟「Google Home」應用程式,然後查看名稱為「洗衣機」的洗衣機裝置。請務必將裝置指派給裝有 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 裝置,例如:

「Ok Google,打開洗衣機。」

「Ok Google,開啟洗衣機。」

「Ok Google,強制地方。」

「Ok Google,停止洗手。」

當你嘗試控制「強制在本機位置」設定洗衣機時,Google 助理會回應「很抱歉,系統目前無法顯示故障洗衣機」,

也就是說,無法透過本機路徑連接裝置。這項功能可在發出「Hey Google,強制使用本機」指令之前運作,因為裝置無法透過本機路徑到達時,就會改用雲端路徑。不過,在「強制在本機位置」之後,無法切換回雲端路徑的選項。

為了瞭解問題所在,建議您使用以下工具:Google Cloud Platform (GCP) MetricsLogging 和 Chrome 開發人員工具。

5. 對本機主畫面應用程式進行偵錯

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

連結 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 裝置,讓裝置載入新版的本機主畫面應用程式。您可以透過 Chrome 開發人員工具查看 Console 記錄,瞭解 Google Home 裝置是否使用預期的版本。

ecc56508ebcf9ab.png

存取 Cloud Logging

讓我們來看看如何使用 Cloud Logging 找出錯誤。為您的專案存取 Cloud Logging:

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

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

使用進階篩選器

系統發現本機裝置無法辨別本機路徑失敗,因此會在 IDENTIFY 意圖中發生錯誤。不過,我們想要瞭解發生的問題,因此先排除 IDENTIFY 處理常式中發生的錯誤。

展開「Query Preview」(查詢預覽) 方塊,應該會變成「Query Builder」(查詢產生器) 方塊。在「Query Builderer」(查詢產生器) 方塊中輸入 jsonPayload.intent="IDENTIFY",然後按一下 [Run query] (執行查詢) 按鈕。

4c0b9d2828ee2447.png

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

71f2f156c6887496.png

我們可以從 debugString 得知本機裝置 ID 未採用預期的格式。本機主畫面應用程式預期將以 deviceid 開頭的 3 位數字形式取得本機裝置 ID,但此處的本機裝置 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 應用程式的觸控設定或語音指令驗證裝置後,您可以使用智慧型住宅測試套件,根據與動作相關的裝置類型和特性驗證用途。「測試套件」會執行一系列測試來偵測您的「動作」,並在發生這類事件時,顯示測試失敗訊息以協助您加快偵錯速度,再深入探討事件記錄。

執行智慧型住宅測試套件

請按照以下測試套件測試智慧型住宅動作的執行方式:

  1. 在網路瀏覽器中開啟智慧型住宅測試套件
  2. 使用右上角的按鈕登入 Google。讓「測試套件」可將指令直接傳送至「Google 助理」。
  3. 在 [專案 ID] 欄位中,輸入智慧住宅動作的專案 ID。然後點選 [下一步] 繼續。
  4. 在「Test Settings」(測試設定) 步驟中,「Device and Trais」(裝置及風險) 部分應會顯示發生問題的洗衣機。
  5. 停用 [Test Request Sync] 選項,因為範例洗衣機應用程式沒有可新增 / 移除 / 重新命名洗衣機的 UI。在正式版系統中,每當使用者新增 / 移除 / 重新命名裝置時,您都必須觸發 Request Sync
  6. 將「Local Home SDK」選項保持啟用,因為我們將會測試本機和雲端路徑。
  7. 點選 [下一步] 即可開始執行測試。

67433d9190fa770e.png

測試完成後,當本機路徑的暫停/繼續測試通過時,本機路徑中的暫停/繼續測試會失敗。

d1ebd5cfae2a2a47.png

分析錯誤訊息

檢查失敗測試案例中的錯誤訊息。並指出測試的預期狀態,以及實際狀態。在本範例中,「暫停洗衣機」的狀態為 isPaused: true,但在實際狀態中,我們得到了 isPaused: false。同樣的,「暫停洗衣機」預期狀態為 isPaused: true,但在實際狀態中卻得到 isPaused: false

6bfd3acef9c16b84.png

從本機錯誤訊息中,我們發現本機路徑的 isPaused 狀態是反向設定。

找出並修正錯誤

讓我們找出「Google 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,否則會設為 true。讓我們一起解決這個問題!

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 應用程式為 1.0.3 版。

測試修正結果

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

b7fc8c5d3c727d8d.png

7. 恭喜

764dbc83b95782a.png

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

瞭解詳情

你可以試試以下方法:

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