OpenThread एपीआई के साथ डेवलप करना

1. शुरुआती जानकारी

26b7f4f6b3ea0700.png

Nest से रिलीज़ किया गया OpenThread, Thread® नेटवर्किंग प्रोटोकॉल का एक ओपन सोर्स सॉफ़्टवेयर है. Nest के प्रॉडक्ट में इस्तेमाल की गई टेक्नोलॉजी को बड़े पैमाने पर डेवलपर के लिए उपलब्ध कराने के लिए, Nest ने OpenThread रिलीज़ किया है. इससे, कनेक्टेड होम के लिए प्रॉडक्ट को बेहतर बनाने में मदद मिलेगी.

Thread की खास जानकारी में, IPv6 आधारित, सुरक्षित, और कम पावर वाले वायरलेस डिवाइस-से-डिवाइस कम्यूनिकेशन प्रोटोकॉल के बारे में बताया गया है. OpenThread, IPv6, 6LoWPAN, IEEE 802.15.4, MAC सुरक्षा, मेश लिंक इंस्टॉलेशन, और मेश रूटिंग के साथ सभी थ्रेड नेटवर्किंग लेयर को लागू करता है.

इस कोडलैब (कोड बनाना सीखना) में, Thread नेटवर्क की शुरुआत करने और डिवाइस की भूमिकाओं में होने वाले बदलावों पर नज़र रखने और उन पर प्रतिक्रिया देने के लिए, OpenThread एपीआई का इस्तेमाल किया जा सकता है. साथ ही, इन कार्रवाइयों को असली हार्डवेयर के बटन और एलईडी से जोड़ा जा सकता है.

2a6db2e258c32237.png

आप इन चीज़ों के बारे में जानेंगे

  • नॉर्डिक nRF52840 डेव बोर्ड पर बटन और एलईडी लाइट कैसे सेट करें
  • आम OpenThread एपीआई और otInstance क्लास को इस्तेमाल करने का तरीका
  • OpenThread की स्थिति में हुए बदलावों पर नज़र रखने और उन पर प्रतिक्रिया देने का तरीका
  • किसी Thread नेटवर्क के सभी डिवाइसों पर यूडीपी मैसेज भेजने का तरीका
  • Makefile में बदलाव करने का तरीका

आपको इनकी ज़रूरत होगी

हार्डवेयर:

  • नॉर्डिक सेमीकंडक्टर nRF52840 डेव बोर्ड 3
  • बोर्ड कनेक्ट करने के लिए, तीन यूएसबी माइक्रो-यूएसबी केबल
  • कम से कम 3 यूएसबी पोर्ट वाली Linux मशीन

सॉफ़्टवेयर:

  • जीएनयू टूलचेन
  • नॉर्डिक nRF5x कमांड लाइन टूल
  • सेगर जे-लिंक सॉफ़्टवेयर
  • OpenThread
  • Git

ध्यान दें कि इस कोडलैब के कॉन्टेंट को क्रिएटिव कॉमंस एट्रिब्यूशन 3.0 लाइसेंस के तहत लाइसेंस मिला है. साथ ही, कोड सैंपल को Apache 2.0 लाइसेंस के तहत लाइसेंस मिला है.

2. शुरुआत करना

हार्डवेयर कोडलैब की प्रोसेस पूरी करें

इस कोडलैब को शुरू करने से पहले, आपको nRF52840 बोर्ड और OpenThread के साथ एक थ्रेड नेटवर्क बनाना कोडलैब पूरा करना होगा, जो:

  • उन सभी सॉफ़्टवेयर के बारे में जानकारी जिन्हें बनाने और फ़्लैश करने के लिए ज़रूरी है
  • आपको OpenThread का इस्तेमाल करने और नॉर्डिक nRF52840 बोर्ड पर फ़्लैश करने का तरीका बताया गया है
  • किसी Thread नेटवर्क की बुनियादी जानकारी दिखाता है

OpenThread को बनाने और बोर्ड को फ़्लैश करने के लिए, सेट अप किए गए किसी भी एनवायरमेंट में कोडलैब के बारे में ज़्यादा जानकारी नहीं दी गई है. सिर्फ़ इन फ़्लैश बोर्ड को फ़्लैश करने के बुनियादी निर्देश दिए गए हैं. यह माना जाता है कि आपने थ्रेड थ्रेड कोडलैब बनाना पहले ही पूरा कर लिया है.

