1. לפני שמתחילים
שילובים בין עננים משתמשים בסוגי מכשירים כדי להודיע ל-Google Assistant באיזו דקדוק צריך להשתמש עם מכשיר מסוים. מאפייני המכשיר מגדירים את היכולות של סוג מכשיר מסוים. מכשיר מקבל בירושה את המצבים של כל מאפיין מכשיר שנוסף לשילוב.
אתם יכולים לחבר כל מאפיין נתמך לסוג המכשיר שבחרתם כדי להתאים אישית את הפונקציונליות של המכשירים של המשתמשים. אם רוצים להטמיע מאפיינים מותאמים אישית בפעולות שלא זמינים כרגע בסכימת המכשיר, המאפיינים Modes ו-Toggles מאפשרים לשלוט בהגדרות ספציפיות באמצעות שם מותאם אישית שאתם מגדירים.
בנוסף ליכולת הבקרה הבסיסית שמסופקת על ידי סוגים ומאפיינים, ל-Smart Home API יש תכונות נוספות לשיפור חוויית המשתמש. תשובות שגיאה מספקות משוב מפורט מהמשתמשים כשהכוונה לא מצליחה. אימות משני של משתמשים מרחיב את התגובות האלה ומוסיף אבטחה נוספת למאפיין המכשיר שתבחרו. על ידי שליחת תגובות שגיאה ספציפיות לחסימות של אתגרים שהונפקו מ-Assistant, השילוב שלכם מ-Cloud ל-Cloud יכול לדרוש הרשאה נוספת כדי להשלים פקודה.
דרישות מוקדמות
- יצירת שילוב בין עננים מדריך למפתחים
- Smart Home Washer codelab
- סוגי מכשירים ו-traits מדריך למפתחים
מה תפַתחו
ב-codelab הזה תפרסו שילוב מוכן מראש של בית חכם עם Firebase, ואז תלמדו איך להוסיף מאפיינים לא סטנדרטיים למכונת הכביסה החכמה לגבי גודל הטעינה ומצב טורבו. תטמיעו גם דיווח על שגיאות וחריגים, ותלמדו לאכוף אישור מילולי להפעלת מכונת הכביסה באמצעות אימות משני של המשתמש.
מה תלמדו
- איך מוסיפים את התכונות Modes ו-Toggles לשילוב
- איך מדווחים על שגיאות וחריגים
- איך מפעילים אימות משתמש משני
מה צריך בשביל להצטרף
- דפדפן אינטרנט, כמו Google Chrome
- מכשיר iOS או Android שמותקנת בו אפליקציית Google Home
- Node.js מגרסה 10.16 ואילך
- חשבון Google
- חשבון לחיוב ב-Google Cloud
2. תחילת העבודה
הפעלת בקרת הפעילות בחשבון
כדי להשתמש ב-Google Assistant, אתם צריכים לשתף עם Google נתונים מסוימים של פעילות. Google Assistant זקוקה לנתונים האלה כדי לפעול כראוי, אבל הדרישה לשיתוף נתונים לא ספציפית ל-SDK. כדי לשתף את הנתונים האלה, צריך ליצור חשבון Google אם עדיין אין לכם חשבון. אפשר להשתמש בכל חשבון Google – לא צריך להשתמש בחשבון הפיתוח.
פותחים את דף בקרת הפעילות בחשבון Google שבו רוצים להשתמש עם Assistant.
מוודאים שהמתגים הבאים מופעלים:
- פעילות באינטרנט ובאפליקציות – בנוסף, חשוב לסמן את תיבת הסימון שמירה של ההיסטוריה והפעילות של Chrome מאתרים, מאפליקציות וממכשירים המשתמשים בשירותי Google.
- פרטי המכשיר
- תיעוד קול ואודיו
יצירת פרויקט של שילוב בין עננים
- נכנסים אל Developer Console.
- לוחצים על Create Project, מזינים שם לפרויקט ולוחצים על Create Project.
בחירת שילוב בין ענן לענן
בדף Project Home ב-Developer Console, בוחרים באפשרות Add cloud-to-cloud integration בקטע Cloud-to-cloud.
התקנת Firebase CLI
ממשק שורת הפקודה (CLI) של Firebase מאפשר להפעיל את אפליקציות האינטרנט באופן מקומי ולפרוס אותן באירוח ב-Firebase.
כדי להתקין את ה-CLI, מריצים את פקודת ה-npm הבאה מהטרמינל:
npm install -g firebase-tools
כדי לוודא שה-CLI הותקן בצורה נכונה, מריצים את הפקודה:
firebase --version
כדי לתת הרשאה ל-Firebase CLI באמצעות חשבון Google, מריצים את הפקודה:
firebase login
הוספת Firebase לפרויקט ב-Google Home Developer Console
שיטה 1: דרך מסוף Firebase
- עוברים אל Firebase.
- לוחצים על יצירת פרויקט Firebase.
- במסך Create a project (יצירת פרויקט), לוחצים על Add Firebase to Google Cloud project (הוספת Firebase לפרויקט Google Cloud).
- במסך Get started, בוחרים את הפרויקט ב-Google Cloud שיצרתם זה עתה במסוף הפיתוח של Google Home ולוחצים על Continue.
שיטה 2: דרך Firebase CLI
firebase projects:addfirebase
בוחרים את הפרויקט ב-Google Home Developer Console שיצרתם כדי להוסיף את Firebase.
כשמוסיפים את Firebase לפרויקט ב-Google Home Developer Console, הוא מופיע במסוף Firebase. מזהה הפרויקט ב-Firebase יהיה זהה למזהה הפרויקט ב-Google Home Developer Console.
הפעלת HomeGraph API
HomeGraph API מאפשר אחסון של מכשירים והמצבים שלהם ב-Home Graph של המשתמש, וגם שליפת נתונים לגביהם. כדי להשתמש ב-API הזה, קודם צריך לפתוח את מסוף Google Cloud ולהפעיל את HomeGraph API.
במסוף Google Cloud, בוחרים את הפרויקט שתואם לפעולות שלכם <firebase-project-id>.
ואז, במסך API Library של HomeGraph API, לוחצים על Enable (הפעלה).
3. הפעלת האפליקציה למתחילים
אחרי שמגדירים את סביבת הפיתוח, אפשר לפרוס את פרויקט המתחילים כדי לוודא שהכול מוגדר בצורה תקינה.
קבלת קוד המקור
כדי להוריד את הדוגמה ל-codelab הזה למחשב הפיתוח, לוחצים על הקישור הבא:
…או שאפשר לשכפל את מאגר GitHub משורת הפקודה:
git clone https://github.com/google-home/smarthome-traits.git
מחלצים את קובץ ה-ZIP שהורד.
מידע על הפרויקט
פרויקט המתחיל מכיל את ספריות המשנה הבאות:
public:
ממשק משתמש קל לשימוש שמאפשר לשלוט במכונת הכביסה החכמה ולעקוב אחרי המצב שלה.functions:
שירות ענן מיושם במלואו שמנהל את מכונת הכביסה החכמה באמצעות Cloud Functions for Firebase ו-Firebase Realtime Database.
המימוש בענן שסיפקתם כולל את הפונקציות הבאות ב-index.js
:
-
fakeauth
: נקודת קצה להרשאה לקישור חשבונות -
faketoken
: נקודת הקצה של האסימון לקישור חשבונות -
smarthome
: נקודת קצה לביצוע כוונות של בית חכם -
reportstate
: הפעלת Home Graph API בשינויים במצב המכשיר -
requestsync
: מאפשר עדכונים במכשירי המשתמשים בלי שיהיה צורך לקשר מחדש את החשבון
התחברות אל Firebase
עוברים אל הספרייה washer-start
ומגדירים את Firebase CLI עם פרויקט השילוב:
cd washer-start firebase use <project-id>
הגדרת פרויקט Firebase
מאתחלים פרויקט Firebase.
firebase init
בוחרים את התכונות של ה-CLI, Realtime Database ו-Functions.
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed) >( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore ( ) Genkit: Setup a new Genkit project with Firebase (*) Functions: Configure a Cloud Functions directory and its files ( ) App Hosting: Configure an apphosting.yaml file for App Hosting ( ) Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys ( ) Storage: Configure a security rules file for Cloud Storage ( ) Emulators: Set up local emulators for Firebase products ( ) Remote Config: Configure a template file for Remote Config ( ) Extensions: Set up an empty Extensions manifest (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore
הפעולה הזו תאתחל את ממשקי ה-API והתכונות הנדרשים לפרויקט.
כשמתבקשים, מאתחלים את Realtime Database. אפשר להשתמש במיקום ברירת המחדל של מופע מסד הנתונים.
? 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
מכיוון שאתם משתמשים בקוד של פרויקט המתחילים, בוחרים את קובץ ברירת המחדל של כללי האבטחה ומוודאים שלא דורסים את קובץ הכללים הקיים של מסד הנתונים.
? 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
אם אתם מאתחלים מחדש את הפרויקט, בוחרים באפשרות Overwrite (החלפה) כשמוצגת השאלה אם אתם רוצים לאתחל או להחליף בסיס קוד.
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite
כשמגדירים את הפונקציות, צריך להשתמש בקובצי ברירת המחדל ולוודא שלא דורסים את הקבצים הקיימים index.js ו-package.json בדוגמה של הפרויקט.
? What language would you like to use to write Cloud Functions? JavaScript ? Do you want to use ESLint to catch probable bugs and enforce style? No ? File functions/package.json already exists. Overwrite? No ? File functions/index.js already exists. Overwrite? No
אם אתם מאתחלים מחדש את הפרויקט, בוחרים באפשרות No כשנשאלים אם אתם רוצים לאתחל או להחליף את functions/.gitignore.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
אם הפעלתם את ESLint בטעות, יש שתי דרכים להשבית אותו:
- בממשק המשתמש הגרפי, עוברים לתיקייה
../functions
מתחת לפרויקט, בוחרים את הקובץ המוסתר.eslintrc.js
ומוחקים אותו. אל תתבלבלו בינו לבין.eslintrc.json
, ששמו דומה. - באמצעות שורת הפקודה:
cd functions rm .eslintrc.js
פריסה ב-Firebase
אחרי שמתקינים את יחסי התלות ומגדירים את הפרויקט, אפשר להריץ את האפליקציה בפעם הראשונה.
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.
פותחים את כתובת ה-URL של האירוח בדפדפן (https://<firebase-project-id>.web.app
) כדי לראות את אפליקציית האינטרנט. יוצג לכם הממשק הבא:
ממשק המשתמש הזה באינטרנט מייצג פלטפורמה של צד שלישי שמאפשרת לראות או לשנות את מצבי המכשיר. כדי להתחיל לאכלס את מסד הנתונים בפרטי המכשיר, לוחצים על עדכון. לא תראו שינויים בדף, אבל המצב הנוכחי של מכונת הכביסה יישמר במסד הנתונים.
עכשיו צריך לחבר את שירות הענן שפרסתם ל-Google Assistant באמצעות Developer Console.
הגדרת הפרויקט ב-Developer Console
בכרטיסייה פיתוח, מוסיפים שם לתצוגה לאינטראקציה. השם הזה יופיע באפליקציית Google Home.
בקטע מיתוג האפליקציה, מעלים קובץ png
של סמל האפליקציה בגודל 144x144 פיקסלים, עם השם
.
כדי להפעיל קישור לחשבון, משתמשים בהגדרות הבאות של קישור לחשבון:
Client-ID |
|
סוד לקוח |
|
כתובת אתר להרשאה |
|
כתובת URL לטוקן |
|
בקטע כתובת URL של מילוי הזמנות בענן, מזינים את כתובת ה-URL של פונקציית הענן שמספקת מילוי הזמנות לכוונות של בית חכם.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
לוחצים על שמירה כדי לשמור את הגדרות הפרויקט, ואז לוחצים על הבא: בדיקה כדי להפעיל את הבדיקה בפרויקט.
עכשיו אפשר להתחיל להטמיע את ה-webhook שנדרשים כדי לקשר את מצב המכשיר ל-Assistant.
קישור אל Google Assistant
כדי לבדוק את השילוב בין ענן לענן, צריך לקשר את הפרויקט לחשבון Google. כך אפשר לבצע בדיקות באמצעות ממשקי Google Assistant ואפליקציית Google Home שמחוברים לאותו חשבון.
- בטלפון, פותחים את ההגדרות של Google Assistant. שימו לב שאתם צריכים להיות מחוברים לאותו חשבון שדרכו נכנסתם למסוף.
- עוברים אל Google Assistant > הגדרות > שליטה בבית (בקטע Assistant).
- לוחצים על סמל החיפוש בפינה השמאלית העליונה.
- מחפשים את אפליקציית הבדיקה באמצעות הקידומת [test] כדי למצוא את אפליקציית הבדיקה הספציפית.
- בוחרים את הפריט. לאחר מכן, Google Assistant תבצע אימות מול השירות שלכם ותשלח בקשת
SYNC
, שבה היא מבקשת מהשירות שלכם לספק רשימה של מכשירים עבור המשתמש.
פותחים את אפליקציית Google Home ומוודאים שמכונת הכביסה מופיעה ברשימת המכשירים.
מוודאים שאפשר לשלוט במכונת הכביסה באמצעות פקודות קוליות באפליקציית Google Home. בנוסף, צריך לראות את שינוי מצב המכשיר בממשק המשתמש של חזית האתר של הענן.
עכשיו, אחרי שפרסתם כלי בסיסי לניקוי המחשב, אתם יכולים להתאים אישית את המצבים שזמינים במכשיר.
4. הוספת אמצעי תחבורה
התכונה action.devices.traits.Modes
מאפשרת למכשיר להגדיר מספר שרירותי של הגדרות למצב מסוים, אבל רק אחת מהן יכולה להיות מוגדרת בכל פעם. תוסיפו מצב למכונת הכביסה כדי להגדיר את גודל הכביסה: קטן, בינוני או גדול.
עדכון תגובת הסנכרון
צריך להוסיף מידע על המאפיין החדש לתגובה שלך בטופס SYNC
ב-functions/index.js
. הנתונים האלה מופיעים במערך traits
ובאובייקט attributes
, כמו שמוצג בקטע הקוד הבא.
index.js
app.onSync(body => {
return {
requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
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',
// Add Modes trait
'action.devices.traits.Modes',
],
name: { ... },
deviceInfo: { ... },
attributes: {
pausable: true,
//Add availableModes
availableModes: [{
name: 'load',
name_values: [{
name_synonym: ['load'],
lang: 'en',
}],
settings: [{
setting_name: 'small',
setting_values: [{
setting_synonym: ['small'],
lang: 'en',
}]
}, {
setting_name: 'medium',
setting_values: [{
setting_synonym: ['medium'],
lang: 'en',
}]
}, {
setting_name: 'large',
setting_values: [{
setting_synonym: ['large'],
lang: 'en',
}]
}],
ordered: true,
}],
},
}],
},
};
});
הוספת פקודות חדשות של כוונת EXECUTE
בכוונת EXECUTE
, מוסיפים את הפקודה action.devices.commands.SetModes
כמו בקטע הקוד הבא.
index.js
const updateDevice = async (execution,deviceId) => {
const {params,command} = execution;
let state, 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;
// Add SetModes command
case 'action.devices.commands.SetModes':
state = {load: params.updateModeSettings.load};
ref = firebaseRef.child(deviceId).child('Modes');
break;
}
};
עדכון התגובה של QUERY
לאחר מכן, מעדכנים את QUERY
התשובה כדי לדווח על המצב הנוכחי של מכונת הכביסה.
מוסיפים את השינויים המעודכנים לפונקציות queryFirebase
ו-queryDevice
כדי לקבל את המצב כפי שהוא מאוחסן ב-Realtime Database.
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,
// Add Modes snapshot
load: snapshotVal.Modes.load,
};
};
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{ ... }],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
// Add currentModeSettings
currentModeSettings: {
load: data.load,
},
};
};
עדכון מצב הדוח
לבסוף, מעדכנים את הפונקציה reportstate
כדי לדווח ל-Home Graph על הגדרת העומס הנוכחית של מכונת הכביסה.
index.js
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of your washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
// Add currentModeSettings
currentModeSettings: {
load: snapshot.Modes.load,
},
},
},
},
},
};
פריסה ב-Firebase
מריצים את הפקודה הבאה כדי לפרוס את השילוב המעודכן:
firebase deploy --only functions
אחרי שהפריסה מסתיימת, עוברים לממשק המשתמש האינטרנטי ולוחצים על הלחצן רענון בסרגל הכלים. הפעולה הזו מפעילה סנכרון של הבקשה, כדי ש-Assistant תקבל את נתוני התגובה המעודכנים של
SYNC
.
עכשיו אפשר לתת פקודה להגדרת המצב של מכונת הכביסה, למשל:
"Ok Google, set the washer load to large."
בנוסף, אתם יכולים לשאול שאלות לגבי מכונת הכביסה, כמו:
"Ok Google, what is the washer load?"
5. הוספת מתגים
מאפיין action.devices.traits.Toggles
מייצג היבטים בעלי שם של מכשיר שיכולים להיות במצב True או False, למשל אם מכונת הכביסה נמצאת במצב טורבו.
עדכון תגובת הסנכרון
בתגובה של SYNC
, צריך להוסיף מידע על מאפיין המכשיר החדש. הוא יופיע במערך traits
ובאובייקט attributes
כמו בקטע הקוד הבא.
index.js
app.onSync(body => {
return {
requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
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',
'action.devices.traits.Modes',
// Add Toggles trait
'action.devices.traits.Toggles',
],
name: { ... },
deviceInfo: { ... },
attributes: {
pausable: true,
availableModes: [{
name: 'load',
name_values: [{
name_synonym: ['load'],
lang: 'en'
}],
settings: [{ ... }],
ordered: true,
}],
//Add availableToggles
availableToggles: [{
name: 'Turbo',
name_values: [{
name_synonym: ['turbo'],
lang: 'en',
}],
}],
},
}],
},
};
});
הוספת פקודות חדשות של כוונת EXECUTE
בכוונת EXECUTE
, מוסיפים את הפקודה action.devices.commands.SetToggles
כמו בקטע הקוד הבא.
index.js
const updateDevice = async (execution,deviceId) => {
const {params,command} = execution;
let state, 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;
case 'action.devices.commands.SetModes':
state = {load: params.updateModeSettings.load};
ref = firebaseRef.child(deviceId).child('Modes');
break;
// Add SetToggles command
case 'action.devices.commands.SetToggles':
state = {Turbo: params.updateToggleSettings.Turbo};
ref = firebaseRef.child(deviceId).child('Toggles');
break;
}
עדכון התגובה של QUERY
לבסוף, צריך לעדכן את התגובה של QUERY
כדי לדווח על מצב הטורבו של מכונת הכביסה. מוסיפים את השינויים המעודכנים לפונקציות queryFirebase
ו-queryDevice
כדי לקבל את מצב המתג כפי שהוא מאוחסן ב-Realtime Database.
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,
load: snapshotVal.Modes.load,
// Add Toggles snapshot
Turbo: snapshotVal.Toggles.Turbo,
};
}
const queryDevice = async (deviceId) => {
const data = queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{ ... }],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
currentModeSettings: {
load: data.load,
},
// Add currentToggleSettings
currentToggleSettings: {
Turbo: data.Turbo,
},
};
};
עדכון מצב הדוח
לבסוף, מעדכנים את הפונקציה reportstate
כדי לדווח ל-Home Graph אם מכונת הכביסה מוגדרת למצב טורבו.
index.js
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of your washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
currentModeSettings: {
load: snapshot.Modes.load,
},
// Add currentToggleSettings
currentToggleSettings: {
Turbo: snapshot.Toggles.Turbo,
},
},
},
},
},
};
פריסה ב-Firebase
מריצים את הפקודה הבאה כדי לפרוס את הפונקציות המעודכנות:
firebase deploy --only functions
לוחצים על הלחצן רענון בממשק המשתמש האינטרנטי כדי להפעיל בקשת סנכרון אחרי שהפריסה מסתיימת.
עכשיו אפשר להגיד פקודה כדי להגדיר את מכונת הכביסה למצב טורבו:
"Ok Google, set the washer to turbo mode" (הפעלת מכונת הכביסה במצב טורבו).
אפשר גם לשאול אם מכונת הכביסה כבר במצב טורבו:
"Ok Google, is my washer in turbo mode?"
6. דיווח על שגיאות וחריגות
טיפול בשגיאות בשילוב בין ענן לענן מאפשר לכם לדווח למשתמשים על בעיות שגורמות לתגובות EXECUTE
ו-QUERY
להיכשל. ההתראות יוצרות חוויית משתמש חיובית יותר למשתמשים כשהם מבצעים אינטראקציה עם המכשיר החכם והשילוב.
בכל פעם שבקשת EXECUTE
או QUERY
נכשלת, השילוב צריך להחזיר קוד שגיאה. לדוגמה, אם רוצים להציג שגיאה כשמשתמש מנסה להפעיל את מכונת הכביסה כשהמכסה פתוח, התגובה של EXECUTE
תיראה כמו קטע הקוד הבא:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [
{
"ids": [
"456"
],
"status": "ERROR",
"errorCode": "deviceLidOpen"
}
]
}
}
עכשיו, כשמשתמש מבקש להפעיל את מכונת הכביסה, ה-Assistant משיב:
"המכסה של מכונת הכביסה פתוח. צריך לסגור אותה ולנסות שוב".
חריגים דומים לשגיאות, אבל הם מציינים מתי התראה משויכת לפקודה, שיכול להיות שהיא תחסום את ההפעלה המוצלחת ויכול להיות שלא. חריגה יכולה לספק מידע קשור באמצעות מאפיין StatusReport
, כמו רמת הסוללה או שינוי מצב אחרון. קודי חריגה שאינם חוסמים מוחזרים עם הסטטוס SUCCESS
, וקודי חריגה חוסמים מוחזרים עם הסטטוס EXCEPTIONS
.
בדוגמה הבאה מוצגת תגובה עם חריגה:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [{
"ids": ["123"],
"status": "SUCCESS",
"states": {
"online": true,
"isPaused": false,
"isRunning": false,
"exceptionCode": "runCycleFinished"
}
}]
}
}
Assistant מגיבה באמירה:
"המכונה סיימה את הפעולה".
כדי להוסיף דיווח על שגיאות למכונת הכביסה, פותחים את functions/index.js
ומוסיפים את הגדרת מחלקת השגיאות כמו שמופיע בקטע הקוד הבא:
index.js
app.onQuery(async (body) => {...});
// Add SmartHome error handling
class SmartHomeError extends Error {
constructor(errorCode, message) {
super(message);
this.name = this.constructor.name;
this.errorCode = errorCode;
}
}
מעדכנים את תגובת ההפעלה כדי להחזיר את קוד השגיאה ואת סטטוס השגיאה:
index.js
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) => {
...
})
//Add error response handling
.catch((error) => {
functions.logger.error('EXECUTE', device.id, error);
result.ids.push(device.id);
if (error instanceof SmartHomeError) {
result.status = 'ERROR';
result.errorCode = error.errorCode;
}
})
);
}
}
}
Assistant יכולה עכשיו לספר למשתמשים שלכם על כל קוד שגיאה שאתם מדווחים עליו. דוגמה ספציפית מופיעה בקטע הבא.
7. הוספת אימות משתמש משני
אם למכשיר שלכם יש מצבים שצריך לאבטח או להגביל לקבוצה מסוימת של משתמשים מורשים, כמו עדכון תוכנה או ביטול נעילה, כדאי להטמיע אימות משני של משתמש בשילוב.
אתם יכולים להטמיע אימות משתמש משני בכל סוגי המכשירים והמאפיינים, ולהתאים אישית את האופן שבו אתגר האבטחה מתרחש – בכל פעם או רק כשמתקיימים קריטריונים ספציפיים.
יש שלושה סוגים נתמכים של אתגרים:
-
No
challenge
– בקשה ותגובה שלא משתמשות באתגר אימות (זו התנהגות ברירת המחדל) ackNeeded
—אימות משתמש משני שדורש אישור מפורש (כן או לא)pinNeeded
—אימות משני של משתמש שדורש קוד אימות (PIN)
ב-codelab הזה, מוסיפים ackNeeded
אתגר לפקודה להפעלת מכונת הכביסה, ומוסיפים את הפונקציונליות להחזרת שגיאה אם האתגר של האימות המשני נכשל.
פותחים את functions/index.js
ומוסיפים הגדרה של מחלקת שגיאות שמחזירה את קוד השגיאה ואת סוג האתגר, כמו בקטע הקוד הבא:
index.js
class SmartHomeError extends Error { ... }
// Add secondary user verification error handling
class ChallengeNeededError extends SmartHomeError {
/**
* Create a new ChallengeNeededError
* @param {string} suvType secondary user verification challenge type
*/
constructor(suvType) {
super('challengeNeeded', suvType);
this.suvType = suvType;
}
}
בנוסף, צריך לעדכן את תגובת ההפעלה כדי להחזיר את השגיאה challengeNeeded
באופן הבא:
index.js
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) => {
...
})
.catch((error) => {
functions.logger.error('EXECUTE', device.id, error);
result.ids.push(device.id);
if (error instanceof SmartHomeError) {
result.status = 'ERROR';
result.errorCode = error.errorCode;
//Add error response handling
if (error instanceof ChallengeNeededError) {
result.challengeNeeded = {
type: error.suvType
};
}
}
})
);
}
}
}
לבסוף, משנים את updateDevice
כך שתידרש הסכמה מפורשת כדי להפעיל או להשבית את מכונת הכביסה.
index.js
const updateDevice = async (execution,deviceId) => {
const {challenge,params,command} = execution; //Add secondary user challenge
let state, ref;
switch (command) {
case 'action.devices.commands.OnOff':
//Add secondary user verification challenge
if (!challenge || !challenge.ack) {
throw new ChallengeNeededError('ackNeeded');
}
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
...
}
return ref.update(state)
.then(() => state);
};
פריסה ב-Firebase
מריצים את הפקודה הבאה כדי לפרוס את הפונקציה המעודכנת:
firebase deploy --only functions
אחרי שמטמיעים את הקוד המעודכן, צריך לאשר את הפעולה באופן מילולי כשמבקשים מ-Assistant להפעיל או להשבית את מכונת הכביסה, כמו בדוגמה הבאה:
אתם: "Ok Google, turn on the washer" (הפעל את מכונת הכביסה).
ה-Assistant: "Are you sure you want to turn on the washer?"
אתם: "כן".
אפשר גם לראות תגובה מפורטת לכל שלב בתהליך האימות של המשתמש המשני על ידי פתיחת היומנים של Firebase.
8. מזל טוב
מעולה! הרחבתם את התכונות של שילובים בין עננים באמצעות המאפיינים Modes
ו-Toggles
, ואבטחתם את ההפעלה שלהם באמצעות אימות משני של המשתמש.
מידע נוסף
הנה כמה רעיונות להעמקה:
- להוסיף למכשירים שלכם יכולות של הרצה מקומית.
- כדי לשנות את מצב המכשיר, צריך להשתמש בסוג אחר של אתגר אימות משתמש משני.
- מעדכנים את התגובה של מאפיין
RunCycle
שאילתת החיפוש כדי שהעדכון יהיה דינמי. - אפשר לעיין בדוגמה הזו ב-GitHub.