ניפוי באגים בבית המקומי

1. לפני שמתחילים

שילובים של בית חכם מאפשרים ל-Google Assistant לשלוט במכשירים מחוברים בבית של המשתמשים. כדי ליצור פעולה בבית חכם, צריך לספק נקודת קצה (endpoint) של Cloud webhook שיכולה לטפל באובייקטים מסוג Intent בבית חכם. לדוגמה, כשמשתמש אומר "Ok Google, turn on the lights", Assistant שולחת את הפקודה למילוי הבקשה בענן כדי לעדכן את מצב המכשיר.

ה-Local Home SDK משפר את השילוב של הבית החכם על ידי הוספת נתיב מקומי לניתוב כוונות של בית חכם ישירות למכשיר Google Home. הנתיב הזה משפר את האמינות ומפחית את זמן האחזור בעיבוד הפקודות של המשתמשים. היא מאפשרת לכתוב ולפרוס אפליקציית מילוי הזמנות מקומית ב-TypeScript או JavaScript שמזהה מכשירים ומבצעת פקודות בכל רמקול חכם של Google Home או מסך חכם של Google Nest. לאחר מכן האפליקציה מתקשרת ישירות עם המכשירים החכמים הקיימים של המשתמשים דרך רשת האזור המקומית באמצעות פרוטוקולים סטנדרטיים קיימים כדי למלא פקודות.

72ffb320986092c.png

ניפוי באגים בפעולות של בית חכם הוא שלב קריטי ביצירת הפעולות באיכות ייצור. עם זאת, הוא מאתגר וגוזל זמן ללא כלים אינפורמטיביים וקלים לשימוש לפתרון בעיות ובדיקה. כדי להקל על ניפוי באגים בפעולות לבית חכם, המדדים, Logging וחבילת הבדיקות של הבית החכם ב-Google Cloud Platform (GCP) יכולים לעזור לכם לזהות ולפתור בעיות בפעולות.

דרישות מוקדמות

מה תפַתחו

בשיעור ה-Codelab הזה תיצרו מילוי בקשה מקומי ל-Actions של בית חכם ותחברו אותו ל-Assistant, ולאחר מכן תנפו באגים באפליקציית Local Home באמצעות Test Bundle עבור מדדים ורישום ב-Google Cloud Platform (GCP) לבית חכם ו-Google Cloud Platform.

מה תלמדו

  • איך משתמשים במדדים וברישום של GCP כדי לזהות בעיות בסביבת הייצור ולפתור אותן.
  • איך משתמשים ב-Test Suite כדי לזהות בעיות בפונקציונליות וב-API?
  • איך להשתמש בכלי הפיתוח של Chrome בזמן פיתוח של אפליקציית Local Home

מה הדרישות כדי להצטרף לתוכנית?

2. הפעלת האפליקציה של מכונת הכביסה

איך מקבלים את קוד המקור

כדי להוריד למחשב הפיתוח את הדוגמה של Codelab זה, יש ללחוץ על הקישור הבא:

...או שאפשר לשכפל את המאגר של GitHub משורת הפקודה:

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

מידע על הפרויקט

האפליקציה לתחילת הדרך כוללת ספריות משנה ופונקציות בענן דומות כמו ה-codelab הפעלת מילוי הזמנות מקומי לפעולות בבית חכם. אבל במקום app-start, יש לנו כאן app-faulty. נתחיל עם אפליקציית דף בית מקומית שעובדת, אבל לא כל כך טובה.

קישור ל-Firebase

אנחנו נשתמש באותו הפרויקט שיצרת ב-codelab בנושא הפעלת מילוי הזמנות מקומי לפעולות של בית חכם, אבל נפרוס את הקבצים שהורדו ב-Codelab הזה.

עוברים לספרייה app-faulty, ואז מגדירים את ה-CLI של Firebase עם פרויקט הפעולות שנוצר ב-codelab הפעלת מילוי הזמנות מקומי לפעולות בית חכם:

$ 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

פותחים את כתובת ה-URL לאירוח בדפדפן (https://<project-id>.web.app) כדי להציג את אפליקציית האינטרנט. בממשק המשתמש של האינטרנט, לוחצים על הלחצן רענוןae8d3b25777a5e30.png כדי לעדכן את HomeGraph דרך בקשת סנכרון עם המטא-נתונים העדכניים של המכשיר מהאפליקציה הפגומה של מכונת הכביסה:

fa3c47f293cfe0b7.png

פותחים את אפליקציית Google Home ומוודאים שאפשר לראות את מכונת הכביסה בשם החדש 'מכונת כביסה פגומה'. חשוב לזכור להקצות את המכשיר לחדר שיש בו מכשיר Nest.

2a082ee11d47ad1a.png

3. הפעלת מכונת הכביסה החכמה

אם הפעלתם את ה-Codelab הפעלת מילוי הזמנות מקומי לפעולות בית חכם, הייתם אמורים כבר להפעיל את מכונת הכביסה החכמה הווירטואלית. אם היא הופסקה, חשוב לזכור להפעיל מחדש את המכשיר הווירטואלי.

הפעלת המכשיר

עוברים לספרייה 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. בדיקת אפליקציית Home המקומית

אתם יכולים לשלוח פקודות למכשיר באמצעות פקודות קוליות למכשיר Google Home, כמו:

"Hey Google, turn on my Waher".

"Ok Google, start my Wash"

"Ok Google, force local"

"Ok Google, stop my Waher"

אם תנסו לשלוט במכונת הכביסה אחרי שתנסו לשלוט במכונת הכביסה אחרי שתנסו לשלוט במכונת הכביסה, תראו את התשובה "מצטערים, נראה שמכונת הכביסה הפגומה לא זמינה כרגע".

המשמעות היא שלא ניתן להגיע למכשיר דרך נתיב מקומי. היא עבדה לפני פרסום הפקודה "Ok Google, force local", כי נחזור להשתמש בנתיב בענן במקרים שבהם לא ניתן יהיה להגיע למכשיר דרך נתיב מקומי. עם זאת, לאחר 'אילוץ מקומי', האפשרות לחזור לנתיב בענן מושבתת.

כדי לבדוק מה הבעיה, נשתמש בכלים שיש לנו: מדדים של Google Cloud Platform (GCP), Logging וכלים למפתחים ב-Chrome.

5. ניפוי באגים באפליקציית Home המקומית

בקטע הבא נשתמש בכלים ש-Google מספקת כדי לגלות מדוע לא ניתן להגיע למכשיר דרך הנתיב המקומי. אפשר להשתמש בכלים למפתחים של Google Chrome כדי להתחבר למכשיר Google Home, להציג את יומני המסוף ולנפות באגים באפליקציית Local Home. אפשר גם לשלוח יומנים בהתאמה אישית אל Cloud Logging כדי שתהיה מודע לשגיאות הנפוצות ביותר שהמשתמשים שלך מוצאים באפליקציית Local Home.

חיבור הכלים למפתחים ב-Chrome

כך מקשרים את הכלי לניפוי באגים לאפליקציה המקומית למילוי הזמנות:

  1. ודאו שקישרתם את מכשיר Google Home למשתמש שיש לו הרשאת גישה לפרויקט במסוף הפעולות.
  2. עליך להפעיל מחדש את מכשיר Google Home, כדי שהוא יוכל לקבל את כתובת ה-URL של ה-HTML ואת הגדרות הסריקה שהגדרת במסוף הפעולות.
  3. מפעילים את Chrome במחשב הפיתוח.
  4. כדי להפעיל את הבדיקה, צריך לפתוח כרטיסייה חדשה ב-Chrome ולהזין chrome://inspect בשדה הכתובת.

בדף אמורה להופיע רשימת מכשירים, וכתובת ה-URL של האפליקציה אמורה להופיע מתחת לשם של מכשיר Google Home.

567f97789a7d8846.png

הפעלת הכלי לבדיקה

לוחצים על בדיקה מתחת לכתובת ה-URL של האפליקציה כדי להפעיל את הכלים למפתחים ב-Chrome. צריך לבחור בכרטיסייה מסוף ולוודא שאפשר לראות את התוכן של Intent IDENTIFY שהודפס על ידי אפליקציית TypeScript שלך.

774c460c59f9f84a.png

המשמעות של הפלט הזה היא שה-handler של IDENTIFY הופעל בהצלחה, אבל ה-verificationId שהוחזר ב-IdentifyResponse לא תואם לאף אחד מהמכשירים ב-HomeGraph שלך. בואו נוסיף כמה יומנים מותאמים אישית כדי לגלות את הסיבה.

הוספת יומנים בהתאמה אישית

למרות שהשגיאה DEVICE_VERIFICATION_FAILED מודפסת על ידי Local Home SDK, היא לא עוזרת במיוחד במציאת שורש הבעיה. בואו נוסיף כמה יומנים מותאמים אישית כדי לוודא שאנחנו קוראים ומעבדים את נתוני הסריקה בצורה תקינה, ושימו לב שאם אנחנו דוחים את ההבטחה עם שגיאה, הודעת השגיאה למעשה נשלחת גם ל-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);
}

צריך גם לשנות את הגרסה המקומית של אפליקציית דף הבית, כדי שנוכל לזהות אם אנחנו משתמשים בגרסה הנכונה.

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 אם במכשיר Google Home מותקנת הגרסה הצפויה.

ecc56508ebcf9ab.png

גישה ל-Cloud Logging

בואו נראה איך להשתמש ב-Cloud Logging כדי למצוא את השגיאות. כדי לקבל גישה ל-Cloud Logging בפרויקט:

  1. נכנסים לדף Projects במסוף Cloud Platform.
  2. בוחרים את הפרויקט לבית החכם.
  3. בקטע Operations, בוחרים באפשרות Logging > Logs Explorer.

הגישה לנתוני הרישום ביומן מנוהלת באמצעות ניהול זהויות והרשאות גישה (IAM) עבור המשתמשים בפרויקט הפעולות. מידע נוסף על התפקידים וההרשאות לרישום נתונים זמין במאמר בקרת גישה ב-Cloud Logging.

שימוש במסננים מתקדמים

ברור לנו ששגיאות קורות ב-Intent IDENTIFY, כי הנתיב המקומי לא פועל כי המכשיר המקומי לא מזוהה. עם זאת, אנחנו רוצים לדעת בדיוק מה הבעיה, לכן קודם נסנן את השגיאות שמתרחשות ב-handler של IDENTIFY.

מרחיבים את התיבה תצוגה מקדימה של שאילתה. היא אמורה להפוך לתיבה של Query builder. מזינים jsonPayload.intent="IDENTIFY" בתיבה Query builder, ולוחצים על הלחצן Run query.

4c0b9d2828ee2447.png

כתוצאה מכך, מקבלים את כל יומני השגיאות שמושמעים ב-handler של IDENTIFY. לאחר מכן, מרחיבים את השגיאה האחרונה. אפשר למצוא את errorCode ו-debugString שהגדרת עכשיו כשדחית את ההבטחה ב-handler של IDENTIFY.

71f2f156c6887496.png

לפי ה-debugString אפשר לראות שמזהה המכשיר המקומי הוא לא בפורמט הצפוי. אפליקציית Local Home מצפה לקבל את מזהה המכשיר המקומי כמחרוזת שמתחילה ב-deviceid ואחריה 3 ספרות, אבל מזהה המכשיר המקומי הוא מחרוזת הקסדצימלית.

תיקון השגיאה

נחזור לקוד המקור שבו ניתחנו את מזהה המכשיר המקומי מנתוני הסריקה. אנחנו רואים שלא סיפקנו את הקידוד בהמרת המחרוזת לבייטים. נתוני הסריקה מתקבלים כמחרוזת הקסדצימלית, לכן יש להעביר את hex כקידוד התווים בעת קריאה ל-Buffer.from().

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);
}

צריך גם לשנות את הגרסה המקומית של אפליקציית דף הבית, כדי שנוכל לזהות אם אנחנו משתמשים בגרסה הנכונה.

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 Developers Tools Console.

c8456f7b5f77f894.png

עכשיו אפשר לנסות לשלוח שוב פקודות למכשיר שלך.

"Ok Google, force local".

"Ok Google, stop my Waher"

"Hey Google, turn on my Waher".

...

"Ok Google, force default"

6. הרצה של חבילת הבדיקה לבית החכם

אחרי שתאמתו את המכשיר באמצעות פקדי המגע באפליקציית Google Home או באמצעות פקודות קוליות, תוכלו להשתמש בכלי לבדיקת ההגדרה האוטומטית לבית חכם כדי לאמת תרחישים לדוגמה על סמך סוגי המכשירים והפיצ'רים שמשויכים לפעולה. חבילת הבדיקה מריצה סדרה של בדיקות כדי לזהות בעיות בפעולה, ומציגה הודעות אינפורמטיביות למקרי בדיקה שנכשלו כדי לזרז את ניפוי הבאגים לפני שאתם צוללים ליומני האירועים.

הרצה של חבילת הבדיקות לבית חכם

כדי לבדוק את הפעולה של הבית החכם באמצעות Test Suite, עליכם לפעול לפי ההוראות הבאות:

  1. בדפדפן האינטרנט, פותחים את חבילת הבדיקה לבית חכם.
  2. נכנסים לחשבון Google באמצעות הלחצן שבפינה השמאלית העליונה. ההרשאה הזו מאפשרת לחבילת הבדיקה לשלוח את הפקודות ישירות אל Google Assistant.
  3. בשדה Project ID מזינים את מזהה הפרויקט של פעולת הבית החכם. לאחר מכן, לוחצים על הבא כדי להמשיך.
  4. בשלב Test Settings אמור להופיע מכונת הכביסה הפגומה בקטע Devices and Trais.
  5. משביתים את האפשרות בדיקת הבקשה לסנכרון כי באפליקציה של מכונת הכביסה לדוגמה אין ממשק משתמש שאפשר להוסיף, להסיר או לשנות את השם של מכונת הכביסה. במערכת ייצור, צריך להפעיל בקשת סנכרון בכל פעם שמשתמש מוסיף מכשירים, מסיר אותם או משנה את השם שלהם.
  6. אנחנו עומדים לבדוק גם את הנתיב המקומי וגם את הנתיב בענן, ולכן צריך להשאיר את האפשרות Local Home SDK מופעלת.
  7. לוחצים על הבא כדי להתחיל להריץ את הבדיקה.

67433d9190fa770e.png

אחרי שהבדיקות יסתיימו, תבחינו שבדיקות ההשהיה/המשך בנתיב המקומי נכשלות בזמן שבדיקות ההשהיה/המשך במסלול הענן עוברות בהצלחה.

d1ebd5cfae2a2a47.png

ניתוח הודעת השגיאה

מומלץ לקרוא בעיון את הודעות השגיאה במקרים לדוגמה שנכשלו. הן מאפשרות לכם לדעת מה המצב הצפוי של הבדיקה ומה היה המצב בפועל. במקרה הזה, המצב הצפוי של מכונת הכביסה הוא isPaused: true, אבל המצב בפועל שהתקבל הוא isPaused: false. באותו האופן, במצב 'השהיית מכונת הכביסה', המצב הצפוי הוא isPaused: true, אבל המצב בפועל שהתקבל הוא isPaused: false.

6bfd3acef9c16b84.png

לפי הודעות השגיאה, נראה שבנתיב המקומי אנחנו מגדירים את מצב isPaused הפוך.

מזהים את השגיאה ומתקנים אותה

נמצא את קוד המקור שאליו אפליקציית Local 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 במצב ההפוך. אחרת, יש להגדיר אותו כ-true אם params.pause הוא true. אחרת, יש להגדיר אותו כך: false. אז בואו נתקן את זה.

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 כדי לטעון את אפליקציית Home המקומית המעודכנת. חשוב לוודא שהגרסה של אפליקציית Home המקומית היא 1.0.3.

בדיקת התיקון

עכשיו, מריצים מחדש את חבילת הבדיקות לבית החכם עם אותן הגדרות כדי לראות שכל מקרי הבדיקה עברו.

b7fc8c5d3c727d8d.png

7. מזל טוב

764dbc83b95782a.png

כל הכבוד! למדתם בהצלחה איך לפתור בעיות באפליקציית בית מקומי באמצעות Test Suite לבית חכם ול-Cloud Logging.

מידע נוסף

יש עוד כמה דברים שאפשר לנסות:

אפשר גם לעיין במידע נוסף על בדיקה ושליחה של פעולה לבדיקה, כולל תהליך האישור לפרסום הפעולה למשתמשים.