בניית רשת בפרוטוקול Thread עם לוחות nRF52840 ו-OpenThread

1. מבוא

26b7f4f6b3ea0700.png

OpenThread שפורסם על ידי Google הוא הטמעה בקוד פתוח של פרוטוקול הרשת Thread®‎. ‫Google Nest פרסמה את OpenThread כדי להפוך את הטכנולוגיה שמשמשת במוצרי Nest לזמינה למפתחים באופן נרחב, במטרה להאיץ את פיתוח המוצרים לבית החכם.

במפרט של Thread מוגדר פרוטוקול תקשורת אלחוטי אמין ומאובטח בין מכשירים, שמבוסס על IPv6 וצורך מעט חשמל, לשימוש באפליקציות ביתיות. ‫OpenThread מטמיע את כל שכבות הרשת של Thread, כולל IPv6, ‏ 6LoWPAN, ‏ IEEE 802.15.4 עם אבטחת MAC, ‏ Mesh Link Establishment ו-Mesh Routing.

ב-Codelab הזה תתכנתו את OpenThread בחומרה אמיתית, תיצרו ותנהלו רשת פרוטוקול Thread ותעבירו הודעות בין צמתים.

4806d16a8c137c6d.jpeg

מה תלמדו

  • יצירה והעברה של קובצי הפעלה של OpenThread CLI ללוחות פיתוח
  • בניית RCP שכולל מכונת Linux ולוח פיתוח
  • תקשורת עם RCP באמצעות OpenThread Daemon ו-ot-ctl
  • ניהול ידני של צמתי Thread באמצעות GNU Screen ו-OpenThread CLI
  • הקצאת הרשאות מאובטחת למכשירים ברשת Thread
  • איך שידור מרובה משתתפים ב-IPv6 עובד
  • העברת הודעות בין צמתי Thread באמצעות UDP

הדרישות

חומרה:

  • ‫3 לוחות פיתוח Nordic Semiconductor nRF52840
  • ‫3 כבלים מ-USB למיקרו USB לחיבור הלוחות
  • מחשב Linux עם לפחות 3 יציאות USB

תוכנה:

  • GNU Toolchain
  • כלי שורת הפקודה Nordic nRF5x
  • תוכנת Segger J-Link
  • OpenThread
  • Git

2. תחילת העבודה

סימולציה של OpenThread

לפני שמתחילים, כדאי לעבור על הסדנה האינטראקטיבית בנושא סימולציה של OpenThread כדי להכיר את מושגי הבסיס של פרוטוקול Thread ואת OpenThread CLI.

מסופי יציאה טורית

צריך לדעת איך להתחבר ליציאה טורית דרך מסוף. ב-Codelab הזה נעשה שימוש ב-GNU Screen ומוצג סקירה כללית של השימוש, אבל אפשר להשתמש בכל תוכנת טרמינל אחרת.

מכונת Linux

ה-Codelab הזה נועד לשימוש במכונת Linux מבוססת i386 או x86, שתשמש כמארח למכשיר Radio Co-Processor (RCP) Thread, ולעדכון של כל לוחות הפיתוח של Thread. כל השלבים נבדקו ב-Ubuntu 14.04.5 LTS ‏ (Trusty Tahr).

לוחות Nordic Semiconductor nRF52840

ב-Codelab הזה משתמשים בשלושה לוחות nRF52840 PDK.

a6693da3ce213856.png

אנחנו משתמשים ב-SEGGER J-Link כדי לתכנת את לוחות nRF52840, שיש להם מודולי JTAG מובנים. מתקינים את התוכנה במחשב Linux.

מורידים את החבילה המתאימה למחשב ומתקינים אותה במיקום הנכון. ב-Linux, זה /opt/SEGGER/JLink.

התקנה של כלי שורת הפקודה nRF5x

הכלי nRF5x Command Line Tools מאפשר להעביר את קובצי ה-binary של OpenThread ללוחות nRF52840. מתקינים את ה-build המתאים של nRF5x-Command-Line-Tools-<OS> במחשב Linux.

ממקמים את החבילה שחולצה בתיקיית השורש ~/

התקנה של ARM GNU Toolchain

ערכת הכלים ARM GNU משמשת לבנייה.

מומלץ למקם את הארכיון שחולץ ב-/opt/gnu-mcu-eclipse/arm-none-eabi-gcc/ במחשב Linux. פועלים לפי ההוראות שבקובץ readme.txt בארכיון.

מסך ההתקנה (אופציונלי)

‫Screen הוא כלי פשוט לגישה למכשירים שמחוברים באמצעות יציאה טורית. ב-Codelab הזה נעשה שימוש ב-Screen, אבל אתם יכולים להשתמש בכל אפליקציית מסוף של יציאה טורית שתרצו.

$ sudo apt-get install screen

3. שכפול מאגרי נתונים

OpenThread

משכפלים את OpenThread ומתקינים אותו. הפקודות script/bootstrap מוודאות ששרשרת הכלים מותקנת ושהסביבה מוגדרת בצורה תקינה:

$ mkdir -p ~/src
$ cd ~/src
$ git clone --recursive https://github.com/openthread/openthread.git
$ cd openthread
$ ./script/bootstrap

בניית OpenThread Daemon:

$ script/cmake-build posix -DOT_DAEMON=ON

עכשיו אתם מוכנים לבנות את OpenThread ולצרוב אותו ללוחות nRF52840.

4. הגדרת הכלי להצטרפות לתוכנית RCP

בנייה והפעלה

פיתוח הדוגמה OpenThread nRF52840 עם Joiner ופונקציונליות USB מקורית. מכשיר משתמש בתפקיד Joiner כדי לעבור אימות מאובטח ולהצטרף לרשת Thread. USB מקורי מאפשר שימוש ב-USB CDC ACM כהעברה טורית בין nRF52840 לבין המארח.

