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

1. परिचय

26b7f4f6b3ea0700.png

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

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

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

2a6db2e258c32237.png

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

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

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

हार्डवेयर:

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

सॉफ़्टवेयर:

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

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

2. रिपोर्ट का इस्तेमाल करना

हार्डवेयर कोडलैब (कोड बनाना सीखना) पूरा करना

इस कोडलैब का इस्तेमाल शुरू करने से पहले, आपको nRF52840 बोर्ड और ओपन थ्रेड के साथ थ्रेड नेटवर्क बनाने की प्रक्रिया पूरी करनी होगी, जो:

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

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

Linux मशीन

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

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

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

a6693da3ce213856.png

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

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

3. डेटा स्टोर करने की जगह की क्लोन करें

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

OpenThread Nordic nRF528xx के रेपो को क्लोन करें और OpenThread बनाएं:

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

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

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

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

सभी OpenThread API पर संदर्भ जानकारी 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 इंस्टेंस

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 के साथ दिए गए किसी उदाहरण ऐप्लिकेशन में प्लैटफ़ॉर्म के हिसाब से फ़ंक्शन जोड़ना चाहते हैं, तो सबसे पहले सभी फ़ंक्शन के लिए otSys नेमस्पेस का इस्तेमाल करके, उन्हें ./openthread/examples/platforms/openthread-system.h हेडर में तय करें. इसके बाद, इन्हें प्लैटफ़ॉर्म के हिसाब से बनी सोर्स फ़ाइल में लागू करें. इस तरह संक्षिप्त किए गए, आप अन्य उदाहरण प्लैटफ़ॉर्म के लिए एक ही फ़ंक्शन हेडर का इस्तेमाल कर सकते हैं.

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

कार्रवाई: बटन 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;
    }
}

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

इस डिवाइस का इस्तेमाल तब किया जाएगा, जब डिवाइस को मल्टीकास्ट यूडीपी मैसेज मिलता है.

/**
 * @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 दबाने पर, मल्टीकास्ट यूडीपी मैसेज भेजता है.

/**
 * @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 file सेव करें और बंद करें

6. एपीआई: डिवाइस की भूमिका में हुए बदलावों पर प्रतिक्रिया देना

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

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

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

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

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

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

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

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

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

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

void handleNetifStateChanged(uint32_t aFlags, void *aContext);

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

main.c में, इस फ़ंक्शन को otAppCliInit कॉल के बाद main() फ़ंक्शन में जोड़ें. इस कॉलबैक रजिस्ट्रेशन से, 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. एपीआई: एलईडी चालू करने के लिए मल्टीकास्ट का इस्तेमाल करना

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

इस सुविधा को चालू करने के लिए, ऐप्लिकेशन को:

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

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

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

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

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

#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 LED और बटन शुरू करने के लिए कॉल जोड़ें.

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

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

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

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

initUdp(instance);

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

कार्रवाई: 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 को पास करके, सॉकेट को थ्रेड नेटवर्क इंटरफ़ेस से जोड़ता है. अन्य नेटवर्क इंटरफ़ेस विकल्पों के लिए, UDP एपीआई पहचान फ़ाइल में 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 ब्लॉक पर जाकर गड़बड़ी को हैंडल करता है, जहां बफ़र बफ़र हो जाता है.

UDP शुरू करने के लिए इस्तेमाल किए जाने वाले फ़ंक्शन के बारे में ज़्यादा जानकारी के लिए, OpenIP.6 पर 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. API: थ्रेड नेटवर्क कॉन्फ़िगर करें

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

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

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

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

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

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

#include <openthread/dataset_ftd.h>

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

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

static void setNetworkConfiguration(otInstance *aInstance);

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

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

/* 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);

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

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);
}

फ़ंक्शन में विस्तार से बताया गया है कि हम इस ऐप्लिकेशन के लिए इस्तेमाल किए जा रहे थ्रेड नेटवर्क पैरामीटर हैं:

  • चैनल = 15
  • पैन आईडी = 0x2222
  • पैन कार्ड का आईडी = C0DE1AB5C0DE1AB5
  • नेटवर्क कुंजी = 1234C0DE1AB51234C0DE1AB51234C0DE
  • नेटवर्क का नाम = OTCodelab

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

9. एपीआई: प्रतिबंधित फ़ंक्शन

कुछ OpenThread's API ऐसी सेटिंग को संशोधित करते हैं जिन्हें केवल डेमो या परीक्षण उद्देश्यों के लिए संशोधित किया जाना चाहिए. OpenAPI का इस्तेमाल करने वाले ऐप्लिकेशन के प्रोडक्शन डिप्लॉयमेंट में इन एपीआई का इस्तेमाल नहीं किया जाना चाहिए.

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

ध्यान दें: MTD डिवाइस राऊटर में नहीं बदलते. साथ ही, MTD बिल्ड में 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

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

कार्रवाई: NordicSemiconductor CMakeLists.txt फ़ाइल में gpio ड्राइवर जोड़ें.

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

...

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

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

सभी कोड अपडेट हो जाने पर, आप #3 नॉर्डिक nRF52840 डेवलपर बोर्ड पर ऐप्लिकेशन बनाने और फ़्लैश करने के लिए तैयार होते हैं. हर डिवाइस, फ़ुल थ्रेड डिवाइस (एफ़टीडी) के तौर पर काम करेगा.

ओपनथ्रेड बनाएं

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

बोर्ड फ़्लैश करें

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

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

20a3b4b480356447.png

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

c00d519ebec7e5f0.jpeg

nRFx कमांड लाइन टूल की जगह पर जाएं. साथ ही, बोर्ड और#39; के सीरियल नंबर का इस्तेमाल करके, 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 मशीन से एक ही तरह से कनेक्ट होना चाहिए. साथ ही, बोर्ड और #39; के सीरियल नंबर को छोड़कर, फ़्लैश का निर्देश एक ही होता है. पक्का करें कि हर बोर्ड' का खास सीरियल नंबर इस्तेमाल किया गया हो

nrfjprog फ़्लैश करने वाला निर्देश.

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

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

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

डिवाइस रोल इंडिकेटर

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

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

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

UDP मल्टीकास्ट

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

203dd094aca1f97.png

9bbd96d9b1c63504.png

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

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

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

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

4e1e885861a66570.png

लीडर हटाएं

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

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

4c57c87adb40e0e3.png

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

5f40afca2dcc4b5b.png

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

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

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

नेटवर्क विभाजन

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

थ्रेड अपने-आप ठीक होने की सुविधा है, इसलिए पार्टीशन बनाने के बाद, उन्हें लीडर के किसी एक ग्रुप में वापस मर्ज किया जाना चाहिए.

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

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

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

f186a2618fdbe3fd.png

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

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

f5865ccb8ab7aa34.png

नेटवर्क विभाजन

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

15. बधाई हो!

आपने' एक ऐप्लिकेशन बनाया है जो OpenThread API का उपयोग करता है!

अब आपको पता है कि:

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

अगले चरण

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

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

इसके बारे में और पढ़ें

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

  • काम करने वाले प्लैटफ़ॉर्म — उन सभी प्लैटफ़ॉर्म के बारे में जानें जो OpenThread का इस्तेमाल करते हैं
  • OpenThread बनाएं — ओपन थ्रेड बनाने और उसे कॉन्फ़िगर करने के बारे में ज़्यादा जानकारी
  • Thread Primer — थ्रेड के सिद्धांतों के लिए एक बेहतरीन रेफ़रंस

रेफ़रंस: