1. 事前準備
物聯網 (IoT) 開發人員可以建立智慧型住宅動作,讓使用者能夠透過 Google Home 應用程式的觸控設定和 Google 助理語音指令來控制裝置。
智慧住宅動作需使用 Home Graph 取得與住家和裝置相關的情境資料,為住家建立邏輯地圖。並根據上文內容,Google 助理更瞭解使用者要求在家中的相對位置。舉例來說,「住家圖」可以儲存客廳的概念,其中包含多種製造商的多種裝置,例如溫度控制器、燈具、風扇和吸塵器。
必要條件
- 打造智慧型住宅動作開發人員指南
建構項目
在本程式碼研究室中,您將發布管理虛擬智慧型洗衣機的雲端服務,然後打造智慧型居家動作並將其連結至 Google 助理。
課程內容
- 如何部署智慧型居家雲端服務
- 如何將服務連結至 Google 助理
- 如何將裝置狀態變更發布至 Google
軟硬體需求
- 使用 Google Chrome 等網路瀏覽器
- 已安裝 Google Home 應用程式的 iOS 或 Android 裝置
- Node.js 10.16 以上版本
- Google Cloud 帳單帳戶
2. 開始使用
啟用活動控制項
如要使用 Google 助理,您必須將特定活動資料提供給 Google。Google 助理需要這類資料才能正常運作;不過,分享資料並非要求 SDK 的必要條件。如要分享這項資料,請建立 Google 帳戶 (如果還沒有帳戶)。您可以使用任何 Google 帳戶,例如您的開發人員帳戶。
開啟要與 Google 助理搭配使用的 Google 帳戶的活動控制項頁面。
確認下列切換開關已啟用:
- 網路和應用程式活動:此外,請務必勾選 [包括 Chrome 歷史記錄以及採用 Google 服務的網站、應用程式和裝置中的活動記錄] 核取方塊。
- 裝置資訊
- 語音和音訊活動
建立 Actions 專案
- 前往 Actions on Google Developer Console。
- 按一下 [新專案],輸入專案名稱,然後按一下 [建立專案]。
選取智慧住宅應用程式
在動作控制台的總覽畫面上,選取 [智慧型首頁]。
選擇 [智慧型住宅] 體驗資訊卡,然後點選 [開始建立],系統隨即會將您導向專案控制台。
安裝 Firebase CLI
Firebase 指令列介面 (CLI) 可讓您在本機環境中提供網路應用程式,並將網路應用程式部署到 Firebase 託管。
如要安裝 CLI,請在終端機中執行下列 npm 指令:
npm install -g firebase-tools
如要確認 CLI 是否已正確安裝,請執行:
firebase --version
執行下列指令,以您的 Google 帳戶授權 Firebase CLI:
firebase login
3. 執行入門應用程式
開發環境已設置完成之後,您可以部署入門專案,確認所有設定皆正確無誤。
取得原始碼
點選下列連結,在開發機器下載本程式碼研究室的範例:
...您也可以透過指令列複製 GitHub 存放區:
git clone https://github.com/googlecodelabs/smarthome-washer.git
關於專案
範例專案包含下列子目錄:
public:
前端 UI 可輕鬆控制及監控智慧型洗衣機的狀態。functions:
功能完整的實作雲端服務,透過 Cloud Functions for Firebase 和 Firebase 即時資料庫管理智慧型洗衣機。
連結至 Firebase
前往 washer-start
目錄,然後使用 Actions 專案設定 Firebase CLI:
cd washer-start firebase use <project-id>
設定 Firebase 專案
初始化 Firebase 專案。
firebase init
選取 [Database]、[Functions] 和 [Hosting] CLI 功能。
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. ❯◉ Database: Configure Firebase Realtime Database and deploy rules ◯ Firestore: Deploy rules and create indexes for Firestore ◉ Functions: Configure and deploy Cloud Functions ◉ Hosting: Configure and deploy Firebase Hosting sites ◯ Storage: Deploy Cloud Storage security rules ◯ Emulators: Set up local emulators for Firebase features ◯ Remote Config: Get, deploy, and rollback configurations for Remote Config
系統就會為專案初始化必要的 API 和功能。
出現提示時,請初始化即時資料庫。您可以使用資料庫執行個體的預設位置。
? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up? Yes ? Please choose the location for your default Realtime Database instance: us-central1
由於您使用的是入門專案程式碼,因此請針對安全性規則選擇預設檔案,並確保您不會覆寫現有的資料庫規則檔案。
? What file should be used for Realtime Database Security Rules? Database.rules.json ? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console? No
同樣地,在設定函式時,您應使用預設檔案,並確保不會覆寫專案範例中現有的 index.js 和 package.json 檔案。
? What language would you like to use to write Cloud Functions? JavaScript ? File functions/package.json already exists. Overwrite? No ? File functions/index.js already exists. Overwrite? No ? Do you want to install dependencies with npm now? Yes
最後,將主機設定調整為在專案程式碼中使用 public
目錄,然後使用現有的 index.html 檔案。
? What do you want to use as your public directory? public ? Configure as a single-page app (rewrite all urls to /index.html)? Yes ? File public/index.html already exists. Overwrite? No
部署至 Firebase
前往 functions
資料夾,然後使用 npm.
安裝所有必要的依附元件
cd functions npm install
您已安裝依附元件並設定專案,現在可開始使用首次執行應用程式了。
firebase deploy
以下是您應該會看到的主控台輸出結果:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<project-id>.web.app
這個指令會部署網路應用程式和數個 Cloud Functions for Firebase。
在瀏覽器中開啟代管網址 (https://<project-id>.web.app
),查看網路應用程式。您會看到以下介面:
這個網頁版 UI 代表可檢視或修改裝置狀態的第三方平台。如要開始將資料庫資訊填入裝置資訊,請按一下「Update」。您將不會在網頁上看到任何變更,但資料庫的目前狀態將儲存在資料庫中。
您現在可以使用 Actions 主控台將您部署的雲端服務連結至 Google 助理。
設定 Actions 主控台專案
在 [總覽] > [建立動作] 之下,選取 [新增動作]。輸入要為智慧型住宅意圖提供出貨功能的 Cloud 函式網址,然後按一下 [儲存]。
https://us-central1-<project-id>.cloudfunctions.net/smarthome
在 [開發] > [叫用] 分頁中,為動作新增「顯示名稱」,然後按一下 [儲存]。這個名稱會顯示在 Google Home 應用程式中。
如要啟用帳戶連結功能,請在左側導覽面板中選取「開發」>「帳戶連結」選項。請使用以下帳戶連結設定:
Client-ID |
|
用戶端密碼 |
|
驗證網址 |
|
權杖網址 |
|
按一下 [儲存] 以儲存帳戶連結設定,然後按一下 [測試] 以為專案啟用測試。
系統會將您重新導向至 Simulator。如果畫面顯示 [立即測試],請按一下 [重設測試] 確認已啟用測試。
現在您可以開始實作連結裝置狀態與 Google 助理所需的 Webhook。
4. 建立洗衣機
您的動作已設定完成,可以開始新增裝置及傳送資料。您的雲端服務必須處理下列意圖:
- 當 Google 助理想知道使用者連結了哪些裝置時,就會發生
SYNC
意圖。使用者連結帳戶之後,系統就會將這項資訊傳送至您的服務。您應針對所有使用者的裝置及其功能,以 JSON 酬載回應。 - 當 Google 助理想掌握裝置目前的狀態或狀態時,就會觸發
QUERY
意圖。您的 JSON 酬載應會回應每個要求裝置的狀態。 - 當 Google 助理想要代表使用者控制裝置時,就會發生
EXECUTE
意圖。您的 JSON 酬載應以個別要求裝置的執行狀態回應。 - 當使用者取消連結自己的帳戶與 Google 助理時,就會產生
DISCONNECT
意圖。您應停止將這位使用者的裝置事件傳送給 Google 助理。
您將在以下各節中更新先前部署的函式來處理這些意圖。
更新同步處理回應
開啟 functions/index.js
,其中包含回應 Google 助理要求的代碼。
您必須傳回裝置中繼資料和功能來處理 SYNC
意圖。更新 onSync
陣列中的 JSON,為洗衣機提供裝置資訊和建議的特性。
index.js
app.onSync((body) => {
return {
requestId: body.requestId,
payload: {
agentUserId: USER_ID,
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle',
],
name: {
defaultNames: ['My Washer'],
name: 'Washer',
nicknames: ['Washer'],
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-washer',
hwVersion: '1.0',
swVersion: '1.0.1',
},
willReportState: true,
attributes: {
pausable: true,
},
}],
},
};
});
部署至 Firebase
使用 Firebase CLI 部署已更新的雲端出貨要求:
firebase deploy --only functions
連結至 Google 助理
為測試智慧型住宅動作,你必須將專案連結至 Google 帳戶。以便透過 Google 助理平台和登入同一個帳戶的 Google Home 應用程式進行測試。
- 開啟手機上的「Google 助理」設定。請注意,您應該使用與主控台相同的帳戶登入。
- 依序前往 [Google 助理] > [設定] > [居家控制系統] (位於「Google 助理」下方)。
- 選取右下角的加號 (+) 圖示
- 畫面上應該會出現測試應用程式,其中含有 [test] 前置字元以及您設定的顯示名稱。
- 選取該項目。Google 助理隨即會驗證你的服務並傳送
SYNC
要求,要求你的服務為使用者提供裝置清單。
開啟「Google Home」應用程式,確認你可以看到洗衣機裝置。
5. 處理指令和查詢
您的雲端服務已成功將洗衣機回報給 Google,因此您需要新增要求裝置狀態及傳送指令的功能。
處理 QUERY 意圖
QUERY
意圖包含一組裝置。您可以針對每個裝置回應目前的狀態。
在 functions/index.js
中,編輯 QUERY
處理常式來處理意圖要求中包含的目標裝置清單。
index.js
app.onQuery(async (body) => {
const {requestId} = body;
const payload = {
devices: {},
};
const queryPromises = [];
const intent = body.inputs[0];
for (const device of intent.payload.devices) {
const deviceId = device.id;
queryPromises.push(queryDevice(deviceId)
.then((data) => {
// Add response to device payload
payload.devices[deviceId] = data;
}
));
}
// Wait for all promises to resolve
await Promise.all(queryPromises);
return {
requestId: requestId,
payload: payload,
};
});
針對要求中包含的裝置,傳回儲存在即時資料庫中的目前狀態。更新 queryFirebase
和 queryDevice
函式,以傳回洗衣機的狀態資料。
index.js
const queryFirebase = async (deviceId) => {
const snapshot = await firebaseRef.child(deviceId).once('value');
const snapshotVal = snapshot.val();
return {
on: snapshotVal.OnOff.on,
isPaused: snapshotVal.StartStop.isPaused,
isRunning: snapshotVal.StartStop.isRunning,
};
};
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
};
};
處理 EXECUTE 意圖
EXECUTE
意圖會處理指令以更新裝置狀態。回應會傳回各個指令的狀態 (例如 SUCCESS
、ERROR
或 PENDING
),以及新的裝置狀態。
在 functions/index.js
中,編輯 EXECUTE
處理常式,以處理需要更新的更新屬性,以及每個指令的目標裝置集:
index.js
app.onExecute(async (body) => {
const {requestId} = body;
// Execution results are grouped by status
const result = {
ids: [],
status: 'SUCCESS',
states: {
online: true,
},
};
const executePromises = [];
const intent = body.inputs[0];
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(() => functions.logger.error('EXECUTE', device.id)));
}
}
}
await Promise.all(executePromises);
return {
requestId: requestId,
payload: {
commands: [result],
},
};
});
針對每個指令和目標裝置,在即時資料庫中更新與所需特性相對應的值。修改 updateDevice
函式以更新適當的 Firebase 參照並傳回更新後的裝置狀態。
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
case 'action.devices.commands.OnOff':
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
case 'action.devices.commands.StartStop':
state = {isRunning: params.start};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
state = {isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
6. 測試動作
實作全部三個意圖之後,您可以測試動作是否能夠控制洗手。
部署至 Firebase
使用 Firebase CLI 部署已更新的雲端出貨要求:
firebase deploy --only functions
測試洗衣機
現在,如果您嘗試在手機上使用下列任一語音指令,就能看到這個值的變化:
「Ok Google,打開洗衣機。」
「Ok Google,暫停洗衣機。」
「Ok Google,停止洗手。」
你也可以提問,查看洗衣機目前的狀態。
「Ok Google,我的洗手時間了嗎?」
「Ok Google,我的洗衣機正在運轉嗎?」
「Ok Google,洗衣機在我的生理週期如何?」
您也可以在 Firebase 控制台記錄中查看這些查詢和指令,只要在導覽選單中依序點選 [開發] > [函式] > [記錄] 即可。
7. 向 Google 回報更新問題
你已將雲端服務與智慧型住宅意圖完全整合,可讓使用者控制及查詢裝置目前的狀態。不過,實作完成後,您的服務仍無法透過各種方式主動將事件資訊 (例如裝置狀態或狀態變化) 傳送給 Google 助理。
使用要求同步處理功能時,您可以在使用者新增或移除裝置,或是裝置功能改變時觸發新的同步處理要求。透過回報狀態,當使用者實際變更裝置狀態 (例如開啟燈具開關),或使用其他服務變更裝置狀態時,您的雲端服務可以主動將裝置的狀態傳送至住家圖表。
在本節中,您將新增程式碼,從前端網路應用程式呼叫這些方法。
啟用 HomeGraph API
使用 HomeGraph API 即可儲存及查詢使用者 Home 圖中的裝置及其狀態。如要使用這個 API,您必須先開啟 Google Cloud 控制台並啟用 HomeGraph API。
在 Google Cloud 控制台中,選取與動作對應的專案 <project-id>.
。然後在 HomeGraph API 的 API 程式庫畫面中,按一下 [啟用]。
啟用報告狀態
寫入即時資料庫會觸發入門專案中的 reportstate
函式。更新 functions/index.js
中的 reportstate
函式以擷取寫入資料庫的資料,然後透過報告狀態發布至主圖。
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
async (change, context) => {
functions.logger.info('Firebase write event triggered Report State');
const snapshot = change.after.val();
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of our washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
},
},
},
},
};
const res = await homegraph.devices.reportStateAndNotification({
requestBody,
});
functions.logger.info('Report state response:', res.status, res.data);
});
啟用 Request Sync
在前端網路 UI 中重新整理圖示,會觸發入門專案的 requestsync
函式。在 functions/index.js
中實作 requestsync
函式,以呼叫 HomeGraph API。
index.js
exports.requestsync = functions.https.onRequest(async (request, response) => {
response.set('Access-Control-Allow-Origin', '*');
functions.logger.info(`Request SYNC for user ${USER_ID}`);
try {
const res = await homegraph.devices.requestSync({
requestBody: {
agentUserId: USER_ID,
},
});
functions.logger.info('Request sync response:', res.status, res.data);
response.json(res.data);
} catch (err) {
functions.logger.error(err);
response.status(500).send(`Error requesting sync: ${err}`);
}
});
部署至 Firebase
使用 Firebase CLI 部署更新後的程式碼:
firebase deploy --only functions
測試實作成果
按一下網頁 UI 中的「Refresh」(重新整理) 按鈕,然後確認 Firebase 控制台記錄中顯示同步處理要求。
接著,調整前端網路 UI 中洗衣機的屬性,然後按一下 [更新]。確認 Firebase 控制台記錄中會顯示向 Google 回報的狀態變更。
8. 恭喜
恭喜!你成功透過智慧型住宅動作將 Google 助理與裝置雲端服務整合。
瞭解詳情
歡迎參考下列建議,進一步深入瞭解:
您也可以進一步瞭解如何測試並提交審核動作,包括向使用者發布動作的認證程序。