1. ভূমিকা

নেস্ট কর্তৃক প্রকাশিত ওপেনথ্রেড হল থ্রেড® নেটওয়ার্কিং প্রোটোকলের একটি ওপেন-সোর্স বাস্তবায়ন। নেস্ট ওপেনথ্রেড প্রকাশ করেছে যাতে নেস্ট পণ্যগুলিতে ব্যবহৃত প্রযুক্তি ডেভেলপারদের কাছে ব্যাপকভাবে উপলব্ধ করা যায় এবং সংযুক্ত বাড়ির জন্য পণ্যের উন্নয়ন ত্বরান্বিত করা যায়।
থ্রেড স্পেসিফিকেশন হোম অ্যাপ্লিকেশনের জন্য একটি IPv6-ভিত্তিক নির্ভরযোগ্য, নিরাপদ এবং কম-পাওয়ার ওয়্যারলেস ডিভাইস-টু-ডিভাইস যোগাযোগ প্রোটোকল সংজ্ঞায়িত করে। OpenThread সমস্ত থ্রেড নেটওয়ার্কিং স্তর বাস্তবায়ন করে যার মধ্যে রয়েছে IPv6, 6LoWPAN, IEEE 802.15.4 যার মধ্যে MAC নিরাপত্তা, মেশ লিঙ্ক স্থাপন এবং মেশ রাউটিং রয়েছে।
এই কোডল্যাবে, আপনি একটি থ্রেড নেটওয়ার্ক শুরু করতে, ডিভাইসের ভূমিকার পরিবর্তনগুলি পর্যবেক্ষণ করতে এবং প্রতিক্রিয়া জানাতে এবং UDP বার্তা পাঠাতে, এবং সেইসাথে এই ক্রিয়াগুলিকে বাস্তব হার্ডওয়্যারে বোতাম এবং LED-এর সাথে সংযুক্ত করতে OpenThread API ব্যবহার করবেন।

তুমি কি শিখবে
- নর্ডিক nRF52840 ডেভ বোর্ডে বোতাম এবং LED কীভাবে প্রোগ্রাম করবেন
- সাধারণ OpenThread API এবং
otInstanceক্লাস কীভাবে ব্যবহার করবেন - ওপেনথ্রেড অবস্থার পরিবর্তনগুলি কীভাবে পর্যবেক্ষণ এবং প্রতিক্রিয়া জানাবেন
- থ্রেড নেটওয়ার্কের সকল ডিভাইসে UDP বার্তা কীভাবে পাঠাবেন
- মেকফাইল কিভাবে পরিবর্তন করবেন
তোমার যা লাগবে
হার্ডওয়্যার:
- ৩টি নর্ডিক সেমিকন্ডাক্টর nRF52840 ডেভ বোর্ড
- বোর্ডগুলি সংযুক্ত করার জন্য 3টি USB থেকে Micro-USB কেবল
- কমপক্ষে ৩টি USB পোর্ট সহ একটি লিনাক্স মেশিন
সফটওয়্যার:
- জিএনইউ টুলচেইন
- নর্ডিক nRF5x কমান্ড লাইন টুলস
- সেগার জে-লিংক সফটওয়্যার
- ওপেনথ্রেড
- গিট
অন্যথায় উল্লেখ করা ছাড়া, এই কোডল্যাবের বিষয়বস্তু ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন 3.0 লাইসেন্সের অধীনে লাইসেন্সপ্রাপ্ত, এবং কোড নমুনাগুলি অ্যাপাচি 2.0 লাইসেন্সের অধীনে লাইসেন্সপ্রাপ্ত ।
2. শুরু করা
হার্ডওয়্যার কোডল্যাব সম্পূর্ণ করুন
এই কোডল্যাবটি শুরু করার আগে, আপনার nRF52840 বোর্ড এবং ওপেনথ্রেড কোডল্যাব দিয়ে একটি থ্রেড নেটওয়ার্ক তৈরি করা সম্পূর্ণ করা উচিত, যা:
- বিল্ডিং এবং ফ্ল্যাশিংয়ের জন্য আপনার প্রয়োজনীয় সমস্ত সফ্টওয়্যারের বিশদ বিবরণ দিন।
- আপনাকে শেখায় কিভাবে OpenThread তৈরি করতে হয় এবং Nordic nRF52840 বোর্ডে ফ্ল্যাশ করতে হয়।
- থ্রেড নেটওয়ার্কের মূল বিষয়গুলি প্রদর্শন করে
ওপেনথ্রেড তৈরি এবং বোর্ড ফ্ল্যাশ করার জন্য প্রয়োজনীয় পরিবেশের কোনও সেটআপ এই কোডল্যাবে বিস্তারিতভাবে উল্লেখ করা হয়নি - বোর্ড ফ্ল্যাশ করার জন্য শুধুমাত্র মৌলিক নির্দেশাবলী। ধরে নেওয়া হচ্ছে যে আপনি ইতিমধ্যেই একটি থ্রেড নেটওয়ার্ক তৈরি করুন কোডল্যাব সম্পন্ন করেছেন।
লিনাক্স মেশিন
এই কোডল্যাবটি i386- অথবা x86-ভিত্তিক লিনাক্স মেশিন ব্যবহার করে সমস্ত থ্রেড ডেভেলপমেন্ট বোর্ড ফ্ল্যাশ করার জন্য ডিজাইন করা হয়েছিল। সমস্ত ধাপ উবুন্টু 14.04.5 LTS (Trusty Tahr) এ পরীক্ষা করা হয়েছিল।
নর্ডিক সেমিকন্ডাক্টর nRF52840 বোর্ড
এই কোডল্যাবটিতে তিনটি nRF52840 PDK বোর্ড ব্যবহার করা হয়েছে।

সফটওয়্যার ইনস্টল করুন
OpenThread তৈরি এবং ফ্ল্যাশ করার জন্য, আপনাকে SEGGER J-Link, nRF5x কমান্ড লাইন টুলস, ARM GNU টুলচেইন এবং বিভিন্ন Linux প্যাকেজ ইনস্টল করতে হবে। যদি আপনি প্রয়োজন অনুসারে Build a Thread Network Codelab সম্পন্ন করে থাকেন, তাহলে আপনার প্রয়োজনীয় সবকিছু ইতিমধ্যেই ইনস্টল করা থাকবে। যদি না হয়, তাহলে nRF52840 ডেভ বোর্ডে OpenThread তৈরি এবং ফ্ল্যাশ করতে পারেন তা নিশ্চিত করার জন্য চালিয়ে যাওয়ার আগে সেই Codelabটি সম্পূর্ণ করুন।
৩. সংগ্রহস্থলটি ক্লোন করুন
OpenThread-এ এমন একটি অ্যাপ্লিকেশন কোড রয়েছে যা আপনি এই কোডল্যাবের জন্য একটি সূচনা বিন্দু হিসেবে ব্যবহার করতে পারেন।
OpenThread নর্ডিক nRF528xx উদাহরণ রেপো ক্লোন করুন এবং OpenThread তৈরি করুন:
$ git clone --recursive https://github.com/openthread/ot-nrf528xx $ cd ot-nrf528xx $ ./script/bootstrap
৪. ওপেনথ্রেড এপিআই বেসিকস
OpenThread এর পাবলিক API গুলি OpenThread রিপোজিটরিতে ./openthread/include/openthread এ অবস্থিত। এই API গুলি আপনার অ্যাপ্লিকেশনগুলিতে ব্যবহারের জন্য থ্রেড- এবং প্ল্যাটফর্ম-স্তরে বিভিন্ন ধরণের OpenThread বৈশিষ্ট্য এবং কার্যকারিতা অ্যাক্সেস প্রদান করে:
- ওপেনথ্রেড ইনস্ট্যান্স তথ্য এবং নিয়ন্ত্রণ
- আইপিভি৬, ইউডিপি এবং কোএপির মতো অ্যাপ্লিকেশন পরিষেবা
- নেটওয়ার্ক শংসাপত্র ব্যবস্থাপনা, কমিশনার এবং জয়েনারের ভূমিকা সহ
- বর্ডার রাউটার ব্যবস্থাপনা
- শিশু তত্ত্বাবধান এবং জ্যাম সনাক্তকরণের মতো উন্নত বৈশিষ্ট্য
সকল OpenThread API-এর রেফারেন্স তথ্য openthread.io/reference ওয়েবসাইটে পাওয়া যাবে।
একটি API ব্যবহার করা
একটি API ব্যবহার করতে, আপনার অ্যাপ্লিকেশন ফাইলগুলির একটিতে এর হেডার ফাইলটি অন্তর্ভুক্ত করুন। তারপর পছন্দসই ফাংশনটি কল করুন।
উদাহরণস্বরূপ, OpenThread-এর সাথে অন্তর্ভুক্ত CLI উদাহরণ অ্যাপটি নিম্নলিখিত API হেডার ব্যবহার করে:
./openthread/examples/apps/cli/main.c
#include <openthread/config.h> #include <openthread/cli.h> #include <openthread/diag.h> #include <openthread/tasklet.h> #include <openthread/platform/logging.h>
ওপেনথ্রেড ইনস্ট্যান্স
OpenThread API গুলির সাথে কাজ করার সময় otInstance কাঠামোটি প্রায়শই ব্যবহার করা হবে। একবার শুরু হয়ে গেলে, এই কাঠামোটি OpenThread লাইব্রেরির একটি স্ট্যাটিক ইনস্ট্যান্স উপস্থাপন করে এবং ব্যবহারকারীকে OpenThread API কল করতে দেয়।
উদাহরণস্বরূপ, OpenThread ইনস্ট্যান্সটি CLI উদাহরণ অ্যাপের main() ফাংশনে ইনিশিয়ালাইজ করা হয়েছে:
./openthread/examples/apps/cli/main.c
int main(int argc, char *argv[])
{
otInstance *instance
...
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
// Call to query the buffer size
(void)otInstanceInit(NULL, &otInstanceBufferLength);
// Call to allocate the buffer
otInstanceBuffer = (uint8_t *)malloc(otInstanceBufferLength);
assert(otInstanceBuffer);
// Initialize OpenThread with the buffer
instance = otInstanceInit(otInstanceBuffer, &otInstanceBufferLength);
#else
instance = otInstanceInitSingle();
#endif
...
return 0;
}
প্ল্যাটফর্ম-নির্দিষ্ট ফাংশন
যদি আপনি OpenThread-এর সাথে অন্তর্ভুক্ত উদাহরণ অ্যাপ্লিকেশনগুলির মধ্যে একটিতে প্ল্যাটফর্ম-নির্দিষ্ট ফাংশন যোগ করতে চান, তাহলে প্রথমে ./openthread/examples/platforms/openthread-system.h হেডারে সমস্ত ফাংশনের জন্য otSys নেমস্পেস ব্যবহার করে সেগুলি ঘোষণা করুন। তারপর একটি প্ল্যাটফর্ম-নির্দিষ্ট সোর্স ফাইলে সেগুলি বাস্তবায়ন করুন। এইভাবে বিমূর্ত করে, আপনি অন্যান্য উদাহরণ প্ল্যাটফর্মের জন্য একই ফাংশন হেডার ব্যবহার করতে পারেন।
উদাহরণস্বরূপ, nRF52840 বোতাম এবং LED গুলিকে সংযুক্ত করার জন্য আমরা যে GPIO ফাংশনগুলি ব্যবহার করব সেগুলি openthread-system.h তে ঘোষণা করতে হবে।
আপনার পছন্দের টেক্সট এডিটরে ./openthread/examples/platforms/openthread-system.h ফাইলটি খুলুন।
./openthread/examples/platforms/openthread-system.h
পদক্ষেপ: প্ল্যাটফর্ম-নির্দিষ্ট GPIO ফাংশন ঘোষণা যোগ করুন।
openthread/instance.h হেডারের জন্য #include এর পরে এই ফাংশন ঘোষণাগুলি যোগ করুন:
/** * Init LED module. * */ void otSysLedInit(void); void otSysLedSet(uint8_t aLed, bool aOn); void otSysLedToggle(uint8_t aLed); /** * A callback will be called when GPIO interrupts occur. * */ typedef void (*otSysButtonCallback)(otInstance *aInstance); void otSysButtonInit(otSysButtonCallback aCallback); void otSysButtonProcess(otInstance *aInstance);
আমরা পরবর্তী ধাপে এগুলো বাস্তবায়ন করব।
মনে রাখবেন যে otSysButtonProcess ফাংশন ঘোষণায় একটি otInstance ব্যবহার করা হয়েছে। এইভাবে অ্যাপ্লিকেশনটি প্রয়োজনে একটি বোতাম টিপলে OpenThread ইনস্ট্যান্স সম্পর্কে তথ্য অ্যাক্সেস করতে পারে। এটি সব আপনার অ্যাপ্লিকেশনের প্রয়োজনীয়তার উপর নির্ভর করে। যদি আপনার ফাংশন বাস্তবায়নের জন্য এটির প্রয়োজন না হয়, তাহলে আপনি কিছু টুলচেইনের জন্য অব্যবহৃত ভেরিয়েবলের চারপাশে বিল্ড ত্রুটিগুলি দমন করতে OpenThread API থেকে OT_UNUSED_VARIABLE ম্যাক্রো ব্যবহার করতে পারেন। আমরা এর উদাহরণ পরে দেখব।
৫. GPIO প্ল্যাটফর্ম বিমূর্তকরণ বাস্তবায়ন করুন
পূর্ববর্তী ধাপে, আমরা ./openthread/examples/platforms/openthread-system.h এ প্ল্যাটফর্ম-নির্দিষ্ট ফাংশন ঘোষণাগুলি পর্যালোচনা করেছি যা GPIO-এর জন্য ব্যবহার করা যেতে পারে। nRF52840 ডেভ বোর্ডে বোতাম এবং LED অ্যাক্সেস করার জন্য, আপনাকে nRF52840 প্ল্যাটফর্মের জন্য সেই ফাংশনগুলি বাস্তবায়ন করতে হবে। এই কোডে, আপনি এমন ফাংশনগুলি যুক্ত করবেন যা:
- GPIO পিন এবং মোড শুরু করুন
- একটি পিনের ভোল্টেজ নিয়ন্ত্রণ করুন
- GPIO ইন্টারাপ্ট সক্রিয় করুন এবং একটি কলব্যাক নিবন্ধন করুন
./src/src ডিরেক্টরিতে, gpio.c নামে একটি নতুন ফাইল তৈরি করুন। এই নতুন ফাইলে, নিম্নলিখিত বিষয়বস্তু যোগ করুন।
./src/src/gpio.c (নতুন ফাইল)
ক্রিয়া: সংজ্ঞা যোগ করুন।
এই সংজ্ঞাগুলি nRF52840-নির্দিষ্ট মান এবং OpenThread অ্যাপ্লিকেশন স্তরে ব্যবহৃত ভেরিয়েবলের মধ্যে বিমূর্ততা হিসাবে কাজ করে।
/** * @file * This file implements the system abstraction for GPIO and GPIOTE. * */ #define BUTTON_GPIO_PORT 0x50000300UL #define BUTTON_PIN 11 // button #1 #define GPIO_LOGIC_HI 0 #define GPIO_LOGIC_LOW 1 #define LED_GPIO_PORT 0x50000300UL #define LED_1_PIN 13 // turn on to indicate leader role #define LED_2_PIN 14 // turn on to indicate router role #define LED_3_PIN 15 // turn on to indicate child role #define LED_4_PIN 16 // turn on to indicate UDP receive
nRF52840 বোতাম এবং LED সম্পর্কে আরও তথ্যের জন্য, নর্ডিক সেমিকন্ডাক্টর ইনফোসেন্টার দেখুন।
ক্রিয়া: শিরোনাম যোগ করুন।
এরপর, GPIO কার্যকারিতার জন্য আপনার প্রয়োজনীয় হেডার অন্তর্ভুক্তগুলি যোগ করুন।
/* Header for the functions defined here */ #include "openthread-system.h" #include <string.h> /* Header to access an OpenThread instance */ #include <openthread/instance.h> /* Headers for lower-level nRF52840 functions */ #include "platform-nrf5.h" #include "hal/nrf_gpio.h" #include "hal/nrf_gpiote.h" #include "nrfx/drivers/include/nrfx_gpiote.h"
ক্রিয়া: বোতাম ১ এর জন্য কলব্যাক এবং ইন্টারাপ্ট ফাংশন যোগ করুন।
পরবর্তীতে এই কোডটি যোগ করুন। in_pin1_handler ফাংশন হল কলব্যাক যা বোতাম প্রেস কার্যকারিতা শুরু করার সময় নিবন্ধিত হয় (পরে এই ফাইলে)।
লক্ষ্য করুন কিভাবে এই কলব্যাকটি OT_UNUSED_VARIABLE ম্যাক্রো ব্যবহার করে, কারণ in_pin1_handler এ পাস করা ভেরিয়েবলগুলি আসলে ফাংশনে ব্যবহৃত হয় না।
/* Declaring callback function for button 1. */
static otSysButtonCallback sButtonHandler;
static bool sButtonPressed;
/**
* @brief Function to receive interrupt and call back function
* set by the application for button 1.
*
*/
static void in_pin1_handler(uint32_t pin, nrf_gpiote_polarity_t action)
{
OT_UNUSED_VARIABLE(pin);
OT_UNUSED_VARIABLE(action);
sButtonPressed = true;
}
পদক্ষেপ: LED গুলি কনফিগার করার জন্য একটি ফাংশন যোগ করুন।
ইনিশিয়ালাইজেশনের সময় সমস্ত LED এর মোড এবং অবস্থা কনফিগার করতে এই কোডটি যোগ করুন।
/**
* @brief Function for configuring: PIN_IN pin for input, PIN_OUT pin for output,
* and configures GPIOTE to give an interrupt on pin change.
*/
void otSysLedInit(void)
{
/* Configure GPIO mode: output */
nrf_gpio_cfg_output(LED_1_PIN);
nrf_gpio_cfg_output(LED_2_PIN);
nrf_gpio_cfg_output(LED_3_PIN);
nrf_gpio_cfg_output(LED_4_PIN);
/* Clear all output first */
nrf_gpio_pin_write(LED_1_PIN, GPIO_LOGIC_LOW);
nrf_gpio_pin_write(LED_2_PIN, GPIO_LOGIC_LOW);
nrf_gpio_pin_write(LED_3_PIN, GPIO_LOGIC_LOW);
nrf_gpio_pin_write(LED_4_PIN, GPIO_LOGIC_LOW);
/* Initialize gpiote for button(s) input.
Button event handlers are set in the application (main.c) */
ret_code_t err_code;
err_code = nrfx_gpiote_init();
APP_ERROR_CHECK(err_code);
}
ক্রিয়া: একটি LED এর মোড সেট করার জন্য একটি ফাংশন যোগ করুন।
ডিভাইসের ভূমিকা পরিবর্তন হলে এই ফাংশনটি ব্যবহার করা হবে।
/**
* @brief Function to set the mode of an LED.
*/
void otSysLedSet(uint8_t aLed, bool aOn)
{
switch (aLed)
{
case 1:
nrf_gpio_pin_write(LED_1_PIN, (aOn == GPIO_LOGIC_HI));
break;
case 2:
nrf_gpio_pin_write(LED_2_PIN, (aOn == GPIO_LOGIC_HI));
break;
case 3:
nrf_gpio_pin_write(LED_3_PIN, (aOn == GPIO_LOGIC_HI));
break;
case 4:
nrf_gpio_pin_write(LED_4_PIN, (aOn == GPIO_LOGIC_HI));
break;
}
}
ক্রিয়া: একটি LED এর মোড টগল করার জন্য একটি ফাংশন যোগ করুন।
ডিভাইসটি যখন মাল্টিকাস্ট UDP বার্তা পাবে তখন LED4 টগল করতে এই ফাংশনটি ব্যবহার করা হবে।
/**
* @brief Function to toggle the mode of an LED.
*/
void otSysLedToggle(uint8_t aLed)
{
switch (aLed)
{
case 1:
nrf_gpio_pin_toggle(LED_1_PIN);
break;
case 2:
nrf_gpio_pin_toggle(LED_2_PIN);
break;
case 3:
nrf_gpio_pin_toggle(LED_3_PIN);
break;
case 4:
nrf_gpio_pin_toggle(LED_4_PIN);
break;
}
}
ক্রিয়া: বোতাম টিপে শুরু এবং প্রক্রিয়া করার জন্য ফাংশন যোগ করুন।
প্রথম ফাংশনটি বোতাম টিপে বোর্ডটি চালু করে, এবং দ্বিতীয়টি বোতাম 1 টিপলে মাল্টিকাস্ট UDP বার্তা পাঠায়।
/**
* @brief Function to initialize the button.
*/
void otSysButtonInit(otSysButtonCallback aCallback)
{
nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
in_config.pull = NRF_GPIO_PIN_PULLUP;
ret_code_t err_code;
err_code = nrfx_gpiote_in_init(BUTTON_PIN, &in_config, in_pin1_handler);
APP_ERROR_CHECK(err_code);
sButtonHandler = aCallback;
sButtonPressed = false;
nrfx_gpiote_in_event_enable(BUTTON_PIN, true);
}
void otSysButtonProcess(otInstance *aInstance)
{
if (sButtonPressed)
{
sButtonPressed = false;
sButtonHandler(aInstance);
}
}
পদক্ষেপ: gpio.c ফাইলটি সংরক্ষণ করুন এবং বন্ধ করুন।
৬. API: ডিভাইসের ভূমিকা পরিবর্তনের প্রতিক্রিয়া দেখান
আমাদের অ্যাপ্লিকেশনে, আমরা ডিভাইসের ভূমিকার উপর নির্ভর করে বিভিন্ন LED জ্বলতে চাই। আসুন নিম্নলিখিত ভূমিকাগুলি ট্র্যাক করি: লিডার, রাউটার, এন্ড ডিভাইস। আমরা এগুলিকে LED-তে এইভাবে বরাদ্দ করতে পারি:
- LED1 = লিডার
- LED2 = রাউটার
- LED3 = শেষ ডিভাইস
এই কার্যকারিতা সক্ষম করার জন্য, অ্যাপ্লিকেশনটিকে জানতে হবে কখন ডিভাইসের ভূমিকা পরিবর্তন হয়েছে এবং প্রতিক্রিয়ায় সঠিক LED কীভাবে চালু করতে হবে। আমরা প্রথম অংশের জন্য OpenThread ইনস্ট্যান্স এবং দ্বিতীয় অংশের জন্য GPIO প্ল্যাটফর্ম অ্যাবস্ট্রাকশন ব্যবহার করব।
আপনার পছন্দের টেক্সট এডিটরে ./openthread/examples/apps/cli/main.c ফাইলটি খুলুন।
./openthread/examples/apps/cli/main.c
ক্রিয়া: শিরোনাম যোগ করুন।
main.c ফাইলের "Includes" বিভাগে, ভূমিকা পরিবর্তন বৈশিষ্ট্যের জন্য আপনার প্রয়োজনীয় API হেডার ফাইলগুলি যোগ করুন।
#include <openthread/instance.h> #include <openthread/thread.h> #include <openthread/thread_ftd.h>
ক্রিয়া: OpenThread ইনস্ট্যান্স স্টেট পরিবর্তনের জন্য হ্যান্ডলার ফাংশন ঘোষণা যোগ করুন।
এই ঘোষণাটি main.c তে যোগ করুন, হেডার অন্তর্ভুক্ত করার পরে এবং যেকোনো #if স্টেটমেন্টের আগে। এই ফাংশনটি main অ্যাপ্লিকেশনের পরে সংজ্ঞায়িত করা হবে।
void handleNetifStateChanged(uint32_t aFlags, void *aContext);
ক্রিয়া: স্টেট চেঞ্জ হ্যান্ডলার ফাংশনের জন্য একটি কলব্যাক নিবন্ধন যোগ করুন।
main.c তে, otAppCliInit কলের পরে main() ফাংশনে এই ফাংশনটি যোগ করুন। এই কলব্যাক রেজিস্ট্রেশনটি OpenThread কে OpenThread ইনস্ট্যান্স স্টেট পরিবর্তন হলে handleNetifStateChange ফাংশনটি কল করতে বলে।
/* Register Thread state change handler */ otSetStateChangedCallback(instance, handleNetifStateChanged, instance);
পদক্ষেপ: রাজ্য পরিবর্তন বাস্তবায়ন যোগ করুন।
main.c তে, main() ফাংশনের পরে, handleNetifStateChanged ফাংশনটি প্রয়োগ করুন। এই ফাংশনটি OpenThread ইনস্ট্যান্সের OT_CHANGED_THREAD_ROLE ফ্ল্যাগটি পরীক্ষা করে এবং যদি এটি পরিবর্তিত হয়ে থাকে, তাহলে প্রয়োজন অনুসারে LED চালু/বন্ধ করে।
void handleNetifStateChanged(uint32_t aFlags, void *aContext)
{
if ((aFlags & OT_CHANGED_THREAD_ROLE) != 0)
{
otDeviceRole changedRole = otThreadGetDeviceRole(aContext);
switch (changedRole)
{
case OT_DEVICE_ROLE_LEADER:
otSysLedSet(1, true);
otSysLedSet(2, false);
otSysLedSet(3, false);
break;
case OT_DEVICE_ROLE_ROUTER:
otSysLedSet(1, false);
otSysLedSet(2, true);
otSysLedSet(3, false);
break;
case OT_DEVICE_ROLE_CHILD:
otSysLedSet(1, false);
otSysLedSet(2, false);
otSysLedSet(3, true);
break;
case OT_DEVICE_ROLE_DETACHED:
case OT_DEVICE_ROLE_DISABLED:
/* Clear LED4 if Thread is not enabled. */
otSysLedSet(4, false);
break;
}
}
}
৭. API: LED চালু করতে মাল্টিকাস্ট ব্যবহার করুন
আমাদের অ্যাপ্লিকেশনে, আমরা নেটওয়ার্কের অন্যান্য সমস্ত ডিভাইসে UDP বার্তা পাঠাতে চাই যখন একটি বোর্ডে Button1 চাপা হয়। বার্তা প্রাপ্তি নিশ্চিত করতে, আমরা প্রতিক্রিয়া হিসাবে অন্যান্য বোর্ডগুলিতে LED4 টগল করব।
এই কার্যকারিতা সক্ষম করতে, অ্যাপ্লিকেশনটির প্রয়োজন:
- শুরু করার সময় একটি UDP সংযোগ শুরু করুন
- মেশ-স্থানীয় মাল্টিকাস্ট ঠিকানায় একটি UDP বার্তা পাঠাতে সক্ষম হবেন
- ইনকামিং UDP বার্তাগুলি পরিচালনা করুন
- আগত UDP বার্তাগুলির প্রতিক্রিয়ায় LED4 টগল করুন
আপনার পছন্দের টেক্সট এডিটরে ./openthread/examples/apps/cli/main.c ফাইলটি খুলুন।
./openthread/examples/apps/cli/main.c
ক্রিয়া: শিরোনাম যোগ করুন।
main.c ফাইলের উপরের অংশে "Includes" বিভাগে, মাল্টিকাস্ট UDP বৈশিষ্ট্যের জন্য আপনার প্রয়োজনীয় API হেডার ফাইলগুলি যোগ করুন।
#include <string.h> #include <openthread/message.h> #include <openthread/udp.h> #include "utils/code_utils.h"
code_utils.h হেডারটি otEXPECT এবং otEXPECT_ACTION ম্যাক্রোগুলির জন্য ব্যবহৃত হয় যা রান-টাইম শর্তগুলি যাচাই করে এবং সুন্দরভাবে ত্রুটিগুলি পরিচালনা করে।
ক্রিয়া: সংজ্ঞা এবং ধ্রুবক যোগ করুন:
main.c ফাইলে, includes বিভাগের পরে এবং যেকোনো #if স্টেটমেন্টের আগে, UDP-নির্দিষ্ট ধ্রুবক যোগ করুন এবং সংজ্ঞায়িত করুন:
#define UDP_PORT 1212 static const char UDP_DEST_ADDR[] = "ff03::1"; static const char UDP_PAYLOAD[] = "Hello OpenThread World!";
ff03::1 হল মেশ-স্থানীয় মাল্টিকাস্ট ঠিকানা। এই ঠিকানায় প্রেরিত যেকোনো বার্তা নেটওয়ার্কের সমস্ত ফুল থ্রেড ডিভাইসে পাঠানো হবে। OpenThread-এ মাল্টিকাস্ট সমর্থন সম্পর্কে আরও তথ্যের জন্য openthread.io-তে মাল্টিকাস্ট দেখুন।
ক্রিয়া: ফাংশন ঘোষণা যোগ করুন।
main.c ফাইলে, otTaskletsSignalPending সংজ্ঞার পরে এবং main() ফাংশনের আগে, UDP-নির্দিষ্ট ফাংশন যোগ করুন, সেইসাথে একটি UDP সকেট উপস্থাপন করার জন্য একটি স্ট্যাটিক ভেরিয়েবল যোগ করুন:
static void initUdp(otInstance *aInstance);
static void sendUdp(otInstance *aInstance);
static void handleButtonInterrupt(otInstance *aInstance);
void handleUdpReceive(void *aContext, otMessage *aMessage,
const otMessageInfo *aMessageInfo);
static otUdpSocket sUdpSocket;
পদক্ষেপ: GPIO LED এবং বোতামটি চালু করতে কল যোগ করুন।
main.c তে, otSetStateChangedCallback কলের পরে main() ফাংশনে এই ফাংশন কলগুলি যোগ করুন। এই ফাংশনগুলি GPIO এবং GPIOTE পিনগুলিকে ইনিশিয়ালাইজ করে এবং বোতাম পুশ ইভেন্টগুলি পরিচালনা করার জন্য একটি বোতাম হ্যান্ডলার সেট করে।
/* init GPIO LEDs and button */ otSysLedInit(); otSysButtonInit(handleButtonInterrupt);
ক্রিয়া: UDP ইনিশিয়ালাইজেশন কল যোগ করুন।
main.c তে, আপনার যোগ করা otSysButtonInit কলের পরে main() ফাংশনে এই ফাংশনটি যোগ করুন:
initUdp(instance);
এই কলটি নিশ্চিত করে যে অ্যাপ্লিকেশন শুরু হওয়ার সাথে সাথে একটি UDP সকেট শুরু হয়েছে। এটি ছাড়া, ডিভাইসটি UDP বার্তা পাঠাতে বা গ্রহণ করতে পারবে না।
ক্রিয়া: GPIO বোতাম ইভেন্ট প্রক্রিয়া করার জন্য কল যোগ করুন।
main.c তে, while লুপে otSysProcessDrivers কলের পরে main() ফাংশনে এই ফাংশন কলটি যোগ করুন। gpio.c তে ঘোষিত এই ফাংশনটি বোতামটি চাপা হয়েছে কিনা তা পরীক্ষা করে এবং যদি তাই হয়, তাহলে উপরের ধাপে সেট করা হ্যান্ডলার ( handleButtonInterrupt ) কে কল করে।
otSysButtonProcess(instance);
ক্রিয়া: বোতাম ইন্টারাপ্ট হ্যান্ডলার বাস্তবায়ন করুন।
main.c তে, আগের ধাপে যোগ করা handleNetifStateChanged ফাংশনের পরে handleButtonInterrupt ফাংশনের বাস্তবায়ন যোগ করুন:
/**
* Function to handle button push event
*/
void handleButtonInterrupt(otInstance *aInstance)
{
sendUdp(aInstance);
}
পদক্ষেপ: UDP ইনিশিয়ালাইজেশন বাস্তবায়ন করুন।
main.c তে, handleButtonInterrupt ফাংশনের পরে initUdp ফাংশনের বাস্তবায়ন যোগ করুন:
/**
* Initialize UDP socket
*/
void initUdp(otInstance *aInstance)
{
otSockAddr listenSockAddr;
memset(&sUdpSocket, 0, sizeof(sUdpSocket));
memset(&listenSockAddr, 0, sizeof(listenSockAddr));
listenSockAddr.mPort = UDP_PORT;
otUdpOpen(aInstance, &sUdpSocket, handleUdpReceive, aInstance);
otUdpBind(aInstance, &sUdpSocket, &listenSockAddr, OT_NETIF_THREAD);
}
UDP_PORT হল সেই পোর্ট যা আপনি আগে সংজ্ঞায়িত করেছিলেন (1212)। otUdpOpen ফাংশনটি সকেটটি খোলে এবং একটি কলব্যাক ফাংশন ( handleUdpReceive ) নিবন্ধন করে যখন একটি UDP বার্তা প্রাপ্ত হয়। otUdpBind OT_NETIF_THREAD পাস করে সকেটটিকে থ্রেড নেটওয়ার্ক ইন্টারফেসের সাথে আবদ্ধ করে। অন্যান্য নেটওয়ার্ক ইন্টারফেস বিকল্পগুলির জন্য, UDP API Reference এ otNetifIdentifier গণনা দেখুন।
পদক্ষেপ: UDP মেসেজিং বাস্তবায়ন করুন।
main.c তে, আপনার যোগ করা initUdp ফাংশনের পরে sendUdp ফাংশনের বাস্তবায়ন যোগ করুন:
/**
* Send a UDP datagram
*/
void sendUdp(otInstance *aInstance)
{
otError error = OT_ERROR_NONE;
otMessage * message;
otMessageInfo messageInfo;
otIp6Address destinationAddr;
memset(&messageInfo, 0, sizeof(messageInfo));
otIp6AddressFromString(UDP_DEST_ADDR, &destinationAddr);
messageInfo.mPeerAddr = destinationAddr;
messageInfo.mPeerPort = UDP_PORT;
message = otUdpNewMessage(aInstance, NULL);
otEXPECT_ACTION(message != NULL, error = OT_ERROR_NO_BUFS);
error = otMessageAppend(message, UDP_PAYLOAD, sizeof(UDP_PAYLOAD));
otEXPECT(error == OT_ERROR_NONE);
error = otUdpSend(aInstance, &sUdpSocket, message, &messageInfo);
exit:
if (error != OT_ERROR_NONE && message != NULL)
{
otMessageFree(message);
}
}
otEXPECT এবং otEXPECT_ACTION ম্যাক্রোগুলি লক্ষ্য করুন। এগুলি নিশ্চিত করে যে UDP বার্তাটি বৈধ এবং বাফারে সঠিকভাবে বরাদ্দ করা হয়েছে, এবং যদি তা না হয়, তাহলে ফাংশনটি exit ব্লকে লাফিয়ে ত্রুটিগুলি সুন্দরভাবে পরিচালনা করে, যেখানে এটি বাফারটি মুক্ত করে।
UDP আরম্ভ করার জন্য ব্যবহৃত ফাংশন সম্পর্কে আরও তথ্যের জন্য openthread.io-তে IPv6 এবং UDP রেফারেন্স দেখুন।
পদক্ষেপ: UDP বার্তা পরিচালনা বাস্তবায়ন করুন।
main.c তে, আপনার যোগ করা sendUdp ফাংশনের পরে handleUdpReceive ফাংশনের বাস্তবায়ন যোগ করুন। এই ফাংশনটি কেবল LED4 টগল করে।
/**
* Function to handle UDP datagrams received on the listening socket
*/
void handleUdpReceive(void *aContext, otMessage *aMessage,
const otMessageInfo *aMessageInfo)
{
OT_UNUSED_VARIABLE(aContext);
OT_UNUSED_VARIABLE(aMessage);
OT_UNUSED_VARIABLE(aMessageInfo);
otSysLedToggle(4);
}
৮. API: থ্রেড নেটওয়ার্ক কনফিগার করুন
সহজে প্রদর্শনের জন্য, আমরা চাই আমাদের ডিভাইসগুলি অবিলম্বে থ্রেড শুরু করুক এবং চালু হওয়ার সাথে সাথে একটি নেটওয়ার্কে একত্রিত হোক। এটি করার জন্য, আমরা otOperationalDataset কাঠামো ব্যবহার করব। এই কাঠামোটি একটি ডিভাইসে থ্রেড নেটওয়ার্ক শংসাপত্র প্রেরণের জন্য প্রয়োজনীয় সমস্ত পরামিতি ধারণ করে।
এই কাঠামোর ব্যবহার OpenThread-এ বিল্ট-ইন নেটওয়ার্ক ডিফল্টগুলিকে ওভাররাইড করবে, যার ফলে আমাদের অ্যাপ্লিকেশনটি আরও সুরক্ষিত হবে এবং আমাদের নেটওয়ার্কে থ্রেড নোডগুলি কেবলমাত্র অ্যাপ্লিকেশনটি চালানোর ক্ষেত্রে সীমাবদ্ধ থাকবে।
আবার, আপনার পছন্দের টেক্সট এডিটরে ./openthread/examples/apps/cli/main.c ফাইলটি খুলুন।
./openthread/examples/apps/cli/main.c
ক্রিয়া: হেডার অন্তর্ভুক্ত যোগ করুন।
main.c ফাইলের উপরের অংশে "includes" অংশের মধ্যে, Thread নেটওয়ার্ক কনফিগার করার জন্য আপনার প্রয়োজনীয় API হেডার ফাইলটি যোগ করুন:
#include <openthread/dataset_ftd.h>
ক্রিয়া: নেটওয়ার্ক কনফিগারেশন সেট করার জন্য ফাংশন ঘোষণা যোগ করুন।
হেডার অন্তর্ভুক্ত করার পরে এবং যেকোনো #if স্টেটমেন্টের আগে main.c তে এই ঘোষণাটি যোগ করুন। এই ফাংশনটি main অ্যাপ্লিকেশন ফাংশনের পরে সংজ্ঞায়িত করা হবে।
static void setNetworkConfiguration(otInstance *aInstance);
ক্রিয়া: নেটওয়ার্ক কনফিগারেশন কল যোগ করুন।
main.c তে, otSetStateChangedCallback কলের পরে main() ফাংশনে এই ফাংশন কলটি যোগ করুন। এই ফাংশনটি থ্রেড নেটওয়ার্ক ডেটাসেট কনফিগার করে।
/* Override default network credentials */ setNetworkConfiguration(instance);
ক্রিয়া: থ্রেড নেটওয়ার্ক ইন্টারফেস এবং স্ট্যাক সক্ষম করতে কল যোগ করুন।
main.c তে, otSysButtonInit কলের পরে main() ফাংশনে এই ফাংশন কলগুলি যোগ করুন।
/* Start the Thread network interface (CLI cmd > ifconfig up) */ otIp6SetEnabled(instance, true); /* Start the Thread stack (CLI cmd > thread start) */ otThreadSetEnabled(instance, true);
পদক্ষেপ: থ্রেড নেটওয়ার্ক কনফিগারেশন বাস্তবায়ন করুন।
main.c তে, main() ফাংশনের পরে setNetworkConfiguration ফাংশনের বাস্তবায়ন যোগ করুন:
/**
* Override default network settings, such as panid, so the devices can join a
network
*/
void setNetworkConfiguration(otInstance *aInstance)
{
static char aNetworkName[] = "OTCodelab";
otOperationalDataset aDataset;
memset(&aDataset, 0, sizeof(otOperationalDataset));
/*
* Fields that can be configured in otOperationDataset to override defaults:
* Network Name, Mesh Local Prefix, Extended PAN ID, PAN ID, Delay Timer,
* Channel, Channel Mask Page 0, Network Key, PSKc, Security Policy
*/
aDataset.mActiveTimestamp.mSeconds = 1;
aDataset.mActiveTimestamp.mTicks = 0;
aDataset.mActiveTimestamp.mAuthoritative = false;
aDataset.mComponents.mIsActiveTimestampPresent = true;
/* Set Channel to 15 */
aDataset.mChannel = 15;
aDataset.mComponents.mIsChannelPresent = true;
/* Set Pan ID to 2222 */
aDataset.mPanId = (otPanId)0x2222;
aDataset.mComponents.mIsPanIdPresent = true;
/* Set Extended Pan ID to C0DE1AB5C0DE1AB5 */
uint8_t extPanId[OT_EXT_PAN_ID_SIZE] = {0xC0, 0xDE, 0x1A, 0xB5, 0xC0, 0xDE, 0x1A, 0xB5};
memcpy(aDataset.mExtendedPanId.m8, extPanId, sizeof(aDataset.mExtendedPanId));
aDataset.mComponents.mIsExtendedPanIdPresent = true;
/* Set network key to 1234C0DE1AB51234C0DE1AB51234C0DE */
uint8_t key[OT_NETWORK_KEY_SIZE] = {0x12, 0x34, 0xC0, 0xDE, 0x1A, 0xB5, 0x12, 0x34, 0xC0, 0xDE, 0x1A, 0xB5, 0x12, 0x34, 0xC0, 0xDE};
memcpy(aDataset.mNetworkKey.m8, key, sizeof(aDataset.mNetworkKey));
aDataset.mComponents.mIsNetworkKeyPresent = true;
/* Set Network Name to OTCodelab */
size_t length = strlen(aNetworkName);
assert(length <= OT_NETWORK_NAME_MAX_SIZE);
memcpy(aDataset.mNetworkName.m8, aNetworkName, length);
aDataset.mComponents.mIsNetworkNamePresent = true;
otDatasetSetActive(aInstance, &aDataset);
/* Set the router selection jitter to override the 2 minute default.
CLI cmd > routerselectionjitter 20
Warning: For demo purposes only - not to be used in a real product */
uint8_t jitterValue = 20;
otThreadSetRouterSelectionJitter(aInstance, jitterValue);
}
ফাংশনে বিস্তারিতভাবে উল্লেখ করা হয়েছে, এই অ্যাপ্লিকেশনের জন্য আমরা যে থ্রেড নেটওয়ার্ক প্যারামিটারগুলি ব্যবহার করছি তা হল:
- চ্যানেল = ১৫
- প্যান আইডি = ০x২২২২
- বর্ধিত প্যান আইডি = C0DE1AB5C0DE1AB5
- নেটওয়ার্ক কী = 1234C0DE1AB51234C0DE1AB51234C0DE
- নেটওয়ার্কের নাম = OTCodelab
এছাড়াও, এখানেই আমরা রাউটার সিলেকশন জিটার কমিয়ে দেই, যাতে আমাদের ডিভাইসগুলি ডেমোর উদ্দেশ্যে দ্রুত ভূমিকা পরিবর্তন করে। মনে রাখবেন যে এটি কেবল তখনই করা হয় যদি নোডটি একটি FTD (ফুল থ্রেড ডিভাইস) হয়। পরবর্তী ধাপে এই সম্পর্কে আরও জানুন।
৯. API: সীমাবদ্ধ ফাংশন
OpenThread-এর কিছু API এমন সেটিংস পরিবর্তন করে যা শুধুমাত্র ডেমো বা পরীক্ষার উদ্দেশ্যে পরিবর্তন করা উচিত। OpenThread ব্যবহার করে কোনও অ্যাপ্লিকেশনের উৎপাদন স্থাপনে এই API ব্যবহার করা উচিত নয়।
উদাহরণস্বরূপ, otThreadSetRouterSelectionJitter ফাংশনটি একটি End Device-কে রাউটারে প্রচার করতে যে সময় লাগে (সেকেন্ডে) তা সামঞ্জস্য করে। Thread Specification অনুসারে, এই মানের ডিফল্ট মান হল 120। এই কোডল্যাবে ব্যবহারের সুবিধার জন্য, আমরা এটিকে 20 এ পরিবর্তন করতে যাচ্ছি, যাতে আপনাকে Thread node-এর ভূমিকা পরিবর্তনের জন্য খুব বেশি সময় অপেক্ষা করতে না হয়।
দ্রষ্টব্য: MTD ডিভাইসগুলি রাউটারে পরিণত হয় না, এবং otThreadSetRouterSelectionJitter এর মতো ফাংশনের জন্য সমর্থন MTD বিল্ডে অন্তর্ভুক্ত নয়। পরে আমাদের CMake বিকল্প -DOT_MTD=OFF নির্দিষ্ট করতে হবে, অন্যথায় আমরা একটি বিল্ড ব্যর্থতার সম্মুখীন হব।
আপনি otThreadSetRouterSelectionJitter ফাংশন সংজ্ঞাটি দেখে এটি নিশ্চিত করতে পারেন, যা OPENTHREAD_FTD এর একটি প্রিপ্রসেসর নির্দেশিকার মধ্যে রয়েছে:
./openthread/src/core/api/thread_ftd_api.cpp
#if OPENTHREAD_FTD
#include <openthread/thread_ftd.h>
...
void otThreadSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter)
{
Instance &instance = *static_cast<Instance *>(aInstance);
instance.GetThreadNetif().GetMle().SetRouterSelectionJitter(aRouterJitter);
}
...
#endif // OPENTHREAD_FTD
১০. সিমেক আপডেট
আপনার অ্যাপ্লিকেশন তৈরি করার আগে, তিনটি CMake ফাইলের জন্য কয়েকটি ছোটখাটো আপডেট প্রয়োজন। এগুলি বিল্ড সিস্টেম দ্বারা আপনার অ্যাপ্লিকেশন কম্পাইল এবং লিঙ্ক করার জন্য ব্যবহৃত হয়।
./third_party/NordicSemiconductor/CMakeLists.txt
এখন NordicSemiconductor CMakeLists.txt এ কিছু ফ্ল্যাগ যোগ করুন, যাতে অ্যাপ্লিকেশনটিতে GPIO ফাংশনগুলি সংজ্ঞায়িত করা যায়।
ক্রিয়া: CMakeLists.txt ফাইলে পতাকা যোগ করুন।
আপনার পছন্দের টেক্সট এডিটরে ./third_party/NordicSemiconductor/CMakeLists.txt খুলুন এবং COMMON_FLAG বিভাগে নিম্নলিখিত লাইনগুলি যোগ করুন।
...
set(COMMON_FLAG
-DSPIS_ENABLED=1
-DSPIS0_ENABLED=1
-DNRFX_SPIS_ENABLED=1
-DNRFX_SPIS0_ENABLED=1
...
# Defined in ./third_party/NordicSemiconductor/nrfx/templates/nRF52840/nrfx_config.h
-DGPIOTE_ENABLED=1
-DGPIOTE_CONFIG_IRQ_PRIORITY=7
-DGPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS=1
)
...
./src/CMakeLists.txt
নতুন gpio.c সোর্স ফাইল যোগ করতে ./src/CMakeLists.txt ফাইলটি সম্পাদনা করুন:
পদক্ষেপ: ./src/CMakeLists.txt ফাইলে gpio সোর্স যোগ করুন ।
আপনার পছন্দের টেক্সট এডিটরে ./src/CMakeLists.txt খুলুন এবং ফাইলটি NRF_COMM_SOURCES বিভাগে যুক্ত করুন।
... set(NRF_COMM_SOURCES ... src/gpio.c ... ) ...
./third_party/NordicSemiconductor/CMakeLists.txt
সবশেষে, nrfx_gpiote.c ড্রাইভার ফাইলটি NordicSemiconductor CMakeLists.txt ফাইলে যোগ করুন, যাতে এটি নর্ডিক ড্রাইভারের লাইব্রেরি বিল্ডের সাথে অন্তর্ভুক্ত থাকে।
পদক্ষেপ: NordicSemiconductor CMakeLists.txt ফাইলে gpio ড্রাইভার যোগ করুন ।
আপনার পছন্দের টেক্সট এডিটরে ./third_party/NordicSemiconductor/CMakeLists.txt খুলুন এবং ফাইলটি COMMON_SOURCES বিভাগে যোগ করুন।
... set(COMMON_SOURCES ... nrfx/drivers/src/nrfx_gpiote.c ... ) ...
১১. ডিভাইসগুলি সেট আপ করুন
সমস্ত কোড আপডেট সম্পন্ন হওয়ার পর, আপনি তিনটি নর্ডিক nRF52840 ডেভ বোর্ডে অ্যাপ্লিকেশনটি তৈরি এবং ফ্ল্যাশ করতে প্রস্তুত। প্রতিটি ডিভাইস একটি ফুল থ্রেড ডিভাইস (FTD) হিসেবে কাজ করবে।
ওপেনথ্রেড তৈরি করুন
nRF52840 প্ল্যাটফর্মের জন্য OpenThread FTD বাইনারি তৈরি করুন।
$ cd ~/ot-nrf528xx $ ./script/build nrf52840 UART_trans -DOT_MTD=OFF -DOT_APP_RCP=OFF -DOT_RCP=OFF
OpenThread FTD CLI বাইনারি সহ ডিরেক্টরিতে নেভিগেট করুন এবং ARM Embedded Toolchain ব্যবহার করে এটিকে হেক্স ফর্ম্যাটে রূপান্তর করুন:
$ cd build/bin $ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex
বোর্ডগুলো ফ্ল্যাশ করো
প্রতিটি nRF52840 বোর্ডে ot-cli-ftd.hex ফাইলটি ফ্ল্যাশ করুন।
nRF52840 বোর্ডের বাহ্যিক পাওয়ার পিনের পাশে থাকা মাইক্রো-USB ডিবাগ পোর্টে USB কেবলটি সংযুক্ত করুন এবং তারপর এটি আপনার Linux মেশিনে প্লাগ করুন। সঠিকভাবে সেট করুন, LED5 চালু আছে।