תמיד צריך לנקות קודם את המאגר מבנייה קודמת על ידי הפעלת rm -rf build.

$ cd ~/src
$ git clone --recursive https://github.com/openthread/ot-nrf528xx.git
$ cd ot-nrf528xx
$ script/build nrf52840 USB_trans

עוברים אל הספרייה עם הקובץ הבינארי של OpenThread RCP וממירים אותו לפורמט הקסדצימלי:

$ cd ~/src/ot-nrf528xx/build/bin
$ arm-none-eabi-objcopy -O ihex ot-rcp ot-rcp.hex

מחברים את כבל ה-USB ליציאת הניפוי באגים מיקרו USB שליד פין החשמל החיצוני בלוח nRF52840, ואז מחברים אותו למכונת Linux. מגדירים את המתג nRF power source בלוח nRF52840 לערך VDD. כשמחברים את המכשיר בצורה נכונה, נורית LED5 נדלקת.

20a3b4b480356447.png

אם זוהי הלוח הראשון שמחובר למכונת Linux, הוא יופיע כיציאה טורית /dev/ttyACM0 (כל לוחות nRF52840 משתמשים ב-ttyACM כמזהה של היציאה הטורית).

$ ls /dev/ttyACM*
/dev/ttyACM0

רושמים את המספר הסידורי של לוח nRF52840 שמשמש ל-RCP:

c00d519ebec7e5f0.jpeg

עוברים למיקום של כלי שורת הפקודה nRFx וצורבים את קובץ ה-hex של OpenThread RCP בלוח nRF52840 באמצעות המספר הסידורי של הלוח. שימו לב: אם לא תכללו את האפשרות --verify, תוצג הודעת אזהרה שלפיה תהליך הצריבה עלול להיכשל ללא שגיאה.

$ cd ~/nrfjprog/
$ ./nrfjprog -f nrf52 -s 683704924  --verify --chiperase --program \
       ~/src/ot-nrf528xx/build/bin/ot-rcp.hex --reset

אם הפעולה תצליח, יווצר הפלט הבא:

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.

כדאי לתת ללוח את השם 'RCP' כדי שלא תתבלבלו בין התפקידים בלוח בהמשך.

חיבור ל-USB מקורי

מכיוון שה-build של OpenThread RCP מאפשר שימוש ב-USB CDC ACM מקומי כהעברה טורית, צריך להשתמש ביציאת nRF USB בלוח nRF52840 כדי לתקשר עם מארח ה-RCP (מחשב Linux).

מנתקים את קצה המיקרו USB של כבל ה-USB מיציאת הניפוי באגים של לוח nRF52840 שהופעל, ואז מחברים אותו מחדש ליציאת המיקרו USB nRF USB שליד הלחצן RESET. מעבירים את המתג nRF power source (מקור המתח של nRF) למצב USB.

46e7b670d2464842.png

הפעלת דימון OpenThread

בתכנון של RCP, משתמשים ב-OpenThread Daemon כדי לתקשר עם מכשיר Thread ולנהל אותו. מפעילים את ot-daemon עם הדגל -v verbose כדי לראות את פלט היומן ולוודא שהוא פועל:

$ cd ~/src/openthread
$ sudo ./build/posix/src/posix/ot-daemon -v \
    'spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800'

אם הפעולה בוצעה בהצלחה, הפלט של ot-daemon במצב מפורט ייראה כך:

ot-daemon[12463]: Running OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; POSIX; Aug 30 2022 10:55:05
ot-daemon[12463]: Thread version: 4
ot-daemon[12463]: Thread interface: wpan0
ot-daemon[12463]: RCP version: OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; SIMULATION; Aug 30 2022 10:54:10

משאירים את חלון הטרמינל הזה פתוח כדי שאפשר יהיה לראות את היומנים מ-ot-daemon.

אפשר להשתמש ב-ot-ctl כדי לתקשר עם צומת ה-RCP. ‫ot-ctl משתמש באותו CLI כמו אפליקציית OpenThread CLI. לכן, אפשר לשלוט בצמתי ot-daemon באותו אופן כמו במכשירי Thread המדומים האחרים.

בחלון טרמינל שני, מפעילים את ot-ctl:

$ sudo ./build/posix/src/posix/ot-ctl
>

בודקים את state של Node 2 (צומת ה-RCP) שהתחלתם איתו ot-daemon:

> state
disabled
Done

5. הגדרת ה-FTD

שני צמתי ה-Thread האחרים שמשמשים ב-Codelab הזה הם מכשירי Thread מלאים (FTD) בתכנון הסטנדרטי של System-on-Chip ‏ (SoC). מכשיר אחד מתפקד כנציב, כדי לאמת ולהפעיל מכשירים ברשת הזו בצורה מאובטחת. המכשיר השני פועל כמכשיר מצטרף שהמכשיר המקצה יכול לאמת ברשת Thread.

בנייה והפעלה

יוצרים את הדוגמה OpenThread FTD לפלטפורמת nRF52840, עם התפקידים Commissioner ו-Joiner מופעלים:

$ cd ~/src/ot-nrf528xx
$ rm -rf build
$ script/build nrf52840 USB_trans -DOT_JOINER=ON -DOT_COMMISSIONER=ON

עוברים לספרייה עם קובץ ה-CLI הבינארי של OpenThread Full Thread Device (FTD) וממירים אותו לפורמט הקסדצימלי:

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

מחברים את כבל ה-USB ליציאת המיקרו USB שליד פין החשמל החיצוני בלוח nRF52840, ואז מחברים אותו למכונת Linux. אם ה-RCP עדיין מחובר למכונת Linux, הלוח החדש אמור להופיע כיציאה טורית /dev/ttyACM1 (כל לוחות nRF52840 משתמשים ב-ttyACM כמזהה של היציאה הטורית).

$ ls /dev/ttyACM*
/dev/ttyACM0  /dev/ttyACM1

כמו קודם, מציינים את המספר הסידורי של לוח nRF52840 שמשמש ל-FTD:

c00d519ebec7e5f0.jpeg

עוברים למיקום של nRFx Command Line Tools ומפעילים את קובץ ה-hex של OpenThread CLI FTD בלוח nRF52840 באמצעות המספר הסידורי של הלוח:

$ cd ~/nrfjprog/
$ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \
       ~/src/ot-nrf528xx/build/bin/ot-cli-ftd.hex --reset

נותנים ללוח את התווית 'נציב'.

חיבור ל-USB מקורי

מכיוון שגרסת ה-FTD של OpenThread מאפשרת שימוש ב-USB CDC ACM מקורי כהעברה טורית, צריך להשתמש ביציאת nRF USB בלוח nRF52840 כדי לתקשר עם מארח ה-RCP (מחשב Linux).

מנתקים את קצה המיקרו USB של כבל ה-USB מיציאת הניפוי באגים של לוח nRF52840 שהופעל, ואז מחברים אותו מחדש ליציאת המיקרו USB nRF USB שליד הלחצן RESET. מעבירים את המתג nRF power source (מקור המתח של nRF) למצב USB.

46e7b670d2464842.png

אימות גרסת ה-Build

כדי לוודא שהבנייה הושלמה בהצלחה, ניגשים אל OpenThread CLI באמצעות GNU Screen מחלון טרמינל.

$ screen /dev/ttyACM1

בחלון החדש, לוחצים על מקש Return במקלדת כמה פעמים כדי להציג את ההנחיה של OpenThread CLI >. מציגים את ממשק IPv6 ובודקים אם יש כתובות:

> ifconfig up
Done
> ipaddr
fe80:0:0:0:1cd6:87a9:cb9d:4b1d
Done

משתמשים ב-Ctrl+a →

d כדי להתנתק ממסך ה-CLI של FTD Commissioner ולחזור לטרמינל של Linux כדי שאפשר יהיה להפעיל את הלוח הבא. כדי לחזור ל-CLI בכל שלב, משתמשים בפקודה screen -r משורת הפקודה. כדי לראות רשימה של מסכים זמינים, משתמשים בפקודה screen -ls:

$ screen -ls
There is a screen on:
        74182.ttys000.mylinuxmachine        (Detached)
1 Socket in /tmp/uscreens/S-username.

הגדרת הכלי FTD Joiner

חוזרים על התהליך שלמעלה כדי לצרוב את הלוח השלישי מסוג nRF52840, באמצעות ה-build הקיים ot-cli-ftd.hex. בסיום, חשוב לחבר מחדש את הלוח למחשב באמצעות יציאת ה-USB של nRF ולהעביר את המתג nRF power source למצב VDD.

אם שני הצמתים האחרים מחוברים למכונת Linux כשמחברים את הלוח השלישי, הוא אמור להופיע כיציאה טורית /dev/ttyACM2:

$ ls /dev/ttyACM*
/dev/ttyACM0  /dev/ttyACM1  /dev/ttyACM2

נותנים ללוח את התווית Joiner.

כשמאמתים באמצעות Screen, במקום ליצור מופע חדש של Screen משורת הפקודה, צריך לצרף מחדש את המופע הקיים וליצור בו חלון חדש (שבו השתמשתם בשביל הנציב של FTD):

$ screen -r

יוצרים את החלון החדש בתוך Screen באמצעות Ctrl+a → c.

מופיעה שורת פקודה חדשה. ניגשים אל OpenThread CLI עבור FTD Joiner:

$ screen /dev/ttyACM2

בחלון החדש, לוחצים על מקש Return במקלדת כמה פעמים כדי להציג את ההנחיה של OpenThread CLI >. מציגים את ממשק IPv6 ובודקים אם יש כתובות:

> ifconfig up
Done
> ipaddr
fe80:0:0:0:6c1e:87a2:df05:c240
Done

עכשיו, כשה-CLI של FTD Joiner נמצא באותו מופע של Screen כמו FTD Commissioner, אפשר לעבור ביניהם באמצעות Ctrl+a → n.

משתמשים ב-Ctrl+a →

d בכל שלב כדי לצאת מ-Screen.

6. הגדרת חלון הטרמינל

מעכשיו והלאה, תעברו בין מכשירי Thread לעיתים קרובות, לכן חשוב לוודא שכולם פעילים ונגישים בקלות. עד עכשיו השתמשנו ב-Screen כדי לגשת לשני ה-FTD, והכלי הזה מאפשר גם מסך מפוצל באותו חלון מסוף. אפשר להשתמש באפשרות הזו כדי לראות איך צומת אחד מגיב לפקודות שמונפקות בצומת אחר.

מומלץ שיהיו לכם ארבעה חלונות זמינים:

  1. שירות ot-daemon / יומנים
  2. RCP Joiner דרך ot-ctl
  3. FTD Commissioner באמצעות OpenThread CLI
  4. FTD Joiner דרך OpenThread CLI

אם אתם רוצים להשתמש במסוף, בהגדרת יציאה טורית או בכלי משלכם, אתם יכולים לדלג לשלב הבא. אתם יכולים להגדיר את חלונות הטרמינל בכל המכשירים בצורה שהכי מתאימה לכם.

שימוש במסך

כדי להקל על השימוש, מומלץ להפעיל רק סשן Screen אחד. אמור להיות לכם אחד כזה מההגדרה של שני ה-FTD.

כל הפקודות ב-Screen מתחילות ב-Ctrl+a.

פקודות בסיסיות למסך:

חיבור מחדש לסשן Screen (משורת הפקודה)

screen -r

יציאה מהפעלת Screen

Ctrl+a → d

יצירת חלון חדש בסשן של שיתוף המסך

Ctrl+a → c

מעבר בין חלונות באותו סשן של Screen

‫Ctrl+a → n (קדימה)‫Ctrl+a → p (אחורה)

הפסקת הפעולה של החלון הנוכחי בסשן Screen

Ctrl+a → k

מסך מפוצל

באמצעות Screen, אפשר לפצל את הטרמינל לכמה חלונות:

f1cbf1258cf0a5a.png

כדי לגשת לפקודות ב-screen, משתמשים ב-Ctrl+a. כל פקודה צריכה להתחיל בשילוב מקשי הגישה הזה.

אם פעלתם בדיוק לפי ההוראות ב-Codelab, אמורים להיות לכם שני חלונות (FTD Commissioner, ‏ FTD Joiner) באותו מופע של Screen. כדי לפצל את המסך בין שתי התוכנות, קודם צריך להיכנס לסשן Screen הקיים:

$ screen -r

צריך להיות מחוברים לאחד ממכשירי FTD. פועלים לפי השלבים הבאים ב-Screen:

  1. ‫Ctrl+a → S כדי לפצל את החלון אופקית
  2. ‫Ctrl+a → Tab כדי להעביר את הסמן לחלון הריק החדש
  3. ‫Ctrl+a → n כדי להעביר את החלון החדש לחלון הבא
  4. אם הוא זהה לחלון העליון, לוחצים שוב על Ctrl+a → n כדי לראות את מכשיר ה-FTD השני

עכשיו שניהם גלויים. כדי לעבור ביניהם, מקישים על Ctrl+a → Tab. כדי למנוע בלבול, מומלץ לשנות את השם של כל חלון באמצעות Ctrl+a → A.

שימוש מתקדם

כדי לפצל עוד יותר את המסך לרבעים ולצפות ביומני ot-daemon וב-RCP Joiner ot-ctl, צריך להפעיל את השירותים האלה באותו מופע של המסך. כדי לעשות זאת, מפסיקים את ot-daemon ויוצאים מ-ot-ctl, ואז מפעילים אותם מחדש בחלונות חדשים של Screen ‏ (Ctrl+a → c).

ההגדרה הזו לא נדרשת, והיא נשארת כתרגיל למשתמש.

אפשר לפצל את המסך ולעבור בין החלונות באמצעות הפקודות הבאות:

יצירת חלון חדש

Ctrl+a → c

פיצול אנכי של החלון

Ctrl+a →

פיצול אופקי של החלון

Ctrl+a → S

מעבר לחלון המוצג הבא

Ctrl+a → Tab

החלפת החלון המוצג קדימה או אחורה

‫Ctrl+a → n או p

שינוי השם של החלון הנוכחי

Ctrl+a → A

אפשר לצאת מ-Screen בכל שלב באמצעות Ctrl+a ‏→ d ולחבר מחדש באמצעות screen -r משורת הפקודה.

מידע נוסף על Screen זמין במדריך המהיר של GNU Screen.

7. יצירת רשת Thread

אחרי שמגדירים את כל החלונות והמסכים של הטרמינל, אפשר ליצור את רשת Thread. ב-FTD Commissioner, יוצרים מערך נתונים תפעולי חדש ומבצעים commit שלו כמערך הנתונים הפעיל. מערך הנתונים התפעולי הוא ההגדרה של רשת Thread שאתם יוצרים.

## FTD Commissioner ##
----------------------

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 11
Channel Mask: 07fff800
Ext PAN ID: c0de7ab5c0de7ab5
Mesh Local Prefix: fdc0:de7a:b5c0/64
Network Key: 1234c0de7ab51234c0de7ab51234c0de
Network Name: OpenThread-c0de
PAN ID: 0xc0de
PSKc: ebb4f2f8a68026fc55bcf3d7be3e6fe4
Security Policy: 0, onrcb
Done

חשוב לשים לב למפתח הרשת 1234c0de7ab51234c0de7ab51234c0de שבו תשתמשו בהמשך.

מאשרים את מערך הנתונים הזה כמערך הנתונים הפעיל:

> dataset commit active
Done

פותחים את ממשק IPv6:

> ifconfig up
Done

התחלת פעולה של פרוטוקול Thread:

> thread start
Done

אחרי רגע, בודקים את מצב המכשיר. הוא צריך להיות המנהיג. כדאי גם לשמור את RLOC16 למקרה שתצטרכו אותו בעתיד.

## FTD Commissioner ##
----------------------

> state
leader
Done
> rloc16
0c00
Done

בודקים את כתובות ה-IPv6 של המכשיר:

## FTD Commissioner ##
----------------------

> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:fc00        # Leader Anycast Locator (ALOC)
fdc0:de7a:b5c0:0:0:ff:fe00:c00         # Routing Locator (RLOC)
fdc0:de7a:b5c0:0:6394:5a75:a1ad:e5a    # Mesh-Local EID (ML-EID)
fe80:0:0:0:1cd6:87a9:cb9d:4b1d         # Link-Local Address (LLA)

הרשת codelab גלויה עכשיו כשסורקים ממכשירי Thread אחרים.

מ-ot-ctl ב-RCP Joiner:

## RCP Joiner ##
----------------

> scan
| PAN  | MAC Address      | Ch | dBm | LQI |
+------+------------------+----+-----+-----+
| c0de | 1ed687a9cb9d4b1d | 11 | -36 | 232 |

מ-OpenThread CLI ב-FTD Joiner:

## FTD Joiner ##
----------------

> scan
| PAN  | MAC Address      | Ch | dBm | LQI |
+------+------------------+----+-----+-----+
| c0de | 1ed687a9cb9d4b1d | 11 | -38 | 229 |

אם רשת ה-codelab לא מופיעה ברשימה, נסו לסרוק שוב.

8. הוספת הכלי להצטרפות לתוכנית

הפעלת Thread לא פעילה ברשת, ולכן נצטרך להוסיף את ה-RCP Joiner לרשת Thread שיצרנו באמצעות תהליך הפעלה מחוץ לפס.

ב-FTD Commissioner, רשמנו את מפתח הרשת, לדוגמה 1234c0de7ab51234c0de7ab51234c0de. אם צריך לחפש שוב את מפתח הרשת, מריצים את הפקודה הבאה ב-FTD Commissioner:

## FTD Commissioner ##

> dataset networkkey
1234c0de7ab51234c0de7ab51234c0de
Done

בשלב הבא, ב-RCP Joiner, מגדירים את Network Key (מפתח הרשת) של מערך הנתונים הפעיל למפתח הרשת של FTD Commissioner:

## RCP Joiner ##
----------------

> dataset networkkey 1234c0de7ab51234c0de7ab51234c0de
Done
> dataset commit active
Done

בודקים את מערך הנתונים כדי לוודא שהוא מוגדר בצורה נכונה.

## RCP Joiner ##
----------------

> dataset
Network Key: 1234c0de7ab51234c0de7ab51234c0de

מפעילים את Thread כדי שה-RCP Joiner יצטרף לרשת codelab. מחכים כמה שניות, בודקים את המצב, את RLOC16 ואת כתובות ה-IPv6 שלו:

## RCP Joiner ##
----------------

> ifconfig up
Done
> thread start
Done
> state
child
Done
> rloc16
0c01
Done
> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:0c01         # Routing Locator (RLOC)
fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f    # Mesh-Local EID (ML-EID)
fe80:0:0:0:18e5:29b3:a638:943b          # Link-Local Address (LLA)
Done

חשוב לרשום את כתובת ה-IPv6 המקומית של הרשת (fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f כאן), תצטרכו אותה בהמשך.

חוזרים אל FTD Commissioner, בודקים את הנתב ואת טבלאות הצאצא כדי לוודא ששני המכשירים הם חלק מאותה רשת. משתמשים ב-RLOC16 כדי לזהות את ה-RCP Joiner.

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  35 | 1ed687a9cb9d4b1d |

Done
> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|VER| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+---+------------------+
|   1 | 0x0c01 |        240 |         25 |     3 |   89 |1|1|1|  2| 1ae529b3a638943b |
Done

כדי לאמת את הקישוריות, שולחים פינג לכתובת המקומית של הרשת של ה-RCP Joiner (הכתובת המקומית של הרשת שמתקבלת מהפלט של ipaddr של ה-RCP Joiner):

## FTD Commissioner ##
----------------------

> ping fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f
> 8 bytes from fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f: icmp_seq=1 hlim=64 time=40ms

עכשיו יש לנו רשת פרוטוקול Thread שמורכבת משני צמתים, כפי שמודגם בתרשים הטופולוגיה הזה:

otcodelab_top01C_2nodes.png

תרשימי טופולוגיה

בהמשך ה-Codelab, נציג תרשים חדש של טופולוגיית פרוטוקול Thread בכל פעם שהמצב של הרשת משתנה. תפקידי הצמתים מסומנים כך:

b75a527be4563215.png

נתבים הם תמיד מחומשים, ומכשירי קצה הם תמיד עיגולים. המספרים בכל צומת מייצגים את מזהה הנתב או מזהה הצומת הצאצא שמוצגים בפלט של ממשק שורת הפקודה, בהתאם לתפקיד ולמצב הנוכחיים של כל צומת באותו זמן.

9. הפעלת התכונה 'הצטרפות ל-FTD'

עכשיו נוסיף את מכשיר Thread השלישי לרשת codelab. הפעם נשתמש בתהליך ההפעלה המאובטח יותר בתוך הלהקה, ונאפשר רק ל-FTD Joiner להצטרף.

ב-FTD Joiner, מאתרים את eui64 כדי שהנציב של FTD יוכל לזהות אותו:

## FTD Joiner ##
----------------

> eui64
2f57d222545271f1
Done

ב-FTD Commissioner, מפעילים את ה-Commissioner ומציינים את eui64 של המכשיר שיכול להצטרף, יחד עם פרטי הכניסה של המכשיר המצטרף, למשל J01NME. האישורים של המצטרף הם מחרוזת ספציפית למכשיר שמורכבת מתווים אלפאנומריים באותיות רישיות (0-9 ו-A-Y, לא כולל I, ‏ O, ‏ Q ו-Z כדי לשפר את הקריאות), באורך של 6 עד 32 תווים.

## FTD Commissioner ##
----------------------

> commissioner start
Done
> commissioner joiner add 2f57d222545271f1 J01NME
Done

עוברים אל FTD Joiner. מתחילים את תפקיד המצטרף באמצעות אישור המצטרף שהגדרתם זה עתה ב-FTD Commissioner:

## FTD Joiner ##
----------------

> ifconfig up
Done
> joiner start J01NME
Done

תוך דקה בערך, תקבלו אישור שהאימות בוצע בהצלחה:

## FTD Joiner ##
----------------

>
Join success

מפעילים את Thread כדי שה-FTD Joiner יצטרף לרשת codelab, ובודקים מיד את הסטטוס ואת RLOC16:

## FTD Joiner ##
----------------

> thread start
Done
> state
child
Done
> rloc16
0c02
Done

בודקים את כתובות ה-IPv6 של המכשיר. שימו לב שאין ALOC. הסיבה לכך היא שהמכשיר הזה הוא לא ה-Leader, וגם לא מוגדר בו תפקיד ספציפי ל-Anycast שדורש ALOC.

## FTD Joiner ##
----------------

> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:c02         # Routing Locator (RLOC)
fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd    # Mesh-Local EID (ML-EID)
fe80:0:0:0:e4cd:d2d9:3249:a243         # Link-Local Address (LLA)

עוברים מיד אל FTD Commissioner ובודקים את טבלאות הנתבים והילדים כדי לוודא שקיימים שלושה מכשירים ברשת codelab:

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  50 | 1ed687a9cb9d4b1d |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0x0c01 |        240 |         25 |     3 |   89 |1|1|1|1| 1ae529b3a638943b |
|   2 | 0x0c02 |        240 |         15 |     3 |   44 |1|1|1|1| e6cdd2d93249a243 |
Done

בהתבסס על RLOC16, מכשיר ה-FTD Joiner מצורף לרשת כמכשיר קצה (משני). זו הטופולוגיה המעודכנת שלנו:

otcodelab_top01C_ed01.png

10. שרשור בפעולה

מכשירי Thread ב-Codelab הזה הם סוג ספציפי של מכשיר Thread מלא (FTD) שנקרא מכשיר קצה כשיר לניתוב (REED). המשמעות היא שהם יכולים לפעול כנתב או כמכשיר קצה, ויכולים לשדרג את עצמם ממכשיר קצה לנתב.

רשת Thread יכולה לתמוך בעד 32 נתבים, אבל המערכת מנסה לשמור על מספר הנתבים בין 16 ל-23. אם מכשיר REED מצורף כמכשיר קצה (צאצא) ומספר הנתבים נמוך מ-16, אחרי תקופה אקראית של עד שתי דקות הוא מקודם אוטומטית לנתב.

אם היו לכם שני ילדים ברשת Thread אחרי הוספת ה-FTD Joiner, צריך להמתין לפחות שתי דקות ואז לבדוק מחדש את טבלאות הנתב והצאצא ב-FTD Commissioner:

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  50 | 1ed687a9cb9d4b1d |
| 46 | 0xb800 |       63 |         0 |     3 |      3 |   1 | e6cdd2d93249a243 |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0x0c01 |        240 |         61 |     3 |   89 |1|1|1|1| 1ae529b3a638943b |
Done

ה-FTD Joiner (כתובת MAC מורחבת = e6cdd2d93249a243) קידם את עצמו לנתב. שימו לב ש-RLOC16 שונה (b800 במקום 0c02). הסיבה לכך היא ש-RLOC16 מבוסס על מזהה הנתב ומזהה הצאצא של המכשיר. כשהוא עובר ממכשיר קצה לנתב, הערכים של מזהה הנתב ומזהה הצאצא משתנים, וכך גם ה-RLOC16.

otcodelab_top01C.png

מאשרים את המצב החדש ואת RLOC16 ב-FTD Joiner:

## FTD Joiner ##
----------------

> state
router
Done
> rloc16
b800
Done

שדרוג לאחור של FTD Joiner

כדי לבדוק את ההתנהגות הזו, אפשר להוריד באופן ידני את הגרסה של FTD Joiner מנתב בחזרה למכשיר קצה. משנים את המצב לילד ובודקים את RLOC16:

## FTD Joiner ##
----------------

> state child
Done
> rloc16
0c03
Done

otcodelab_top01C_ed02.png

בחזרה אל FTD Commissioner, הרשומה FTD Joiner אמורה להופיע עכשיו בטבלת הצאצא (מזהה = 3). יכול להיות שהתכנים יהיו זמינים בשתי האפליקציות במהלך המעבר:

## FTD Commissioner ##
----------------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |        3 |         0 |     0 |      0 |  50 | 1ed687a9cb9d4b1d |
| 46 | 0xb800 |       63 |         0 |     3 |      3 |   1 | e6cdd2d93249a243 |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0x0c01 |        240 |         61 |     3 |   89 |1|1|1|1| 1ae529b3a638943b |
|   3 | 0x0c03 |        240 |         16 |     3 |   94 |1|1|1|1| e6cdd2d93249a243 |
Done

אחרי זמן מה, הוא יחזור לנתב עם RLOC של b800.

otcodelab_top01C.png

הסרת הבכיר בארגון

הנתב הראשי נבחר באופן עצמאי מבין כל נתבי ה-Thread. המשמעות היא שאם הנתב הנוכחי מסוג Leader יוסר מרשת Thread, אחד מהנתבים האחרים יהפוך לנתב החדש מסוג Leader.

ב-FTD Commissioner, משביתים את Thread כדי להסיר אותו מרשת Thread:

## FTD Commissioner ##
----------------------

> thread stop
Done
> ifconfig down
Done

תוך שתי דקות, FTD Joiner הופך למוביל השרשור החדש. כדי לוודא:

## FTD Joiner ##
----------------

> state
leader
Done
> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:fc00       # Now it has the Leader ALOC!
fdc0:de7a:b5c0:0:0:ff:fe00:b800
fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd
fe80:0:0:0:e4cd:d2d9:3249:a243
Done

otcodelab_top02C_01.png

בודקים את טבלת הצאצא. שימו לב שיש RLOC16 חדש. זהו ה-RCP Joiner, כפי שמצוין על ידי המזהה וכתובת ה-MAC המורחבת שלו. כדי לשמור על רשת פרוטוקול Thread, הוא החליף נתבי הורה, מה-FTD Commissioner ל-FTD Joiner. התוצאה היא RLOC16 חדש עבור ה-RCP Joiner (כי מזהה הנתב שלו השתנה, מ-3 ל-46).

## FTD Joiner ##
----------------

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0xb801 |        240 |         27 |     3 |  145 |1|1|1|1| 1ae529b3a638943b |
Done

יכול להיות שתצטרכו לחכות כמה דקות עד ש-RCP Joiner יצורף ל-FTD Joiner כרכיב צאצא. בודקים את המצב ואת RLOC16 כדי לוודא ש:

## RCP Joiner ##
--------------

> state
child
> rloc16
b801

צירוף מחדש של FTD Commissioner

רשת Thread עם שני צמתים היא לא כיף גדול. בואו נחזיר את נציב ה-FTD למצב אונליין.

