1. परिचय

Nest ने OpenThread को रिलीज़ किया है. यह Thread® नेटवर्किंग प्रोटोकॉल का ओपन-सोर्स वर्शन है. Nest ने OpenThread को रिलीज़ किया है, ताकि Nest के प्रॉडक्ट में इस्तेमाल की गई टेक्नोलॉजी को डेवलपर के लिए ज़्यादा से ज़्यादा उपलब्ध कराया जा सके. इससे कनेक्टेड होम के लिए प्रॉडक्ट को तेज़ी से डेवलप किया जा सकेगा.
Thread स्पेसिफ़िकेशन, होम ऐप्लिकेशन के लिए डिवाइस-से-डिवाइस के बीच कम पावर में वायरलेस तरीके से कम्यूनिकेट करने का एक भरोसेमंद और सुरक्षित प्रोटोकॉल है. यह IPv6 पर आधारित है. OpenThread, Thread की सभी नेटवर्किंग लेयर लागू करता है. इनमें IPv6, 6LoWPAN, IEEE 802.15.4 with MAC security, Mesh Link Establishment, और Mesh Routing शामिल हैं.
इस कोडलैब में, Thread नेटवर्क शुरू करने के लिए OpenThread API का इस्तेमाल किया जाएगा. साथ ही, डिवाइस की भूमिकाओं में होने वाले बदलावों को मॉनिटर किया जाएगा और उन पर प्रतिक्रिया दी जाएगी. इसके अलावा, यूडीपी मैसेज भेजे जाएंगे. साथ ही, इन कार्रवाइयों को असली हार्डवेयर पर मौजूद बटन और एलईडी से जोड़ा जाएगा.

आपको क्या सीखने को मिलेगा
- Nordic nRF52840 dev बोर्ड पर बटन और एलईडी को प्रोग्राम करने का तरीका
- OpenThread के सामान्य एपीआई और
otInstanceक्लास का इस्तेमाल करने का तरीका - OpenThread की स्थिति में होने वाले बदलावों को मॉनिटर करने और उन पर प्रतिक्रिया देने का तरीका
- Thread नेटवर्क में मौजूद सभी डिवाइसों को यूडीपी मैसेज भेजने का तरीका
- मेकफ़ाइलों में बदलाव करने का तरीका
आपको किन चीज़ों की ज़रूरत होगी
हार्डवेयर:
- Nordic Semiconductor nRF52840 के तीन डेवलपमेंट बोर्ड
- बोर्ड को कनेक्ट करने के लिए, यूएसबी से माइक्रो-यूएसबी केबल
- कम से कम तीन यूएसबी पोर्ट वाली Linux मशीन
सॉफ़्टवेयर:
- GNU टूलचेन
- Nordic nRF5x कमांड-लाइन टूल
- Segger J-Link सॉफ़्टवेयर
- OpenThread
- Git
जब तक कोई और सूचना न दी जाए, इस कोडलैब का कॉन्टेंट क्रिएटिव कॉमंस एट्रिब्यूशन 3.0 लाइसेंस के तहत आता है. साथ ही, कोड सैंपल Apache 2.0 लाइसेंस के तहत आते हैं.
2. शुरू करना
हार्डवेयर कोडलैब पूरा करें
इस कोडलैब को शुरू करने से पहले, आपको nRF52840 बोर्ड और OpenThread की मदद से थ्रेड नेटवर्क बनाना कोडलैब पूरा करना होगा. इसमें यह जानकारी दी गई है:
- इसमें, ऐप्लिकेशन बनाने और फ़्लैश करने के लिए ज़रूरी सभी सॉफ़्टवेयर की जानकारी दी गई है
- इस वीडियो में, OpenThread बनाने और उसे Nordic nRF52840 बोर्ड पर फ़्लैश करने का तरीका बताया गया है
- इसमें थ्रेड नेटवर्क की बुनियादी बातें बताई गई हैं
इस कोडलैब में, OpenThread बनाने और बोर्ड को फ़्लैश करने के लिए ज़रूरी एनवायरमेंट सेट अप के बारे में कोई जानकारी नहीं दी गई है. इसमें सिर्फ़ बोर्ड को फ़्लैश करने के बारे में बुनियादी निर्देश दिए गए हैं. यह मान लिया गया है कि आपने Thread नेटवर्क बनाने वाला कोडलैब पहले ही पूरा कर लिया है.
Linux मशीन
इस कोडलैब को i386- या x86-आधारित Linux मशीन का इस्तेमाल करके, सभी थ्रेड डेवलपमेंट बोर्ड को फ़्लैश करने के लिए डिज़ाइन किया गया था. सभी चरणों को Ubuntu 14.04.5 LTS (Trusty Tahr) पर टेस्ट किया गया था.
Nordic Semiconductor nRF52840 बोर्ड
इस कोडलैब में, तीन nRF52840 PDK बोर्ड का इस्तेमाल किया गया है.