আগের মতো, nRF52840 বোর্ডের সিরিয়াল নম্বরটি লক্ষ্য করুন:

nRFx কমান্ড লাইন টুলের অবস্থানে যান এবং বোর্ডের সিরিয়াল নম্বর ব্যবহার করে nRF52840 বোর্ডে OpenThread CLI FTD হেক্স ফাইলটি ফ্ল্যাশ করুন:
$ cd ~/nrfjprog
$ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \
~/openthread/output/nrf52840/bin/ot-cli-ftd.hex --reset
ফ্ল্যাশ করার সময় LED5 কিছুক্ষণের জন্য বন্ধ হয়ে যাবে। সফল হলে নিম্নলিখিত আউটপুট তৈরি হবে:
Parsing hex file. Erasing user available code and UICR flash areas. Applying system reset. Checking that the area to write is not protected. Programing device. Applying system reset. Run.
অন্য দুটি বোর্ডের জন্য "ফ্ল্যাশ দ্য বোর্ড" ধাপটি পুনরাবৃত্তি করুন। প্রতিটি বোর্ড একইভাবে লিনাক্স মেশিনের সাথে সংযুক্ত থাকা উচিত এবং ফ্ল্যাশ করার কমান্ড একই, বোর্ডের সিরিয়াল নম্বর ব্যতীত। প্রতিটি বোর্ডের অনন্য সিরিয়াল নম্বর ব্যবহার করতে ভুলবেন না।
nrfjprog ফ্ল্যাশিং কমান্ড।
সফল হলে, প্রতিটি বোর্ডে LED1, LED2, অথবা LED3 জ্বলবে। এমনকি ফ্ল্যাশ করার পরপরই (ডিভাইসের ভূমিকা পরিবর্তন বৈশিষ্ট্য) আপনি 3 থেকে 2 (অথবা 2 থেকে 1) জ্বলন্ত LED সুইচটি দেখতে পাবেন।
১২. অ্যাপ্লিকেশন কার্যকারিতা
তিনটি nRF52840 বোর্ডই এখন চালিত এবং আমাদের OpenThread অ্যাপ্লিকেশনটি চালানো উচিত। যেমনটি আগে বিস্তারিত বলা হয়েছে, এই অ্যাপ্লিকেশনটির দুটি প্রাথমিক বৈশিষ্ট্য রয়েছে।
ডিভাইসের ভূমিকা নির্দেশক
প্রতিটি বোর্ডে আলোকিত LED থ্রেড নোডের বর্তমান ভূমিকা প্রতিফলিত করে:
- LED1 = লিডার
- LED2 = রাউটার
- LED3 = শেষ ডিভাইস
ভূমিকা পরিবর্তনের সাথে সাথে আলোকিত LEDও পরিবর্তিত হয়। প্রতিটি ডিভাইস চালু হওয়ার ২০ সেকেন্ডের মধ্যে একটি বা দুটি বোর্ডে এই পরিবর্তনগুলি আপনার ইতিমধ্যেই দেখা উচিত ছিল।
ইউডিপি মাল্টিকাস্ট
যখন একটি বোর্ডে বোতাম১ চাপা হয়, তখন মেশ-স্থানীয় মাল্টিকাস্ট ঠিকানায় একটি UDP বার্তা পাঠানো হয়, যার মধ্যে থ্রেড নেটওয়ার্কের অন্যান্য সমস্ত নোড অন্তর্ভুক্ত থাকে। এই বার্তাটি পাওয়ার প্রতিক্রিয়ায়, অন্যান্য সমস্ত বোর্ডে LED4 চালু বা বন্ধ হয়ে যায় । প্রতিটি বোর্ডের জন্য LED4 চালু বা বন্ধ থাকে যতক্ষণ না এটি অন্য একটি UDP বার্তা পায়।


১৩. ডেমো: ডিভাইসের ভূমিকার পরিবর্তনগুলি পর্যবেক্ষণ করুন
আপনি যে ডিভাইসগুলি ফ্ল্যাশ করেছেন সেগুলি হল একটি নির্দিষ্ট ধরণের ফুল থ্রেড ডিভাইস (FTD) যাকে রাউটার এলিজিবল এন্ড ডিভাইস (REED) বলা হয়। এর অর্থ হল তারা রাউটার বা এন্ড ডিভাইস হিসাবে কাজ করতে পারে এবং একটি এন্ড ডিভাইস থেকে রাউটারে নিজেদের প্রচার করতে পারে।
থ্রেড ৩২টি রাউটার পর্যন্ত সাপোর্ট করতে পারে, কিন্তু রাউটারের সংখ্যা ১৬ থেকে ২৩টির মধ্যে রাখার চেষ্টা করে। যদি একটি REED একটি End Device হিসেবে সংযুক্ত হয় এবং রাউটারের সংখ্যা ১৬টির নিচে হয়, তাহলে এটি স্বয়ংক্রিয়ভাবে একটি রাউটারে নিজেকে উন্নীত করে। এই পরিবর্তনটি আপনি অ্যাপ্লিকেশনে otThreadSetRouterSelectionJitter মানটি যে সেকেন্ডে সেট করেছেন (২০ সেকেন্ড) তার মধ্যে একটি এলোমেলো সময়ে ঘটবে।
প্রতিটি থ্রেড নেটওয়ার্কের একজন লিডারও থাকে, যা একটি রাউটার যা থ্রেড নেটওয়ার্কে রাউটারগুলির সেট পরিচালনার জন্য দায়ী। সমস্ত ডিভাইস চালু থাকার পর, 20 সেকেন্ড পরে তাদের মধ্যে একটি লিডার (LED1 চালু) এবং অন্য দুটি রাউটার (LED2 চালু) হওয়া উচিত।

