פיתוח אפליקציה לנייד באמצעות ממשקי ה-API של Home ב-iOS

1. מבוא

f154e30306882c74.png

מהם ממשקי ה-API של Home?

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

3e11583c779a2cec.png

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

רכיבים של Home APIs

ממשקי ה-API של Home מורכבים מהרכיבים הבאים:

  • ממשקי Device ו-Structure API: אינטראקציה עם הבית של המשתמש. אפליקציות יכולות להשתמש בממשקי ה-API האלה כדי לקרוא מידע על מכשירים, חדרים ומבנים (לדוגמה, לראות את רמת האקראיות הנוכחית של התרמוסטט) ולשלוט במכשירים (לדוגמה, לשנות את הטמפרטורה לשמירה בתרמוסטט).
  • Commissioning API: מאפשר להוסיף (להגדיר) מכשירי Matter חדשים לרשת בקלות.
  • Automation API: יצירה, מחיקה ושאילתות של פעולות אוטומטיות שפועלות בבית של המשתמש.

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

מה תלמדו

  • איך לפתח אפליקציה ל-iOS באמצעות ממשקי Home API, עם שיטות מומלצות.
  • איך משתמשים בממשקי ה-API של מכשירים ומבנים כדי לייצג בית חכם ולשלוט בו.
  • איך משתמשים ב-Commissioning API כדי להוסיף מכשירים לאקוסיסטם של Google Home.
  • איך משתמשים ב-Automation API כדי ליצור אוטומציה בסיסית.

2. הגדרת הבית

הכנת המכשירים

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

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

c892afce113abe8f.png

3. תהליך ההגדרה

קבלת הקוד של אפליקציה לדוגמה

מתחילים בשיבוט קוד המקור מ-GitHub:

git clone https://github.com/google-home/google-home-api-sample-app-ios.git

ספריית הדוגמה מכילה שני ענפים, start ו-finished, ל-codelab הזה.

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

הסבר על הקוד 'start'

כדי להתחיל את ה-codelab הזה, צריך לעבור להסתעפות start של המאגר המשוכפל:

git checkout start

ההסתעפות הזו מכילה את קוד לתחילת הדרך של הפרויקט. תשנו את הקוד הזה במהלך ה-codelab כדי להטמיע את הפונקציונליות המלאה. אפליקציית הדוגמה של ה-codelab מספקת מבנה בסיסי שנבנה ב-Swift לאינטראקציה עם ה-SDK של Home APIs ל-iOS. בואו נבחן בקצרה את הרכיבים העיקריים בפרויקט start:

  • Main Entry (GoogleHomeAPISampleIOSApp): נמצא ב-GoogleHomeAPISampleIOS/Main/GoogleHomeAPISampleIOS.swift, זו נקודת הכניסה הראשית לאפליקציה. הוא מגדיר ומפעיל את ה-SDK ומגדיר את ממשק המשתמש הראשי.
  • Core Views (View/):
    • MainView.swift: תצוגת הרמה הבסיסית אחרי ההפעלה, שמכילה את NavigationView הראשי. הוא בוחר את המבנה הפעיל ב-Google Home ומציג את StructureView המתאים.
    • StructureView.swift: מציג את התוכן של המבנה שנבחר כרגע, באמצעות כרטיסיות למעבר בין רשת של מכשירים לבין רשימת הפעולות האוטומטיות. יש גם תפריטים להוספת חדרים או מכשירים.
    • DeviceView.swift: מייצג את המשבצת האינטראקטיבית של מכשיר יחיד בתוך רשת StructureView.
    • AutomationsView.swift: הצגת רשימת האוטומציות הקיימות במבנה ומתן אפשרות ליצור אוטומציה חדשה או להציג את פרטי האוטומציות הקיימות.
  • ViewModels (ViewModel/): המחלקות האלה מנהלות את המצב והלוגיקה של התצוגות.
    • AccountViewModel.swift: מטפל בחיבור לאובייקט Home ומנהל את מצב האימות.
    • MainViewModel.swift: מנהל את רשימת האובייקטים הזמינים Structure ועוקב אחרי המבנה שנבחר.
    • StructureViewModel.swift: ניהול התצוגה של חדרים ושל אובייקטים DeviceControl במבנה שנבחר.
    • AutomationList.swift, AutomationViewModel.swift וכן הלאה: מנהל את השליפה, ההצגה, היצירה והניהול של אוטומציות.
  • Device Controls (ViewModel/Device/):
    • DeviceControl.swift: מחלקה בסיסית לייצוג מכשירים שאפשר לשלוט בהם בממשק המשתמש.
    • תת-מחלקות ספציפיות (LightControl.swift,‏ FanControl.swift,‏ OnOffPlugInUnitControl.swift וכן הלאה): מיישמות את הלוגיקה של ממשק המשתמש, את השליטה במכשיר ואת מיפוי המצב לסוגים שונים של מכשירים על סמך המאפיינים שלהם.
    • DeviceControlFactory.swift: אחראי ליצירת מחלקת המשנה המתאימה DeviceControl עבור HomeDevice נתון.
  • Commissioning (Commissioning/):
    • CommissioningManager.swift: מכיל את הלוגיקה לניהול תהליך ההפעלה של מכשיר Matter.
  • Utilities & UX (Utils/, UX/, Storage/): מכיל קוד עזר לרכיבי ממשק משתמש (צבעים, מידות), לטיפול בשגיאות, לאחסון נתונים (SelectedStructureStorage.swift) ולכלי עזר אחרים.

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

יצירת קובצי תצורה לפריסה של Apple

כדי להגדיר את App Attest, פועלים לפי ההוראות ליצירת קבצים להגדרת פריסה של אפליקציות של אפל. שימו לב: אחרי ההגדרה, אפשר לפרוס את האפליקציה רק במכשיר אמיתי, ולא בסימולטור.

מגדירים אימות

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

הגדרת ה-SDK

מורידים את Home APIs iOS SDK ומגדירים אותו לפי הוראות ההגדרה שמופיעות במאמר הגדרת ה-SDK. חשוב לזכור להחליף את HOME_API_TODO_ADD_APP_GROUP בקבוצת האפליקציות שלכם.

בנייה והרצה של הפרויקט

אחרי שיוצרים את הפרויקט ומריצים אותו באמצעות ההסתעפות start, אמורות להופיע תיבת דו-שיח TODO ומסך עם הכיתוב 'נדרשת כניסה'. האינטראקציה עם ממשקי ה-API של Home תיושם בקטעים הבאים.

bd56b7080037e38a.png 9c0f08a3f4197a77.png

הערה: כדי למצוא את הקוד שצריך לשנות, מחפשים בפרויקט את הטקסט שמוצג בתיבת הדו-שיח. לדוגמה, מחפשים את המחרוזת "TODO: initialize Home".

4. אתחול

הפעלת הבית

לפני שמשתמשים באחד מממשקי ה-API של Home ל-iOS, צריך לאתחל את Home באפליקציה. Home הוא נקודת הכניסה ברמה העליונה ל-SDK ומספק גישה לכל הישויות במבנה של המשתמש. כשמבקשים את כל הישויות מסוג מסוים, ה-API מחזיר אובייקט Query שמאפשר לבחור איך לקבל את התוצאות. ב-GoogleHomeAPISampleIOS/Accounts/AccountViewModel.swift, מסירים את התגובה ואת ההתראה ב-connect() כדי להטמיע את ההגדרה של הבית.

  /// TODO: initialize Home
  /// Remove comments to initialize Home and handling permission.
  private func connect() {
    Task {
      do {
        self.home = try await Home.connect()
      } catch {
        Logger().error("Auth error: \(error).")
      }
    }
  }

הרשאה לשימוש בממשקי ה-API של Home

מסך ההסכמה יופיע כשמפעילים את האפליקציה. בוחרים את המבנה של Google Home ובוחרים את החשבון שנמצא ברשימת ההיתרים של פרויקט Google Cloud.

47310f458c0094d9.png 4a571dbd9979a88c.png e29c75891a3a67af.png

5. מכשירים ומבנים

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

ב-GoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, מסירים את התגובה ואת ההתראה ב-getRoomsAndDevices() כדי לקבל את החדרים והמכשירים במבנה שנבחר עם home.rooms() ו-home.devices(), בהתאמה.

  /// TODO: get rooms and devices
  /// Remove comments to get the rooms and devices from home entry
  private func getRoomsAndDevices(){
    self.home.rooms().batched()
      .combineLatest(self.home.devices().batched())
      .receive(on: DispatchQueue.main)
      .catch { error in
        Logger().error("Failed to load rooms and devices: \(error)")
        return Just((Set<Room>(), Set<HomeDevice>()))
      }
      .map { [weak self] rooms, devices in
        guard let self = self else { return [] }
        self.hasLoaded = true
        return self.process(rooms: rooms, devices: devices)
      }
      /// receive from .map and .assign() to publisher entries
      .assign(to: &self.$entries)
  }

הפונקציה process() מוודאת קודם שהמכשירים נמצאים באותו חדר, ורק אז גורמת להם לקיים אינטראקציה כHomeDevices באמצעות DeviceControl ו-DeviceControlFactory.

4c677c4c294e67ca.png

הערה: אם המכשיר שלכם לא מופיע בDeviceControlFactory, הוא יוצג כ'לא נתמך'. מידע נוסף על מכשירים נתמכים זמין בדף סוגי מכשירים נתמכים ב-iOS.

אינטראקציה עם מכשיר

התוסף outlet1 לא פעיל בהתחלה כשמקישים על המכשירים או מחליקים עליהם. כדי לאפשר אינטראקציה עם הרכיב, מאתרים את GoogleHomeAPISampleIOS/ViewModel/Device/OnOffPlugInUnitControl.swift ומסירים את ההערה וההתראה בפונקציה primaryAction().

  /// TODO: primary action of OnOffPlug
  /// Toggles the plug; usually provided as the `action` callback on a Button.
  public override func primaryAction() {
    self.updateTileInfo(isBusy: true)
    Task { @MainActor [weak self] in
      guard
        let self = self,
        let onOffPluginUnitDeviceType = self.onOffPluginUnitDeviceType,
        let onOffTrait = onOffPluginUnitDeviceType.matterTraits.onOffTrait
      else { return }

      do {
        try await onOffTrait.toggle()
      } catch {
        Logger().error("Failed to to toggle OnOffPluginUnit on/off trait: \(error)")
        self.updateTileInfo(isBusy: false)
      }
    }
  }

הפונקציה primaryAction(), שנמצאת במחלקה OnOffPlugInUnitControl, מחליפה את מצב ההפעלה/ההשבתה של שקע חכם או של כל מכשיר שמיוצג על ידי OnOffPluginUnitDeviceType.

דוגמאות נוספות לשליטה במכשיר זמינות במאמר GoogleHomeAPISampleIOS/ViewModel/Device.

יצירת חדר חדש

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

בGoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, מסירים את התגובה ואת ההתראה בaddRoom().

  /// TODO: add room
  /// Add a new room in a given structure.
  func addRoom(name: String, structure: Structure) {
    Task {
      do {
        // The view will be updated with the values from the devices publisher.
        _ = try await structure.createRoom(name: name)
      } catch {
        Logger().error("Failed to create room: \(error)")
      }
    }
  }

כדי ליצור חדר חדש עם structure.createRoom(), עוברים לפינה הימנית העליונה ולוחצים על סמל הפלוס > הוספת חדר. מזינים את השם החדש של החדר ולוחצים על 'יצירת חדר'. החדר החדש יופיע אחרי כמה שניות.

b122ae6642b7da1c.png a45f785e1d51938e.png 7753b56cbdcff8d6.png

העברת המכשיר לחדר אחר

בGoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, מסירים את התגובה ואת ההתראה בmoveDevice().

  /// TODO: move device
  /// Move a device into a different room.
  func moveDevice(device deviceID: String, to roomID: String, structure: Structure) {
    Task {
      do {
        _ = try await structure.move(device: deviceID, to: roomID)
      } catch {
        Logger().error("Failed to move to room: \(error)")
      }
    }
  }

כדי להעביר את המכשיר באמצעות structure.move(), לוחצים עליו לחיצה ארוכה, בוחרים באפשרות 'העברה לחדר אחר' ובוחרים את החדר החדש.

f9627592af44163d.png fd126fabb454f2bf.png 813e1e23e50cd9f6.png

מחיקת חדר ריק

בGoogleHomeAPISampleIOS/ViewModel/StructureViewModel.swift, מסירים את התגובה ואת ההתראה בremoveRoom().

  /// TODO: delete room
  /// Delete an empty room in a given structure.
  func removeRoom(id: String, structure: Structure) {
    Task {
      do {
        // The view will be updated with the values from the devices publisher.
        _ = try await structure.deleteRoom(id: id)
      } catch {
        Logger().error("Failed to remove room: \(error)")
      }
    }
  }

כדי למחוק חדר ריק עם structure.deleteRoom(), לוחצים על סמל האשפה משמאל לשם החדר ומאשרים את הפעולה. לתשומת ליבכם, אפשר למחוק רק חדרים ריקים.

4f129262ad67f564.png

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

6. הפעלה

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

הוספת מכשיר Matter

Commissioning API מאפשר לאפליקציה שלכם להוסיף מכשירי Matter חדשים לבית של המשתמש ולחשבון Google שלו. כך תוכלו ליהנות מחוויית הגדרה חלקה ישירות באפליקציה.

בGoogleHomeAPISampleIOS/Commissioning/CommissioningManager.swift, מסירים את התגובה ואת ההתראה בaddMatterDevice().

  /// TODO: add Matter Device
  /// Starts the Matter device commissioning flow to add the device to the user's home.
  /// - Parameters:
  ///   - structure: The structure to add the device to.
  ///   - add3PFabricFirst: Whether to add the device to a third party fabric first.
  public func addMatterDevice(to structure: Structure, add3PFabricFirst: Bool) {
    self.isCommissioning = true

    /// pass if it's 1p or 3p commissioning
    let userDefaults = UserDefaults(
      suiteName: CommissioningManager.appGroup)
    userDefaults?.set(
    add3PFabricFirst, forKey: CommissioningUserDefaultsKeys.shouldPerform3PFabricCommissioning)

    Task {
      do {
        try await structure.prepareForMatterCommissioning()
      } catch {
        Logger().error("Failed to prepare for Matter Commissioning: \(error).")
        self.isCommissioning = false
        return
      }

      // Prepare the Matter request by providing the ecosystem name and home to be added to.
      let topology = MatterAddDeviceRequest.Topology(
        ecosystemName: "Google Home",
        homes: [MatterAddDeviceRequest.Home(displayName: structure.name)]
      )
      let request = MatterAddDeviceRequest(topology: topology)

      do {
        Logger().info("Starting MatterAddDeviceRequest.")
        try await request.perform()
        Logger().info("Completed MatterAddDeviceRequest.")
        let commissionedDeviceIDs = try structure.completeMatterCommissioning()
        Logger().info("Commissioned device IDs: \(commissionedDeviceIDs).")
      } catch let error {
        structure.cancelMatterCommissioning()
        Logger().error("Failed to complete MatterAddDeviceRequest: \(error).")
      }

      self.isCommissioning = false
    }
  }

כדי ליצור מרחב חדש עם structure.prepareForMatterCommissioning(), עוברים לפינה הימנית העליונה ולוחצים על הסמל '+' > הוספת מכשיר ל-Google Fabric. הוא משתמש ב-MatterAddDeviceRequest כדי להוסיף את מכשיר Matter לחדר. אחרי שבוחרים את החדר ואת שם המכשיר, המכשיר מוצג במסך 'מכשירים'.

adf6cbb531787aaf.png f002bd6320bc480d.png

7. אוטומציה

צפייה בכל האוטומציות במבנה

מקישים על אוטומציות בסרגל הניווט התחתון. כל הפעולות האוטומטיות במבנה יופיעו עם structure.listAutomations().

cc6d50f72f812c24.png

הערה: אם לא הגדרתם אוטומציות לבית, תופיע ההודעה 'כדי להתחיל, צריך להוסיף אוטומציה'.

יצירת פעולה אוטומטית

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

ב-GoogleHomeAPISampleIOS/ViewModel/Automation/AutomationsRepository.swift, מסירים את התגובה, את ההתראה ואת הפעולה האוטומטית הריקה ב-lightAutomation().

  /// TODO: create automation
  /// - Parameter devices: devices in current selected structure
  /// - Returns: the automation object to be created
  /// This automation will turn off the light after 5 seconds.
  public func lightAutomation(devices: Set<HomeDevice>) async throws -> any DraftAutomation {
    let light = devices.first { $0.name == "light2" }
    
    guard let light else {
      Logger().error("Unable to find light device with name light2")
      throw HomeError.notFound("No devices support OnOffLightDeviceType")
    }
    
    return automation(
      name: "Turn off light after 5 seconds",
      description:
        """
        Turns off light2 after it has been on for 5 seconds.
        """
    ) {
      let onOffStarter = starter(light, OnOffLightDeviceType.self, OnOffTrait.self)
      onOffStarter
      condition {
        onOffStarter.onOff.equals(true)
      }
      delay(for: Duration.seconds(5))
      action(light, OnOffLightDeviceType.self) {
        OnOffTrait.off()
      }
    }
  }

כדי ליצור אוטומציה שתכבה את האור חמש שניות אחרי שהוא נדלק, עוברים לתצוגת האוטומציה ולוחצים על הלחצן + הוספה. לאחר מכן בוחרים באפשרות האור יכבה אחרי 5 שניות. יוצגו פרטי האוטומציה, כולל starter, condition ו-action. לוחצים על שמירה כדי ליצור את האוטומציה לפי structure.createAutomation().

21c1f8ea2a29134b.png 4bd36f6ed9c5f6e9.png

הערה: הפעולות האוטומטיות שזמינות לכם תלויות במכשירים שיש לכם בבית. אם לא מופיעות אוטומציות זמינות, נסו לשנות את השם של מכשיר התאורה ל-light2.

חוזרים לכרטיסייה 'מכשירים' ומפעילים את הנורה שנקראת light2. הוא יושבת אוטומטית אחרי חמש שניות.

הרכיבים של אוטומציה הם:

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

דוגמאות נוספות זמינות בדף דוגמאות לאוטומציות.

מחיקת פעולה אוטומטית

השיטה structure.deleteAutomation() מופעלת כשמחליקים ימינה על אוטומציה קיימת ומקישים על סמל הפח כדי להסיר אותה מהמבנה.

dc678cd9e16f89a5.png

8. מזל טוב

מעולה! יצרתם בהצלחה אפליקציה בסיסית לבית חכם באמצעות Home APIs ל-iOS.

מה השגתם:

  • הפעלה ראשונית: חיברתם את האפליקציה למערכת האקולוגית של Google Home באמצעות Home.connect().
  • הרשאות: טיפול באימות משתמשים ובהרשאות גישה לנתונים בבית.
  • מכשירים ומבנים: חדרים ומכשירים שאוחזרו ומוצגים באמצעות home.rooms() ו-home.devices().
  • שליטה במכשיר: הטמענו אינטראקציה עם מכשיר, כמו שינוי המצב של OnOffPluginUnitDeviceType על ידי הפעלת פקודות במאפיינים שלו.
  • ניהול המבנה: נוספה פונקציונליות ליצירת חדרים חדשים (structure.createRoom()), להעברת מכשירים בין חדרים (structure.move()) ולמחיקת חדרים ריקים (structure.deleteRoom()).
  • הפעלה: שילבנו את תהליך ההפעלה של ה-SDK כדי להוסיף מכשירי Matter חדשים (MatterAddDeviceRequest).
  • אוטומציה: הסברנו איך לראות רשימה של פעולות אוטומטיות, ליצור (structure.createAutomation()) ולמחוק (structure.deleteAutomation()) פעולות אוטומטיות במסגרת מבנה.

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

השלבים הבאים:

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

כל הכבוד!