सॉफ़्टवेयर इंस्टॉल करना
OpenThread को बनाने और फ़्लैश करने के लिए, आपको SEGGER J-Link, nRF5x कमांड लाइन टूल, ARM GNU टूलचेन, और Linux के अलग-अलग पैकेज इंस्टॉल करने होंगे. अगर आपने Build a Thread Network Codelab को ज़रूरी शर्तों के मुताबिक पूरा कर लिया है, तो आपके पास पहले से ही वे सभी चीज़ें इंस्टॉल होंगी जिनकी आपको ज़रूरत है. अगर आपने ऐसा नहीं किया है, तो इस Codelab को पूरा करें. इससे यह पक्का किया जा सकेगा कि आपके पास nRF52840 डेवलपमेंट बोर्ड पर OpenThread को बिल्ड और फ़्लैश करने की सुविधा हो.
3. रिपॉज़िटरी को क्लोन करना
OpenThread में, ऐप्लिकेशन कोड का उदाहरण दिया गया है. इसका इस्तेमाल, इस कोडलैब के लिए शुरुआती बिंदु के तौर पर किया जा सकता है.
OpenThread Nordic nRF528xx examples repo को क्लोन करें और OpenThread बनाएं:
$ git clone --recursive https://github.com/openthread/ot-nrf528xx $ cd ot-nrf528xx $ ./script/bootstrap
4. OpenThread API की बुनियादी बातें
OpenThread के सार्वजनिक एपीआई, OpenThread रिपॉज़िटरी में ./openthread/include/openthread पर मौजूद हैं. ये एपीआई, Thread और प्लैटफ़ॉर्म, दोनों लेवल पर OpenThread की कई सुविधाओं और फ़ंक्शन का ऐक्सेस देते हैं. इनका इस्तेमाल आपके ऐप्लिकेशन में किया जा सकता है:
- OpenThread इंस्टेंस की जानकारी और कंट्रोल
- ऐप्लिकेशन सेवाएं, जैसे कि IPv6, UDP, और CoAP
- नेटवर्क क्रेडेंशियल मैनेजमेंट के साथ-साथ, कमिश्नर और जॉइनर की भूमिकाएं
- बॉर्डर राऊटर को मैनेज करना
- बेहतर सुविधाएं, जैसे कि माता-पिता के कंट्रोल में डिवाइस का इस्तेमाल करना और जाम का पता लगाना
सभी OpenThread एपीआई के बारे में रेफ़रंस जानकारी, openthread.io/reference पर उपलब्ध है.
एपीआई का इस्तेमाल करना
किसी एपीआई का इस्तेमाल करने के लिए, उसकी हेडर फ़ाइल को अपने किसी ऐप्लिकेशन की फ़ाइल में शामिल करें. इसके बाद, अपनी पसंद के फ़ंक्शन को कॉल करें.
उदाहरण के लिए, OpenThread के साथ शामिल CLI उदाहरण ऐप्लिकेशन, इन एपीआई हेडर का इस्तेमाल करता है:
./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 इंस्टेंस
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 के बटन और एलईडी में हुक करने के लिए इस्तेमाल किए जाने वाले 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 मैक्रो का इस्तेमाल किया जा सकता है. इससे कुछ टूलचेन के लिए, इस्तेमाल नहीं किए गए वैरिएबल से जुड़ी बिल्ड गड़बड़ियों को रोका जा सकता है. हम इसके उदाहरण बाद में देखेंगे.
5. GPIO प्लैटफ़ॉर्म ऐब्स्ट्रैक्शन लागू करना
पिछले चरण में, हमने ./openthread/examples/platforms/openthread-system.h में प्लैटफ़ॉर्म के हिसाब से फ़ंक्शन के एलान के बारे में बताया था. इनका इस्तेमाल GPIO के लिए किया जा सकता है. nRF52840 डेवलपमेंट बोर्ड पर मौजूद बटन और एलईडी को ऐक्सेस करने के लिए, आपको nRF52840 प्लैटफ़ॉर्म के लिए उन फ़ंक्शन को लागू करना होगा. इस कोड में, आपको ऐसे फ़ंक्शन जोड़ने होंगे जो:
- GPIO पिन और मोड शुरू करना
- किसी पिन पर वोल्टेज को कंट्रोल करना
- GPIO इंटरप्ट चालू करें और कॉलबैक रजिस्टर करें
./src/src डायरेक्ट्री में, gpio.c नाम की एक नई फ़ाइल बनाएं. इस नई फ़ाइल में, यह कॉन्टेंट जोड़ें.
./src/src/gpio.c (नई फ़ाइल)
कार्रवाई: Add defines.
ये परिभाषाएं, 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 के बटन और एलईडी के बारे में ज़्यादा जानने के लिए, Nordic Semiconductor Infocenter पर जाएं.
कार्रवाई: हेडर शामिल करें.
इसके बाद, 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"
कार्रवाई: बटन 1 के लिए कॉलबैक और इंटरप्ट फ़ंक्शन जोड़ें.
इसके बाद, यह कोड जोड़ें. 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;
}
कार्रवाई: एलईडी को कॉन्फ़िगर करने के लिए, एक फ़ंक्शन जोड़ें.
इस कोड को जोड़कर, शुरू करने के दौरान सभी एलईडी के मोड और स्थिति को कॉन्फ़िगर करें.
/**
* @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);
}
कार्रवाई: एलईडी का मोड सेट करने के लिए, एक फ़ंक्शन जोड़ें.
इस फ़ंक्शन का इस्तेमाल तब किया जाएगा, जब डिवाइस की भूमिका बदल जाएगी.
/**
* @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;
}
}
कार्रवाई: एलईडी के मोड को टॉगल करने के लिए एक फ़ंक्शन जोड़ें.
इस फ़ंक्शन का इस्तेमाल, डिवाइस को मल्टीकास्ट यूडीपी मैसेज मिलने पर 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;
}
}
कार्रवाई: बटन दबाने की प्रोसेस को शुरू करने और उसे प्रोसेस करने के लिए फ़ंक्शन जोड़ें.
पहला फ़ंक्शन, बटन दबाने के लिए बोर्ड को शुरू करता है. वहीं, दूसरा फ़ंक्शन, Button 1 दबाने पर मल्टीकास्ट यूडीपी मैसेज भेजता है.
/**
* @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 फ़ाइल को सेव करें और बंद करें.
6. एपीआई: डिवाइस की भूमिका में हुए बदलावों पर प्रतिक्रिया करना
हमें अपने ऐप्लिकेशन में, डिवाइस की भूमिका के हिसाब से अलग-अलग एलईडी लाइटें जलानी हैं. आइए, इन भूमिकाओं को ट्रैक करते हैं: लीडर, राऊटर, एंड डिवाइस. हम उन्हें इस तरह एलईडी को असाइन कर सकते हैं:
- LED1 = लीडर
- LED2 = Router
- LED3 = एंड डिवाइस
इस सुविधा को चालू करने के लिए, ऐप्लिकेशन को यह पता होना चाहिए कि डिवाइस की भूमिका कब बदली है और इसके जवाब में सही एलईडी को कैसे चालू करना है. पहले हिस्से के लिए, हम OpenThread इंस्टेंस का इस्तेमाल करेंगे. वहीं, दूसरे हिस्से के लिए, GPIO प्लैटफ़ॉर्म ऐब्स्ट्रैक्शन का इस्तेमाल करेंगे.
./openthread/examples/apps/cli/main.c फ़ाइल को अपने पसंदीदा टेक्स्ट एडिटर में खोलें.
./openthread/examples/apps/cli/main.c
कार्रवाई: हेडर शामिल करें.
main.c फ़ाइल के includes सेक्शन में, एपीआई की उन हेडर फ़ाइलों को जोड़ें जिनकी ज़रूरत आपको भूमिका बदलने की सुविधा के लिए होगी.
#include <openthread/instance.h> #include <openthread/thread.h> #include <openthread/thread_ftd.h>
कार्रवाई: OpenThread इंस्टेंस की स्थिति में बदलाव के लिए, हैंडलर फ़ंक्शन का एलान करें.
इस एलान को main.c में जोड़ें. इसे हेडर में शामिल करने के बाद और किसी भी #if स्टेटमेंट से पहले जोड़ें. इस फ़ंक्शन को मुख्य ऐप्लिकेशन के बाद तय किया जाएगा.
void handleNetifStateChanged(uint32_t aFlags, void *aContext);
कार्रवाई: स्थिति में बदलाव करने वाले फ़ंक्शन के लिए, कॉलबैक रजिस्ट्रेशन जोड़ें.
main.c में, इस फ़ंक्शन को main() फ़ंक्शन में otAppCliInit कॉल के बाद जोड़ें. यह कॉलबैक रजिस्ट्रेशन, OpenThread को यह बताता है कि जब भी OpenThread इंस्टेंस की स्थिति में बदलाव हो, तो handleNetifStateChange फ़ंक्शन को कॉल करें.
/* Register Thread state change handler */ otSetStateChangedCallback(instance, handleNetifStateChanged, instance);
कार्रवाई: स्थिति में बदलाव करने की सुविधा लागू करें.
main.c में, main() फ़ंक्शन के बाद, handleNetifStateChanged फ़ंक्शन लागू करें. यह फ़ंक्शन, OpenThread इंस्टेंस के OT_CHANGED_THREAD_ROLE फ़्लैग की जांच करता है. अगर इसमें बदलाव हुआ है, तो ज़रूरत के हिसाब से एलईडी चालू/बंद करता है.
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;
}
}
}
7. एपीआई: एलईडी चालू करने के लिए मल्टीकास्ट का इस्तेमाल करना
हमें अपने ऐप्लिकेशन में, नेटवर्क से जुड़े सभी डिवाइसों को यूडीपी मैसेज भेजने हैं. ऐसा तब करना है, जब किसी बोर्ड पर Button1 को दबाया जाए. मैसेज मिलने की पुष्टि करने के लिए, हम जवाब में अन्य बोर्ड पर LED4 को टॉगल करेंगे.
इस सुविधा को चालू करने के लिए, ऐप्लिकेशन को यह काम करना होगा:
- शुरू होने पर, यूडीपी कनेक्शन शुरू करना
- मेश-लोकल मल्टीकास्ट पते पर यूडीपी मैसेज भेज सके
- इनकमिंग यूडीपी मैसेज मैनेज करना
- आने वाले यूडीपी मैसेज के जवाब में LED4 को टॉगल करना
./openthread/examples/apps/cli/main.c फ़ाइल को अपने पसंदीदा टेक्स्ट एडिटर में खोलें.
./openthread/examples/apps/cli/main.c
कार्रवाई: हेडर शामिल करें.
main.c फ़ाइल में सबसे ऊपर मौजूद includes सेक्शन में, एपीआई की उन हेडर फ़ाइलों को जोड़ें जिनकी ज़रूरत आपको मल्टीकास्ट यूडीपी सुविधा के लिए पड़ेगी.
#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 स्टेटमेंट से पहले, यूडीपी से जुड़े कॉन्स्टेंट और डिफ़ाइन जोड़ें:
#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() फ़ंक्शन से पहले, यूडीपी से जुड़े फ़ंक्शन जोड़ें. साथ ही, यूडीपी सॉकेट को दिखाने के लिए एक स्टैटिक वैरिएबल जोड़ें:
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 एलईडी और बटन को चालू करने के लिए, कॉल जोड़ें.
main.c में, इन फ़ंक्शन कॉल को otSetStateChangedCallback कॉल के बाद, main() फ़ंक्शन में जोड़ें. ये फ़ंक्शन, GPIO और GPIOTE पिन को शुरू करते हैं. साथ ही, बटन दबाने के इवेंट को मैनेज करने के लिए, बटन हैंडलर सेट करते हैं.
/* init GPIO LEDs and button */ otSysLedInit(); otSysButtonInit(handleButtonInterrupt);
कार्रवाई: यूडीपी को शुरू करने के लिए कॉल जोड़ें.
main.c में, इस फ़ंक्शन को main() फ़ंक्शन में जोड़ें. इसे otSysButtonInit कॉल के बाद जोड़ें, जिसे आपने अभी जोड़ा है:
initUdp(instance);
इस कॉल से यह पक्का किया जाता है कि ऐप्लिकेशन शुरू होने पर, यूडीपी सॉकेट शुरू हो जाए. इसके बिना, डिवाइस 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);
}
कार्रवाई: यूडीपी को शुरू करें.
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) को रजिस्टर करता है. otUdpBind, OT_NETIF_THREAD पास करके सॉकेट को Thread नेटवर्क इंटरफ़ेस से बाइंड करता है. नेटवर्क इंटरफ़ेस के अन्य विकल्पों के लिए, UDP API के रेफ़रंस में otNetifIdentifier एन्यूमरेशन देखें.
कार्रवाई: यूडीपी मैसेजिंग लागू करें.
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 मैक्रो का इस्तेमाल करें. इनसे यह पक्का किया जाता है कि यूडीपी मैसेज मान्य है और उसे बफ़र में सही तरीके से असाइन किया गया है. अगर ऐसा नहीं होता है, तो फ़ंक्शन exit ब्लॉक पर जाकर, गड़बड़ियों को ठीक करता है. यहां यह बफ़र को खाली कर देता है.
यूडीपी को शुरू करने के लिए इस्तेमाल किए गए फ़ंक्शन के बारे में ज़्यादा जानकारी पाने के लिए, openthread.io पर IPv6 और 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);
}
8. एपीआई: Thread नेटवर्क को कॉन्फ़िगर करना
हम चाहते हैं कि हमारे डिवाइस चालू होने पर, तुरंत Thread नेटवर्क शुरू कर दें और एक साथ जुड़ जाएं, ताकि उन्हें आसानी से दिखाया जा सके. इसके लिए, हम otOperationalDataset स्ट्रक्चर का इस्तेमाल करेंगे. इस स्ट्रक्चर में, Thread नेटवर्क के क्रेडेंशियल को किसी डिवाइस पर ट्रांसमिट करने के लिए ज़रूरी सभी पैरामीटर होते हैं.
इस स्ट्रक्चर का इस्तेमाल करने से, OpenThread में पहले से मौजूद नेटवर्क डिफ़ॉल्ट सेटिंग बदल जाएंगी. इससे हमारा ऐप्लिकेशन ज़्यादा सुरक्षित हो जाएगा. साथ ही, हमारे नेटवर्क में थ्रेड नोड की संख्या सीमित हो जाएगी. ये नोड सिर्फ़ ऐप्लिकेशन चलाने वाले नोड होंगे.
फिर से, अपनी पसंद के टेक्स्ट एडिटर में ./openthread/examples/apps/cli/main.c फ़ाइल खोलें.
./openthread/examples/apps/cli/main.c
कार्रवाई: हेडर शामिल करें.
main.c फ़ाइल में सबसे ऊपर मौजूद includes सेक्शन में, वह एपीआई हेडर फ़ाइल जोड़ें जिसकी ज़रूरत आपको थ्रेड नेटवर्क को कॉन्फ़िगर करने के लिए पड़ेगी:
#include <openthread/dataset_ftd.h>
कार्रवाई: नेटवर्क कॉन्फ़िगरेशन सेट करने के लिए, फ़ंक्शन का एलान जोड़ें.
इस एलान को main.c में जोड़ें. इसे हेडर में शामिल करने के बाद और किसी भी #if स्टेटमेंट से पहले जोड़ें. इस फ़ंक्शन को मुख्य ऐप्लिकेशन फ़ंक्शन के बाद तय किया जाएगा.
static void setNetworkConfiguration(otInstance *aInstance);
कार्रवाई: नेटवर्क कॉन्फ़िगरेशन कॉल जोड़ें.
main.c में, इस फ़ंक्शन कॉल को otSetStateChangedCallback कॉल के बाद main() फ़ंक्शन में जोड़ें. यह फ़ंक्शन, Thread नेटवर्क के डेटासेट को कॉन्फ़िगर करता है.
/* Override default network credentials */ setNetworkConfiguration(instance);
कार्रवाई: Thread नेटवर्क इंटरफ़ेस और स्टैक चालू करने के लिए, कॉल जोड़ें.
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);
कार्रवाई: Thread नेटवर्क कॉन्फ़िगरेशन लागू करें.
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);
}
फ़ंक्शन में दी गई जानकारी के मुताबिक, इस ऐप्लिकेशन के लिए हम Thread नेटवर्क के इन पैरामीटर का इस्तेमाल कर रहे हैं:
- चैनल = 15
- PAN ID = 0x2222
- एक्सटेंडेड पैन आईडी = C0DE1AB5C0DE1AB5
- नेटवर्क कुंजी = 1234C0DE1AB51234C0DE1AB51234C0DE
- Network Name = OTCodelab
इसके अलावा, हम यहां राउटर चुनने की प्रक्रिया में होने वाले उतार-चढ़ाव को कम करते हैं, ताकि हमारे डिवाइस डेमो के लिए भूमिकाएं तेज़ी से बदल सकें. ध्यान दें कि ऐसा सिर्फ़ तब किया जाता है, जब नोड एक एफ़टीडी (फ़ुल थ्रेड डिवाइस) हो. इसके बारे में अगले चरण में ज़्यादा जानें.
9. एपीआई: पाबंदी वाले फ़ंक्शन
OpenThread के कुछ एपीआई, ऐसी सेटिंग में बदलाव करते हैं जिनमें सिर्फ़ डेमो या टेस्टिंग के लिए बदलाव किया जाना चाहिए. OpenThread का इस्तेमाल करने वाले ऐप्लिकेशन के प्रोडक्शन डिप्लॉयमेंट में, इन एपीआई का इस्तेमाल नहीं किया जाना चाहिए.
उदाहरण के लिए, otThreadSetRouterSelectionJitter फ़ंक्शन उस समय (सेकंड में) को अडजस्ट करता है जब किसी एंड डिवाइस को खुद को राउटर के तौर पर प्रमोट करने में लगता है. थ्रेड स्पेसिफ़िकेशन के मुताबिक, इस वैल्यू की डिफ़ॉल्ट वैल्यू 120 है. इस कोडलैब में इसका इस्तेमाल आसान बनाने के लिए, हम इसे 20 पर सेट करेंगे. इससे आपको थ्रेड नोड की भूमिका बदलने के लिए ज़्यादा इंतज़ार नहीं करना पड़ेगा.
ध्यान दें: एमटीडी डिवाइस, राउटर नहीं बनते हैं. साथ ही, एमटीडी बिल्ड में otThreadSetRouterSelectionJitter जैसे फ़ंक्शन के लिए सहायता शामिल नहीं होती है. बाद में, हमें 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
10. CMake से जुड़े अपडेट
ऐप्लिकेशन बनाने से पहले, तीन 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 फ़ाइल में जोड़ें, ताकि इसे Nordic ड्राइवर की लाइब्रेरी बिल्ड में शामिल किया जा सके.
कार्रवाई: NordicSemiconductor CMakeLists.txt फ़ाइल में gpio ड्राइवर जोड़ें.
अपने पसंदीदा टेक्स्ट एडिटर में ./third_party/NordicSemiconductor/CMakeLists.txt खोलें और फ़ाइल को COMMON_SOURCES सेक्शन में जोड़ें.
... set(COMMON_SOURCES ... nrfx/drivers/src/nrfx_gpiote.c ... ) ...
11. डिवाइसों को सेट अप करना
कोड से जुड़े सभी अपडेट करने के बाद, ऐप्लिकेशन को तीनों नॉर्डिक nRF52840 डेवलपमेंट बोर्ड पर बनाया और फ़्लैश किया जा सकता है. हर डिवाइस, फ़ुल थ्रेड डिवाइस (एफ़टीडी) के तौर पर काम करेगा.
OpenThread बनाना
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 फ़ाइल फ़्लैश करें.
USB केबल को nRF52840 बोर्ड पर मौजूद, बाहरी पावर पिन के बगल में मौजूद माइक्रो-यूएसबी डीबग पोर्ट से कनेक्ट करें. इसके बाद, इसे अपने Linux मशीन में प्लग करें. सही तरीके से सेट किया गया है, LED5 चालू है.

पहले की तरह, nRF52840 बोर्ड का सीरियल नंबर नोट करें:

nRFx Command Line Tools की जगह पर जाएं और बोर्ड के सीरियल नंबर का इस्तेमाल करके, nRF52840 बोर्ड पर OpenThread CLI FTD हेक्स फ़ाइल फ़्लैश करें:
$ cd ~/nrfjprog
$ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \
~/openthread/output/nrf52840/bin/ot-cli-ftd.hex --reset
एलईडी5, फ़्लैश होने के दौरान कुछ समय के लिए बंद हो जाएगी. अपग्रेड होने के बाद यह आउटपुट जनरेट होता है:
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.
"बोर्ड को फ़्लैश करें" चरण को अन्य दो बोर्ड के लिए दोहराएं. हर बोर्ड को Linux मशीन से एक ही तरीके से कनेक्ट किया जाना चाहिए. साथ ही, बोर्ड के सीरियल नंबर को छोड़कर, फ़्लैश करने का कमांड भी एक जैसा होना चाहिए. पक्का करें कि हर बोर्ड का यूनीक सीरियल नंबर,
nrfjprog फ़्लैश करने का निर्देश.
अगर यह प्रक्रिया सही से पूरी हो जाती है, तो हर बोर्ड पर LED1, LED2 या LED3 चालू हो जाएगा. डिवाइस की भूमिका बदलने की सुविधा के तहत, आपको एलईडी लाइट के फ़्लैश होने के तुरंत बाद, 3 से 2 (या 2 से 1) पर स्विच होते हुए दिख सकती है.
12. ऐप्लिकेशन की मुख्य सुविधाएं और उनके काम करने का तरीका
अब तीनों nRF52840 बोर्ड चालू होने चाहिए और उन पर हमारा OpenThread ऐप्लिकेशन चल रहा होना चाहिए. जैसा कि पहले बताया गया है, इस ऐप्लिकेशन में दो मुख्य सुविधाएं हैं.
डिवाइस की भूमिका के इंडिकेटर
हर बोर्ड पर जलने वाली एलईडी, थ्रेड नोड की मौजूदा भूमिका को दिखाती है:
- LED1 = लीडर
- LED2 = Router
- LED3 = एंड डिवाइस
भूमिका बदलने पर, एलईडी भी बदल जाती है. डिवाइस चालू होने के 20 सेकंड के अंदर, आपको एक या दो बोर्ड पर ये बदलाव दिख जाने चाहिए.
यूडीपी मल्टीकास्ट
जब किसी बोर्ड पर Button1 को दबाया जाता है, तो यूडीपी मैसेज को मेश-लोकल मल्टीकास्ट पते पर भेजा जाता है. इसमें Thread नेटवर्क के सभी नोड शामिल होते हैं. यह मैसेज मिलने पर, अन्य सभी बोर्ड पर LED4 चालू या बंद हो जाता है. जब तक इसे कोई दूसरा यूडीपी मैसेज नहीं मिलता, तब तक हर बोर्ड पर LED4 चालू या बंद रहता है.


