iOS-এ ডিভাইস কন্ট্রোল করা

এই নির্দেশিকা iOS-এ ডিভাইস ও ডিভাইসের মেটাডেটা অ্যাক্সেস করা থেকে শুরু করে ডিভাইস কন্ট্রোল ও অ্যাক্সেসের অতিরিক্ত উদাহরণ দেয়।

নির্দিষ্ট ডিভাইসের ধরন বা বৈশিষ্ট্য ব্যবহার করতে, যেমন এখানে অনেক উদাহরণে ব্যবহৃত Matter OnOffTrait, সেগুলি অবশ্যই ইম্পোর্ট করতে হবে:

import GoogleHomeSDK
import GoogleHomeTypes

কোনও কমান্ডের ক্ষেত্রে কোনও বৈশিষ্ট্য কাজ করে কিনা তা চেক করুন

কোনও নির্দিষ্ট ডিভাইসের জন্য কমান্ড কাজ করে কিনা তা চেক করতে, ট্রেইট-লেভেল supports ফাংশন ব্যবহার করুন।

যেমন, কোনও ডিভাইসে চালু/বন্ধ করার বৈশিষ্ট্য toggle কমান্ড কাজ করে কিনা তা চেক করতে:

// Check if the OnOff trait supports the toggle command.
if onOffTraitTest.supportsToggleCommand {
  print("onOffTrait supports toggle command")
} else {
  print("onOffTrait does not support stateful toggle command")
}

ডিভাইসে কমান্ড পাঠানো

কমান্ড পাঠানো হল কোনও ট্রেট থেকে স্টেট অ্যাট্রিবিউট পড়ার মতো। ডিভাইস চালু বা বন্ধ করতে, OnOffTrait টগল কমান্ড ব্যবহার করুন, যা Google Home ইকোসিস্টেম ডেটা মডেলে toggle() হিসেবে সংজ্ঞায়িত করা আছে। এই পদ্ধতি onOff-কে false-এ পরিবর্তন করে যদি এটি true হয়, অথবা true-এ পরিবর্তন করে যদি এটি false হয়:

// Calling a command on a trait.
do {
  try await onOffTraitTest.toggle()
} catch let _ as HomeError {
  // Code for handling the exception
}

এক্সিকিউশন ফ্লোতে কোনও সমস্যা শনাক্ত করা হলে, কমান্ড ব্যতিক্রমী ফলাফল দেখাতে পারে। ডেভেলপার হিসেবে, এইসব ব্যতিক্রম সঠিকভাবে ম্যানেজ করতে আপনার do-catch ব্লক ব্যবহার করা উচিত এবং যেসব ক্ষেত্রে সমস্যার সমাধান করা সম্ভব, সেখানে ব্যবহারকারীদের বিস্তারিত তথ্য দেখানো উচিত। হ্যান্ডেল না করা ব্যতিক্রম অ্যাপ রানটাইম বন্ধ করে দেবে এবং এর ফলে আপনার অ্যাপ ক্র্যাশ করতে পারে।

অন্যথায়, স্পষ্টভাবে স্ট্যাটাস সেট করতে off() বা on() কমান্ড ব্যবহার করুন:

do {
  try await onOffTraitTest.off()
  try await onOffTraitTest.on()
} catch let _ as HomeError {
  // Code for handling the exception
}

স্ট্যাটাস পরিবর্তন করার জন্য কমান্ড পাঠানোর পরে, সেটি সম্পূর্ণ হলে, আপনার অ্যাপে এটি ম্যানেজ করার জন্য ডিভাইসের স্ট্যাটাস পড়ুন-এ যেমন বর্ণনা করা হয়েছে, সেই অনুযায়ী আপনি স্ট্যাটাস পড়তে পারবেন।

প্যারামিটার সহ কমান্ড পাঠান

কিছু কমান্ড প্যারামিটার ব্যবহার করতে পারে, যেমন OnOffTrait বা LevelControlTrait-এ থাকা প্যারামিটার:

offWithEffect

// Turn off the light using the DyingLight effect.
do {
  try await onOffTraitTest.offWithEffect(
    effectIdentifier: Matter.OnOffTrait.EffectIdentifierEnum.dyingLight,
    effectVariant: 0
  )
} catch let _ as HomeError {
  // Code for handling the exception
}

moveToLevel

// Change the brightness of the light to 50%
do {
  try await levelControlTraitTest.moveToLevel(
    level: UInt8(127),
    transitionTime: 0,
    optionsMask: Matter.LevelControlTrait.OptionsBitmap(),
    optionsOverride: Matter.LevelControlTrait.OptionsBitmap()
  )
} catch let _ as HomeError {
  // Code for handling the exception
}

কোনও অ্যাট্রিবিউটে কোনও ট্রেট কাজ করে কিনা তা চেক করুন

কিছু ডিভাইসে Matter ট্রেট কাজ করতে পারে, কিন্তু নির্দিষ্ট অ্যাট্রিবিউট কাজ নাও করতে পারে। যেমন, Matter-এর সাথে ম্যাপ করা Cloud-to-cloud ডিভাইসে Matter-এর সব অ্যাট্রিবিউট কাজ নাও করতে পারে। এই ধরনের কেস ম্যানেজ করতে, কোনও নির্দিষ্ট ডিভাইসের জন্য অ্যাট্রিবিউট কাজ করে কিনা তা চেক করতে, ট্রেইট-লেভেল isSupported প্রপার্টি ব্যবহার করুন।

যেমন, কোনও ডিভাইসে চালু/বন্ধ করার বৈশিষ্ট্য onOff অ্যাট্রিবিউট কাজ করে কিনা তা চেক করতে:

// Check if the OnOff trait supports the onOff attribute.
if onOffTrait.attributes.$onOff.isSupported {
  print("onOffTrait supports onOff state")
} else {
  print("onOffTrait is for a command only device!")
}

Matter স্পেসিফিকেশন বা Cloud-to-cloud smart home স্কিমায় কিছু অ্যাট্রিবিউট নালেবেল। এইসব অ্যাট্রিবিউটের ক্ষেত্রে, আপনি নির্ধারণ করতে পারবেন যে অ্যাট্রিবিউটের মাধ্যমে রিটার্ন করা nil ডিভাইস সেই ভ্যালু রিপোর্ট না করার কারণে হয়েছে নাকি অ্যাট্রিবিউটের ভ্যালু আসলে nil, isSupported-এর সাথে isNullable ব্যবহার করে:

// Check if a nullable attribute is set or is not supported.
if let deviceType = await device.types.get(OnOffLightDeviceType.self) {
  if let onOffTrait = deviceType.traits[Matter.OnOffTrait.self] {
    if onOffTrait.attributes.startUpOnOff == nil {
      if onOffTrait.attributes.$startUpOnOff.isSupported {
        print(
          "onOffTrait supports startUpOnOff and it is nil. Check the spec for the contextual meaning."
        )
      } else {
        print("onOffTrait does not support startUpOnOff!")
      }
    } else {
      print(
        "onOffTrait supports startUpOnOff and it is set to \(String(describing: onOffTrait.attributes.startUpOnOff))"
      )
    }
  }
}

বৈশিষ্ট্যের অ্যাট্রিবিউট আপডেট করুন

আপনি যদি কোনও অ্যাট্রিবিউটের ভ্যালু পরিবর্তন করতে চান এবং কোনও ট্রেটের কমান্ড যদি তা না করে, তাহলে অ্যাট্রিবিউটটি তার ভ্যালু স্পষ্টভাবে সেট করার সুবিধা দিতে পারে।

কোনও অ্যাট্রিবিউটের ভ্যালু পরিবর্তন করা যাবে কিনা তা দুটি বিষয়ের উপর নির্ভর করে:

  • অ্যাট্রিবিউট কি রাইট করা যাবে?
  • Can the value of the attribute change as a side effect of sending a trait command?

বৈশিষ্ট্য ও তাদের অ্যাট্রিবিউটের জন্য রেফারেন্স ডকুমেন্টেশন এই তথ্য প্রদান করে।

তাই, কোনও অ্যাট্রিবিউটের ভ্যালু কীভাবে পরিবর্তন করা যেতে পারে তা নির্ধারণ করে এমন প্রপার্টির কম্বিনেশনগুলি হল:

কোনও অ্যাট্রিবিউটের ভ্যালু পরিবর্তন করার জন্য আপডেট ফাংশন ব্যবহার করার উদাহরণ

এই উদাহরণে দেখানো হয়েছে কীভাবে DoorLockTrait.wrongCodeEntryLimit অ্যাট্রিবিউটের ভ্যালু স্পষ্টভাবে সেট করতে হয়।

অ্যাট্রিবিউট ভ্যালু সেট করতে, ট্রেইটের update ফাংশন কল করুন এবং এটিতে একটি আপডেট ফাংশন পাস করুন যা নতুন ভ্যালু সেট করে। প্রথমে বৈশিষ্ট্যটি কোনও অ্যাট্রিবিউটকে সমর্থন করে কিনা তা যাচাই করা একটি ভালো অভ্যাস।

যেমন:

if doorLockTraitTest.attributes.$wrongCodeEntryLimit.isSupported {
  let _ = try await doorLockTraitTest.update {
    $0.setWrongCodeEntryLimit(3)
  }
}

ডিভাইস গ্রুপ নিয়ন্ত্রণ করা

মেম্বার ডিভাইসের মাধ্যমে পুনরাবৃত্তি করে গ্রুপের প্রতিটি মেম্বারের উপর সূক্ষ্ম কন্ট্রোল ছাড়াও, আপনি একটি DeviceGroup-কে একটি এন্টিটি হিসেবে কন্ট্রোল করতে পারবেন। DeviceGroup HasParts প্রোটোকল মেনে চলে এবং গ্রুপের ডিভাইস দ্বারা সমর্থিত DeviceType অংশগুলি প্রকাশ করে:

  • await group.part(_:) নির্দিষ্ট করা প্রথম ইনস্ট্যান্স ফিরিয়ে দেয় DeviceType যদি গ্রুপ এটি সাপোর্ট করে, অথবা অন্যথায় nil।
  • try await group.parts(_:) নির্দিষ্ট DeviceType-এর সাথে ম্যাচ করা সব টপ-লেভেল পার্টের অ্যারে রিটার্ন করে।

আপনি DeviceGroup-এর অংশ হিসেবে কোনও ডিভাইস টাইপে ট্রেট কমান্ড ইনভোক করলে, SDK গ্রুপের সেইসব সংশ্লিষ্ট মেম্বার ডিভাইসে কমান্ড রিলে করে যেগুলি সেই ক্ষমতাকে সাপোর্ট করে, তাদের অন্তর্নিহিত কানেক্টিভিটি বা ট্রান্সপোর্ট (যেমন Matter বা Cloud-to-cloud) যাই হোক না কেন।

গ্রুপ পার্ট ট্রেট অ্যাট্রিবিউট ও সমস্যা সমাধান

গ্রুপের কোনও অংশকে টার্গেট করলে, সাধারণ ক্ষেত্রে কাজ সহজ হয়ে যায়। যেমন, আপনি কোনও গ্রুপে আইডেমপোটেন্ট কমান্ড (যেমন, আলো জ্বালানো বা নেভানো অথবা উজ্জ্বলতার লেভেল সেট করা) পাঠাতে চান। DeviceGroup পার্টে ট্রেট ও কমান্ড নিয়ে কাজ করার সময়, নিম্নলিখিত আচরণগুলি মনে রাখবেন:

  • ডাইনামিক স্টেট অ্যাট্রিবিউট (যেমন OnOffTrait-এর onOff অ্যাট্রিবিউট বা LevelControlTrait-এর currentLevel অ্যাট্রিবিউট) সাধারণত গ্রুপ পার্টের বৈশিষ্ট্যে পপুলেট করা হয় না কারণ গ্রুপের মেম্বার ডিভাইসগুলি বিভিন্ন স্টেটে থাকতে পারে যেগুলি একটি একক ভ্যালুতে একত্রিত করা যায় না। তবে, কাজ করে এমন কমান্ড (supports(_:)-এর মাধ্যমে চেক করা, যেমন .moveToLevelWithOnOff ডিম করা যায় এমন লাইটে) এবং বেছে নেওয়া অ্যাট্রিবিউট (যেমন colorTempPhysicalMinMireds এবং colorTempPhysicalMaxMireds ColorControlTrait-এ রঙিন লাইটের জন্য) পপুলেট করা হয় যাতে আপনার অ্যাপ UI কন্ট্রোল সঠিকভাবে কনফিগার করতে পারে।
  • গ্রুপের মেম্বারদের বৈশিষ্ট্যের উপর সব কমান্ড গ্রুপের অংশে উপলভ্য নয়। বিশেষ করে, যেসব কমান্ড ভ্যালু রিটার্ন করে সেগুলি উপলভ্য নয়।
  • গ্রুপের কোনও অংশে কমান্ড দিলে, তার মধ্যে থাকা প্রতিটি মেম্বার ডিভাইসের কমান্ডের জন্য আলাদা আলাদা ফলাফল পাওয়া যায় না। এক একটি কমান্ডের ফলাফল পরীক্ষা করতে বা ভ্যালু রিটার্ন করে এমন কমান্ড কল করতে, সরাসরি গ্রুপের মেম্বার ডিভাইসগুলির মাধ্যমে ইটারেট করুন।
  • DeviceGroup-এর কোনও অংশে পাঠানো কমান্ড তখনই সম্পূর্ণ হয় যখন মেম্বার ডিভাইস জুড়ে সম্পূর্ণ ফ্যানআউট শেষ হয় এবং সমস্ত অন্তর্নিহিত কমান্ডের সাফল্য বা ব্যর্থতা সংগ্রহ করা হয়। কোনও কমান্ড তখনই ব্যর্থ হয় (একটি HomeError দেখায়) যদি কমান্ডটি প্রতিটি সংশ্লিষ্ট মেম্বার ডিভাইসের জন্য ব্যর্থ হয় বা যদি সমস্ত টার্গেট ডিভাইস অনুপলভ্য থাকে, যা সিঙ্গেল-কমান্ড কল সিনট্যাক্সের সাথে মিলে যাওয়া সিঙ্গেল কমান্ড ব্যর্থতা হিসেবে দেখা যায়। অন্তত একটি মেম্বার ডিভাইস কমান্ডটি কার্যকর করলে, গ্রুপ কমান্ডটি কোনও সমস্যা ছাড়াই সম্পূর্ণ হয়।

গ্রুপের কোনও অংশে কমান্ড পাঠান

ডিভাইস গ্রুপের সব OnOffLightDeviceType লাইট চালু করতে:

if let lightPart = await group.part(OnOffLightDeviceType.self),
   let onOffTrait = lightPart.matterTraits.onOffTrait,
   onOffTrait.supports(.on) {
  try await onOffTrait.on()
}

এছাড়াও, আপনি একাধিক সম্পর্কিত ডিভাইসের ধরন চেক করতে পারেন (যেমন, গ্রুপে থাকা যেকোনও লাইট ডিভাইসের ধরন বন্ধ করা যা OnOffTrait কাজ করে):

func onOffTrait(in group: DeviceGroup) async -> Matter.OnOffTrait? {
  if let light = await group.part(OnOffLightDeviceType.self) {
    return light.matterTraits.onOffTrait
  }
  if let light = await group.part(DimmableLightDeviceType.self) {
    return light.matterTraits.onOffTrait
  }
  if let light = await group.part(ColorTemperatureLightDeviceType.self) {
    return light.matterTraits.onOffTrait
  }
  if let light = await group.part(ExtendedColorLightDeviceType.self) {
    return light.matterTraits.onOffTrait
  }
  return nil
}

if let trait = await onOffTrait(in: group) {
  try await trait.off()
}

আপনি কমান্ড পাঠানোর আগে কমান্ড সাপোর্ট চেক করতে বা গ্রুপের কোনও অংশের রিডিং ক্যাপাবিলিটি বাউন্ড চেক করতে পারেন (যেমন, আলো কমানো যায় এমন লাইটের অংশে .moveToLevelWithOnOff চেক করা বা কালার টেম্পারেচার লাইটের অংশে colorTempPhysicalMinMireds ও colorTempPhysicalMaxMireds চেক করা):

if let dimmableLight = await group.part(DimmableLightDeviceType.self),
   let levelTrait = dimmableLight.matterTraits.levelControlTrait,
   levelTrait.supports(.moveToLevelWithOnOff) {
  try await levelTrait.moveToLevelWithOnOff(
    level: 127,
    transitionTime: nil,
    optionsMask: [],
    optionsOverride: []
  )
}

if let colorLight = await group.part(ColorTemperatureLightDeviceType.self),
   let colorTrait = colorLight.matterTraits.colorControlTrait,
   let minMireds = colorTrait.attributes.colorTempPhysicalMinMireds,
   let maxMireds = colorTrait.attributes.colorTempPhysicalMaxMireds {
  let midMireds = UInt16((UInt32(minMireds) + UInt32(maxMireds)) / 2)
  try await colorTrait.moveToColorTemperature(
    colorTemperatureMireds: midMireds,
    transitionTime: 0,
    optionsMask: [],
    optionsOverride: []
  )
}