Linux मशीन

इस कोडलैब को किसी i386 या x86-आधारित Linux मशीन का इस्तेमाल करके, सभी थ्रेड डेवलपमेंट बोर्ड को फ़्लैश करने के लिए डिज़ाइन किया गया था. सभी चरणों की जांच Ubuntu 14.04.5 LTS (Trusty Tahr) पर की गई है.

नॉर्डिक सेमीकंडक्टर nRF52840 बोर्ड

यह कोडलैब तीन nRF52840 PDK बोर्ड का इस्तेमाल करता है.

a6693da3ce213856.png

सॉफ़्टवेयर इंस्टॉल करें

OpenThread को बनाने और फ़्लैश करने के लिए, आपको SEGGER J-Link, nRF5x कमांड लाइन टूल, ARM GNU टूलचेन, और अलग-अलग Linux पैकेज इंस्टॉल करने होंगे. अगर आपने Thread नेटवर्क कोडलैब बनाना शुरू किया है, तो आपकी ज़रूरत की हर चीज़ पहले से इंस्टॉल होगी. अगर ऐसा नहीं है, तो जारी रखने से पहले, उस कोडलैब को पूरा करें. इससे, OpenThread को nRF52840 डेवलपर बोर्ड पर बनाया और फ़्लैश किया जा सकता है.

3. रिपॉज़िटरी को क्लोन करें

OpenThread में ऐप्लिकेशन कोड का एक उदाहरण होता है, जिसे इस कोडलैब (कोड बनाना सीखना) के लिए शुरुआती पॉइंट के तौर पर इस्तेमाल किया जा सकता है.

OpenThread नॉर्डिक nRF528xx के उदाहरणों को रिपो करें और OpenThread को बनाएं:

$ git clone --recursive https://github.com/openthread/ot-nrf528xx
$ cd ot-nrf528xx
$ ./script/bootstrap

4. OpenThread एपीआई की बुनियादी बातें

OpenThread के सार्वजनिक एपीआई, OpenThread डेटा स्टोर करने की जगह में ./openthread/include/openthread पर मौजूद हैं. ये API, आपके ऐप्लिकेशन में इस्तेमाल करने के लिए, थ्रेड और प्लैटफ़ॉर्म लेवल, दोनों पर कई तरह की OpenThread सुविधाओं और फ़ंक्शन को ऐक्सेस देते हैं:

  • OpenThread इंस्टेंस की जानकारी और कंट्रोल
  • ऐप्लिकेशन सेवाएं, जैसे कि IPv6, यूडीपी, और सीओएपी
  • कमिश्नर और जॉइनर की भूमिकाओं के साथ-साथ, नेटवर्क क्रेडेंशियल मैनेजमेंट
  • बॉर्डर राऊटर मैनेजमेंट
  • बच्चों की निगरानी और जैम की पहचान करने जैसी बेहतर सुविधाएं

सभी OpenThread एपीआई की जानकारी openthread.io/reference पर मौजूद है.

एपीआई का इस्तेमाल करना

किसी एपीआई का इस्तेमाल करने के लिए, अपनी किसी एक ऐप्लिकेशन फ़ाइल में इसकी हेडर फ़ाइल शामिल करें. इसके बाद, मनचाहे फ़ंक्शन को कॉल करें.

उदाहरण के लिए, OpenThread के साथ शामिल सीएलआई उदाहरण ऐप्लिकेशन में इन एपीआई हेडर का इस्तेमाल किया जाता है:

./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 इंस्टेंस

otInstance स्ट्रक्चर ऐसी चीज़ है जिसका इस्तेमाल आप OpenThread एपीआई के साथ काम करते समय करेंगे. शुरू करने के बाद, यह स्ट्रक्चर OpenThread लाइब्रेरी के स्टैटिक इंस्टेंस को दिखाता है और उपयोगकर्ता को OpenThread एपीआई कॉल करने की अनुमति देता है.