নেতাকে সরিয়ে দিন
যদি থ্রেড নেটওয়ার্ক থেকে লিডার অপসারণ করা হয়, তাহলে নেটওয়ার্কটিতে এখনও একজন লিডার আছে কিনা তা নিশ্চিত করার জন্য একটি ভিন্ন রাউটার নিজেকে লিডারে উন্নীত করে।
পাওয়ার সুইচ ব্যবহার করে লিডার বোর্ড (যেটিতে LED1 লাইট আছে) বন্ধ করুন। প্রায় 20 সেকেন্ড অপেক্ষা করুন। বাকি দুটি বোর্ডের একটিতে, LED2 (রাউটার) বন্ধ হয়ে যাবে এবং LED1 (লিডার) চালু হবে। এই ডিভাইসটি এখন থ্রেড নেটওয়ার্কের লিডার।

আসল লিডার বোর্ডটি আবার চালু করুন। এটি স্বয়ংক্রিয়ভাবে থ্রেড নেটওয়ার্কে একটি এন্ড ডিভাইস হিসেবে পুনরায় যুক্ত হবে (LED3 জ্বলছে)। 20 সেকেন্ডের মধ্যে (রাউটার সিলেকশন জিটার) এটি নিজেকে একটি রাউটারে উন্নীত করে (LED2 জ্বলছে)।

বোর্ডগুলি পুনরায় সেট করুন
তিনটি বোর্ডই বন্ধ করে দিন, তারপর আবার চালু করুন এবং LED গুলি পর্যবেক্ষণ করুন। প্রথম যে বোর্ডটি চালু করা হয়েছিল সেটি লিডার ভূমিকায় শুরু হওয়া উচিত (LED1 জ্বলছে) - থ্রেড নেটওয়ার্কের প্রথম রাউটারটি স্বয়ংক্রিয়ভাবে লিডার হয়ে যায়।
অন্য দুটি বোর্ড প্রাথমিকভাবে এন্ড ডিভাইস (LED3 জ্বলছে) হিসেবে নেটওয়ার্কের সাথে সংযুক্ত হয় কিন্তু 20 সেকেন্ডের মধ্যে রাউটারগুলিতে (LED2 জ্বলছে) নিজেদেরকে প্রচার করবে।
নেটওয়ার্ক পার্টিশন
যদি আপনার বোর্ডগুলি পর্যাপ্ত শক্তি না পায়, অথবা তাদের মধ্যে রেডিও সংযোগ দুর্বল থাকে, তাহলে থ্রেড নেটওয়ার্কটি পার্টিশনে বিভক্ত হতে পারে এবং আপনার একাধিক ডিভাইস লিডার হিসেবে প্রদর্শিত হতে পারে।
থ্রেডটি স্ব-নিরাময়কারী, তাই পার্টিশনগুলি অবশেষে একটি লিডার সহ একটি একক পার্টিশনে একত্রিত হওয়া উচিত।
১৪. ডেমো: UDP মাল্টিকাস্ট পাঠান
পূর্ববর্তী অনুশীলন থেকে অব্যাহত থাকলে, কোনও ডিভাইসে LED4 জ্বালানো উচিত নয়।
যেকোনো বোর্ড বেছে নিন এবং বোতাম ১ টিপুন। থ্রেড নেটওয়ার্কের অ্যাপ্লিকেশনটি চালানোর সময় LED4 তাদের অবস্থা পরিবর্তন করবে। যদি আগের অনুশীলন থেকে চালিয়ে যান, তাহলে এখন সেগুলি চালু থাকা উচিত।

একই বোর্ডের জন্য আবার বোতাম 1 টিপুন। অন্য সব বোর্ডে LED4 আবার টগল করা উচিত।
অন্য বোর্ডে বোতাম 1 টিপুন এবং লক্ষ্য করুন কিভাবে LED4 অন্যান্য বোর্ডে টগল করে। যে বোর্ডে LED4 বর্তমানে চালু আছে তার একটিতে বোতাম 1 টিপুন। LED4 সেই বোর্ডে চালু থাকে কিন্তু অন্য বোর্ডগুলিতে টগল করে।

নেটওয়ার্ক পার্টিশন
যদি আপনার বোর্ডগুলি পার্টিশন করা থাকে এবং তাদের মধ্যে একাধিক লিডার থাকে, তাহলে মাল্টিকাস্ট বার্তার ফলাফল বোর্ডগুলির মধ্যে ভিন্ন হবে। যদি আপনি এমন একটি বোর্ডে বোতাম 1 চাপেন যা পার্টিশন করা হয়েছে (এবং তাই পার্টিশন করা থ্রেড নেটওয়ার্কের একমাত্র সদস্য), তাহলে অন্যান্য বোর্ডগুলিতে LED4 প্রতিক্রিয়া হিসাবে জ্বলবে না। যদি এটি ঘটে, তাহলে বোর্ডগুলি পুনরায় সেট করুন - আদর্শভাবে তারা একটি একক থ্রেড নেটওয়ার্ক সংস্কার করবে এবং UDP মেসেজিং সঠিকভাবে কাজ করবে।
১৫. অভিনন্দন!
আপনি এমন একটি অ্যাপ্লিকেশন তৈরি করেছেন যা OpenThread API ব্যবহার করে!
তুমি এখন জানো:
- নর্ডিক nRF52840 ডেভ বোর্ডে বোতাম এবং LED কীভাবে প্রোগ্রাম করবেন
- সাধারণ OpenThread API এবং
otInstanceক্লাস কীভাবে ব্যবহার করবেন - ওপেনথ্রেড অবস্থার পরিবর্তনগুলি কীভাবে পর্যবেক্ষণ এবং প্রতিক্রিয়া জানাবেন
- থ্রেড নেটওয়ার্কের সকল ডিভাইসে UDP বার্তা কীভাবে পাঠাবেন
- মেকফাইল কিভাবে পরিবর্তন করবেন
পরবর্তী পদক্ষেপ
এই কোডল্যাব তৈরি করার জন্য, নিম্নলিখিত অনুশীলনগুলি চেষ্টা করে দেখুন:
- অনবোর্ড LED-এর পরিবর্তে GPIO পিন ব্যবহার করার জন্য GPIO মডিউলটি পরিবর্তন করুন এবং রাউটারের ভূমিকার উপর ভিত্তি করে রঙ পরিবর্তনকারী বহিরাগত RGB LED সংযোগ করুন।
- একটি ভিন্ন উদাহরণ প্ল্যাটফর্মের জন্য GPIO সমর্থন যোগ করুন
- মাল্টিকাস্ট ব্যবহার করে একটি বোতাম টিপে সমস্ত ডিভাইস পিং করার পরিবর্তে, একটি পৃথক ডিভাইস সনাক্ত এবং পিং করার জন্য রাউটার/লিডার API ব্যবহার করুন।
- একটি ওপেনথ্রেড বর্ডার রাউটার ব্যবহার করে আপনার মেশ নেটওয়ার্ককে ইন্টারনেটের সাথে সংযুক্ত করুন এবং LED লাইট জ্বালানোর জন্য থ্রেড নেটওয়ার্কের বাইরে থেকে মাল্টিকাস্ট করুন।
আরও পড়া
বিভিন্ন ধরণের OpenThread রিসোর্সের জন্য openthread.io এবং GitHub দেখুন, যার মধ্যে রয়েছে:
- সমর্থিত প্ল্যাটফর্ম — OpenThread সমর্থন করে এমন সমস্ত প্ল্যাটফর্ম আবিষ্কার করুন
- ওপেনথ্রেড তৈরি করুন — ওপেনথ্রেড তৈরি এবং কনফিগার করার বিষয়ে আরও বিশদ বিবরণ
- থ্রেড প্রাইমার — থ্রেড ধারণার উপর একটি দুর্দান্ত রেফারেন্স
তথ্যসূত্র: