iOS पर Structure APIs

iOS के लिए Home APIs के ज़रिए, स्ट्रक्चर एपीआई को ऐक्सेस किया जा सकता है.

स्ट्रक्चर एपीआई का इस्तेमाल करने के लिए, पहले अपने ऐप्लिकेशन में GoogleHomeSDK पैकेज इंपोर्ट करें:

import GoogleHomeSDK

गड़बड़ी ठीक करना

Home APIs के कुछ तरीके HomeError दिखाते हैं. इसलिए, हमारा सुझाव है कि आप उन कॉल पर HomeError को पकड़ने के लिए, do-catch ब्लॉक का इस्तेमाल करें.

HomeError को हैंडल करते समय, इसके code और message फ़ील्ड देखें, ताकि आपको पता चल सके कि गड़बड़ी क्या है.

अगर गड़बड़ियों को ठीक नहीं किया जाता है, तो आपका ऐप्लिकेशन क्रैश हो जाएगा.

ज़्यादा जानकारी के लिए, गड़बड़ी ठीक करना लेख पढ़ें.

Structure API

Home, होम ग्राफ़ को दिखाता है. साथ ही, यह स्ट्रक्चर एपीआई का एंट्री पॉइंट है. इससे होम, कमरों, और डिवाइसों के रेफ़रंस मिलते हैं.

Structure, आपके होम ग्राफ़ में मौजूद एक स्ट्रक्चर को दिखाता है. इससे id और name जैसे स्ट्रक्चर मेटाडेटा का ऐक्सेस मिलता है.

अपने खाते में मौजूद सभी स्ट्रक्चर पाने के लिए, structures() का इस्तेमाल करें. स्ट्रक्चर, Query के तौर पर दिखाए जाते हैं. इसमें डेटा को इस्तेमाल करने के लिए, ये विकल्प मिलते हैं:

एपीआई ब्यौरा
stream() यह फ़ंक्शन, एक Publisher दिखाता है. यह बदलाव होने पर, हर ऑब्जेक्ट को अलग-अलग दिखाता है.
batched() यह एक Publisher दिखाता है, जो मौजूदा नतीजे को ऑब्जेक्ट के Set के तौर पर दिखाता है. हर Set, ऑब्जेक्ट ग्राफ़ की मौजूदा स्थिति को दिखाता है.
list() यह मौजूदा नतीजे को ऑब्जेक्ट के Set के तौर पर दिखाता है.

ऐसा हो सकता है कि structures().list() कॉल, स्ट्रक्चर का मान्य सेट तुरंत न दिखाए. अगर आपका ऐप्लिकेशन रिएक्टिव है और यूज़र इंटरफ़ेस (यूआई) को चलाने के लिए, स्ट्रक्चर में होने वाले सभी बदलावों की सदस्यता लेने के लिए stream() को कॉल करता है, तो स्ट्रक्चर की एक मान्य सूची दिखनी चाहिए. ऐसी अन्य स्थितियां भी हो सकती हैं जिनमें स्ट्रक्चर की खाली सूची दिख सकती है. उदाहरण के लिए, अगर उपयोगकर्ता के फ़ोन का इंटरनेट कनेक्शन टूट जाता है या उपयोगकर्ता ने आपके ऐप्लिकेशन को दी गई अनुमतियां वापस ले ली हैं. आपको अपने ऐप्लिकेशन में इन मामलों को मैनेज करना चाहिए.

@Published public private(set) var structures: [Structure] = []
private var structuresCancellable: AnyCancellable?

  self.structuresCancellable = home
    .structures()
    .batched()
    .receive(on: DispatchQueue.main)
    .map { Array($0) }
    .catch {
      // Failed to load structures
      return Just([Structure]())
    }
    .assign(to: \.structures, on: self)

सैंपल स्ट्रक्चर कॉल

स्ट्रक्चर का सेट पाना

list() को Query<Structure> पर कॉल करने से, एलिमेंट का सबसे हाल का सेट दिखता है:

// Get a stream of all structures accessible to the user
let allStructuresChanges = self.home.structures()
let allStructures = try? await allStructuresChanges.list()

रिएक्टिव ऐप्लिकेशन डिज़ाइन करते समय, list() के बजाय batched() और stream() कॉल का इस्तेमाल करें. ऐसा इसलिए, क्योंकि होम ग्राफ़ में बदलाव होने पर, ये अपने-आप डेटा जनरेट करते हैं.

स्ट्रक्चर की प्रॉपर्टी पाना

स्ट्रक्चर की सूची की मदद से, उनकी प्रॉपर्टी ऐक्सेस की जा सकती हैं:

// Get a stream of changes taking place on a structure.
let structureChanges = try await home.structures().list().filter { $0.id == structureID }

// Get a snapshot of the structure.
let structure = structureChanges.first!

// Get structure properties
print("id \(structure.id) ")
print("name \(structure.name) ")

नाम से कोई होम ढूंढना

अगर आपको किसी स्ट्रक्चर का नाम पता है, तो name प्रॉपर्टी का इस्तेमाल करके भी उसे ऐक्सेस किया जा सकता है:

do {
  structure1 = try await home.structures().list().first(where: { $0.name == "Main House" })
} catch let _ as HomeError {
  // Code for handling the exception
}

वहां से, हर स्ट्रक्चर के लिए प्रॉपर्टी, रूम, और डिवाइसों को ऐक्सेस किया जा सकता है.

एक से ज़्यादा स्ट्रक्चर के साथ काम करना

एक से ज़्यादा स्ट्रक्चर का इस्तेमाल करने के लिए, हर स्ट्रक्चर का अलग रेफ़रंस लें:

var structure1: Structure!
var structure2: Structure!
do {
  structure1 = try await home.structures().list().first(where: { $0.name == "Main House" })
} catch let _ as HomeError {
  // Code for handling the exception
}
do {
  structure2 = try await home.structures().list().first(where: { $0.name == "Guest Cottage" })
} catch let _ as HomeError {
  // Code for handling the exception
}

कमरे

किसी रूम में डिवाइसों का एक ग्रुप होता है. कमरा हमेशा किसी स्ट्रक्चर का हिस्सा होता है और एक स्ट्रक्चर में कई कमरे हो सकते हैं. किसी स्ट्रक्चर से कमरे को हटाने पर, उस कमरे में मौजूद डिवाइसों को स्ट्रक्चर से नहीं हटाया जाता. हालांकि, अगर रूम को मिटा दिया जाता है, तो उसमें मौजूद डिवाइसों को असाइन नहीं किया जाता.

खाते में मौजूद सभी कमरों की जानकारी पाने के लिए, Home.rooms() का इस्तेमाल करें. इसके बाद, हर कमरे में मौजूद डिवाइसों को दिखाने के लिए, roomID = device.roomID का इस्तेमाल करें.

self.home.rooms().batched()
  .combineLatest(self.home.devices().batched())
  .receive(on: DispatchQueue.main)
  .catch { error in
    // Failed to load rooms and devices
    return Just((Set<Room>(), Set<HomeDevice>()))
  }
  .map { rooms, devices in
    var devicesByRoom = [Room: [HomeDevice]]()
    for room in rooms where room.structureID == currentStructureID {
      devicesByRoom[room] = devices.filter { $0.roomID == room.id }
    }
    return devicesByRoom
  }.assign(to: &self.$devicesByRoom)

Sample Room calls

कमरों की सूची पाना

Home क्लास का इस्तेमाल करके, रूम की सूची देखी जा सकती है. साथ ही, उनकी प्रॉपर्टी ऐक्सेस की जा सकती हैं:

let allRoomsChanges = self.home.rooms()
let allRooms = try await allRoomsChanges.list()
let room = allRooms.first!
XCTAssertTrue(allRooms.contains(room))

print("id \(room.id) ")
print("name \(room.name) ")

चैट रूम बनाएं

Structure में नया रूम बनाने के लिए:

let testName = "Test Room Name"
var newRoom: Room!
do {
  newRoom = try await structure.createRoom(name: testName)
  XCTAssertNotNil(newRoom)
} catch let _ as HomeError {
  // Code for handling the exception
}

किसी रूम को मिटाना

इसके अलावा, किसी रूम को मिटाया भी जा सकता है:

val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull()
    structure.deleteRoom(roomToDelete!!)

किसी रूम को उसके आईडी का इस्तेमाल करके भी मिटाया जा सकता है:

let roomToDelete = allRooms.first(where: { $0.id == room.id })
if let roomToDelete1 = roomToDelete {
  do {
    try await structure.deleteRoom(roomToDelete1)
  } catch let _ as HomeError {
    // Code for handling the exception
  }
}

अगर डिवाइसों वाले किसी रूम को मिटाया जाता है, तो डिवाइस अब भी स्ट्रक्चर में मौजूद रहेंगे. हालांकि, वे किसी रूम को असाइन नहीं किए जाएंगे.

डिवाइसों को किसी दूसरे रूम में ट्रांसफ़र करना

Structure की मदद से, किसी डिवाइस को दूसरे रूम में भी ट्रांसफ़र किया जा सकता है:

do {
  try await structure.move(device: light, to: room)
} catch let _ as HomeError {
  // Code for handling the exception
}

किसी रूम का नाम बदलना

किसी स्पेस का नाम बदलने के लिए, setName(_:) मेथड को कॉल करें:

let updatedRoom = try await theRoom.setName("new room name")

किसी रूम का नाम बदलने पर, ओरिजनल Room स्ट्रक्चर में कोई बदलाव नहीं होता. साथ ही, अपडेट किए गए Room ऑब्जेक्ट में बदलाव दिखता है.

अगर नाम 60 यूनिकोड कोड पॉइंट (वर्ण) की सीमा से ज़्यादा हैं, तो उन्हें छोटा कर दिया जाएगा. साथ ही, कोई गड़बड़ी नहीं दिखाई जाएगी. लंबे नामों को मैनेज करने की ज़िम्मेदारी डेवलपर की होती है. उदाहरण के लिए, वे यह तय कर सकते हैं कि उपयोगकर्ताओं को यह बताना है या नहीं कि उनके नाम छोटे कर दिए जाएंगे.

डिवाइस ग्रुप

डिवाइस ग्रुप, किसी एक स्ट्रक्चर में मौजूद डिवाइसों का कलेक्शन होता है. इसे उपयोगकर्ता तय करता है. ग्रुप की सदस्यता, Google की सेवाओं में बनी रहती है. साथ ही, यह स्ट्रक्चर के अन्य सदस्यों और स्ट्रक्चर का ऐक्सेस रखने वाले अन्य ऐप्लिकेशन को दिखती है.

फ़िज़िकल रूम की तरह ही, डिवाइस ग्रुप भी एक ही स्ट्रक्चर से जुड़े होते हैं. हालांकि, रूम के उलट, डिवाइस ग्रुप लॉजिकल ग्रुप होते हैं. किसी डिवाइस को एक साथ कई डिवाइस ग्रुप में शामिल किया जा सकता है. डिवाइस ग्रुप में ज़्यादा से ज़्यादा 100 डिवाइस शामिल किए जा सकते हैं.

डिवाइस ग्रुप को DeviceGroup इकाई से दिखाया जाता है. यह HomeDevice से अलग होती है. डिवाइस ग्रुप के साथ इंटरैक्ट करने के लिए, Home.configure में ReferencedAutomationTypes को कॉन्फ़िगर करते समय, डिवाइस के काम के टाइप और विशेषताओं को शामिल करें. साथ ही, GroupTrait, GroupManagementTrait, और GroupMembershipTrait विशेषताओं को भी शामिल करें.

किसी ग्रुप में मौजूद डिवाइसों के साथ इंटरैक्ट करने के लिए, सीधे तौर पर उसके सदस्य डिवाइसों को बार-बार इस्तेमाल करें (ग्रुप के सदस्य डिवाइसों के साथ इंटरैक्ट करना देखें) या DeviceGroup पर डिवाइस टाइप के किसी हिस्से को टारगेट करें (डिवाइस ग्रुप को कंट्रोल करना देखें).

डिवाइस ग्रुप की सूची देखना

होम में मौजूद सभी डिवाइस ग्रुप के बारे में क्वेरी करने के लिए:

let groups = try await home.entities(DeviceGroup.self).list()
for group in groups {
  let groupTrait = await group.traits.get(Google.GroupTrait.self)
  let name = groupTrait?.attributes.name ?? "Device Group"
  print("Found group: \(name) with ID: \(group.id)")
}

ग्रुप में शामिल डिवाइसों के साथ इंटरैक्ट करना

किसी ग्रुप के सदस्य डिवाइसों को बार-बार इस्तेमाल करने से, आपको अलग-अलग सदस्यों पर बेहतर कंट्रोल मिलता है. इससे, एक ही अनुरोध में निर्देशों को बैच में भेजा जा सकता है. साथ ही, सदस्यों के एट्रिब्यूट को एग्रीगेट किया जा सकता है या लिखा जा सकता है.

सबसे पहले, होम में मौजूद डिवाइसों को फ़िल्टर करें. इसके लिए, हर डिवाइस के GroupMembershipTrait में जाकर, टारगेट ग्रुप आईडी देखें:

let allDevices = try await home.devices().list()
var members: [HomeDevice] = []
for device in allDevices {
  if let membership = await device.traits.get(
    Google.GroupMembershipTrait.self
  ),
  membership.attributes.groupObjectIdsArray.contains(group.id) {
    members.append(device)
  }
}

किसी ग्रुप के साथ काम करने वाले सभी डिवाइसों पर, किसी विशेषता के लिए कमांड के साथ एक ही बैच वाला अनुरोध भेजने के लिए:

var onOffTraits: [Matter.OnOffTrait] = []
for device in members {
  if let light = await device.types.get(OnOffLightDeviceType.self),
     let onOff = light.matterTraits.onOffTrait {
    onOffTraits.append(onOff)
  }
}

let traitsToUse = onOffTraits
let responses = try await home.sendBatchedCommands { batcher in
  return try traitsToUse.map { batcher.add(try $0.onBatchable()) }
}

for response in responses {
  try response.getOrThrow()
}

आपके पास किसी ग्रुप में मौजूद, एक जैसे सभी डिवाइसों के लिए किसी एट्रिब्यूट को अपडेट करने का विकल्प भी होता है. उदाहरण के लिए, सभी DimmableLightDeviceType डिवाइसों पर onTransitionTime को 1 पर सेट करना. इसके बाद, तय समयसीमा के अंदर इसके पूरा होने का इंतज़ार करें:

try await withThrowingTaskGroup(of: Void.self) { taskGroup in
  taskGroup.addTask {
    try await Task.sleep(for: .seconds(5))
    throw CancellationError()
  }

  for device in members {
    taskGroup.addTask {
      guard let light = await device.types.get(DimmableLightDeviceType.self),
            let levelControl = light.matterTraits.levelControlTrait,
            levelControl.attributes.$onTransitionTime.isSupported
      else { return }
      _ = try await levelControl.update {
        $0.setOnTransitionTime(1)
      }
    }
  }

  for _ in 0..<members.count {
    try await taskGroup.next()
  }
  taskGroup.cancelAll()
}

किसी ग्रुप के सदस्यों के लिए किसी एट्रिब्यूट को एग्रीगेट करने के लिए, जैसे कि ग्रुप में मौजूद सभी कलर टेंपरेचर लाइट के लिए, कम से कम colorTempPhysicalMaxMireds का पता लगाना:

var maxMiredsValues: [UInt16] = []
for device in members {
  if let light = await device.types.get(ColorTemperatureLightDeviceType.self),
     let mireds = light.matterTraits.colorControlTrait?.attributes
       .colorTempPhysicalMaxMireds {
    maxMiredsValues.append(mireds)
  }
}
let minMaxMireds = maxMiredsValues.min()

डिवाइस ग्रुप बनाना

डिवाइस ग्रुप बनाने के लिए, स्ट्रक्चर पर GroupManagementTrait का इस्तेमाल करें:

let groupsManagementTrait =
  try await structure.traits(Google.GroupManagementTrait)
let _ = try await groupsManagementTrait.createUserDefinedGroup(
  withName: "Kitchen Lights",
  withDevices: [light1, light2]
)

ग्रुप की सदस्यता मैनेज करना

किसी मौजूदा ग्रुप में सदस्यों को जोड़ने के लिए:

let groupManagementTrait =
  try await structure.traits(Google.GroupManagementTrait.self)
groupManagementTrait.addGroupMembers(
  groupObjectId: group.id,
  memberDeviceObjectIds = [light3.id],
)

किसी ग्रुप से सदस्यों को हटाने के लिए:

let groupManagementTrait =
  try await structure.traits(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.removeGroupMembers(
  groupObjectId: group.id,
  memberDeviceObjectIdsArray: Array(removedIDs)
)

डिवाइस ग्रुप का नाम बदलना

किसी डिवाइस ग्रुप का नाम बदलने के लिए, GroupTrait के name फ़ील्ड को अपडेट करें:

let groupTrait = group.traits.get(Google.GroupTrait.self)
_ = try await groupTrait.update { $0.name = "Movie Corner" }

किसी डिवाइस ग्रुप को मिटाना

किसी स्ट्रक्चर से डिवाइस ग्रुप को मिटाने के लिए:

let groupManagementTrait =
  try await structure.traits.get(Google.GroupManagementTrait.self)

_ = try await groupManagementTrait.deleteGroup(groupObjectId: group.id)