उदाहरण के लिए, OpenThread इंस्टेंस को सीएलआई उदाहरण ऐप्लिकेशन के 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 नेमस्पेस का इस्तेमाल करें. इसके बाद, उन्हें प्लैटफ़ॉर्म के हिसाब से बनी सोर्स फ़ाइल में लागू करें. इस तरीके से, आप अन्य उदाहरण के प्लैटफ़ॉर्म के लिए एक जैसे फ़ंक्शन हेडर का इस्तेमाल कर सकते हैं.

उदाहरण के लिए, nIO52840 बटन और एलईडी लाइट लगाने के लिए, हम जो GPIO फ़ंक्शन इस्तेमाल करेंगे उसका एलान openthread-system.h में किया जाना चाहिए.

अपनी पसंद के टेक्स्ट एडिटर में ./openthread/examples/platforms/openthread-system.h फ़ाइल खोलें.

./openthread/examples/platforms/openthread-system.h

कार्रवाई: प्लैटफ़ॉर्म के हिसाब से जीपीआई फ़ंक्शन से जुड़े एलान जोड़ें.

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 (नई फ़ाइल)

कार्रवाई: जोड़ें.

ये वैल्यू, 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 बटन और एलईडी के बारे में ज़्यादा जानकारी के लिए, नॉर्डिक सेमीकंडक्टर इन्फ़ोसेंटर देखें.

कार्रवाई: हेडर जोड़ें में शामिल है.

इसके बाद, हेडर जोड़ें जिसमें आपको 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;
}

कार्रवाई: एलईडी लाइट कॉन्फ़िगर करने के लिए, कोई फ़ंक्शन जोड़ें.

शुरू करने के दौरान, सभी एलईडी लाइटों की स्थिति और मोड को कॉन्फ़िगर करने के लिए यह कोड जोड़ें.

/**
 * @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;
    }
}

कार्रवाई: बटन दबाने की प्रक्रिया शुरू करने और उसे प्रोसेस करने के लिए, फ़ंक्शन जोड़ें.

पहला फ़ंक्शन, बटन दबाने पर बोर्ड को शुरू करता है और दूसरा बटन दबाने पर, मल्टीकास्ट यूडीपी मैसेज भेजता है.

/**
 * @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. API: डिवाइस की भूमिका में बदलाव करने के लिए प्रतिक्रिया दें

हमारे ऐप्लिकेशन में, हम डिवाइस की भूमिका के हिसाब से अलग-अलग एलईडी लाइट चालू करना चाहते हैं. ये भूमिकाएं ट्रैक करें: लीडर, राऊटर, एंड डिवाइस. हम इन्हें इस तरह एलईडी लाइट असाइन कर सकते हैं:

  • LED1 = लीडर
  • LED2 = राऊटर
  • LED3 = डिवाइस बंद करें

इस सुविधा को चालू करने के लिए, ऐप्लिकेशन को यह पता होना चाहिए कि डिवाइस की भूमिका कब बदल गई है और जवाब में सही एलईडी चालू कैसे करें. हम पहले हिस्से के लिए OpenThread इंस्टेंस का और दूसरे हिस्से के लिए GPIO प्लैटफ़ॉर्म ऐब्स्ट्रैक्शन का इस्तेमाल करेंगे.

अपनी पसंद के टेक्स्ट एडिटर में ./openthread/examples/apps/cli/main.c फ़ाइल खोलें.

./openthread/examples/apps/cli/main.c

कार्रवाई: हेडर जोड़ें में शामिल है.

main.c फ़ाइल के 'शामिल है' सेक्शन में, एपीआई हेडर फ़ाइलें जोड़ें. आपको ये भूमिकाएं बदलने के लिए ज़रूरी हैं.

#include <openthread/instance.h>
#include <openthread/thread.h>
#include <openthread/thread_ftd.h>

कार्रवाई: OpenThread इंस्टेंस की स्थिति में बदलाव के लिए हैंडलर फ़ंक्शन का एलान जोड़ें.

इस एलान को main.c में जोड़ें. ऐसा, हेडर के बाद और #if स्टेटमेंट से पहले करें. यह फ़ंक्शन मुख्य ऐप्लिकेशन के बाद तय किया जाएगा.

void handleNetifStateChanged(uint32_t aFlags, void *aContext);

कार्रवाई: राज्य के बदलाव हैंडलर फ़ंक्शन के लिए कॉलबैक रजिस्ट्रेशन जोड़ें.

इस फ़ंक्शन को otAppCliInit कॉल के बाद, main() फ़ंक्शन में जोड़ें.main.c इस कॉलबैक रजिस्ट्रेशन से, OpenThread को handleNetifStateChange फ़ंक्शन को कॉल करने के लिए कहा जाता है. ऐसा तब होता है, जब OpenThread इंस्टेंस की स्थिति बदलती है.

/* 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. एपीआई: एलईडी चालू करने के लिए, मल्टीकास्ट सुविधा का इस्तेमाल करें

हमारे ऐप्लिकेशन में, एक बार में बटन1 दबाने पर हम नेटवर्क में मौजूद दूसरे सभी डिवाइस पर यूडीपी मैसेज भेजना चाहते हैं. मैसेज मिल जाने की पुष्टि करने के लिए, हम जवाब में अन्य बोर्ड पर LED4 को टॉगल करेंगे.

इस फ़ंक्शन को चालू करने के लिए, ऐप्लिकेशन को:

  • शुरू होने पर, यूडीपी कनेक्शन शुरू करें
  • मेश-स्थानीय मल्टीकास्ट पते पर यूडीपी मैसेज भेजने की सुविधा पाएं
  • आने वाले यूडीपी मैसेज हैंडल करें
  • आने वाले यूडीपी मैसेज के जवाब में LED4 टॉगल करें

अपनी पसंद के टेक्स्ट एडिटर में ./openthread/examples/apps/cli/main.c फ़ाइल खोलें.

./openthread/examples/apps/cli/main.c

कार्रवाई: हेडर जोड़ें में शामिल है.

इसमें, main.c फ़ाइल के सबसे ऊपर मौजूद 'शामिल है' सेक्शन में, एपीआई हेडर की फ़ाइलें जोड़ें. यह सुविधा मल्टीकास्ट यूडीपी सुविधा के लिए ज़रूरी है.

#include <string.h>

#include <openthread/message.h>
#include <openthread/udp.h>

#include "utils/code_utils.h"

code_utils.h हेडर का इस्तेमाल otEXPECT और otEXPECT_ACTION मैक्रो के लिए किया जाता है, जो रनटाइम के दौरान होने वाली स्थितियों की पुष्टि करते हैं और गड़बड़ियों को अच्छी तरह से मैनेज करते हैं.

कार्रवाई: परिभाषाएं और कॉन्सटेंट जोड़ें:

main.c फ़ाइल में, 'शामिल है' सेक्शन के बाद और किसी #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 एलईडी और बटन शुरू करने के लिए कॉल जोड़ें.

otSetStateChangedCallback फ़ंक्शन के बाद, main() फ़ंक्शन में ये फ़ंक्शन कॉल जोड़ें.main.c ये फ़ंक्शन, GPIO और GPIOTE पिन शुरू करते हैं और बटन पुश इवेंट मैनेज करने के लिए बटन हैंडलर सेट करते हैं.

/* init GPIO LEDs and button */
otSysLedInit();
otSysButtonInit(handleButtonInterrupt);

कार्रवाई: यूडीपी शुरू करने का कॉल जोड़ें.

हाल ही में जोड़े गए otSysButtonInit कॉल के बाद, इस फ़ंक्शन को main() फ़ंक्शन में जोड़ें:main.c

initUdp(instance);

यह कॉल पक्का करता है कि ऐप्लिकेशन शुरू होने पर यूडीपी सॉकेट शुरू हो गया है. इसके बिना, डिवाइस यूडीपी मैसेज भेज या पा नहीं सकता.

कार्रवाई: GPIO बटन इवेंट को प्रोसेस करने के लिए कॉल जोड़ें.

while फ़ंक्शन में, otSysProcessDrivers कॉल के बाद, main() फ़ंक्शन में यह फ़ंक्शन कॉल जोड़ें.main.c gpio.c में बताया गया यह फ़ंक्शन, यह जांच करता है कि बटन दबाया गया था या नहीं. अगर ऐसा है, तो वह ऊपर बताए गए हैंडलर (handleButtonInterrupt) को कॉल करता है.

otSysButtonProcess(instance);

कार्रवाई: बटन के साथ दिखने वाला हैंडलर लागू करें.

main.c में handleButtonInterrupt फ़ंक्शन को लागू करने के लिए, पिछले चरण में जोड़े गए handleNetifStateChanged फ़ंक्शन का इस्तेमाल करें:

/**
 * Function to handle button push event
 */
void handleButtonInterrupt(otInstance *aInstance)
{
    sendUdp(aInstance);
}

कार्रवाई: यूडीपी शुरू करें.

main.c में जोड़े गए initUdp फ़ंक्शन का इस्तेमाल करने वाले handleButtonInterrupt फ़ंक्शन को लागू करने की सुविधा जोड़ें:

/**
 * 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 में जोड़े गए sendUdp फ़ंक्शन का इस्तेमाल करने वाले initUdp फ़ंक्शन को लागू करने की सुविधा जोड़ें:

/**
 * 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 और यूडीपी रेफ़रंस देखें.

कार्रवाई: यूडीपी मैसेज हैंडलिंग लागू करें.

हाल ही में जोड़े गए sendUdp फ़ंक्शन के बाद, handleUdpReceive फ़ंक्शन को लागू करें.main.c यह फ़ंक्शन 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. API: थ्रेड नेटवर्क को कॉन्फ़िगर करें

प्रदर्शन करने में आसान बनाने के लिए, हम चाहते हैं कि हमारे डिवाइस Thread को तुरंत चालू करें और नेटवर्क में शामिल होने पर उन सभी को एक साथ शामिल करें. ऐसा करने के लिए, हम otOperationalDataset स्ट्रक्चर का इस्तेमाल करेंगे. इस स्ट्रक्चर में, Thread नेटवर्क के क्रेडेंशियल को डिवाइस पर भेजने के लिए ज़रूरी सभी पैरामीटर मौजूद हैं.

हमारे ऐप्लिकेशन को ज़्यादा सुरक्षित बनाने और हमारे नेटवर्क में थ्रेड नोड को सीमित करने के लिए, इस स्ट्रक्चर का इस्तेमाल करने से OpenThread में नेटवर्क की डिफ़ॉल्ट सेटिंग बदल जाएंगी.

इसके बाद, अपने पसंदीदा टेक्स्ट एडिटर में ./openthread/examples/apps/cli/main.c फ़ाइल खोलें.

./openthread/examples/apps/cli/main.c

कार्रवाई: हेडर जोड़ें शामिल है.

main.c फ़ाइल के सबसे ऊपर, शामिल करने वाले सेक्शन में, एपीआई हेडर फ़ाइल जोड़ें. आपको इसे थ्रेड नेटवर्क को कॉन्फ़िगर करने की ज़रूरत होगी:

#include <openthread/dataset_ftd.h>

कार्रवाई: नेटवर्क कॉन्फ़िगरेशन सेट करने के लिए, फ़ंक्शन का एलान जोड़ें.

इस एलान को main.c में जोड़ें. ऐसा, हेडर के बाद और #if स्टेटमेंट से पहले करें. यह फ़ंक्शन, मुख्य ऐप्लिकेशन फ़ंक्शन के बाद तय किया जाएगा.

static void setNetworkConfiguration(otInstance *aInstance);

कार्रवाई: नेटवर्क कॉन्फ़िगरेशन कॉल जोड़ें.

इस फ़ंक्शन कॉल को otSetStateChangedCallback कॉल के बाद, main() फ़ंक्शन में जोड़ें.main.c यह फ़ंक्शन, थ्रेड नेटवर्क डेटासेट को कॉन्फ़िगर करता है.

/* Override default network credentials */
setNetworkConfiguration(instance);

कार्रवाई: थ्रेड नेटवर्क इंटरफ़ेस और स्टैक को चालू करने के लिए कॉल जोड़ें.

otSysButtonInit फ़ंक्शन के बाद, main() फ़ंक्शन में ये फ़ंक्शन कॉल जोड़ें.main.c

/* 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() फ़ंक्शन के बाद, setNetworkConfiguration फ़ंक्शन लागू करें:main.c

/**
 * 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
  • पैन आईडी = 0x2222
  • एक्सटेंडेड पैन आईडी = C0DE1AB5C0DE1AB5
  • नेटवर्क कुंजी = 1234C0DE1AB51234C0DE1AB51234C0DE
  • नेटवर्क का नाम = OTCodelab

इसके अलावा, यहां हम राऊटर चुनने के सिग्नल में गड़बड़ी करने की सुविधा को कम करते हैं, ताकि हमारे डिवाइस डेमो के मकसद से तेज़ी से भूमिकाएं बदल सकें. ध्यान दें कि यह सिर्फ़ तब किया जाता है, जब नोड एफ़टीडी (फ़ुल थ्रेड डिवाइस) हो. अगले चरण में, इसके बारे में ज़्यादा जानकारी पाएं.

9. एपीआई: पाबंदी वाले फ़ंक्शन

कुछ OpenThread के एपीआई सेटिंग में बदलाव करते हैं. इन्हें सिर्फ़ डेमो या जांच के लिए बदला जाना चाहिए. इन एपीआई का इस्तेमाल OpenThread का इस्तेमाल करके किसी ऐप्लिकेशन के प्रोडक्शन डिप्लॉयमेंट में नहीं किया जाना चाहिए.

उदाहरण के लिए, किसी otThreadSetRouterSelectionJitter डिवाइस को अपने-आप राऊटर का प्रमोशन करने में लगने वाले समय (सेकंड में) को अडजस्ट करता है. थ्रेड की खास बातों के हिसाब से, इस वैल्यू का डिफ़ॉल्ट साइज़ 120 है. कोडलैब में इसे आसानी से इस्तेमाल करने के लिए, हम इसे 20 में बदलना चाहते हैं. इसलिए, आपको थ्रेड नोड की भूमिकाएं बदलने में ज़्यादा समय नहीं लगेगा.

ध्यान दें: 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

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

आखिर में, नॉर्डिक सेमीकंडक्टर CMakeLists.txt फ़ाइल में nrfx_gpiote.c ड्राइवर फ़ाइल जोड़ें, ताकि वह नॉर्डिक ड्राइवर के लाइब्रेरी बिल्ड के साथ शामिल हो जाए.

कार्रवाई: नॉर्डिक सेमीकंडक्टर CMakeLists.txt फ़ाइल में जीपीआई ड्राइवर जोड़ें.

./third_party/NordicSemiconductor/CMakeLists.txt को अपने पसंदीदा टेक्स्ट एडिटर में खोलें और COMMON_SOURCES सेक्शन में जोड़ें.

...

set(COMMON_SOURCES
  ...
  nrfx/drivers/src/nrfx_gpiote.c
  ...
)
...

11. डिवाइसों को सेट अप करें

कोड अपडेट करने के बाद, Nordic के सभी 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 एम्बेड किए गए टूलचेन के साथ इसे हेक्स फ़ॉर्मैट में बदलें:

$ cd build/bin
$ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex

बोर्ड हटाएं

हर nRF52840 बोर्ड पर ot-cli-ftd.hex फ़ाइल को फ़्लैश करें.

nRF52840 बोर्ड पर बाहरी पावर पिन के आगे, माइक्रो-यूएसबी डीबग पोर्ट में यूएसबी केबल अटैच करें. इसके बाद, उसे अपनी Linux मशीन में प्लग करें. सही तरीके से सेट करें, LED5 चालू है.

20a3b4b480356447.png

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

c00d519ebec7e5f0.jpeg

nRFx कमांड लाइन टूल की लोकेशन पर जाएं. इसके बाद, बोर्ड के सीरियल नंबर का इस्तेमाल करके, OpenThread CLI FTD हेक्स फ़ाइल को nRF52840 बोर्ड पर फ़्लैश करें:

$ 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.

अन्य दो बोर्ड के लिए, "बोर्डों को फ़्लैश करें" चरण को दोहराएं. हर बोर्ड को Linux मशीन से एक ही तरह से कनेक्ट किया जाना चाहिए. साथ ही, बोर्ड के सीरियल नंबर को छोड़कर, सभी कमांड को एक ही तरीके से फ़्लैश करना होगा. पक्का करें कि हर बोर्ड का खास सीरियल नंबर इस्तेमाल किया गया हो

nrfjprog फ़्लैशिंग कमांड.

अगर रिकॉर्ड बना दिए जाते हैं, तो हर बोर्ड पर LED1, LED2 या LED3 लाइट डाली जाएगी. हो सकता है कि आपको फ़्लैश करते समय (एलईडी की भूमिका बदलने वाली सुविधा) जल्दी ही एलईडी लाइट स्विच को 3 से 2 या 2 से 1 तक भी दिखाई दे.

12. ऐप्लिकेशन की मुख्य सुविधाओं और उनके काम करने के तरीके के लिए

अब आपके तीनों nRF52840 बोर्ड चालू होने चाहिए और हमारे OpenThread ऐप्लिकेशन का इस्तेमाल किया जाना चाहिए. जैसा कि पहले बताया गया था, इस ऐप्लिकेशन में दो मुख्य सुविधाएं हैं.

डिवाइस की भूमिका के इंंडिकेटर

हर बोर्ड पर हाइलाइट की गई एलईडी, थ्रेड नोड की मौजूदा भूमिका को दिखाती है:

  • LED1 = लीडर
  • LED2 = राऊटर
  • LED3 = डिवाइस बंद करें

भूमिका बदलने के साथ ही, जगमगाती एलईडी भी बदलती है. आपको ये बदलाव, बोर्ड या हर डिवाइस के चालू होने के 20 सेकंड के अंदर दो बार दिखाई दिए होंगे.

यूडीपी मल्टीकास्ट

जब Button1 एक बोर्ड पर दबाया जाता है, तो मेश-लोकल मल्टीकास्ट पते पर एक यूडीपी मैसेज भेजा जाता है. इसमें Thread नेटवर्क के दूसरे सभी नोड भी शामिल होते हैं. यह मैसेज पाने के लिए अन्य सभी बोर्ड पर LED4 टॉगल करके चालू या बंद करें. हर बोर्ड पर LED4 तब तक चालू या बंद रहता है, जब तक उसे कोई दूसरा यूडीपी मैसेज नहीं मिलता.

203dd094acca1f97.png

9bbd96d9b1c63504.png

13. डेमो: डिवाइस की भूमिका में होने वाले बदलावों पर नज़र रखना

फ़्लैश किए गए डिवाइस एक खास तरह के फ़ुल थ्रेड डिवाइस (एफ़टीडी) हैं, जिसे राऊटर की सुविधा वाले एंड डिवाइस (आरईडी) के नाम से जाना जाता है. इसका मतलब है कि ये ऐप्लिकेशन, एक राऊटर या एंड डिवाइस की तरह काम कर सकते हैं. साथ ही, वे एंड डिवाइस से किसी राऊटर में अपना प्रमोशन कर सकते हैं.

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

हर थ्रेड नेटवर्क में एक लीडर भी होता है, जो एक थ्रेड नेटवर्क में राऊटर के सेट को मैनेज करने के लिए ज़िम्मेदार होता है. सभी डिवाइस चालू होने पर, उनमें से एक 20 सेकंड के बाद लीडर (LED1 चालू) होना चाहिए और दूसरे दो राऊटर राऊटर (LED2 चालू) होने चाहिए.

4e1e885861a66570.png

लीडर को हटाएं

अगर लीडर को Thread नेटवर्क से हटा दिया जाता है, तो कोई दूसरा राऊटर खुद को किसी लीडर के तौर पर प्रमोट करता है. इससे यह पक्का किया जाता है कि नेटवर्क में अब भी लीडर मौजूद है.

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

4c57c87adb40e0e3.png

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

5f40afca2dcc4b5b.png

बोर्ड रीसेट करें

तीनों बोर्ड बंद करें और फिर से चालू करें और एलईडी की जानकारी पाएं. सबसे ऊपर दिया गया पहला बोर्ड, लीडर की भूमिका में शुरू होना चाहिए. इसमें LED1 की लाइट जलती है. थ्रेड नेटवर्क में मौजूद पहला राऊटर अपने-आप लीडर बन जाता है.

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

नेटवर्क पार्टीशन

अगर आपके बोर्ड को ज़रूरत के मुताबिक पावर नहीं मिल रहा है या उनके बीच में रेडियो कनेक्शन कमज़ोर है, तो थ्रेड नेटवर्क को सेगमेंट में बांटा जा सकता है. इसके अलावा, यह भी हो सकता है कि आपके एक से ज़्यादा डिवाइस लीडर के तौर पर दिख रहे हों.

थ्रेड अपने-आप ठीक हो रही है. इसलिए, पार्टी बनाने वाली कंपनियां फिर से एक लीडर के साथ मर्ज हो रही हैं.

14. डेमो: यूडीपी मल्टीकास्ट भेजें

अगर पिछले व्यायाम को जारी रखा जाता है, तो LED4 की रोशनी किसी भी डिवाइस पर नहीं पड़नी चाहिए.

कोई भी बोर्ड चुनें और Button1 दबाएं. ऐप्लिकेशन चलाने वाले Thread नेटवर्क के अन्य सभी बोर्ड पर LED4 का स्टेटस टॉगल होना चाहिए. पिछले अभ्यास से जारी रखने पर, वे अब चालू हो जाने चाहिए.

f186a2618fdbe3fd.png

उसी बोर्ड को फिर से चलाने के लिए Button1 दबाएं. दूसरे सभी बोर्ड पर LED4 फिर से टॉगल करना चाहिए.

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

f5865ccb8ab7aa34.png

नेटवर्क पार्टीशन

अगर आपके बोर्ड का बंटवारा हो गया है और उनमें एक से ज़्यादा लीडर हैं, तो मल्टीकास्ट मैसेज का नतीजा बोर्ड के बीच अलग-अलग होगा. अगर किसी ऐसे बोर्ड पर Button1 दबाया जाता है जिसे पार्टी में बांटा गया है (और यह पार्टिशन किए गए थ्रेड नेटवर्क का इकलौता सदस्य है), तो अन्य बोर्ड पर LED4 की लाइट नहीं जलेगी. अगर ऐसा होता है, तो बोर्ड को रीसेट करें—इससे वे एक ही थ्रेड नेटवर्क को फिर से बना देंगे और यूडीपी मैसेजिंग सही तरीके से काम करेगी.

15. बधाई हो!

आपने एक ऐसा ऐप्लिकेशन बनाया है जो OpenThread एपीआई का इस्तेमाल करता है!

अब आप जानते हैं कि:

  • नॉर्डिक nRF52840 डेव बोर्ड पर बटन और एलईडी लाइट कैसे सेट करें
  • आम OpenThread एपीआई और otInstance क्लास को इस्तेमाल करने का तरीका
  • OpenThread की स्थिति में हुए बदलावों पर नज़र रखने और उन पर प्रतिक्रिया देने का तरीका
  • किसी Thread नेटवर्क के सभी डिवाइसों पर यूडीपी मैसेज भेजने का तरीका
  • Makefile में बदलाव करने का तरीका

अगले चरण

इस कोडलैब से शुरुआत करके, ये तरीके आज़माएं:

  • ऑनबोर्ड ऑन LED के बजाय, GPIO पिन का इस्तेमाल करने के लिए, GPIO मॉड्यूल में बदलाव करें. साथ ही, ऐसी बाहरी आरजीबी एलईडी को कनेक्ट करें जो राऊटर की भूमिका के आधार पर रंग बदलती हैं
  • दूसरे उदाहरण के प्लैटफ़ॉर्म के लिए GPIO सहायता जोड़ें
  • कोई बटन दबाने पर सभी डिवाइसों को पिंग करने के बजाय, मल्टीकास्ट के बजाय, रूटीन/लीडर एपीआई का इस्तेमाल करके किसी एक डिवाइस का पता लगाएं और उस पर पिंग करें
  • OpenThread बॉर्डर राऊटर का इस्तेमाल करके, अपने मेश नेटवर्क को इंटरनेट से कनेक्ट करें. साथ ही, एलईडी की रोशनी चालू करने के लिए, उन्हें थ्रेड नेटवर्क के बाहर से कास्ट करें

आगे पढ़ना

कई तरह के OpenThread संसाधनों के लिए, openthread.io और GitHubदेखें. इनमें ये भी शामिल हैं:

रेफ़रंस: