1. לפני שמתחילים
הפעולות בבית החכם מתבססות על סוגי מכשירים כדי לאפשר ל-Google Assistant לדעת באיזה דקדוק צריך להשתמש במכשיר. traits של המכשיר מגדירות את היכולות של סוגי המכשירים. מכשיר יורש את המצבים של כל תכונה של המכשיר שמתווספת לפעולה.
אפשר לחבר כל תכונה נתמכת לסוג המכשיר שבחרת כדי להתאים אישית את הפונקציונליות של המכשירים של המשתמשים. אם רוצים להטמיע תכונות מותאמות אישית בפעולות שלא זמינות כרגע בסכימת המכשיר, התכונות מצבים והחלפה מאפשרות שליטה של הגדרות ספציפיות באמצעות שם מותאם אישית.
מעבר ליכולת השליטה הבסיסית, לפי סוגים ותכונות, Smart Home API כולל תכונות נוספות לשיפור חוויית המשתמש. תגובות לשגיאות מספקות משוב מפורט מהמשתמשים, במקרים שבהם הכוונות לא מצליחות. אימות משתמש משני מרחיב את התגובות האלה ומוסיף עוד אבטחה לתכונת המכשיר שבחרתם. שליחת תגובות ספציפיות לשגיאות בחסימות של חסימות שהונפקו על ידי Assistant, עשויה לחייב הרשאה נוספת לביצוע פקודה בבית החכם.
דרישות מוקדמות
- מדריך למפתחים בנושא יצירת פעולה בבית חכם
- Codelab בנושא מכונת כביסה לבית חכם
- מדריך למפתחים בנושא סוגי מכשירים ותכונות
מה תפַתחו
בשיעור ה-codelab הזה תפרסו שילוב מובנה מראש של בית חכם עם Firebase, ואז תלמדו איך להוסיף תכונות לא סטנדרטיות למכונת הכביסה לבית החכם לפי גודל הטעינה ומצב טורבו. תוכלו גם להטמיע דיווח על שגיאות וחריגות, וגם ללמוד איך לאכוף אישור מילולי כדי להפעיל את מכונת הכביסה באמצעות אימות משתמש משני.
מה תלמדו
- איך מוסיפים את המצבים ואת החלפת התכונות לפעולה
- איך מדווחים על שגיאות וחריגים
- איך מחילים אימות משתמש משני
מה הדרישות כדי להצטרף לתוכנית?
- דפדפן אינטרנט, כמו 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.
- מידע מהמכשירים שלך
- פעילות קול ואודיו
יצירת פרויקט ל'פעולות'
- עוברים אל Actions on Google Developer Console.
- לוחצים על פרויקט חדש, נותנים שם לפרויקט ולוחצים על יצירת פרויקט.
בחירה של אפליקציית הבית החכם
במסך הסקירה הכללית במסוף Actions, בוחרים באפשרות בית חכם.
בוחרים בכרטיס של חוויית הבית החכם, לוחצים על התחלת הבנייה ומשם תועברו אל מסוף הפרויקט.
התקנת ה-CLI של Firebase
ממשק שורת הפקודה (CLI) של Firebase מאפשר להציג את אפליקציות האינטרנט באופן מקומי ולפרוס את אפליקציית האינטרנט באירוח ב-Firebase.
כדי להתקין את ה-CLI, מריצים את פקודת ה-npm הבאה מהטרמינל:
npm install -g firebase-tools
כדי לוודא שה-CLI הותקן כראוי, מריצים את:
firebase --version
מאשרים את ה-CLI של Firebase באמצעות חשבון Google על ידי הרצת:
firebase login
הפעלת HomeGraph API
HomeGraph API מאפשר לאחסן מכשירים והמצבים שלהם בתרשים הבית של המשתמש ולשלוח שאילתות לגביהם. כדי להשתמש ב-API הזה, קודם צריך לפתוח את מסוף Google Cloud ולהפעיל את HomeGraph API.
במסוף Google Cloud, בוחרים את הפרויקט שתואם לפעולות <project-id>.
. לאחר מכן, במסך 'ספריית API' של HomeGraph API, לוחצים על הפעלה.
3. הפעלת האפליקציה לתחילת הדרך
עכשיו, אחרי שמגדירים את סביבת הפיתוח, אפשר לפרוס את הפרויקט לתחילת העבודה כדי לוודא שהכול מוגדר כראוי.
איך מקבלים את קוד המקור
כדי להוריד למחשב הפיתוח את הדוגמה של Codelab זה, יש ללחוץ על הקישור הבא:
...או שאפשר לשכפל את המאגר של GitHub משורת הפקודה:
git clone https://github.com/google-home/smarthome-traits.git
פותחים את קובץ ה-ZIP שהורד.
מידע על הפרויקט
הפרויקט לתחילת העבודה מכיל את ספריות המשנה הבאות:
public:
ממשק משתמש חזיתי שמאפשר לשלוט בקלות במצב של מכונת הכביסה החכמה ולנטר אותה.functions:
שירות ענן מוטמע במלואו שמנהל את מכונת הכביסה החכמה באמצעות Cloud Functions for Firebase ומסד נתונים בזמן אמת ב-Firebase.
מילוי הבקשה בענן כולל את הפונקציות הבאות ב-index.js
:
fakeauth
: נקודת קצה להרשאה לקישור חשבונותfaketoken
: נקודת קצה של אסימון לקישור חשבונותsmarthome
: נקודת קצה למילוי Intent בבית חכםreportstate
: הפעלת ממשק ה-API של Home Graph בשינויים במצב המכשירrequestsync
: מאפשר עדכונים למכשיר של משתמשים בלי שיהיה צורך לקשר מחדש את החשבון
קישור ל-Firebase
עוברים לספרייה washer-start
ומגדירים את ה-CLI של Firebase בפרויקט הפעולות:
cd washer-start firebase use <project-id>
הגדרת פרויקט Firebase
מפעילים פרויקט Firebase.
firebase init
בוחרים את תכונות ה-CLI, מסד נתונים בזמן אמת, פונקציות, והתכונה אירוח שכוללת את האירוח ב-Firebase.
? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. ❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ◯ Firestore: Configure security rules and indexes files for Firestore ◉ Functions: Configure a Cloud Functions directory and its files ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys ◯ Hosting: 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
הפעולה הזו תפעיל את התכונות וממשקי ה-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
מכיוון שבחרת להשתמש בקוד הפרויקט למתחילים, עליך לבחור את קובץ ברירת המחדל של כללי האבטחה ולוודא שלא מחליפים את קובץ כללי מסד הנתונים הקיים.
? 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
אם אתם מאתחלים מחדש את הפרויקט, כשתישאלו אם אתם רוצים לאתחל או להחליף פונקציות/.gitignore, יש לבחור באפשרות לא.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
לסיום, צריך להגדיר את הגדרת האירוח להשתמש בספרייה public
בקוד הפרויקט, ולהשתמש בקובץ index.html הקיים. בוחרים באפשרות לא כשמתבקשים להשתמש ב-ESLint.
? What do you want to use as your public directory? public ? Configure as a single-page app (rewrite all urls to /index.html)? Yes ? Set up automatic builds and deploys with GitHub? No ? File public/index.html already exists. Overwrite? No
אם ESLint הופעל בטעות, יש שתי שיטות זמינות להשבית אותו:
- באמצעות ה-GUI, עוברים לתיקייה
../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://<project-id>.web.app
) כדי להציג את אפליקציית האינטרנט. יוצג הממשק הבא:
ממשק המשתמש הזה באינטרנט מייצג פלטפורמה של צד שלישי להצגה או לשינוי של מצבי המכשיר. כדי להתחיל לאכלס את מסד הנתונים במידע מהמכשירים שלך, לוחצים על עדכון. לא יופיעו שינויים בדף, אבל המצב הנוכחי של מכונת הכביסה יישמר במסד הנתונים.
עכשיו הגיע הזמן לחבר את שירות הענן שפרסתם אל Google Assistant באמצעות Actions Console.
הגדרת הפרויקט במסוף Actions
בקטע סקירה כללית > בניית הפעולה, בוחרים באפשרות הוספת פעולות. מזינים את כתובת ה-URL של הפונקציה ב-Cloud Functions שמספקת מילוי הזמנות עבור ה-Intents של הבית החכם ולוחצים על שמירה.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
בכרטיסייה פיתוח > הפעלה, מוסיפים שם תצוגה לפעולה ולוחצים על שמירה. השם הזה יופיע באפליקציית Google Home.
כדי להפעיל את קישור החשבונות, בוחרים באפשרות פיתוח > קישור חשבון בתפריט הניווט הימני. השתמש בהגדרות הבאות לקישור חשבונות:
Client ID |
|
סוד לקוח |
|
כתובת אתר להרשאה |
|
כתובת ה-URL של האסימון |
|
לוחצים על Save כדי לשמור את הגדרת הקישור של החשבון, ואז לוחצים על Test כדי להפעיל את הבדיקה בפרויקט.
המערכת תפנה אתכם אל הסימולטור. אם לא מופיעה האפשרות הבדיקה מופעלת, לוחצים על איפוס הבדיקה כדי לוודא שהבדיקה מופעלת.
קישור ל-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 חדשות של Intent
ב-Intent 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
כדי לקבל את המצב כפי שנשמר במסד הנתונים בזמן אמת.
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
כדי לדווח על הגדרת העומס הנוכחית של מכונת הכביסה לתרשים הבית.
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 carwash to large".
בנוסף, אפשר לשאול שאלות לגבי מכונת הכביסה, כמו:
"Ok Google, what is the washer load?"
5. הוספת לחצנים להחלפת מצב
התכונה action.devices.traits.Toggles
מייצגת היבטים של מכשירים שנמצאים במצב נכון או לא נכון, למשל אם מכונת הכביסה במצב טורבו.
עדכון תגובת הסנכרון
בתשובה שלך מסוג SYNC
, עליך להוסיף מידע על ה-trait של המכשיר החדש. היא תופיע במערך 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',
}],
}],
},
}],
},
};
});
הוספה של פקודות Intent חדשות EXECUTE
ב-Intent 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
כדי לקבל את מצב המתג כפי שנשמר במסד הנתונים בזמן אמת.
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, turn on turbo for the לתת למכונת הכביסה".
אפשר גם לשאול אם מכונת הכביסה נמצאת במצב טורבו:
"Ok Google, is my Wahr 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( ... )
//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( ... )
.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 weather".
Assistant: "האם אתה בטוח שאתה רוצה להפעיל את מכונת הכביסה?"
את/ה: "כן".
אפשר גם לפתוח את יומני Firebase כדי לראות תשובה מפורטת לכל שלב בתהליך האימות המשני של המשתמש.
8. מזל טוב
כל הכבוד! הרחבת את התכונות של הפעולות בבית החכם באמצעות התכונות Modes
ו-Toggles
, ואבטחת את הביצוע שלהן באמצעות אימות משתמש משני.
מידע נוסף
הנה כמה רעיונות שאפשר ליישם כדי להתעמק בנתונים:
- הוספת יכולות של ביצוע מקומי למכשירים שלכם.
- כדי לשנות את מצב המכשיר, צריך להשתמש בסוג אתגר משני אחר לאימות משתמש.
- יש לעדכן את התגובה QUERY
RunCycle
לעדכון דינמי. - אתם מוזמנים להכיר את הדוגמה הזו ל-GitHub.