Android के लिए डिवाइस और डिवाइस का मेटाडेटा ऐक्सेस करना

डिवाइस एपीआई को Android के लिए Home APIs की मदद से ऐक्सेस किया जा सकता है. इन पैकेज को अपने ऐप्लिकेशन में इंपोर्ट करें:

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

Device API के साथ किसी खास तरह के डिवाइस या विशेषताओं का इस्तेमाल करने के लिए, उन्हें अलग-अलग इंपोर्ट करना ज़रूरी है.

उदाहरण के लिए, Matter On/Off trait और On/Off Plug-in Unit device type का इस्तेमाल करने के लिए, अपने ऐप्लिकेशन में ये पैकेज इंपोर्ट करें:

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

ज़्यादा जानकारी के लिए, Android पर डेटा मॉडल लेख पढ़ें.

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

Home API में मौजूद कोई भी तरीका, HomeException को थ्रो कर सकता है. इसलिए, हमारा सुझाव है कि आप सभी कॉल पर HomeException को कैच करने के लिए, try-catch ब्लॉक का इस्तेमाल करें.

HomeException को हैंडल करते समय, गड़बड़ी के बारे में जानने के लिए इसके error.code और error.message फ़ील्ड देखें. गड़बड़ी के सब-कोड भी हो सकते हैं. इसलिए, getSubErrorCodes() तरीके को कॉल करें और नतीजा देखें.

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

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

उदाहरण के लिए, किसी डिवाइस को निर्देश भेजना देखें.

सैंपल कॉल

डिवाइसों की सूची देखना

Structure इंस्टेंस का रेफ़रंस मिलने के बाद, devices() कॉल से उन डिवाइसों की Flow मिलती है जिन्हें उस स्ट्रक्चर से ऐक्सेस किया जा सकता है:

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

वहां से, हर डिवाइस की स्थिति को ऐक्सेस किया जा सकता है और डिवाइसों को निर्देश भेजे जा सकते हैं.

Home APIs के 1.8 वर्शन में, आपके पास यह विकल्प होता है कि एपीआई, कई हिस्सों वाले हर डिवाइस को एक डिवाइस के तौर पर दिखाए. इसके लिए, devices() तरीके के enableMultipartDevices पैरामीटर को true पर सेट करें. ज़्यादा जानकारी के लिए, Android पर मल्टीपार्ट डिवाइस देखें.

डिवाइस की स्थिति देखना

डिवाइस की चालू/बंद करने की विशेषता से, OnOff एट्रिब्यूट की जाँच करने का उदाहरण देखें. Home APIs के ट्रेट डेटा मॉडल का इस्तेमाल करके, इस ट्रेट की पहचान OnOff के तौर पर की जाती है. डिवाइस टाइप की standardTraits क्लास की मदद से, ट्रेट का डेटा वापस पाया जा सकता है:

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

Kotlin फ़्लो फ़ंक्शन के बारे में ज़्यादा जानने के लिए, distinctUntilChanged देखें.

किसी ट्रेट की सदस्यता में अमान्य स्थिति

TraitStateInvalidation इंटरफ़ेस की मदद से, टारगेट डिवाइस की सदस्यता से मिली स्थिति को अमान्य किया जा सकता है. ऐसा तब किया जाता है, जब स्थिति की जानकारी सही तरीके से न दी जा रही हो. स्थिति की जानकारी सही तरीके से न मिलने के उदाहरणों में, Matter ट्रेट में "C" क्वालिटी वाले एट्रिब्यूट का इस्तेमाल करना या डिवाइस को लागू करने की वजह से अचानक समस्या आना शामिल है.

यह एपीआई, मौजूदा विशेषता की स्थिति को ज़बरदस्ती पढ़ने का निर्देश देता है. साथ ही, मौजूदा विशेषता के फ़्लो के ज़रिए नतीजा दिखाता है.

ट्रेट पाएं. इसके बाद, ट्रेट पर forceRead चलाएं:

val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()

डिवाइस टाइप की विशेषताओं की सूची पाना

डिवाइस के टाइप का इस्तेमाल, विशेषताओं को पढ़ने के लिए एंट्री पॉइंट के तौर पर किया जाना चाहिए. ऐसा इसलिए, क्योंकि वे डिवाइस को उसके काम करने वाले हिस्सों में बांटते हैं. जैसे, Matter में एंडपॉइंट.

ये विशेषता के टकराव को भी ध्यान में रखते हैं. ऐसा तब होता है, जब किसी डिवाइस में दो तरह के डिवाइस टाइप हों और दोनों में एक जैसी विशेषता हो. उदाहरण के लिए, अगर कोई डिवाइस स्पीकर और डिम होने वाली लाइट, दोनों है, तो उसमें दो On/Off और दो Level Control ट्रेट होंगे.

Dimmable Light डिवाइस टाइप के लिए उपलब्ध ट्रेट की सूची पाने के लिए:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

ट्रेट कोलिज़न तब भी हो सकता है, जब किसी डिवाइस में एक ही नाम के दो ट्रेट हों. उदाहरण के लिए, onOff, स्टैंडर्ड OnOff ट्रेट के किसी इंस्टेंस या मैन्युफ़ैक्चरर के तय किए गए OnOff ट्रेट के किसी इंस्टेंस को रेफ़र कर सकता है. किसी डिवाइस से रेफ़रंस किए गए Trait इंस्टेंस से पहले, ज़रूरी शर्तें पूरी करने वाला नेमस्पेस होना चाहिए. इससे, यह साफ़ तौर पर पता चल पाएगा कि किस विशेषता का इस्तेमाल किया जाना है. स्टैंडर्ड विशेषताओं के लिए, यानी कि Matter स्टैंडर्ड क्लस्टर से मिलती-जुलती विशेषताओं के लिए, standardTraits का इस्तेमाल करें. Google की विशेषताओं के लिए, googleTraits का इस्तेमाल करें:

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

मैन्युफ़ैक्चरर के हिसाब से तय की गई किसी सुविधा को ऐक्सेस करने के लिए, उसे सीधे रेफ़र करें:

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

किसी खास विशेषता वाले डिवाइसों की सूची पाना

Kotlin में filter फ़ंक्शन का इस्तेमाल करके, एपीआई कॉल को और बेहतर बनाया जा सकता है. उदाहरण के लिए, घर में मौजूद उन सभी डिवाइसों की सूची पाने के लिए जिनमें चालू/बंद करने की सुविधा है:

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

Home APIs में उपलब्ध सभी ट्रेट की सूची देखने के लिए, Trait इंटरफ़ेस देखें.

एक जैसे डिवाइस टाइप वाले डिवाइसों की सूची पाना

घर की सभी लाइटों को दिखाने वाले डिवाइसों की सूची पाने के लिए:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

Home APIs में कई तरह के डिवाइस टाइप मौजूद हैं, जो किसी मुख्य डिवाइस टाइप को दिखा सकते हैं. उदाहरण के लिए, "लाइट" नाम का कोई डिवाइस टाइप नहीं है. इसके बजाय, चार अलग-अलग तरह के डिवाइस हैं जो लाइट को दिखा सकते हैं, जैसा कि पिछले उदाहरण में दिखाया गया है. इसलिए, किसी घर में मौजूद डिवाइसों के टाइप की पूरी जानकारी पाने के लिए, फ़िल्टर किए गए फ़्लो में कई तरह के डिवाइसों को शामिल करना ज़रूरी है.

Home APIs में उपलब्ध डिवाइस टाइप की पूरी सूची देखने के लिए, DeviceType इंटरफ़ेस देखें.

किसी डिवाइस के लिए वेंडर आईडी या प्रॉडक्ट आईडी पाना

BasicInformation ट्रेट में, किसी डिवाइस के वेंडर आईडी, प्रॉडक्ट आईडी, प्रॉडक्ट का नाम, और सीरियल नंबर जैसी जानकारी शामिल होती है:

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

डिवाइस मैन्युफ़ैक्चरर के लिए, क्लाउड-टू-क्लाउड डिवाइस की पहचान करना

अगर आप डिवाइस बनाने वाली कंपनी हैं और Cloud-to-cloud डिवाइस बनाती हैं, तो BasicInformation ट्रेट की मदद से अपने Cloud-to-cloud डिवाइसों की पहचान करने के लिए, इन स्ट्रिंग फ़ील्ड को उनके SYNC रिस्पॉन्स में शामिल किया जा सकता है:

  • Connectivity Standards Alliance (Alliance) की ओर से जारी किया गया वेंडर आईडी: "matterOriginalVendorId": "0xfff1",

  • प्रॉडक्ट आइडेंटिफ़ायर, जो किसी वेंडर के प्रॉडक्ट की खास तौर पर पहचान करता है: "matterOriginalProductId": "0x1234",

  • डिवाइस के लिए एक यूनीक आइडेंटिफ़ायर, जिसे मैन्युफ़ैक्चरर के हिसाब से बनाया जाता है: "matterUniqueId": "matter-device-id",

इन स्ट्रिंग फ़ील्ड को डालते समय, अपने Matter वेंडर और प्रॉडक्ट आईडी का इस्तेमाल करें, अगर आपके पास ये हैं. अगर आप Alliance के सदस्य नहीं हैं और आपको ये आईडी असाइन नहीं किए गए हैं, तो matterOriginalVendorId और matterOriginalProductId फ़ील्ड को खाली छोड़ा जा सकता है. साथ ही, आइडेंटिफ़ायर के तौर पर matterUniqueId दिया जा सकता है.

SYNC के जवाब के उदाहरण में, इन फ़ील्ड का इस्तेमाल दिखाया गया है:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

ज़्यादा जानकारी के लिए, Cloud-to-cloud SYNC दस्तावेज़ देखें.

डिवाइस और ट्रेट का मेटाडेटा

Home APIs में मौजूद डिवाइसों और उनकी विशेषताओं से जुड़ा मेटाडेटा होता है. इससे किसी ऐप्लिकेशन में उपयोगकर्ता अनुभव को मैनेज करने में मदद मिल सकती है.

Home APIs में मौजूद हर trait में एक sourceConnectivity प्रॉपर्टी होती है. इसमें trait के ऑनलाइन स्टेटस और लोकैलिटी (लोकल या रिमोट रूटिंग) की जानकारी होती है.

किसी डिवाइस के मुख्य टाइप की जानकारी पाना

कुछ डिवाइसों में, Home APIs के ज़रिए कई तरह के डिवाइसों की जानकारी दिख सकती है. यह पक्का करने के लिए कि उपयोगकर्ताओं को किसी ऐप्लिकेशन में उनके डिवाइसों के लिए सही विकल्प (जैसे, डिवाइस कंट्रोल और सुझाए गए ऑटोमेशन) दिखाए जाएं, यह देखना ज़रूरी है कि किसी डिवाइस का मुख्य टाइप क्या है.

सबसे पहले, type() का इस्तेमाल करके, डिवाइस के टाइप की जानकारी पाएं. इसके बाद, मुख्य टाइप तय करें:

val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }

यह देखना कि कोई trait ऑनलाइन है या नहीं

किसी विशेषता की कनेक्टिविटी की जांच करने के लिए, connectivityState() तरीके का इस्तेमाल करें:

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

अगर डिवाइस में इंटरनेट कनेक्टिविटी नहीं है, तो कुछ विशेषताएं ऑफ़लाइन दिख सकती हैं. आम तौर पर, Google smart home की विशेषताएं ऑफ़लाइन दिखती हैं. ऐसा इसलिए है, क्योंकि ये ट्रेट क्लाउड-आधारित होते हैं और इनमें लोकल रूटिंग की सुविधा नहीं होती.

किसी डिवाइस के लिए कनेक्टिविटी की जांच करना

किसी डिवाइस की कनेक्टिविटी की जांच, डिवाइस टाइप के लेवल पर की जाती है. ऐसा इसलिए, क्योंकि कुछ डिवाइसों पर कई तरह के डिवाइस टाइप काम करते हैं. डिवाइस की स्थिति, उस डिवाइस पर मौजूद सभी विशेषताओं के लिए कनेक्टिविटी की स्थितियों का कॉम्बिनेशन होती है.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

अगर इंटरनेट कनेक्टिविटी नहीं है, तो अलग-अलग तरह के डिवाइसों के मामले में PARTIALLY_ONLINE की स्थिति देखी जा सकती है. लोकल रूटिंग की वजह से, Matter स्टैंडर्ड ट्रेट अब भी ऑनलाइन हो सकते हैं. हालांकि, क्लाउड-आधारित ट्रेट ऑफ़लाइन होंगे.

डिवाइस का आईपी पता पाना

डिवाइस का आईपी पता ढूंढने के लिए, GeneralDiagnostics ट्रेट के networkInterfaces एट्रिब्यूट का इस्तेमाल करें. पते, बाइट कलेक्शन के तौर पर दिखाए जाते हैं. इन्हें स्टैंडर्ड IPv4 या IPv6 स्ट्रिंग में फ़ॉर्मैट किया जा सकता है:

val ipAddresses =
  trait.networkInterfaces?.flatMap { networkInterface ->
    (networkInterface.ipv4Addresses + networkInterface.ipv6Addresses).mapNotNull { bytes ->
      try {
        java.net.InetAddress.getByAddress(bytes).hostAddress
      } catch (e: java.net.UnknownHostException) {
        null
      }
    }
  } ?: emptyList()

किसी ट्रेट की नेटवर्क रूटिंग देखना

किसी trait के लिए locality की जानकारी, Home APIs में भी उपलब्ध होती है. dataSourceLocality से पता चलता है कि विशेषता को क्लाउड के ज़रिए, लोकल हब के ज़रिए या पीयर-टू-पीयर (सीधे डिवाइस से डिवाइस पर, कोई हब नहीं) के ज़रिए रूट किया गया है या नहीं.

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

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

किसी डिवाइस के लिए नेटवर्क रूटिंग की जांच करना

कनेक्टिविटी की तरह ही, डिवाइस के टाइप के लेवल पर स्थानीयता की जांच की जाती है. स्टेटस के तौर पर, उस डिवाइस पर मौजूद सभी विशेषताओं की लोकैलिटी का कॉम्बिनेशन दिखता है.

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

MIXED की स्थिति, PARTIALLY_ONLINE कनेक्टिविटी की तरह ही देखी जा सकती है: कुछ विशेषताएं क्लाउड-आधारित होती हैं, जबकि अन्य स्थानीय होती हैं.

किसी डिवाइस का नाम बदलना

किसी डिवाइस का नाम बदलने के लिए, setName() तरीके को कॉल करें:

mixerDevice.setName("Grendel")

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

यह देखना कि कोई डिवाइस किस ग्रुप का सदस्य है

कोई फ़िज़िकल डिवाइस, एक या उससे ज़्यादा डिवाइस ग्रुप का हिस्सा हो सकता है. यह देखने के लिए कि कोई डिवाइस किन ग्रुप में शामिल है, उस डिवाइस पर GroupMembership ट्रेट देखें:

val groupIds = device.trait(GroupMembershipTrait)?.groupObjectIds.orEmpty()
for (groupId in groupIds) {
  println("HomeAPI", "Device belongs to group: $groupId")
}

इसके अलावा, DeviceGroup पर devices() फ़्लो को कॉल करके, DeviceGroup से जुड़े सभी सदस्य डिवाइसों को देखा जा सकता है:

group.devices(enableMultipartDevices = true).collect { members ->
  println("HomeAPI", "Group contains ${members.size} devices")
}

DeviceGroup के साथ काम करने वाले डिवाइस टाइप की जांच करने और ग्रुप को एक इकाई के तौर पर निर्देश भेजने के लिए, डिवाइस ग्रुप को कंट्रोल करना लेख पढ़ें.