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

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



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


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

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

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

যখন অ্যাপটি আপনার ফোনে সফলভাবে চালু হবে, তখন আপনি স্যাম্পল অ্যাপের মূল পৃষ্ঠাটি দেখতে পাবেন। কিন্তু OAuth অথেন্টিকেশন সেট আপ না করা পর্যন্ত এবং পারমিশন এপিআই (Permission API) ব্যবহার করে বাকি অংশগুলো বাস্তবায়ন না করা পর্যন্ত আপনি সাইন ইন করতে পারবেন না।
৩. প্রমাণীকরণ সেট আপ করুন
হোম এপিআইগুলো কাঠামোর মধ্যে থাকা ডিভাইসগুলোতে অ্যাক্সেস দেওয়ার জন্য OAuth 2.0 ব্যবহার করে। OAuth একজন ব্যবহারকারীকে তার লগইন তথ্য প্রকাশ না করেই কোনো অ্যাপ বা পরিষেবাতে অনুমতি দেওয়ার সুযোগ দেয়।
সম্মতি স্ক্রিনটি কনফিগার করতে 'সেট আপ OAuth কনসেন্ট' (Set up OAuth consent) এর নির্দেশাবলী অনুসরণ করুন। অন্তত একটি টেস্ট অ্যাকাউন্ট তৈরি করতে ভুলবেন না।
এরপর অ্যাপটির জন্য ক্রেডেনশিয়াল তৈরি করতে 'Set up OAuth credentials'- এর নির্দেশাবলী অনুসরণ করুন।
৪. প্রারম্ভিককরণ এবং অনুমতি পরিচালনা
এই অংশে, আপনি পারমিশনস এপিআই (Permissions API) ব্যবহার করে অসম্পূর্ণ অংশগুলো পূরণ করার মাধ্যমে এসডিকে (SDK) ইনিশিয়ালাইজ করা এবং ব্যবহারকারীর অনুমতি পরিচালনা করা শিখবেন।
সমর্থিত প্রকার এবং বৈশিষ্ট্য সংজ্ঞায়িত করুন
একটি অ্যাপ তৈরি করার সময়, অ্যাপটি কোন কোন ডিভাইসের ধরন এবং বৈশিষ্ট্য সমর্থন করবে তা আপনাকে স্পষ্টভাবে উল্লেখ করতে হবে। স্যাম্পল অ্যাপটিতে, আমরা HomeApp.kt এর কম্প্যানিয়ন অবজেক্টে স্ট্যাটিক লিস্ট সংজ্ঞায়িত করার মাধ্যমে এটি করে থাকি, যা পরবর্তীতে প্রয়োজন অনুযায়ী পুরো অ্যাপ জুড়ে রেফারেন্স হিসেবে ব্যবহার করা যেতে পারে:
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,
// ...
)
}
সমস্ত সমর্থিত ডিভাইসের ধরন ও বৈশিষ্ট্য দেখতে, অ্যান্ড্রয়েডের সমর্থিত ডিভাইসের ধরন এবং বৈশিষ্ট্য সূচী দেখুন।
অনুমতি অনুরোধকারী সোর্স কোডটি সক্রিয় করতে HomeApp.kt সোর্স ফাইলের ৪.১.১ এবং ৪.১.২ ধাপ দুটি আনকমেন্ট করুন।
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 অবজেক্টটি প্রারম্ভিকীকরণ করুন
হোম এপিআই ব্যবহারকারী সমস্ত অ্যাপ একটি 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 অবজেক্টটির মাধ্যমেই হবে।
অনুমতি এপিআই ব্যবহার করুন
হোম এপিআই-গুলোর জন্য ব্যবহারকারীর প্রমাণীকরণ পারমিশন এপিআই-এর মাধ্যমে করা হয়। স্যাম্পল অ্যাপের PermissionsManager.kt সোর্স ফাইলে ব্যবহারকারী প্রমাণীকরণের জন্য কোড রয়েছে। স্যাম্পল অ্যাপের জন্য পারমিশনগুলো সক্রিয় করতে checkPermissions(...) এবং requestPermissions(...) ফাংশনগুলোর ভেতরের অংশ আনকমেন্ট করুন।
নিবন্ধন:
homeClient.registerActivityResultCallerForPermissions(activity)
চালু করা হচ্ছে:
try {
val result: PermissionsResult
result = homeClient.requestPermissions(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH)
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()) }
}
}
এখন ধাপগুলো অনুসরণ করে আপনার ফোনে অ্যাপটি চালান এবং অনুমতিগুলো দিন। আপনি নিম্নলিখিত প্রবাহটি দেখতে পাবেন:





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

এই অংশে, আপনি শিখবেন কীভাবে স্ট্রাকচার এপিআই ব্যবহার করে আপনার বাড়ির কাঠামো, ঘর, ডিভাইস ইত্যাদি পার্স এবং রেন্ডার করার পদ্ধতি দেখানোর জন্য সোর্স কোড তৈরি করতে হয়।
কাঠামো পড়ুন
হোম এপিআই-এর ডিজাইনটি কোটলিন ফ্লো-এর উপর ভিত্তি করে তৈরি, যা ডেটা মডেলের অবজেক্টগুলো (যেমন, Structure , HomeDevice , ইত্যাদি) স্ট্রিম করে। ডেভেলপাররা একটি Flow -তে সাবস্ক্রাইব করে সেই অবজেক্টের অন্তর্ভুক্ত সমস্ত অবজেক্ট (যেমন, একটি Structure , একটি Room , ইত্যাদি) পেয়ে থাকেন।
সমস্ত স্ট্রাকচার পুনরুদ্ধার করতে, structures() ফাংশনটি কল করুন, যা স্ট্রাকচারের একটি ফ্লো রিটার্ন করে। তারপর, ব্যবহারকারীর মালিকানাধীন সমস্ত স্ট্রাকচার পেতে ফ্লো-টির উপর list ফাংশনটি কল করুন।
// 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 রেন্ডার করতে ভিউ মডেলগুলোতে সাবস্ক্রাইব করে। - যখন কোনো ব্যবহারকারী কোনো ভিউ-এর একটি বোতামে ক্লিক করেন (উদাহরণস্বরূপ, একটি লাইট ডিভাইসের "অন" বোতাম), তখন ইভেন্টগুলো ভিউ মডেলের ফাংশনগুলোকে ট্রিগার করে, যেগুলো সংশ্লিষ্ট হোম এপিআই ফাংশনগুলোকে কল করে (উদাহরণস্বরূপ,
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 সোর্স ফাইলের ৫.২.৩ এবং ৫.২.৪ ধাপ দুটি আনকমেন্ট করুন:
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 অবজেক্টটি কিছু স্থির মান উপস্থাপন করে, যেমন ডিভাইসের নাম বা সংযোগের অবস্থা। একজন ডেভেলপার হিসেবে, আপনি এপিআই থেকে ডিভাইসটি পাওয়ার পরপরই এগুলি সংগ্রহ করতে পারেন:
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
}
একটি OnOff ট্রেইটকে তার নাম এবং স্ট্যাটাস সহ String হিসেবে রেন্ডার করতে DeviceView.kt এর ধাপ 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 -> {
...
}
...
}
আপনি যদি এখন সমর্থিত ডিভাইসের ধরন (যেমন একটি লাইট ডিভাইস) দিয়ে অ্যাপটি চালান, তাহলে এটি সব ডিভাইসের হালনাগাদ অবস্থা দেখাবে।

ডিভাইস কমান্ড জারি করুন
ডিভাইসগুলিতে কমান্ড জারি করার জন্য, Home API-গুলি 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(...)
}
}
}
পরামর্শ: একবার আপনি ট্রেইটের ধরন নির্ধারণ করে ফেললে, ট্রেইটটির সাথে ইন্টারঅ্যাক্ট করার জন্য কী ধরনের অ্যাকশন উপলব্ধ আছে তা দেখতে অ্যান্ড্রয়েড স্টুডিওর অটো-কমপ্লিট ফিচারটি ব্যবহার করুন।
অ্যাপে ফাংশনাল কন্ট্রোল যোগ করতে 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
// )
}
আপনি এখন অ্যাপটি চালালে, এটি আপনাকে বাস্তব ডিভাইসগুলো নিয়ন্ত্রণ করার সুযোগ দেবে।
আপনি যদি আপনার লাইটবাল্বের অন-অফ কন্ট্রোলটি চাপেন, তাহলে ডিভাইসটি এখন চালু হয়ে যাবে।

ডিভাইসগুলি কীভাবে নিয়ন্ত্রণ করবেন সে সম্পর্কে আরও তথ্যের জন্য, অ্যান্ড্রয়েডে ডিভাইস নিয়ন্ত্রণ দেখুন।
৭. ডিভাইস চালু করুন
কমিশনিং এপিআই ডেভেলপারদের গুগল হোম ইকোসিস্টেমে ডিভাইস যুক্ত করতে এবং হোম এপিআই ব্যবহার করে সেগুলোকে নিয়ন্ত্রণের জন্য উপলব্ধ করতে দেয়। শুধুমাত্র ম্যাটার ডিভাইসগুলোই সমর্থিত। এই বিভাগে আমরা আলোচনা করব, কীভাবে আপনি আপনার অ্যাপে ডিভাইস কমিশনিং চালু করতে পারেন।
এই অংশটি শুরু করার আগে, নিম্নলিখিত পূর্বশর্তগুলো পূরণ করা হয়েছে কিনা তা নিশ্চিত করুন:
- আপনার অ্যান্ড্রয়েড ফোনের সাথে একই নেটওয়ার্কে অবস্থিত ম্যাটার (Matter) সমর্থনকারী একটি গুগল হাব আপনার গুগল হোম অ্যাপে যুক্ত করা হয়েছে।
- আপনি গুগল হোম ডেভেলপার কনসোলে VID
0xFFF1এবং PID0x8000দিয়ে একটি ডেভেলপার প্রজেক্ট তৈরি করেছেন ।
আপনার কাছে যদি কমিশনিংয়ের জন্য কিউআর কোডসহ কোনো ফিজিক্যাল ম্যাটার ডিভাইস থাকে, তাহলে আপনি সরাসরি ‘এনাবল কমিশনিং এপিআই’ অংশে চলে যেতে পারেন। অন্যথায়, পরবর্তী বিভাগে যান, যেখানে আমরা আলোচনা করেছি কীভাবে আপনি ম্যাটার ভার্চুয়াল ডিভাইস অ্যাপ (MVD) ব্যবহার করে কমিশনযোগ্য ভার্চুয়াল ডিভাইস তৈরি করতে পারেন।
ঐচ্ছিক: একটি ম্যাটার কমিশনযোগ্য ডিভাইস প্রস্তুত করুন।
একটি ম্যাটার কমিশনযোগ্য ডিভাইস প্রস্তুত করার সবচেয়ে সহজ উপায় হলো ম্যাটার ভার্চুয়াল ডিভাইস অ্যাপ (MVD) দ্বারা প্রদত্ত একটি এমুলেটেড ডিভাইস ব্যবহার করা।
MVD ইনস্টল এবং ফায়ারওয়াল সেট আপ করার পরে, MVD চালান:

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

কমিশনিং এপিআই সক্রিয় করুন
কমিশনিং এপিআই অ্যাপের অ্যাক্টিভিটির বাইরে কাজ করে, তাই অন্যান্য হোম এপিআইগুলোর চেয়ে কমিশনিং ভিন্নভাবে পরিচালনা করতে হয়। আপনার অ্যাপকে কমিশনিংয়ের জন্য প্রস্তুত করতে দুটি ভ্যারিয়েবল প্রয়োজন।
একটি ভেরিয়েবল হলো 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 এলিমেন্টের (যেমন একটি +Add Device বাটন) সাথে যুক্ত করা যেতে পারে এবং ব্যবহারকারীর অনুরোধের ভিত্তিতে চালু করা যেতে পারে:
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())
}
}
স্যাম্পল অ্যাপে কমিশনিং সক্ষমতা চালু করতে এবং +Add Device বাটনটি কার্যকর করতে 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 Home APIs) ব্যবহার করে একটি অ্যান্ড্রয়েড অ্যাপ তৈরি করেছেন। এই কোডল্যাব জুড়ে, আপনি পারমিশন (Permissions), ডিভাইস (Devices), স্ট্রাকচার (Structures), এবং কমিশনিং (Commissioning) এপিআই সম্পর্কে জেনেছেন। পরবর্তী কোডল্যাব, ‘অ্যান্ড্রয়েড কোডল্যাবে হোম এপিআই ব্যবহার করে উন্নত অটোমেশন তৈরি করুন’- এ, আমরা অটোমেশন (Automation) এবং ডিসকভারি (Discovery) এপিআই সম্পর্কে জানব এবং অ্যাপটি সম্পূর্ণ করব।
আমরা আশা করি আপনি গুগল হোম ইকোসিস্টেমের অন্তর্গত ডিভাইসগুলোকে সৃজনশীলভাবে নিয়ন্ত্রণ করে এমন অ্যাপ তৈরি করতে উপভোগ করবেন।
পরবর্তী পদক্ষেপ
- এই সিরিজের দ্বিতীয় কোডল্যাবটি সম্পন্ন করে অ্যান্ড্রয়েডে হোম এপিআই শেখার আপনার যাত্রার পরবর্তী ধাপে এগিয়ে যান: অ্যান্ড্রয়েডে হোম এপিআই ব্যবহার করে উন্নত অটোমেশন তৈরি করুন ।
- আপনি যেকোনো সুপারিশ জানাতে বা যেকোনো সমস্যা রিপোর্ট করতে আমাদের সাথে Issue Tracker- এর Smart Home সাপোর্ট টপিকে যোগাযোগ করতে পারেন।