13. डेमो: डिवाइस की भूमिका में हुए बदलावों पर नज़र रखना
जिन डिवाइसों को आपने फ़्लैश किया है वे एक खास तरह के फ़ुल थ्रेड डिवाइस (एफ़टीडी) हैं. इन्हें राऊटर के तौर पर इस्तेमाल किया जा सकता है. इसका मतलब है कि ये डिवाइस, राऊटर या एंड डिवाइस के तौर पर काम कर सकते हैं. साथ ही, ये खुद को एंड डिवाइस से राऊटर में बदल सकते हैं.
Thread नेटवर्क में ज़्यादा से ज़्यादा 32 राऊटर हो सकते हैं. हालांकि, इसमें राऊटर की संख्या 16 से 23 के बीच रखने की कोशिश की जाती है. अगर कोई REED, एंड डिवाइस के तौर पर अटैच होता है और राउटर की संख्या 16 से कम होती है, तो वह अपने-आप राउटर के तौर पर प्रमोट हो जाता है. यह बदलाव, ऐप्लिकेशन में otThreadSetRouterSelectionJitter एट्रिब्यूट की वैल्यू के तौर पर सेट किए गए सेकंड (20 सेकंड) के अंदर किसी भी समय होना चाहिए.
हर Thread नेटवर्क में एक लीडर भी होता है. यह एक ऐसा राऊटर होता है जो Thread नेटवर्क में राऊटर के सेट को मैनेज करने के लिए ज़िम्मेदार होता है. सभी डिवाइस चालू होने के 20 सेकंड बाद, उनमें से एक डिवाइस लीडर (LED1 चालू) और बाकी दो डिवाइस राउटर (LED2 चालू) होने चाहिए.

लीडर को हटाना
अगर लीडर को Thread नेटवर्क से हटा दिया जाता है, तो कोई दूसरा राऊटर खुद को लीडर के तौर पर प्रमोट करता है, ताकि नेटवर्क में लीडर बना रहे.
पावर स्विच का इस्तेमाल करके, लीडर बोर्ड (जिसमें LED1 चालू है) को बंद करें. करीब 20 सेकंड इंतज़ार करें. बाकी बचे दो बोर्ड में से किसी एक पर, LED2 (राउटर) बंद हो जाएगा और LED1 (लीडर) चालू हो जाएगा. यह डिवाइस अब Thread नेटवर्क का लीडर है.

ओरिजनल लीडर बोर्ड को फिर से चालू करें. इसे एंड डिवाइस के तौर पर, Thread नेटवर्क से अपने-आप फिर से कनेक्ट हो जाना चाहिए (LED3 चालू हो). 20 सेकंड के अंदर (राउटर चुनने में लगने वाला समय), यह खुद को राउटर के तौर पर प्रमोट करता है (LED2 चालू हो जाता है).

बोर्ड रीसेट करना
तीनों बोर्ड बंद करें. इसके बाद, उन्हें फिर से चालू करें और एलईडी पर नज़र रखें. सबसे पहले चालू किए गए बोर्ड को लीडर की भूमिका में शुरू होना चाहिए (LED1 चालू है). थ्रेड नेटवर्क में पहला राउटर अपने-आप लीडर बन जाता है.
शुरुआत में, अन्य दो बोर्ड नेटवर्क से एंड डिवाइस के तौर पर कनेक्ट होते हैं (LED3 चालू होता है). हालांकि, 20 सेकंड के अंदर उन्हें राउटर के तौर पर प्रमोट किया जाना चाहिए (LED2 चालू होता है).
नेटवर्क के सेगमेंट
अगर आपके बोर्ड को ज़रूरत के मुताबिक पावर नहीं मिल रही है या उनके बीच रेडियो कनेक्शन कमज़ोर है, तो Thread नेटवर्क कई हिस्सों में बंट सकता है. साथ ही, आपको एक से ज़्यादा डिवाइस लीडर के तौर पर दिख सकते हैं.
थ्रेड में गड़बड़ी अपने-आप ठीक हो जाती है. इसलिए, कुछ समय बाद सभी पार्टीशन, एक ही पार्टीशन में मर्ज हो जाते हैं. साथ ही, एक लीडर बन जाता है.
14. डेमो: यूडीपी मल्टीकास्ट भेजना
अगर आपको पिछले चरण से आगे बढ़ना है, तो किसी भी डिवाइस पर LED4 चालू नहीं होना चाहिए.
कोई बोर्ड चुनें और Button1 दबाएं. ऐप्लिकेशन चलाने वाले थ्रेड नेटवर्क में मौजूद अन्य सभी बोर्ड पर LED4 की स्थिति टॉगल होनी चाहिए. अगर पिछली कसरत जारी रखनी है, तो अब उन्हें चालू कर देना चाहिए.

उसी बोर्ड के लिए, Button1 को फिर से दबाएं. अन्य सभी बोर्ड पर LED4 फिर से टॉगल होना चाहिए.
किसी दूसरे बोर्ड पर Button1 दबाएं और देखें कि दूसरे बोर्ड पर LED4 कैसे टॉगल होता है. उस बोर्ड पर Button1 दबाएं जिस पर LED4 चालू है. एलईडी4 उस बोर्ड के लिए चालू रहती है, लेकिन अन्य बोर्ड के लिए टॉगल होती है.

नेटवर्क के सेगमेंट
अगर आपके बोर्ड अलग-अलग हिस्सों में बंटे हुए हैं और उनमें एक से ज़्यादा लीडर हैं, तो मल्टीकास्ट किए गए मैसेज का नतीजा अलग-अलग बोर्ड पर अलग-अलग होगा. अगर आपने किसी ऐसे बोर्ड पर Button1 दबाया है जिसे बांटा गया है (और इस वजह से, वह बांटे गए थ्रेड नेटवर्क का एकमात्र सदस्य है), तो दूसरे बोर्ड पर LED4 लाइट नहीं जलेगी. अगर ऐसा होता है, तो बोर्ड रीसेट करें. इससे वे एक ही थ्रेड नेटवर्क में फिर से जुड़ जाएंगे और यूडीपी मैसेजिंग ठीक से काम करेगी.
15. बधाई हो!
आपने एक ऐसा ऐप्लिकेशन बनाया है जो OpenThread API का इस्तेमाल करता है!
अब आपको यह जानकारी मिल गई है:
- Nordic nRF52840 डेवलपमेंट बोर्ड पर बटन और एलईडी को प्रोग्राम करने का तरीका
- OpenThread के सामान्य एपीआई और
otInstanceक्लास का इस्तेमाल करने का तरीका - OpenThread की स्थिति में होने वाले बदलावों को मॉनिटर करने और उन पर प्रतिक्रिया देने का तरीका
- Thread नेटवर्क में मौजूद सभी डिवाइसों को यूडीपी मैसेज भेजने का तरीका
- मेकफ़ाइलों में बदलाव करने का तरीका
अगले चरण
इस कोडलैब के आधार पर, यहां दिए गए टास्क पूरे करें:
- जीपीआईओ मॉड्यूल में बदलाव करके, बोर्ड पर मौजूद एलईडी के बजाय जीपीआईओ पिन का इस्तेमाल करें. साथ ही, बाहरी आरजीबी एलईडी कनेक्ट करें. ये एलईडी, राऊटर की भूमिका के आधार पर रंग बदलती हैं
- किसी दूसरे उदाहरण प्लैटफ़ॉर्म के लिए GPIO की सुविधा जोड़ना
- बटन दबाकर सभी डिवाइसों को पिंग करने के लिए, मल्टीकास्ट का इस्तेमाल करने के बजाय, किसी डिवाइस का पता लगाने और उसे पिंग करने के लिए Router/Leader API का इस्तेमाल करें
- OpenThread बॉर्डर राऊटर का इस्तेमाल करके, अपने मेश नेटवर्क को इंटरनेट से कनेक्ट करें. इसके बाद, Thread नेटवर्क के बाहर से मल्टीकास्ट करके, एलईडी को चालू करें
इस बारे में और पढ़ें
OpenThread के अलग-अलग संसाधनों के लिए, openthread.io और GitHub देखें. इनमें ये संसाधन शामिल हैं:
- OpenThread के साथ काम करने वाले प्लैटफ़ॉर्म — उन सभी प्लैटफ़ॉर्म के बारे में जानें जिन पर OpenThread काम करता है
- OpenThread को बिल्ड करना — OpenThread को बिल्ड और कॉन्फ़िगर करने के बारे में ज़्यादा जानकारी
- Thread Primer — Thread के कॉन्सेप्ट के बारे में बेहतरीन जानकारी
रेफ़रंस: