本地首頁偵錯

1. 事前準備

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

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

72ffb320986092c.png

如要打造出色的動作品質動作,請務必對智慧型住宅動作進行偵錯。然而,如果缺乏資訊豐富且簡單易用的疑難排解和測試工具,就相當麻煩且耗時費力。為協助偵測和解決動作的問題,我們提供了 Google Cloud Platform (GCP) (GCP) 指標LoggingTest Suite for Smart Home

必備條件

建構項目

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

課程內容

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

事前準備

2. 執行 Waher 應用程式

取得原始碼

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

...或透過指令列複製 GitHub 存放區:

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

關於專案

範例應用程式包含類似的子目錄和雲端函式,如「為智慧型住宅動作啟用本機執行要求」程式碼研究室所述。我們沒有 app-start,而是這裡的 app-faulty。我們會先從可正常運作但成效不彰的本地 Google 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

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

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 應用程式

透過語音指令將指令傳送至 Google Home 裝置,例如:

「Ok Google,打開洗衣機。」

「Ok Google,啟動洗衣機。」

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

「Ok Google,停止『洗衣』。」

如果你嘗試在「強制使用本機」設定後控制洗衣機,Google 助理會回應「很抱歉,目前似乎無法使用 Faulty Washer」。

這表示裝置無法透過本機路徑連上。由於無法透過本機路徑與裝置連線,因此在發出「Ok 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 裝置連結至具備 Actions 控制台專案存取權的使用者。
  2. 重新啟動 Google Home 裝置,取得 HTML 網址和您在「動作」控制台中儲存的掃描設定。
  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 控制台中,前往「專案」頁面。
  2. 選取智慧型住宅專案。
  3. 在「作業」下方,選取「記錄」 >「記錄檔探索工具」

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

使用進階篩選器

我們知道 IDENTIFY 意圖發生錯誤,因為系統無法辨識本機裝置,導致本機路徑無效。不過,我們希望確實瞭解問題所在,因此先篩選出 IDENTIFY 處理常式中發生的錯誤。

展開「查詢預覽」方塊,應該就會變成「查詢建構工具」方塊。在「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 應用程式的觸控設定或語音指令驗證裝置後,您可以使用自動化的智慧型住宅測試套件,根據與動作相關的裝置類型和特徵驗證用途。「測試套件」會執行一系列測試來偵測動作中的問題,並顯示失敗測試案例的相關資訊,以加快偵錯速度,然後再深入查看事件記錄。

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

請按照下列操作說明,使用「測試套件」測試智慧住宅動作:

  1. 在網路瀏覽器中開啟測試智慧型住宅套件
  2. 點選右上角的按鈕即可登入 Google。這麼做可讓測試套件直接將指令傳送給 Google 助理。
  3. 在「專案 ID」欄位中,輸入智慧型住宅動作的專案 ID。然後點選「下一步」繼續操作。
  4. 在「Test Settings」步驟的「Device and Trais」區段中,您應該會看到正常的 Faulty Washer。
  5. 停用「Test Request Sync」選項,因為範例應用程式沒有可新增 / 移除 / 重新命名洗衣機的 UI。在工作系統中,每當使用者新增 / 移除 / 重新命名裝置時,您都必須觸發 Request Sync
  6. 我們將測試本機和雲端路徑,因此請保持啟用「Local Home SDK」選項。
  7. 點選「下一步」開始執行測試。

67433d9190fa770e.png

測試完成後,您會發現本機路徑中的「Pause/Resume」(暫停/繼續) 測試失敗,而雲端路徑中的「Pause/Resume」(暫停/恢復) 測試傳遞時就會失敗。

d1ebd5cfae2a2a47.png

分析錯誤訊息

請進一步瞭解失敗測試案例中的錯誤訊息。這些函式會顯示測試的預期狀態和實際狀態。在這個例子中,「暫停使用洗衣機」的預期狀態為 isPaused: true,但在實際狀態中為 isPaused: false。同樣地,「暫停使用洗衣機」的預期狀態是 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.pausetruefalse 則應該設為 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 {};
    }
}

變更本機家庭應用程式版本,以便我們確認使用的是否為正確的版本。

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

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

瞭解詳情

再試試下列功能:

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