ב-FTD Commissioner, מפעילים מחדש את Thread:

## FTD Commissioner ##
----------------------

> ifconfig up
Done
> thread start
Done

תוך שתי דקות, הוא מתחבר מחדש אוטומטית לרשת codelab כמכשיר קצה, ואז הוא הופך לנתב.

## FTD Commissioner ##
----------------------

> state
router
Done

בודקים את טבלאות הנתב והילד ב-FTD Joiner כדי לוודא:

## FTD Joiner ##
----------------

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
+----+--------+----------+-----------+-------+--------+-----+------------------+
|  3 | 0x0c00 |       63 |         0 |     3 |      3 |   0 | 1ed687a9cb9d4b1d |
| 46 | 0xb800 |       46 |         0 |     0 |      0 |  15 | e6cdd2d93249a243 |

> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|S|D|N| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|   1 | 0xb801 |        240 |        184 |     3 |  145 |1|1|1|1| 1ae529b3a638943b |
Done

otcodelab_top02C_02.png

רשת ה-Thread שלנו כוללת שוב שלושה צמתים.

11. פתרון בעיות

ניהול רשת Thread עם כמה מכשירים בחלונות שונים של מסוף או מסך יכול להיות מסובך. אם נתקלים בבעיות, אפשר להשתמש בטיפים האלה כדי 'לאפס' את מצב הרשת או סביבת העבודה.

מסך

אם אתם הולכים לאיבוד בהגדרה (יותר מדי חלונות Screen או מסכים בתוך מסך), המשיכו להרוג חלונות Screen באמצעות Ctrl+a → k עד שלא יישארו חלונות, והפלט של screen -ls בשורת הפקודה יהיה No Sockets found. לאחר מכן, יוצרים מחדש חלונות של מסך לכל מכשיר. מצבי המכשיר נשמרים גם כשהמסך נסגר.

צמתים של פרוטוקול Thread

אם טופולוגיית רשת Thread לא תואמת לתיאור ב-Codelab הזה, או אם הצמתים מתנתקים מסיבה כלשהי (יכול להיות שהמחשב עם Linux שהם מחוברים אליו עבר למצב שינה), מומלץ להשבית את Thread, לנקות את פרטי הכניסה לרשת ולהתחיל מחדש מהשלב יצירת רשת Thread.

כדי לאפס את ה-FTD:

## FTD Commissioner or FTD Joiner ##
------------------------------------

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

אפשר לאפס את ה-RCP באותו אופן דרך ot-ctl:

## RCP Joiner ##
----------------

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

12. שימוש במולטיקאסט

מולטיקאסט משמש להעברת מידע לקבוצת מכשירים בבת אחת. ברשת Thread, כתובות ספציפיות שמורות לשימוש בשידור מרובה משתתפים עם קבוצות שונות של מכשירים, בהתאם להיקף.

כתובת IPv6

היקף

נמסר אל

ff02::1

Link-Local

כל ה-FTD וה-MED

ff02::2

Link-Local

כל נתבי הגבולות ו-FTD

ff03::1

Mesh-Local

כל ה-FTD וה-MED

ff03::2

Mesh-Local

כל נתבי הגבולות ו-FTD

ב-Codelab הזה אנחנו לא משתמשים בנתב גבול, לכן נתמקד בשתי כתובות ה-Multicast של FTD ו-MED.

ההיקף של Link-Local כולל את כל ממשקי ה-פרוטוקול Thread שאפשר להגיע אליהם באמצעות שידור רדיו יחיד או 'צעד' יחיד. טופולוגיית הרשת קובעת אילו מכשירים מגיבים לפינג לff02::1כתובת השידור לקבוצה.

פינג ff02::1 מנציב ה-FTD:

## FTD Commissioner ##
----------------------

> ping ff02::1
> 8 bytes from fe80:0:0:0:e4cd:d2d9:3249:a243: icmp_seq=2 hlim=64 time=9ms

יש עוד שני מכשירים ברשת (FTD Joiner ו-RCP Joiner), אבל FTD Commissioner קיבל רק תגובה אחת, מכתובת Link-Local Address ‏ (LLA) של FTD Joiner. כלומר, מכשיר ה-FTD Joiner הוא המכשיר היחיד שמכשיר ה-FTD Commissioner יכול להגיע אליו בצעד אחד.

otcodelab_top02C_02_LL.png

עכשיו שולחים פינג אל ff02::1 מתוך FTD Joiner:

## FTD Joiner ##
----------------

> ping ff02::1
> 8 bytes from fe80:0:0:0:1cd6:87a9:cb9d:4b1d: icmp_seq=1 hlim=64 time=11ms
8 bytes from fe80:0:0:0:18e5:29b3:a638:943b: icmp_seq=1 hlim=64 time=24ms

שתי תשובות! כשבודקים את כתובות ה-IPv6 של המכשירים האחרים, אפשר לראות שהראשונה (שמספרה מסתיים ב-4b1d) היא כתובת ה-LLA של FTD Commissioner, והשנייה (שמספרה מסתיים ב-943b) היא כתובת ה-LLA של RCP Joiner.

otcodelab_top02C_02_LL02.png

כלומר, רכיב ה-FTD Joiner מחובר ישירות לרכיב ה-FTD Commissioner ולרכיב ה-RCP Joiner, וזה מאשר את הטופולוגיה שלנו.

Mesh-Local

היקף Mesh-Local כולל את כל ממשקי Thread שאפשר להגיע אליהם באותה רשת Thread. נראה את התגובות לפינג לכתובת ה-multicast‏ ff03::1.

פינג ff03::1 מנציב ה-FTD:

## FTD Commissioner ##
----------------------

> ping ff03::1
> 8 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:b800: icmp_seq=3 hlim=64 time=9ms
8 bytes from fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f: icmp_seq=3 hlim=64 time=68ms

הפעם, נציב ה-FTD קיבל שתי תגובות, אחת ממאתר הניתוב של המצטרף ל-FTD (RLOC, מסתיים ב-b800) ואחת מ-EID מקומי של רשת Mesh של המצטרף ל-RCP (ML-EID, מסתיים ב-d55f). הסיבה לכך היא שההיקף המקומי של רשת Mesh כולל את כל רשת Thread. לא משנה איפה ברשת נמצא המכשיר, הוא יירשם לכתובת ff03::1.

otcodelab_top02C_02_ML.png

כדי לאשר את אותה התנהגות, שולחים פינג אל ff03::1 מ-FTD Joiner:

## FTD Joiner ##
----------------

> ping ff03::1
> 8 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:c00: icmp_seq=2 hlim=64 time=11ms
8 bytes from fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f: icmp_seq=2 hlim=64 time=23ms

otcodelab_top02C_02_LL02.png

שימו לב לזמן התגובה של ה-RCP Joiner בשתי הפלטות של הפינג. הזמן שחלף עד שהרכיב RCP Joiner הגיע אל FTD Commissioner (68ms) היה ארוך בהרבה מהזמן שחלף עד שהוא הגיע אל FTD Joiner (23ms). הסיבה לכך היא שהיא צריכה לעבור שני צעדים כדי להגיע לנציב ה-FTD, לעומת צעד אחד עבור ה-FTD Joiner.

יכול להיות ששמתם לב גם שהפינג של שידור מרובה כתובות מקומי ברשת ה-Mesh הגיב עם RLOC רק לשני ה-FTD – ולא ל-RCP Joiner. הסיבה לכך היא שמכשירי ה-FTD הם נתבים ברשת, בעוד שמכשיר ה-RCP הוא מכשיר קצה.

בודקים את הסטטוס של הצטרפות ל-RCP כדי לוודא:

## RCP Joiner ##
----------------

> state
child

13. שליחת הודעות באמצעות UDP

אחד משירותי האפליקציה ש-OpenThread מספק הוא פרוטוקול User Datagram‏ (UDP), פרוטוקול של שכבת התעבורה. אפליקציה שמבוססת על OpenThread יכולה להשתמש ב-UDP API כדי להעביר הודעות בין צמתים ברשת Thread, או למכשירים אחרים ברשת חיצונית (כמו האינטרנט, אם ברשת Thread יש נתב גבולות).

שקעי UDP נחשפים דרך OpenThread CLI. נשתמש בו כדי להעביר הודעות בין שני מכשירי FTD.

מקבלים את כתובת ה-EID המקומית של הרשת עבור FTD Joiner. אנחנו משתמשים בכתובת הזו כי אפשר להגיע אליה מכל מקום ברשת Thread.

## FTD Joiner ##
----------------

> ipaddr
fdc0:de7a:b5c0:0:0:ff:fe00:fc00        # Leader Anycast Locator (ALOC)
fdc0:de7a:b5c0:0:0:ff:fe00:b800        # Routing Locator (RLOC)
fe80:0:0:0:e4cd:d2d9:3249:a243         # Link-Local Address (LLA)
fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd    # Mesh-Local EID (ML-EID)
Done

מפעילים UDP ומקשרים אותו לשקע לכל כתובת IPv6:

## FTD Joiner ##
----------------

> udp open
Done
> udp bind :: 1212

עוברים אל FTD Commissioner, מפעילים את UDP ומתחברים לשקע שהגדרתם ב-FTD Joiner באמצעות ה-ML-EID שלו:

## FTD Commissioner ##
----------------------

> udp open
Done
> udp connect fdc0:de7a:b5c0:0:3e2e:66e:9d41:ebcd 1212
Done

החיבור ב-UDP צריך להיות פעיל בין שני הצמתים. שליחת הודעה מנציב ה-FTD:

## FTD Commissioner ##
----------------------

> udp send hellothere
Done

ב-FTD Joiner, הודעת ה-UDP התקבלה.

## FTD Joiner ##
----------------

> 10 bytes from fdc0:de7a:b5c0:0:0:ff:fe00:c00 49153 hellothere

14. מעולה!

יצרתם רשת פיזית של פרוטוקול Thread!

b915c433e7027cc7.png

עכשיו אתם יודעים:

  • ההבדל בין סוגי מכשירים, תפקידים והיקפים ב-Thread
  • איך מכשירי Thread מנהלים את המצבים שלהם ברשת
  • איך מעבירים הודעות פשוטות בין צמתים באמצעות UDP

השלבים הבאים

אפשר לנסות את התרגילים הבאים על סמך ה-Codelab הזה:

  • מבצעים החזרה לגרסה קודמת של לוח FTD Joiner בתור MTD באמצעות קובץ הבינארי ot-cli-mtd, ורואים שהוא אף פעם לא משדרג את עצמו לנתב או מנסה להפוך ל-Leader.
  • מוסיפים עוד מכשירים לרשת (אפשר לנסות פלטפורמה אחרת!) ויוצרים סקיצה של הטופולוגיה באמצעות טבלאות של נתבים וצאצאים, ופינג לכתובות מולטיקאסט
  • שימוש ב-pyspinel כדי לשלוט ב-NCP
  • ממירים את ה-NCP לנתב גבולות באמצעות OpenThread Border Router ומחברים את רשת Thread לאינטרנט

קריאה נוספת

באתר openthread.io וב-GitHub תוכלו למצוא מגוון משאבים של OpenThread, כולל:

  • פלטפורמות נתמכות – כאן אפשר לראות את כל הפלטפורמות שתומכות ב-OpenThread
  • Build OpenThread – פרטים נוספים על בנייה והגדרה של OpenThread
  • Thread Primer – הסבר על כל המושגים שקשורים ל-Thread ומופיעים ב-Codelab הזה

הפניה: