אירועים

האירועים הם אסינכרוניים ומנוהלים על ידי Google Cloud Pub/Sub, בנושא אחד לכל Project. אירועים מספקים עדכונים לכל המכשירים והמבנים, וקבלה של אירועים מובטחת כל עוד משתמש לא ביטל את אסימון הגישה ופג התוקף של הודעות האירוע.

הפעל אירועים

אירועים הם תכונה אופציונלית של SDM API. במאמר הפעלת אירועים כאן מוסבר איך להפעיל אותם ב- Project.

Google Cloud Pub/Sub

מידע נוסף על אופן הפעולה של Pub/Sub זמין במשאבי העזרה של Google Cloud Pub/Sub. הקפידו במיוחד על הדברים הבאים:

מינוי לאירוע

כשאירועים מופעלים עבור Project, מקבלים נושא ספציפי Project למזהה הזה, בפורמט הבא:

projects/sdm-prod/topics/enterprise-project-id

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

הפעלת אירועים

כדי להתחיל אירועים בפעם הראשונה אחרי יצירת מינוי Pub/Sub, צריך לשלוח קריאה ל-API devices.list כטריגר חד-פעמי. אירועים של כל המבנים והמכשירים יתפרסמו אחרי השיחה הזו.

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

סדר האירוע

מערכת Pub/Sub לא מבטיחה אספקה של אירועים, ויכול להיות שסדר הקבלה של האירועים לא יהיה תואם לסדר שבו האירועים התרחשו בפועל. תוכלו להשתמש בשדה timestamp כדי לבצע התאמה של סדר האירועים. אירועים יכולים גם להגיע בנפרד או לשלב אותם להודעה אחת על אירוע.

מידע נוסף מופיע במאמר סידור ההודעות.

מזהי משתמשים

אם ההטמעה מבוססת על משתמשים (ולא על מבנה או מכשיר), צריך להשתמש בשדה userID מהמטען הייעודי (Payload) של האירועים כדי להתאים בין משאבים לאירועים. השדה הזה הוא מזהה מעורפל שמייצג משתמש ספציפי.

ה-userID זמין גם בכותרת התגובה של ה-HTTP של כל קריאה ל-API.

אירועי קשר

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

יש שלושה סוגים של אירועי קשר:

  • נוצר
  • נמחק
  • מעודכן

המטען הייעודי (Payload) של אירוע קשור הוא:

מטען ייעודי (payload)

{
  "eventId" : "fd72d3b3-41a3-42aa-a93c-84ff2aa346c3",
  "timestamp" : "2019-01-01T00:00:01Z",
  "relationUpdate" : {
    "type" : "CREATED",
    "subject" : "enterprises/project-id/structures/structure-id",
    "object" : "enterprises/project-id/devices/device-id"
  },
  "userId": "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"
}

באירוע קשר, object הוא המשאב שהפעיל את האירוע ו-subject הוא המשאב שאליו יש עכשיו קשר בין object. בדוגמה שלמעלה, user העניק/ה גישה למכשיר הספציפי הזה ל- developer, והמכשיר המורשה של userקשור עכשיו למבנה המורשה שלו, מה שמפעיל את האירוע.

subject יכול להיות רק חדר או מבנה. אם ל- a developer אין הרשאה להציג את המבנה של user, השדה subject תמיד יהיה ריק.

שדות

שדה תיאור סוג הנתונים
eventId המזהה הייחודי של האירוע. string
לדוגמה: '93e6ff86-3afd-4b52-9099-a29871dcf3c4'
timestamp השעה שבה התרחש האירוע. string
לדוגמה: '2019-01-01T00:00:01Z'
relationUpdate אובייקט שמפרט מידע על עדכון הקשר. object
userId מזהה ייחודי ומעורפל שמייצג את המשתמש. string
דוגמה: "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"

מידע נוסף על סוגי האירועים השונים ועל אופן הפעולה שלהם מופיע במאמר אירועים.

דוגמאות

מטענים ייעודיים (payloads) של אירועים משתנים בהתאם לכל סוג של אירוע קשר:

מועד היצירה

המבנה נוצר

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "",
  "object" : "enterprises/project-id/structures/structure-id"
}

המכשיר נוצר

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "enterprises/project-id/structures/structure-id",
  "object" : "enterprises/project-id/devices/device-id"
}

המכשיר נוצר

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

מעודכן

המכשיר הועבר

"relationUpdate" : {
  "type" : "UPDATED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

נמחק

המבנה נמחק

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "",
  "object" : "enterprises/project-id/structures/structure-id"
}

המכשיר נמחק

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "enterprises/project-id/structures/structure-id",
  "object" : "enterprises/project-id/devices/device-id"
}

המכשיר נמחק

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

אירועי קשר לא נשלחים אם:

  • החדר נמחק

אירועים של משאבים

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

אירוע שנוצר בתגובה לשינוי בערך של השדה trait מכיל אובייקט traits, בדומה לקריאה ל-GET של מכשיר:

מטען ייעודי (payload)

{
  "eventId" : "ffe48890-d114-401e-a0b0-44a17d54dc11",
  "timestamp" : "2019-01-01T00:00:01Z",
  "resourceUpdate" : {
    "name" : "enterprises/project-id/devices/device-id",
    "traits" : {
      "sdm.devices.traits.ThermostatMode" : {
        "mode" : "COOL"
      }
    }
  },
  "userId": "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
  "resourceGroup" : [
    "enterprises/project-id/devices/device-id"
  ]
}

אפשר להשתמש במסמכי התיעוד בנושא תכונות ספציפיות כדי להבין את הפורמט של המטען הייעודי (payload) לכל אירוע של שינוי בשדה trait.

לאירוע שנוצר בתגובה לפעולה במכשיר שלא משנה את השדה trait יש גם מטען ייעודי (payload) עם אובייקט resourceUpdate, אבל עם אובייקט events במקום אובייקט traits:

מטען ייעודי (payload)

{
  "eventId" : "14bb7ac1-13ee-4439-9732-3adaaa5adc16",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "Vj1KmB9P-ZVR_V5KMINQsdyUKT...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

סוגים אלה של אירועי משאבים מוגדרים בתכונות ספציפיות. לדוגמה, האירוע 'תנועה' מוגדר בתכונה CameraMotion . אפשר לעיין במסמכי התיעוד של כל תכונה כדי להבין את הפורמט של המטען הייעודי (Payload) לסוגים אלה של אירועי משאבים.

שדות

שדה תיאור סוג הנתונים
eventId המזהה הייחודי של האירוע. string
דוגמה: '14b7ac1-13ee-4439-9732-3adaaa5adc16'
timestamp השעה שבה התרחש האירוע. string
לדוגמה: '2019-01-01T00:00:01Z'
resourceUpdate אובייקט שמכיל מידע על עדכון המשאב. object
userId מזהה ייחודי ומעורפל שמייצג את המשתמש. string
דוגמה: "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"
eventThreadId המזהה הייחודי של השרשור. string
דוגמה: 'd67cd3f7-86a7-425e-8b3-462f92ec9f59'
eventThreadState מצב השרשור של האירוע. string
ערכים: "STARTED", "UPDATED", "ENDED"
resourceGroup אובייקט שמציין משאבים שייתכן שיש להם עדכונים דומים לאירוע הזה. המשאב של האירוע עצמו (מהאובייקט resourceUpdate) תמיד יופיע באובייקט הזה. object

מידע נוסף על סוגי האירועים השונים ועל אופן הפעולה שלהם מופיע במאמר אירועים.

התראות הניתנות לעדכון

אפשר להטמיע התראות על סמך אירועים של משאבים באפליקציה, למשל ב-Android או ב-iOS. כדי לצמצם את מספר ההתראות שנשלחות, צריך להטמיע תכונה שנקראת התראות הניתנות לעדכון, שבה ההתראות הקיימות מתעדכנות במידע חדש על סמך האירועים הבאים באותו שרשור של האירועים.

אירועים נבחרים עם תמיכה בהתראות הניתנות לעדכון, והם מתויגים בתור עדכון  במסמכי התיעוד. לאירועים האלה יש שדה נוסף בשם eventThreadId במטענים הייעודיים (payloads). אפשר להשתמש בשדה הזה כדי לקשר בין אירועים נפרדים כדי לעדכן התראה קיימת שהוצגה למשתמש.

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

למטרות התראות, סוגים שונים של אירועים מקובצים לשרשורים שונים.

לוגיקת הקיבוץ והתזמון של השרשורים מטופלת על ידי Google, והיא עשויה להשתנות בכל שלב. developer צריך לעדכן את ההתראות על סמך השרשורים והסשנים של האירועים שמסופקים על ידי SDM API.

מצב השרשור

אירועים שתומכים בהתראות שניתן לעדכן כוללים גם את השדה eventThreadState שמציין את מצב השרשור של האירוע באותה נקודת זמן. בשדה הזה מופיעים הערכים הבאים:

  • התחיל – האירוע הראשון בשרשור של אירועים.
  • עודכן – אירוע בשרשור של אירוע פעיל. בשרשור אחד יכולים להיות אפס אירועים או יותר במצב הזה.
  • הסתיים – האירוע האחרון בשרשור של אירוע, שיכול להיות כפילות של האירוע האחרון שמעודכן, בהתאם לסוג השרשור.

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

סינון אירועים

בחלק מהמקרים, אירועים שזוהו על ידי מכשיר יסוננו כך שלא יפורסמו לנושא SDM Pub/Sub. ההתנהגות הזו נקראת סינון אירועים. מטרת סינון האירועים היא למנוע פרסום של יותר מדי הודעות אירועים דומות בפרק זמן קצר.

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

באפליקציית Google Home (GHA), אירועים שסוננו עדיין יופיעו בהיסטוריית האירועים של user. עם זאת, אירועים כאלה לא יוצרים התראה באפליקציה (גם אם סוג ההתראה הזה מופעל).

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

חשבונות שירות

מומלץ להשתמש בחשבונות שירות לניהול מינויים ל-SDM API והודעות על אירועים. חשבון שירות משמש אפליקציה או מכונה וירטואלית ולא של אדם, ויש לו מפתח חשבון ייחודי משלו.

בהרשאה באמצעות חשבון שירות ל-Pub/Sub API נעשה שימוש ב-OAuth דו-שלבי (2LO).

בתהליך ההרשאה של 2LO:

  • התקבלה בקשה של developer לאסימון גישה באמצעות מפתח שירות.
  • ה- developer משתמש באסימון הגישה עם קריאות ל-API.

למידע נוסף על Google 2LO ועל אופן ההגדרה, ראו שימוש ב-OAuth 2.0 לאפליקציות משרת לשרת.

אישור

לחשבון השירות צריכה להיות הרשאה לשימוש עם API של Pub/Sub:

  1. מפעילים את Cloud Pub/Sub API ב-Google Cloud.
  2. יוצרים חשבון שירות ומפתח של חשבון שירות, כפי שמתואר במאמר יצירת חשבון שירות. מומלץ להקצות לו רק את התפקיד מנוי ב-Pub/Sub. חשוב להוריד את המפתח של חשבון השירות למכונה שישתמשה ב-Pub/Sub API.
  3. מזינים את פרטי הכניסה לאימות (מפתח לחשבון השירות) לקוד האפליקציה לפי ההוראות שמופיעות בדף בשלב הקודם, או מקבלים אסימון גישה באופן ידני באמצעות oauth2l, אם רוצים לבדוק את הגישה ל-API במהירות.
  4. משתמשים בפרטי הכניסה של חשבון השירות או באסימון הגישה באמצעות Pub/Sub project.subscriptions API כדי לשלוף ולאשר הודעות.

Oauth2l

oauth2l של Google הוא כלי שורת הפקודה OAuth שנכתב ב-Go. אפשר להתקין אותו ל-Mac או ל-Linux באמצעות Go.

  1. אם אפליקציית Go לא מותקנת במערכת, קודם מורידים ומתקינים אותה.
  2. לאחר ההתקנה של Go, מתקינים את oauth2l ומוסיפים את המיקום שלו למשתנה הסביבה PATH:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. משתמשים ב-oauth2l כדי לקבל אסימון גישה ל-API, עם היקפי ההרשאות המתאימים של OAuth:
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    לדוגמה, אם מפתח השירות נמצא ב-~/myServiceKey-eb0a5f900ee3.json:
    oauth2l fetch --credentials ~/myServiceKey-eb0a5f900ee3.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    ya29.c.Elo4BmHXK5...

מידע נוסף על השימוש זמין בקובץ ה-README של oauth2l.

ספריות הלקוח של Google API

יש כמה ספריות לקוח שזמינות ל-Google APIs שנעשה בהם שימוש ב-OAuth 2.0. למידע נוסף על השפה הרצויה, ראו ספריות הלקוח של Google API.

כשמשתמשים בספריות האלה עם Pub/Sub API, צריך להשתמש במחרוזות ההיקפים הבאות:

https://www.googleapis.com/auth/pubsub
https://www.googleapis.com/auth/cloud-platform

שגיאות

קודי השגיאה הבאים עשויים להיות מוחזרים בהקשר למדריך הזה:

הודעת שגיאה הכנסה לקליק פתרון בעיות
תמונת המצלמה כבר לא זמינה להורדה. DEADLINE_EXCEEDED התוקף של תמונות האירוע פג 30 שניות לאחר פרסום האירוע. הקפידו להוריד את התמונה לפני שהתוקף שלה יפוג.
מזהה האירוע לא שייך למצלמה. FAILED_PRECONDITION צריך להשתמש בeventID הנכון שהוחזר על ידי אירוע המצלמה.

הרשימה המלאה של קודי השגיאה של ה-API מופיעה בחומר העזר בנושא קוד שגיאה של API.