১. শুরু করার আগে
গুগল হোম এপিআইগুলি অ্যান্ড্রয়েড ডেভেলপারদের গুগল হোম ইকোসিস্টেমে প্রবেশের জন্য একগুচ্ছ লাইব্রেরি প্রদান করে। এই নতুন এপিআইগুলির সাহায্যে, ডেভেলপাররা এমন অ্যাপ তৈরি করতে পারে যা নির্বিঘ্নে স্মার্ট হোম ডিভাইসগুলিকে কমিশন এবং নিয়ন্ত্রণ করে।
এই ভিডিওটিতে আপনি যে মোবাইল অ্যাপটি তৈরি করবেন তার একটি সংক্ষিপ্ত ওয়াকথ্রু প্রদান করা হয়েছে, তাই কোডল্যাবটি করার সময় ভিডিওটি অনুসরণ করুন।
গুগল হোম এপিআই ব্যবহার করে কার্যকরী উদাহরণ অ্যাক্সেস করতে চান এমন ডেভেলপারদের জন্য গুগল একটি অ্যান্ড্রয়েড স্যাম্পল অ্যাপ প্রদান করে। এই কোডল্যাবটি স্যাম্পল অ্যাপের একটি শাখার উপর ভিত্তি করে তৈরি যা আপনাকে অনুমতি, কমিশনিং, ডিভাইস এবং স্ট্রাকচার এপিআই কীভাবে ব্যবহার করতে হয় তা ব্যাখ্যা করে।
পূর্বশর্ত
- গুগল হোম ইকোসিস্টেম সম্পর্কে জ্ঞান ( ক্লাউড-টু-ক্লাউড এবং ম্যাটার )।
- অ্যান্ড্রয়েড স্টুডিও (২০২৪.৩.১ লেডিবাগ বা তার পরবর্তী) ইনস্টল করা একটি ওয়ার্কস্টেশন।
- এমন একটি অ্যান্ড্রয়েড ফোন যা হোম এপিআই-এর প্রয়োজনীয়তা পূরণ করে ( পূর্বশর্ত দেখুন) এবং গুগল প্লে পরিষেবা এবং গুগল হোম অ্যাপ ইনস্টল করা আছে। একটি এমুলেটর কাজ করবে না , নমুনা অ্যাপের জন্য শুধুমাত্র ফিজিক্যাল অ্যান্ড্রয়েড ফোনগুলি সমর্থিত।
- একটি সামঞ্জস্যপূর্ণ গুগল হোম হাব যা গুগল হোম এপিআই সমর্থন করে।
- ঐচ্ছিক - গুগল হোম এপিআই-এর সাথে সামঞ্জস্যপূর্ণ একটি স্মার্ট হোম ডিভাইস।
তুমি কি শিখবে
- সেরা অনুশীলন সহ গুগল হোম এপিআই ব্যবহার করে কীভাবে একটি অ্যান্ড্রয়েড অ্যাপ তৈরি করবেন।
- একটি স্মার্ট হোম উপস্থাপন এবং নিয়ন্ত্রণ করতে ডিভাইস এবং স্ট্রাকচার API কীভাবে ব্যবহার করবেন।
- গুগল হোম ইকোসিস্টেমে ডিভাইস যোগ করার জন্য কমিশনিং এপিআই কীভাবে ব্যবহার করবেন।
ঐচ্ছিক: আপনার বাড়ি সেট আপ করুন
গুগল হোম এপিআই ব্যবহার করার আগে, আপনাকে গুগল হোম অ্যাপ ব্যবহার করে আপনার গুগল অ্যাকাউন্টে একটি হোম সেট আপ করতে হবে এবং কয়েকটি ডিভাইস যুক্ত করতে হবে। এই বিভাগে ভার্চুয়াল স্মার্ট হোম ডিভাইস সরবরাহকারী গুগল হোম প্লেগ্রাউন্ড ব্যবহার করে এটি কীভাবে করবেন তা আলোচনা করা হয়েছে।
আপনার ওয়েব ব্রাউজারে home-playground.withgoogle.com খুলুন, আপনার গুগল অ্যাকাউন্ট দিয়ে সাইন ইন করুন এবং দেখুন নিম্নলিখিত অনুকরণ করা ডিভাইসগুলি প্রদর্শিত হচ্ছে কিনা:
- আউটলেট ১: চালু/বন্ধ প্লাগ
- আলো২: ডিমেবল আলো
- light3: চালু/বন্ধ আলো
- ac3: এয়ার কন্ডিশনার
- ব্লাইন্ডস৪: জানালার আচ্ছাদন
- ওয়াশার৫: স্মার্ট ওয়াশার

আপনার মোবাইল ডিভাইসে Google Home অ্যাপটি খুলুন, Add বোতামে ট্যাপ করুন এবং Works with Google Home নির্বাচন করুন। তালিকায় "playground" অনুসন্ধান করুন, তারপর "Google Home Playground" প্রকল্পটি নির্বাচন করুন এবং Continue এ ট্যাপ করুন।



গুগল হোম প্লেগ্রাউন্ড আপনাকে একটি অ্যাকাউন্ট অনুমোদন পৃষ্ঠা দেখাবে। অনুমোদন করুন অথবা গুগল দিয়ে সাইন ইন করুন এ আলতো চাপুন। আপনি ওয়েব অ্যাপ থেকে কনফিগার করা সমস্ত ডিভাইস মোবাইল অ্যাপে দেখতে পাবেন।


সমস্ত ডিভাইস নির্বাচন করুন এবং সেটআপ প্রক্রিয়াটি সম্পূর্ণ করুন। হোম পেজে ফিরে গেলে, আপনি সমস্ত উপলব্ধ ডিভাইস দেখতে পাবেন।

তালিকার সমর্থিত ডিভাইসগুলি এখন Google Home API-এর সাথে ব্যবহারের জন্য উপলব্ধ।
2. আপনার প্রকল্প সেট আপ করুন
নিম্নলিখিত চিত্রটি একটি হোম এপিআই অ্যাপের আর্কিটেকচার চিত্রিত করে:

- অ্যাপ কোড: অ্যাপের ইউজার ইন্টারফেস এবং হোম এপিআই SDK এর সাথে ইন্টারঅ্যাক্ট করার জন্য যুক্তি তৈরি করতে ডেভেলপাররা যে মূল কোডের উপর কাজ করে।
- হোম এপিআই এসডিকে: গুগল কর্তৃক প্রদত্ত হোম এপিআই এসডিকে স্মার্ট হোম ডিভাইসগুলি নিয়ন্ত্রণ করার জন্য জিএমএসকোরে হোম এপিআই পরিষেবার সাথে কাজ করে। ডেভেলপাররা হোম এপিআই এসডিকে বান্ডেল করে হোম এপিআইগুলির সাথে কাজ করে এমন অ্যাপ তৈরি করে।
- অ্যান্ড্রয়েডে GMScore: GMScore, যা গুগল প্লে সার্ভিসেস নামেও পরিচিত, একটি গুগল প্ল্যাটফর্ম যা মূল সিস্টেম পরিষেবা প্রদান করে, যা সমস্ত সার্টিফাইড অ্যান্ড্রয়েড ডিভাইসে মূল কার্যকারিতা সক্ষম করে। গুগল প্লে সার্ভিসেসের হোম মডিউলে এমন পরিষেবা রয়েছে যা হোম API গুলির সাথে ইন্টারঅ্যাক্ট করে।
হোম SDK সেট আপ করুন
সর্বশেষ SDK পেতে Set up the SDK- তে বর্ণিত ধাপগুলি অনুসরণ করুন।
নমুনা অ্যাপটি পান
স্যাম্পল অ্যাপের সোর্স কোডটি GitHub-এ পাওয়া যায়। এই কোডল্যাবটি স্যাম্পল অ্যাপের codelab-branch-1 শাখার উদাহরণ ব্যবহার করে।
আপনি যেখানে প্রকল্পটি সংরক্ষণ করতে চান সেখানে নেভিগেট করুন এবং codelab-branch-1 শাখাটি ক্লোন করুন:
$ git clone -b codelab-branch-1 https://github.com/google-home/google-home-api-sample-app-android.git
নমুনা অ্যাপ তৈরি করুন
অ্যাপ তৈরিতে ১-৫ ধাপ সম্পাদন করুন।

যখন আপনার ফোনে অ্যাপটি সফলভাবে চলছে, তখন আপনি Sample App এর মূল পৃষ্ঠাটি দেখতে পাবেন। কিন্তু আপনি OAuth প্রমাণীকরণ সেট আপ না করা এবং Permission API ব্যবহার করে অনুপস্থিত অংশগুলি বাস্তবায়ন না করা পর্যন্ত সাইন ইন করতে পারবেন না।
৩. প্রমাণীকরণ সেট আপ করুন
হোম এপিআইগুলি কাঠামোর মধ্যে থাকা ডিভাইসগুলিতে অ্যাক্সেস প্রদানের জন্য OAuth 2.0 ব্যবহার করে। OAuth ব্যবহারকারীকে তাদের লগইন শংসাপত্রগুলি প্রকাশ না করেই কোনও অ্যাপ বা পরিষেবাতে অনুমতি প্রদানের অনুমতি দেয়।
সম্মতি স্ক্রিন কনফিগার করতে OAuth সম্মতি সেট আপ করুন -এর নির্দেশাবলী অনুসরণ করুন। কমপক্ষে একটি পরীক্ষা অ্যাকাউন্ট তৈরি করতে ভুলবেন না।
তারপর অ্যাপের জন্য শংসাপত্র তৈরি করতে OAuth শংসাপত্র সেট আপ করুন -এর নির্দেশাবলী অনুসরণ করুন।
৪. আরম্ভ এবং পরিচালনার অনুমতি
এই বিভাগে, আপনি শিখবেন কিভাবে SDK চালু করতে হয় এবং Permissions API ব্যবহার করে অনুপস্থিত অংশগুলি পূরণ করে ব্যবহারকারীর অনুমতিগুলি পরিচালনা করতে হয়।
সমর্থিত প্রকার এবং বৈশিষ্ট্য সংজ্ঞায়িত করুন
একটি অ্যাপ তৈরি করার সময়, আপনাকে স্পষ্টভাবে নোট করতে হবে যে অ্যাপটি কোন ডিভাইসের ধরণ এবং বৈশিষ্ট্যগুলিকে সমর্থন করবে। Sample App-এ, আমরা HomeApp.kt এর companion object-এ স্ট্যাটিক তালিকা সংজ্ঞায়িত করে এটি করি, যা প্রয়োজন অনুসারে অ্যাপ জুড়ে উল্লেখ করা যেতে পারে:
companion object {
// List of supported device types by this app:
val supportedTypes: List<DeviceTypeFactory<out DeviceType>> = listOf(
OnOffLightDevice,
DimmableLightDevice,
// ...
)
// List of supported device traits by this app:
val supportedTraits: List<TraitFactory<out Trait>> = listOf(
OnOff,
LevelControl,
// ...
)
}
সমস্ত সমর্থিত ডিভাইসের ধরণ এবং বৈশিষ্ট্য দেখতে Android-এ সমর্থিত ডিভাইসের ধরণ এবং বৈশিষ্ট্য সূচক দেখুন।
অনুমতির অনুরোধকারী সোর্স কোড সক্রিয় করতে HomeApp.kt সোর্স ফাইলে ধাপ 4.1.1 এবং 4.1.2 থেকে মন্তব্য সরিয়ে দিন।
companion object {
// List of supported device types by this app:
val supportedTypes: List<DeviceTypeFactory<out DeviceType>> = listOf(
// TODO: 4.1.1 - Non-registered device types will be unsupported
// ContactSensorDevice,
// ColorTemperatureLightDevice,
// DimmableLightDevice,
// ExtendedColorLightDevice,
// GenericSwitchDevice,
// GoogleDisplayDevice,
// GoogleTVDevice,
// OccupancySensorDevice,
// OnOffLightDevice,
// OnOffLightSwitchDevice,
// OnOffPluginUnitDevice,
// OnOffSensorDevice,
// RootNodeDevice,
// SpeakerDevice,
// ThermostatDevice,
)
// List of supported device traits by this app:
val supportedTraits: List<TraitFactory<out Trait>> = listOf(
// TODO: 4.1.2 - Non-registered traits will be unsupported
// AreaAttendanceState,
// AreaPresenceState,
// Assistant,
// AssistantBroadcast,
// AssistantFulfillment,
// BasicInformation,
// BooleanState,
// OccupancySensing,
// OnOff,
// Notification,
// LevelControl,
// TemperatureControl,
// TemperatureMeasurement,
// Thermostat,
// Time,
// Volume,
)
}
হোমক্লায়েন্ট অবজেক্টটি আরম্ভ করুন
হোম এপিআই ব্যবহারকারী সকল অ্যাপ একটি HomeClient অবজেক্ট ইনিশিয়ালাইজ করে, যা এপিআইগুলির সাথে ইন্টারঅ্যাক্ট করার জন্য প্রধান ইন্টারফেস। আমরা এই অবজেক্টটি HomeApp ( HomeApp.kt ) ক্লাসের ইনিশিয়ালাইজারে প্রস্তুত করি।
// Registry to record device types and traits used in this app:
val registry = FactoryRegistry(
types = supportedTypes,
traits = supportedTraits
)
// Configuration options for the HomeClient:
val config = HomeConfig(
coroutineContext = Dispatchers.IO,
factoryRegistry = registry
)
// Initialize the HomeClient, which is the primary object to use all Home APIs:
homeClient = Home.getClient(context = context, homeConfig = config)
প্রথমে, আমরা পূর্বে সংজ্ঞায়িত সমর্থিত প্রকার এবং বৈশিষ্ট্যগুলি ব্যবহার করে একটি FactoryRegistry তৈরি করি। তারপর, এই রেজিস্ট্রি ব্যবহার করে, আমরা একটি HomeConfig ইনিশিয়ালাইজ করি, যাতে API গুলি চালানোর জন্য প্রয়োজনীয় কনফিগারেশন থাকে। এরপর আমরা HomeClient ইনস্ট্যান্স অর্জন করতে Home.getClient(...) কল ব্যবহার করি।
হোম এপিআই-এর সাথে আমাদের সমস্ত মিথস্ক্রিয়া এই HomeClient অবজেক্টের মাধ্যমে হবে।
অনুমতি API ব্যবহার করুন
হোম এপিআইগুলির জন্য ব্যবহারকারীর প্রমাণীকরণ Permissions API এর মাধ্যমে করা হয়। Sample App এর PermissionsManager.kt সোর্স ফাইলে ব্যবহারকারীর প্রমাণীকরণের জন্য কোড থাকে। Sample অ্যাপের জন্য অনুমতিগুলি সক্ষম করতে checkPermissions(...) এবং requestPermissions(...) ফাংশনের বিষয়বস্তুগুলি মন্তব্যমুক্ত করুন।
নিবন্ধন:
homeClient.registerActivityResultCallerForPermissions(activity)
চালু হচ্ছে:
try {
val result: PermissionsResult
result = homeClient.requestPermissions(forceLaunch = true)
when (result.status) {
PermissionsResultStatus.SUCCESS -> // Success Case
PermissionsResultStatus.CANCELLED -> // User Cancelled
PermissionsResultStatus.ERROR -> // Some Error
else -> // Unsupported Case
}
}
catch (e: HomeException) { ... }
পরীক্ষা করা হচ্ছে:
try {
val state: PermissionsState
state = homeClient.hasPermissions().first { state ->
state != PermissionsState.PERMISSIONS_STATE_UNINITIALIZED
}
when (state) {
PermissionsState.GRANTED -> // Signed In
PermissionsState.NOT_GRANTED -> // Not Signed In
PermissionsState.PERMISSIONS_STATE_UNAVAILABLE -> // ...
PermissionsState.PERMISSIONS_STATE_UNINITIALIZED -> // ...
else -> // Unsupported case
}
}
catch (e: HomeException) { ... }
সাবস্ক্রাইব করা:
homeClient.hasPermissions().collect( { state ->
// Track the changes on state
} )
অনুমতির অনুরোধকারী কোডটি সক্রিয় করতে PermissionsManager.kt এ ধাপ 4.3.1-এ মন্তব্য মুক্ত করুন:
fun requestPermissions() {
scope.launch {
try {
// TODO: 4.3.1 - Request the permissions from the Permissions API
// // Request permissions from the Permissions API and record the result:
// val result: PermissionsResult = client.requestPermissions(forceLaunch = true)
// // Adjust the sign-in status according to permission result:
// if (result.status == PermissionsResultStatus.SUCCESS)
// isSignedIn.emit(true)
// // Report the permission result:
// reportPermissionResult(result)
}
catch (e: HomeException) { MainActivity.showError(this, e.message.toString()) }
}
}
এবার আপনার ফোনে অ্যাপটি চালান, ধাপগুলি অনুসরণ করুন এবং অনুমতিগুলি দিন। আপনি নিম্নলিখিত প্রবাহটি দেখতে পাবেন:





"লোড হচ্ছে" বার্তাটি কখনই চলে যায় না, কিন্তু এর কারণ হল আমরা কাঠামো এবং ডিভাইসগুলি পড়ার কোডটি বাস্তবায়ন করিনি। আমরা পরবর্তী বিভাগে এটি করব।
৫. ডেটা মডেলটি বুঝুন
হোম এপিআই-তে, ডেটা মডেলটি গঠিত হয়:
-
Structureএমন একটি বাড়ির প্রতিনিধিত্ব করে যেখানে ঘর এবং যন্ত্রপাতি রয়েছে। -
Roomএকটি কাঠামোর একটি অংশ এবং এতে ডিভাইস রয়েছে। - ডিভাইসগুলি (
HomeDeviceহিসাবে সংজ্ঞায়িত) একটি কাঠামো (অথবা বাড়ি) বা কাঠামোর একটি কক্ষে বরাদ্দ করা যেতে পারে। - ডিভাইসগুলি এক বা একাধিক
DeviceTypeদৃষ্টান্ত দিয়ে গঠিত। -
DeviceTypeTraitইনস্ট্যান্স দিয়ে গঠিত। -
TraitহলAttributeinstances (পড়া/লেখার জন্য),Commandinstances (বৈশিষ্ট্য নিয়ন্ত্রণের জন্য), এবংEventinstances (অতীতের পরিবর্তনের রেকর্ড পড়ার বা সাবস্ক্রাইব করার জন্য) দিয়ে গঠিত। -
Automationইনস্ট্যান্সগুলি একটি কাঠামোর অংশ এবং বাড়ির কাজগুলি স্বয়ংক্রিয় করতে হোম মেটাডেটা এবং ডিভাইসগুলি ব্যবহার করে।

এই বিভাগে, আপনি শিখবেন কিভাবে সোর্স কোড তৈরি করতে হয় এবং স্ট্রাকচার API ব্যবহার করে আপনার বাড়ির কাঠামো, ঘর, ডিভাইস ইত্যাদি পার্স এবং রেন্ডার করতে হয়।
কাঠামো পড়ুন
হোম এপিআই ডিজাইনটি কোটলিন ফ্লো-এর উপর ভিত্তি করে তৈরি করা হয়েছে যাতে ডেটা মডেল অবজেক্টগুলি (উদাহরণস্বরূপ, Structure , HomeDevice , ইত্যাদি) স্ট্রিম আউট করা যায়। ডেভেলপাররা অবজেক্টে থাকা সমস্ত অবজেক্ট (উদাহরণস্বরূপ, একটি Structure , একটি Room , ইত্যাদি) পেতে একটি Flow সাবস্ক্রাইব করে।
সকল স্ট্রাকচার পুনরুদ্ধার করতে, structures() ফাংশনটি কল করুন, যা স্ট্রাকচারের একটি ফ্লো ফেরত দেয়। তারপর, ব্যবহারকারীর মালিকানাধীন সমস্ত স্ট্রাকচার পেতে ফ্লোতে তালিকা ফাংশনটি কল করুন।
// Get the a snapshot of all structures from the current homeClient
val allStructures : Set<Structure> =
homeClient.structures() // HomeObjectsFlow<Structure>
.list() // Set<Structure>
অ্যাপ আর্কিটেকচারের নির্দেশিকা অ্যাপ ডেটা প্রবাহ এবং অবস্থা ব্যবস্থাপনা উন্নত করার জন্য একটি আধুনিক রিঅ্যাকটিভ প্রোগ্রামিং পদ্ধতি গ্রহণের জোরালো পরামর্শ দেয়।
এখানে স্যাম্পল অ্যাপটি কীভাবে রিঅ্যাকটিভ কোডিং স্টাইল মেনে চলে:
- ভিউ মডেলগুলি (যেমন
StructureViewModelএবংDeviceViewModel, স্টেট হোল্ডার হিসেবে) মান পরিবর্তনগুলি গ্রহণ করতে এবং সর্বশেষ অবস্থা বজায় রাখতে Home APIs SDK থেকে প্রবাহগুলিতে সাবস্ক্রাইব করে। - ভিউ (যেমন
StructureViewএবংDeviceView) স্টেটগুলি গ্রহণ করতে এবং সেই পরিবর্তনগুলি প্রতিফলিত করার জন্য UI রেন্ডার করতে ভিউ মডেলগুলিতে সাবস্ক্রাইব করে। - যখন একজন ব্যবহারকারী একটি ভিউতে একটি বোতামে ক্লিক করেন (উদাহরণস্বরূপ, একটি হালকা ডিভাইসের "চালু" বোতাম), ইভেন্টগুলি ভিউ মডেলের ফাংশনগুলিকে ট্রিগার করে, যা প্রতিক্রিয়াশীল হোম API ফাংশনগুলিকে কল করে (উদাহরণস্বরূপ,
OnOffবৈশিষ্ট্যেরOnকমান্ড)।
HomeAppViewModel.kt এর ধাপ 5.1.1 এ, আমরা collect() ফাংশনটি কল করে স্ট্রাকচার পরিবর্তন ইভেন্টগুলিতে সাবস্ক্রাইব করি। Structures API প্রতিক্রিয়া দ্বারা প্রদত্ত এবং StructureViewModel's StateFlow এ বিতরণ করা structureSet অতিক্রম করে এমন বিভাগটি আনকমেন্ট করুন। এটি অ্যাপটিকে স্ট্রাকচার স্টেট পরিবর্তনগুলি পর্যবেক্ষণ করতে দেয়:
private suspend fun subscribeToStructures() {
// TODO: 5.1.1 - Subscribe the structure data changes
// // Subscribe to structures returned by the Structures API:
// homeApp.homeClient.structures().collect { structureSet ->
// val structureVMList: MutableList<StructureViewModel> = mutableListOf()
// // Store structures in container ViewModels:
// for (structure in structureSet) {
// structureVMList.add(StructureViewModel(structure))
// }
// // Store the ViewModels:
// structureVMs.emit(structureVMList)
//
// // If a structure isn't selected yet, select the first structure from the list:
// if (selectedStructureVM.value == null && structureVMList.isNotEmpty())
// selectedStructureVM.emit(structureVMList.first())
//
// }
}
DevicesView.kt এ, অ্যাপটি StructureViewModel'sStateFlow, যা স্ট্রাকচার ডেটা পরিবর্তনের সময় UI রিকম্পোজিশন ট্রিগার করে। স্ট্রাকচার তালিকাটি ড্রপ-ডাউন মেনু হিসেবে রেন্ডার করতে ধাপ 5.1.2-এ সোর্স কোডটি আনকমেন্ট করুন:
val structureVMs: List<StructureViewModel> = homeAppVM.structureVMs.collectAsState().value
...
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
// TODO: 5.1.2 - Show list of structures in DropdownMenu
// for (structure in structureVMs) {
// DropdownMenuItem(
// text = { Text(structure.name) },
// onClick = {
// scope.launch { homeAppVM.selectedStructureVM.emit(structure) }
// expanded = false
// }
// )
// }
}
...
অ্যাপটি আবার চালান। তীর চিহ্নে ট্যাপ করলে মেনুটি দেখতে পাবেন:

কাঠামো বিশ্লেষণ করুন
পরবর্তী ধাপ হল একটি কাঠামোর মধ্যে ঘরের জিনিসপত্র অতিক্রম করা। কাঠামো থেকে ঘরগুলি উদ্ধার করুন:
val rooms: Set<Room>
rooms = structure.rooms().list()
এরপর আপনি ডিভাইসগুলি পুনরুদ্ধার করতে কক্ষগুলি অতিক্রম করতে পারেন:
val devices: Set<HomeDevice>
devices = room.devices().list()
গুরুত্বপূর্ণ: হোম এপিআই ডেটা মডেলে, একটি কাঠামোতে এমন ডিভাইস থাকতে পারে যা একটি রুমে বরাদ্দ করা হয় না , তাই আপনার অ্যাপে রুম ছাড়া ডিভাইসগুলিও ক্যাপচার করতে ভুলবেন না:
val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()
for (device in structure.devices().list())
if (device.roomId == null)
devicesWithoutRooms.add(device)
আবার, বিদ্যমান নমুনা কোডে, আমরা সর্বশেষ রুম এবং ডিভাইস তালিকা পেতে একটি ফ্লো সাবস্ক্রাইব করি। StructureViewModel.kt সোর্স ফাইলে ধাপ 5.2.1 এবং 5.2.2 এ কোডটি পরীক্ষা করে দেখুন এবং রুম ডেটা সাবস্ক্রিপশন সক্ষম করতে এটি আনকমেন্ট করুন:
val roomVMs : MutableStateFlow<List<RoomViewModel>>
val deviceVMs : MutableStateFlow<List<DeviceViewModel>>
val deviceVMsWithoutRooms : MutableStateFlow<List<DeviceViewModel>>
private suspend fun subscribeToRooms() {
// TODO: 5.2.1 - Subscribe the room data changes
// // Subscribe to changes on rooms:
// structure.rooms().collect { roomSet ->
// val roomVMs = mutableListOf<RoomViewModel>()
// // Store rooms in container ViewModels:
// for (room in roomSet) {
// roomVMs.add(RoomViewModel(room))
// }
// // Store the ViewModels:
// this.roomVMs.emit(roomVMs)
// }
}
private suspend fun subscribeToDevices() {
// TODO: 5.2.2 - Subscribe the device data changes in a structure
// // Subscribe to changes on devices:
// structure.devices().collect { deviceSet ->
// val deviceVMs = mutableListOf<DeviceViewModel>()
// val deviceWithoutRoomVMs = mutableListOf<DeviceViewModel>()
// // Store devices in container ViewModels:
// for (device in deviceSet) {
// val deviceVM = DeviceViewModel(device)
// deviceVMs.add(deviceVM)
// // For any device that's not in a room, additionally keep track of a separate list:
// if (device.roomId == null)
// deviceWithoutRoomVMs.add(deviceVM)
// }
// // Store the ViewModels:
// this.deviceVMs.emit(deviceVMs)
// deviceVMsWithoutRooms.emit(deviceWithoutRoomVMs)
// }
}
রুম তালিকাকে মেনু হিসেবে রেন্ডার করার জন্য DevicesView.kt সোর্স ফাইলে ধাপ 5.2.3 এবং 5.2.4 আনম্যান্ট করুন:
val selectedRoomVMs: List<RoomViewModel> =
selectedStructureVM.roomVMs.collectAsState().value
...
for (roomVM in selectedRoomVMs) {
// TODO: 5.2.3 - Render the list of rooms
// RoomListItem(roomVM)
// TODO: 5.2.4 - Render the list of devices in a room
// val deviceVMsInRoom: List<DeviceViewModel> = roomVM.deviceVMs.collectAsState().value
//
// for (deviceVM in deviceVMsInRoom) {
// DeviceListItem(deviceVM, homeAppVM)
// }
}
এখন যেহেতু আপনার কাছে ডিভাইসগুলি আছে, আমরা শিখব কিভাবে সেগুলি দিয়ে কাজ করতে হয়।

৬. ডিভাইসগুলির সাথে কাজ করুন
হোম এপিআইগুলি ডিভাইস এবং এর ক্ষমতাগুলি ক্যাপচার করার জন্য একটি HomeDevice অবজেক্ট ব্যবহার করে। ডেভেলপাররা ডিভাইসের বৈশিষ্ট্যগুলিতে সাবস্ক্রাইব করতে পারেন এবং তাদের অ্যাপগুলিতে স্মার্ট হোম ডিভাইসগুলি উপস্থাপন করতে সেগুলি ব্যবহার করতে পারেন।
ডিভাইসের অবস্থা পড়ুন
HomeDevice অবজেক্টটি স্ট্যাটিক মানগুলির একটি সেট উপস্থাপন করে, যেমন ডিভাইসের নাম বা সংযোগের অবস্থা। একজন ডেভেলপার হিসেবে, আপনি API গুলি থেকে ডিভাইসটি পাওয়ার পরেই এগুলি পুনরুদ্ধার করতে পারেন:
val id: String = device.id.id
val name: String = device.name
val connectivity: ConnectivityState =
device.sourceConnectivity.connectivityState
ডিভাইসের ক্ষমতা পেতে, আপনাকে HomeDevice থেকে প্রকার এবং বৈশিষ্ট্যগুলি পুনরুদ্ধার করতে হবে। এটি করার জন্য, আপনি নিম্নরূপ ডিভাইস টাইপ ফ্লোতে সাবস্ক্রাইব করতে পারেন এবং ডিভাইসের ধরণগুলি থেকে বৈশিষ্ট্যগুলি পুনরুদ্ধার করতে পারেন:
device.types().collect { typeSet ->
var primaryType : DeviceType = UnknownDeviceType()
for (typeInSet in typeSet)
if (typeInSet.metadata.isPrimaryType)
primaryType = typeInSet
val traits: List<Trait> = mutableListOf()
for (trait in primaryType.traits())
if (trait.factory in myTraits)
traits.add(trait)
for (trait in traits)
parseTrait(trait, primaryType)
}
প্রতিটি ডিভাইসে সমর্থিত DeviceType (বান্ডেল করা ক্ষমতা) এর একটি সেট থাকে, যা আপনি device.types() ব্যবহার করে পুনরুদ্ধার করতে পারেন। এই ডিভাইসের ধরণগুলিতে এমন বৈশিষ্ট্য রয়েছে যা type.traits() ব্যবহার করে পুনরুদ্ধার করা যেতে পারে। প্রতিটি ডিভাইস তার ধরণের একটিকে প্রাথমিক ধরণ হিসাবে চিহ্নিত করে (যা type.metadata.isPrimaryType ব্যবহার করে পরীক্ষা করা যেতে পারে) যা আপনার অ্যাপে উপস্থাপন করা উচিত। ব্যবহারকারীদের একটি সম্পূর্ণ অভিজ্ঞতা প্রদানের জন্য, আমরা সমস্ত ফেরত দেওয়া প্রকারগুলি অতিক্রম করার এবং আপনার জন্য উপলব্ধ সমস্ত বৈশিষ্ট্যগুলিকে একীভূত করার পরামর্শ দিচ্ছি।
একবার আপনি একটি বৈশিষ্ট্য পুনরুদ্ধার করলে, আপনি মানগুলি ব্যাখ্যা করার জন্য নিম্নলিখিত ফাংশন ব্যবহার করে এটি পার্স করতে পারেন:
fun <T : Trait?> parseTrait(trait : T, type: DeviceType) {
val status : String = when (trait) {
is OnOff -> { if (trait.onOff) "On" else "Off" }
is LevelControl -> { trait.currentLevel.toString() }
is BooleanState -> {
when (type.factory) {
ContactSensorDevice -> {
if (trait.stateValue) "Closed"
else "Open"
}
else -> ...
}
}
else -> ...
}
}
মনে রাখবেন যে একটি বৈশিষ্ট্য কী উপস্থাপন করে তার মধ্যে তারতম্য হতে পারে, এটি ডিভাইসের ধরণের উপর নির্ভর করে (পূর্ববর্তী উদাহরণে BooleanState দেখুন), তাই প্রতিটি ডিভাইসের ধরণের বৈশিষ্ট্যগুলি আসলে কী উপস্থাপন করে তা বোঝার জন্য আপনাকে তার প্রেক্ষাপট সম্পর্কে সচেতন থাকতে হবে।
অবস্থাগুলি পুনরুদ্ধার করতে DeviceViewModel.kt সোর্স ফাইলে ধাপ 6.1.1 এবং 6.1.2 আনমন্ট করুন:
private suspend fun subscribeToType() {
// Subscribe to changes on device type, and the traits/attributes within:
device.types().collect { typeSet ->
// Container for the primary type for this device:
var primaryType : DeviceType = UnknownDeviceType()
...
// TODO: 6.1.1 - Determine the primary type for this device
// // Among all the types returned for this device, find the primary one:
// for (typeInSet in typeSet)
// if (typeInSet.metadata.isPrimaryType)
// primaryType = typeInSet
//
// // Optional: For devices with a single type that did not define a primary:
// if (primaryType is UnknownDeviceType && typeSet.size == 1)
// primaryType = typeSet.first()
// Container for list of supported traits present on the primary device type:
val supportedTraits: List<Trait> = getSupportedTraits(primaryType.traits())
...
}
fun getSupportedTraits(traits: Set<Trait>) : List<Trait> {
val supportedTraits: MutableList<Trait> = mutableListOf()
// TODO: 6.1.2 - Get only the supported traits for this device
// for (trait in traits)
// if (trait.factory in HomeApp.supportedTraits)
// supportedTraits.add(trait)
return supportedTraits
}
DeviceView.kt এ String হিসেবে একটি OnOff বৈশিষ্ট্য, যার নাম এবং স্থিতি সহ, রেন্ডার করার জন্য ধাপ 6.1.3-এ মন্তব্য মুক্ত করুন:
Box (Modifier.padding(horizontal = 24.dp, vertical = 8.dp)) {
when (trait) {
is OnOff -> {
// TODO: 6.1.3 - Render controls based on the trait type
// Column (Modifier.fillMaxWidth()) {
// Text(trait.factory.toString(), fontSize = 20.sp)
// Text(DeviceViewModel.getTraitStatus(trait, type), fontSize = 16.sp)
// }
...
}
is LevelControl -> {
...
}
is BooleanState -> {
...
}
is OccupancySensing -> {
...
}
...
}
আপনি যদি এখন সমর্থিত ডিভাইসের ধরণ (উদাহরণস্বরূপ একটি হালকা ডিভাইস) দিয়ে অ্যাপটি চালান, তাহলে এটি সমস্ত ডিভাইসের জন্য আপ-টু-ডেট অবস্থা দেখাবে।

ডিভাইস কমান্ড ইস্যু করুন
ডিভাইসগুলিতে কমান্ড ইস্যু করার জন্য, হোম এপিআইগুলি trait অবজেক্ট যেমন trait.on() অথবা trait.moveToLevel(...) -এ সুবিধাজনক ফাংশন প্রদান করে:
fun <T : Trait?> issueCommand(trait : T) {
when (trait) {
is OnOff -> {
// trait.on()
// trait.off()
}
is LevelControl -> {
// trait.moveToLevel(...)
// trait.moveToLevelWithOnOff(...)
}
}
}
টিপস: একবার আপনি বৈশিষ্ট্যের ধরণ নির্ধারণ করলে, বৈশিষ্ট্যটির সাথে ইন্টারঅ্যাক্ট করার জন্য কী ধরণের ক্রিয়া উপলব্ধ তা দেখতে Android Studio-এর স্বয়ংক্রিয়-সম্পূর্ণ বৈশিষ্ট্যটি ব্যবহার করুন।
অ্যাপে কার্যকরী নিয়ন্ত্রণ যোগ করতে DeviceView.kt এ ধাপ 6.2.1-এ মন্তব্য মুক্ত করুন:
Box (Modifier.padding(horizontal = 24.dp, vertical = 8.dp)) {
when (trait) {
is OnOff -> {
....
// TODO: 6.2.1 - Render controls based on the trait type
// Switch (checked = (trait.onOff == true), modifier = Modifier.align(Alignment.CenterEnd),
// onCheckedChange = { state ->
// scope.launch { if (state) trait.on() else trait.off() }
// },
// enabled = isConnected
// )
}
আপনি যদি এখন অ্যাপটি চালান, তাহলে এটি আপনাকে বাস্তব জীবনের ভৌত ডিভাইসগুলি নিয়ন্ত্রণ করার অনুমতি দেবে।
আপনার লাইটবাল্বের অনঅফ কন্ট্রোলে ট্যাপ করলে, ডিভাইসটি এখন জ্বলে উঠবে।

ডিভাইসগুলি কীভাবে নিয়ন্ত্রণ করবেন সে সম্পর্কে আরও তথ্যের জন্য, Android-এ ডিভাইসগুলি নিয়ন্ত্রণ করুন দেখুন।
৭. কমিশন ডিভাইস
কমিশনিং এপিআই ডেভেলপারদের গুগল হোম ইকোসিস্টেমে ডিভাইস যোগ করতে এবং হোম এপিআই ব্যবহার করে নিয়ন্ত্রণের জন্য উপলব্ধ করতে দেয়। শুধুমাত্র ম্যাটার ডিভাইসগুলি সমর্থিত। এই বিভাগে আমরা আপনার অ্যাপগুলিতে ডিভাইস কমিশনিং কীভাবে সক্ষম করবেন তা অন্বেষণ করব।
এই বিভাগটি শুরু করার আগে, নিশ্চিত করুন যে নিম্নলিখিত পূর্বশর্তগুলি পূরণ হয়েছে:
- আপনার অ্যান্ড্রয়েড ফোনের মতো একই নেটওয়ার্কে অবস্থিত ম্যাটার সমর্থনকারী একটি গুগল হাব আপনার গুগল হোম অ্যাপে যুক্ত করা হয়েছে।
- আপনি Google Home Developer Console- এ VID
0xFFF1এবং PID0x8000ব্যবহার করে একটি ডেভেলপার প্রকল্প তৈরি করেছেন।
যদি আপনার কাছে কমিশনিং করার জন্য QR কোড সহ একটি ফিজিক্যাল ম্যাটার ডিভাইস থাকে, তাহলে আপনি "Enable Commissioning API" এ যেতে পারেন। অন্যথায়, পরবর্তী বিভাগে যান, যেখানে আমরা আলোচনা করব কিভাবে আপনি কমিশনযোগ্য ভার্চুয়াল ডিভাইস তৈরি করতে ম্যাটার ভার্চুয়াল ডিভাইস অ্যাপ (MVD) ব্যবহার করতে পারেন।
ঐচ্ছিক: একটি ম্যাটার কমিশনযোগ্য ডিভাইস প্রস্তুত করুন
ম্যাটার কমিশনেবল ডিভাইস প্রস্তুত করার সবচেয়ে সহজ উপায় হল ম্যাটার ভার্চুয়াল ডিভাইস অ্যাপ (MVD) দ্বারা প্রদত্ত একটি অনুকরণকৃত ডিভাইস ব্যবহার করা।
MVD ইনস্টল করার পরে এবং ফায়ারওয়াল সেট আপ করার পরে, MVD চালান:

একটি OnOff ডিভাইস তৈরি করুন। লক্ষ্য করুন যে এটি এখনও চালু হয়নি - আপনি পরে এই কোডল্যাবে এটি চালু করবেন।

কমিশনিং এপিআই সক্ষম করুন
কমিশনিং এপিআই অ্যাপের অ্যাক্টিভিটির বাইরে কাজ করে, তাই কমিশনিং অন্যান্য হোম এপিআই থেকে ভিন্নভাবে পরিচালনা করতে হবে। আপনার অ্যাপটি কমিশনিংয়ের জন্য প্রস্তুত করার জন্য, আপনার দুটি ভেরিয়েবলের প্রয়োজন।
একটি ভেরিয়েবল হল ActivityResultLauncher , যা কমিশনিং ইন্টেন্ট পাঠাতে এবং ফলাফল কলব্যাক পরিচালনা করতে ব্যবহৃত হয়। অন্য ভেরিয়েবল হল CommissioningResult , যা কমিশনিং ফলাফল সংরক্ষণ করতে ব্যবহৃত অবজেক্ট। কমিশনিং কীভাবে সেট আপ করবেন তার জন্য নিম্নলিখিত উদাহরণটি দেখুন:
var launcher: ActivityResultLauncher<IntentSenderRequest>
lateinit var commissioningResult: CommissioningResult?
launcher = activity.registerForActivityResult(StartIntentSenderForResult()) { result ->
try {
commissioningResult = CommissioningResult.fromIntentSenderResult(
result.resultCode, result.data)
} catch (exception: ApiException) {
// Catch any issues
}
}
একবার আপনার কমিশনিং ফ্লো সেট আপ হয়ে গেলে, আপনি আপনার কমিশনিং ইন্টেন্ট তৈরি করবেন এবং পূর্ববর্তী উদাহরণে তৈরি করা লঞ্চার ব্যবহার করে এটি চালু করবেন। আমরা ইন্টেন্ট এবং লঞ্চারটিকে নিম্নলিখিতগুলির মতো একটি ডেডিকেটেড ফাংশনে রাখার পরামর্শ দিচ্ছি। একটি ডেডিকেটেড ফাংশন একটি UI উপাদানের সাথে সংযুক্ত করা যেতে পারে (যেমন একটি +ডিভাইস যোগ করুন বোতাম) এবং ব্যবহারকারীর অনুরোধের ভিত্তিতে চালু করা যেতে পারে:
fun requestCommissioning() {
// Retrieve the onboarding payload used when commissioning devices:
val payload = activity.intent?.getStringExtra(Matter.EXTRA_ONBOARDING_PAYLOAD)
scope.launch {
// Create a commissioning request to store the device in Google's Fabric:
val request = CommissioningRequest.builder()
.setStoreToGoogleFabric(true)
.setOnboardingPayload(payload)
.build()
// Initialize client and sender for commissioning intent:
val client: CommissioningClient = Matter.getCommissioningClient(context)
val sender: IntentSender = client.commissionDevice(request).await()
// Launch the commissioning intent on the launcher:
launcher.launch(IntentSenderRequest.Builder(sender).build())
}
}
কমিশনিং সক্ষমতা সক্ষম করতে এবং নমুনা অ্যাপে +ডিভাইস যোগ করুন বোতামটি কাজ করতে CommissioningManager.kt এ ধাপ 7.1.1 আনকমেন্ট করুন।
// Called by +Add Device button in DeviceView.kt
fun requestCommissioning() {
// Retrieve the onboarding payload used when commissioning devices:
val payload = activity.intent?.getStringExtra(Matter.EXTRA_ONBOARDING_PAYLOAD)
// TODO: 7.1.1 - Launch the commissioning intent
// scope.launch {
// // Create a commissioning request to store the device in Google's Fabric:
// val request = CommissioningRequest.builder()
// .setStoreToGoogleFabric(true)
// .setOnboardingPayload(payload)
// .build()
// // Initialize client and sender for commissioning intent:
// val client: CommissioningClient = Matter.getCommissioningClient(context)
// val sender: IntentSender = client.commissionDevice(request).await()
// // Launch the commissioning intent on the launcher:
// launcher.launch(IntentSenderRequest.Builder(sender).build())
// }
}
এই ফাংশনটি চালানোর ফলে কমিশনিং ফ্লো শুরু হবে, যা নিম্নলিখিত স্ক্রিনশটের মতো একটি স্ক্রিন প্রদর্শন করবে:

কমিশনিং প্রবাহ বুঝুন
কমিশনিং ফ্লোতে এমন কিছু স্ক্রিন থাকে যা ব্যবহারকারীকে তাদের Google অ্যাকাউন্টে একটি ডিভাইস যোগ করার ক্ষেত্রে গাইড করে:





ব্যবহারকারীদের একটি QR কোড স্ক্যানার দেওয়া হবে যা তারা ম্যাটার ডিভাইস থেকে QR কোড স্ক্যান করতে ব্যবহার করতে পারবেন। এরপর ফ্লোটি ব্যবহারকারীর চুক্তি প্রদর্শন, ডিভাইস আবিষ্কার এবং কমিশনিং এবং ডিভাইসের নামকরণের মধ্য দিয়ে যাবে। ফ্লো সম্পূর্ণ হয়ে গেলে, ফ্লোটি অ্যাপে ফোকাস পরিবর্তন করবে এবং পূর্ববর্তী বিভাগে আমরা যে কলব্যাক ফাংশনটি তৈরি করেছি তাতে কমিশনিং ফলাফলটি প্রেরণ করবে।
কমিশনিং এপিআইগুলির একটি সুবিধা হল যে ইউএক্স ফ্লো SDK দ্বারা পরিচালিত হয়, তাই ডেভেলপাররা খুব দ্রুত কাজ শুরু করতে পারে। এটি ব্যবহারকারীদের বিভিন্ন অ্যাপ জুড়ে ডিভাইস যুক্ত করার সময় একটি ধারাবাহিক অভিজ্ঞতা প্রদান করে।
কমিশনিং এপিআই সম্পর্কে আরও জানতে, কমিশনিং এপিআই অন অ্যান্ড্রয়েড দেখুন।
৮. অভিনন্দন!
অভিনন্দন! আপনি গুগল হোম এপিআই ব্যবহার করে সফলভাবে একটি অ্যান্ড্রয়েড অ্যাপ তৈরি করেছেন। এই কোডল্যাব জুড়ে, আপনি অনুমতি, ডিভাইস, কাঠামো এবং কমিশনিং এপিআই অন্বেষণ করেছেন। পরবর্তী কোডল্যাব, অ্যান্ড্রয়েড কোডল্যাবে হোম এপিআই ব্যবহার করে উন্নত অটোমেশন তৈরি করুন -এ, আমরা অটোমেশন এবং ডিসকভারি এপিআই অন্বেষণ করব এবং অ্যাপটি সম্পূর্ণ করব।
আমরা আশা করি আপনি এমন অ্যাপ তৈরি করতে উপভোগ করবেন যা গুগল হোম ইকোসিস্টেমের মধ্যে সৃজনশীলভাবে ডিভাইস নিয়ন্ত্রণ করে।
পরবর্তী পদক্ষেপ
- এই সিরিজের দ্বিতীয় কোডল্যাবটি সম্পন্ন করে অ্যান্ড্রয়েডে হোম এপিআই শেখার আপনার যাত্রার পরবর্তী অংশে এগিয়ে যান: অ্যান্ড্রয়েডে হোম এপিআই ব্যবহার করে উন্নত অটোমেশন তৈরি করুন ।
- আপনি যেকোনো সুপারিশের জন্য আমাদের সাথে যোগাযোগ করতে পারেন, অথবা ইস্যু ট্র্যাকার , স্মার্ট হোম সাপোর্ট টপিকের মাধ্যমে যেকোনো সমস্যা রিপোর্ট করতে পারেন।