1. 소개
Google에서 출시한 OpenThread는 Thread® 네트워킹 프로토콜의 오픈소스 구현입니다. Google Nest는 Nest 제품에 사용되는 기술을 개발자가 널리 사용할 수 있도록 OpenThread를 출시하여 커넥티드 홈 제품 개발을 가속화했습니다.
스레드 사양은 홈 애플리케이션을 위한 IPv6 기반의 안정적이고 안전하며 저전력 무선 기기 간 통신 프로토콜을 정의합니다. OpenThread는 IPv6, 6LoWPAN, MAC 보안이 적용된 IEEE 802.15.4, 메시 링크 설정, 메시 라우팅을 비롯한 모든 스레드 네트워킹 계층을 구현합니다.
이 Codelab에서는 실제 하드웨어에서 OpenThread를 프로그래밍하고, 스레드 네트워크를 만들고 관리하며, 노드 간에 메시지를 전달합니다.
학습할 내용
- OpenThread CLI 바이너리를 개발 보드에 빌드하고 플래시
- Linux 머신과 개발 보드로 구성된 RCP 빌드
- OpenThread 데몬 및
ot-ctl
를 사용하여 RCP와 통신 - GNU Screen 및 OpenThread CLI를 사용하여 스레드 노드 수동 관리
- 스레드 네트워크에 기기를 안전하게 커미셔닝
- IPv6 멀티캐스트 작동 방식
- UDP를 사용하여 스레드 노드 간 메시지 전달
필요한 항목
하드웨어:
- Nordic Semiconductor nRF52840 개발 보드 3개
- 보드를 연결하는 USB to Micro-USB 케이블 3개
- USB 포트가 3개 이상 있는 Linux 머신
소프트웨어:
- GNU 도구 모음
- Nordic nRF5x 명령줄 도구
- Segger J-Link 소프트웨어
- OpenThread
- Git
2. 시작하기
OpenThread 시뮬레이션
시작하기 전에 OpenThread 시뮬레이션 Codelab을 실행하여 기본 스레드 개념과 OpenThread CLI를 숙지하는 것이 좋습니다.
직렬 포트 터미널
터미널을 통해 직렬 포트에 연결하는 방법을 잘 알고 있어야 합니다. 이 Codelab에서는 GNU Screen을 사용하여 사용 개요를 제공하지만, 다른 터미널 소프트웨어를 사용해도 됩니다.
Linux 시스템
이 Codelab은 i386 또는 x86 기반 Linux 시스템을 사용하여 라디오 공동 프로세서 (RCP) 스레드 기기의 호스트 역할을 하고 모든 스레드 개발 보드를 플래시하도록 설계되었습니다. 모든 단계는 Ubuntu 14.04.5 LTS (Trusty Tahr)에서 테스트했습니다.
Nordic Semiconductor nRF52840 보드
이 Codelab에서는 nRF52840 PDK 보드 3개를 사용합니다.
SEGGER J-Link 설치
온보드 JTAG 모듈이 있는 nRF52840 보드를 프로그래밍하는 데 SEGGER J-Link를 사용합니다. Linux 머신에 이를 설치합니다.
머신에 맞는 패키지를 다운로드하고 적절한 위치에 설치합니다. Linux에서는 /opt/SEGGER/JLink
입니다.
nRF5x 명령줄 도구 설치
nRF5x 명령줄 도구를 사용하면 OpenThread 바이너리를 nRF52840 보드에 플래시할 수 있습니다. Linux 머신에 적절한 nRF5x-Command-Line-Tools-<OS> 빌드를 설치합니다.
추출된 패키지를 루트 폴더 ~/
에 배치합니다.
ARM GNU 도구 모음 설치
빌드에는 ARM GNU 도구 모음이 사용됩니다.
추출된 보관 파일을 Linux 머신의 /opt/gnu-mcu-eclipse/arm-none-eabi-gcc/
에 배치하는 것이 좋습니다. 설치 안내는 보관 파일의 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 데몬을 빌드합니다.
$ script/cmake-build posix -DOT_DAEMON=ON
이제 OpenThread를 nRF52840 보드에 빌드하고 플래시할 준비가 되었습니다.
4. RCP 조이너 설정
빌드 및 플래시
조이너 및 네이티브 USB 기능으로 OpenThread nRF52840 예시를 빌드합니다. 기기는 조이너 역할을 사용하여 Thread 네트워크에서 안전하게 인증되고 커미셔닝됩니다. 네이티브 USB를 사용하면 nRF52840과 호스트 간에 USB CDC ACM을 직렬 전송으로 사용할 수 있습니다.
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 바이너리가 있는 디렉터리로 이동하여 16진수 형식으로 변환합니다.
$ cd ~/src/ot-nrf528xx/build/bin $ arm-none-eabi-objcopy -O ihex ot-rcp ot-rcp.hex
USB 케이블을 nRF52840 보드의 외부 전원 핀 옆에 있는 마이크로 USB 디버그 포트에 연결한 다음 Linux 머신에 연결합니다. nRF52840 보드에서 nRF 전원 스위치를 VDD로 설정합니다. 올바르게 연결되면 LED5가 켜집니다.
Linux 머신에 연결된 첫 번째 보드인 경우 직렬 포트 /dev/ttyACM0
로 표시됩니다 (모든 nRF52840 보드는 직렬 포트 식별자로 ttyACM
사용).
$ ls /dev/ttyACM* /dev/ttyACM0
RCP에 사용되는 nRF52840 보드의 일련번호를 확인합니다.
nRFx 명령줄 도구의 위치로 이동하고 보드의 일련번호를 사용하여 nRF52840 보드에 OpenThread RCP 16진수 파일을 플래시합니다. --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에 연결
OpenThread RCP 빌드는 네이티브 USB CDC ACM을 직렬 전송으로 사용할 수 있으므로 nRF52840 보드의 nRF USB 포트를 사용하여 RCP 호스트 (Linux 머신)와 통신해야 합니다.
플래시된 nRF52840 보드의 디버그 포트에서 USB 케이블의 마이크로 USB 끝을 분리한 다음 RESET 버튼 옆에 있는 마이크로 USB nRF USB 포트에 다시 연결합니다. nRF 전원 스위치를 USB로 설정합니다.
OpenThread 데몬 시작
RCP 설계에서는 OpenThread 데몬을 사용하여 스레드 기기와 통신하고 스레드 기기를 관리합니다. 로그 출력을 확인하고 실행 중인지 확인할 수 있도록 -v
상세 플래그로 ot-daemon
를 시작합니다.
$ 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
는 OpenThread CLI 앱과 동일한 CLI를 사용합니다. 따라서 다른 시뮬레이션된 스레드 기기와 동일한 방식으로 ot-daemon
노드를 제어할 수 있습니다.
두 번째 터미널 창에서 ot-ctl
를 시작합니다.
$ sudo ./build/posix/src/posix/ot-ctl >
ot-daemon
로 시작한 노드 2 (RCP 노드)의 state
를 확인합니다.
> state disabled Done
5. FTD 설정
이 Codelab에서 사용되는 다른 두 스레드 노드는 표준 시스템 온 칩 (SoC) 설계의 전체 스레드 기기 (FTD)입니다. 한 기기는 커미셔너로 작동하여 해당 네트워크에서 기기를 안전하게 인증하고 커미셔닝합니다. 다른 기기는 커미셔너가 스레드 네트워크에 인증할 수 있는 조이너로 작동합니다.
빌드 및 플래시
커미셔너 및 조이너 역할이 사용 설정된 nRF52840 플랫폼용 OpenThread FTD 예시를 빌드합니다.
$ cd ~/src/ot-nrf528xx $ rm -rf build $ script/build nrf52840 USB_trans -DOT_JOINER=ON -DOT_COMMISSIONER=ON
OpenThread 전체 스레드 기기 (FTD) CLI 바이너리가 있는 디렉터리로 이동하여 16진수 형식으로 변환합니다.
$ cd ~/src/ot-nrf528xx/build/bin $ arm-none-eabi-objcopy -O ihex ot-cli-ftd ot-cli-ftd.hex
USB 케이블을 nRF52840 보드의 외부 전원 핀 옆에 있는 마이크로 USB 포트에 연결한 다음 Linux 머신에 연결합니다. RCP가 Linux 머신에 계속 연결되어 있으면 이 새 보드가 직렬 포트 /dev/ttyACM1
로 표시됩니다 (모든 nRF52840 보드는 직렬 포트 식별자로 ttyACM
사용).
$ ls /dev/ttyACM* /dev/ttyACM0 /dev/ttyACM1
이전과 마찬가지로 FTD에 사용되는 nRF52840 보드의 일련번호를 확인합니다.
nRFx 명령줄 도구의 위치로 이동하고 보드의 일련번호를 사용하여 OpenThread CLI FTD 16진수 파일을 nRF52840 보드에 플래시합니다.
$ cd ~/nrfjprog/ $ ./nrfjprog -f nrf52 -s 683704924 --verify --chiperase --program \ ~/src/ot-nrf528xx/build/bin/ot-cli-ftd.hex --reset
보드에 '커미셔너'라는 라벨을 지정합니다.
네이티브 USB에 연결
OpenThread FTD 빌드는 네이티브 USB CDC ACM을 직렬 전송으로 사용할 수 있으므로 nRF52840 보드의 nRF USB 포트를 사용하여 RCP 호스트 (Linux 머신)와 통신해야 합니다.
플래시된 nRF52840 보드의 디버그 포트에서 USB 케이블의 마이크로 USB 끝을 분리한 다음 RESET 버튼 옆에 있는 마이크로 USB nRF USB 포트에 다시 연결합니다. nRF 전원 스위치를 USB로 설정합니다.
빌드 확인
터미널 창에서 GNU Screen을 사용하여 OpenThread CLI에 액세스하여 빌드가 성공했는지 확인합니다.
$ screen /dev/ttyACM1
새 창에서 키보드의 Return 키를 몇 번 눌러 OpenThread CLI >
프롬프트를 표시합니다. IPv6 인터페이스를 가져와 주소를 확인합니다.
> ifconfig up Done > ipaddr fe80:0:0:0:1cd6:87a9:cb9d:4b1d Done
Ctrl+a 사용 →
d
FTD 커미셔너 CLI에서 분리되어 다음 보드를 플래시할 수 있도록 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 조이너 설정
위 프로세스를 반복하여 기존 ot-cli-ftd.hex
빌드를 사용하여 세 번째 nRF52840 보드를 플래시합니다. 완료되면 nRF USB 포트를 사용하여 보드를 PC에 다시 연결하고 nRF 전원 스위치를 VDD로 설정합니다.
이 세 번째 보드가 연결될 때 다른 두 노드가 Linux 머신에 연결되어 있으면 직렬 포트 /dev/ttyACM2
로 표시됩니다.
$ ls /dev/ttyACM* /dev/ttyACM0 /dev/ttyACM1 /dev/ttyACM2
보드에 'Joiner'라는 라벨을 지정합니다.
화면을 사용하여 확인할 때는 명령줄에서 화면의 새 인스턴스를 만드는 대신 기존 인스턴스에 다시 연결하고 그 안에 새 창을 만듭니다 (FTD 커미셔너에 사용한 창).
$ screen -r
Ctrl+a → c
를 사용하여 Screen 내에 새 창을 만듭니다.
새 명령줄 프롬프트가 표시됩니다. FTD Joiner의 OpenThread CLI에 액세스합니다.
$ screen /dev/ttyACM2
이 새 창에서 키보드의 Return 키를 몇 번 눌러 OpenThread CLI >
프롬프트를 표시합니다. IPv6 인터페이스를 가져와 주소를 확인합니다.
> ifconfig up Done > ipaddr fe80:0:0:0:6c1e:87a2:df05:c240 Done
이제 FTD 조이너 CLI가 FTD 커미셔너와 동일한 화면 인스턴스에 있으므로 Ctrl+a → n
를 사용하여 전환할 수 있습니다.
Ctrl+a 사용 →
d
언제든지 눌러 화면을 종료할 수 있습니다.
6. 터미널 창 설정
앞으로 스레드 기기 간에 자주 전환하게 되므로 모든 기기가 작동 중이고 쉽게 액세스할 수 있는지 확인하세요. 지금까지 화면을 사용하여 두 FTD에 액세스했으며 이 도구를 사용하면 동일한 터미널 창에서 화면을 분할할 수도 있습니다. 이를 사용하여 한 노드가 다른 노드에서 실행된 명령어에 어떻게 반응하는지 확인할 수 있습니다.
다음과 같은 4개의 창을 바로 사용할 수 있는 것이 좋습니다.
ot-daemon
서비스 / 로그ot-ctl
를 통한 RCP Joiner- OpenThread CLI를 통한 FTD 커미셔너
- OpenThread CLI를 통한 FTD Joiner
자체 터미널 / 직렬 포트 구성 또는 도구를 사용하려면 다음 단계로 건너뛰어도 됩니다. 모든 기기의 터미널 창을 가장 적합한 방식으로 구성합니다.
화면 사용
사용 편의를 위해 하나의 Screen 세션만 시작하세요. FTD를 모두 설정할 때 이미 하나가 있어야 합니다.
Screen 내의 모든 명령은 Ctrl+a로 시작합니다.
기본 화면 명령어:
명령줄에서 Screen 세션에 다시 연결 |
|
Screen 세션 종료 | Ctrl+a → |
화면 세션 내에 새 창 만들기 | Ctrl+a → |
동일한 화면 세션에서 창 간 전환 | Ctrl+a → |
Screen 세션에서 현재 창을 종료합니다. | Ctrl+a → |
화면 분할
Screen을 사용하면 터미널을 여러 창으로 분할할 수 있습니다.
screen
의 명령어는 Ctrl+a를 사용하여 액세스합니다. 모든 명령어는 이 액세스 키 조합으로 시작해야 합니다.
Codelab을 정확히 따라왔다면 동일한 화면 인스턴스에 두 개의 창 (FTD 커미셔너, FTD 조이너)이 있어야 합니다. 두 화면 간에 화면을 분할하려면 먼저 기존 Screen 세션을 입력합니다.
$ screen -r
FTD 기기 중 하나에 있어야 합니다. 화면에서 다음 단계를 따르세요.
- Ctrl+a →
S
를 눌러 창을 가로로 분할합니다. - Ctrl+a →
Tab
를 눌러 커서를 새 빈 창으로 이동합니다. - Ctrl+a →
n
를 눌러 새 창을 다음 창으로 전환합니다. - 상단 창과 동일한 경우 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 → |
창을 세로로 분할 | Ctrl+a → |
창을 가로로 분할 | Ctrl+a → |
다음 표시된 창으로 이동 | Ctrl+a → |
표시된 창을 앞뒤로 전환 | Ctrl+a → |
현재 창 이름 바꾸기 | Ctrl+a → |
Ctrl+a → d
를 사용하여 언제든지 Screen을 종료하고 명령줄에서 screen -r
를 사용하여 다시 연결합니다.
Screen에 관한 자세한 내용은 GNU Screen 빠른 참조를 참고하세요.
7. 스레드 네트워크 만들기
이제 모든 터미널 창과 화면이 구성되었으므로 스레드 네트워크를 만들어 보겠습니다. FTD 커미셔너에서 새 운영 데이터 세트를 만들고 활성 데이터 세트로 커밋합니다. 운영 데이터 세트는 생성 중인 스레드 네트워크의 구성입니다.
## 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 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' 네트워크가 표시됩니다.
RCP 조이너의 ot-ctl
에서:
## RCP Joiner ## ---------------- > scan | PAN | MAC Address | Ch | dBm | LQI | +------+------------------+----+-----+-----+ | c0de | 1ed687a9cb9d4b1d | 11 | -36 | 232 |
FTD Joiner의 OpenThread CLI에서 다음을 실행합니다.
## FTD Joiner ## ---------------- > scan | PAN | MAC Address | Ch | dBm | LQI | +------+------------------+----+-----+-----+ | c0de | 1ed687a9cb9d4b1d | 11 | -38 | 229 |
'codelab' 네트워크가 목록에 표시되지 않으면 다시 검색해 보세요.
8. RCP 조이너 추가
스레드 커미셔닝이 네트워크에서 활성화되어 있지 않습니다. 즉, 대역 외 커미셔닝 프로세스를 사용하여 방금 만든 스레드 네트워크에 RCP 조이너를 추가해야 합니다.
FTD 커미셔너에서 네트워크 키(예: 1234c0de7ab51234c0de7ab51234c0de
)를 기록했습니다. 네트워크 키를 다시 조회해야 하는 경우 FTD 커미셔너에서 다음 명령어를 실행합니다.
## FTD Commissioner ## > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done
다음으로 RCP 조이너에서 활성 데이터 세트 네트워크 키를 FTD 커미셔너 네트워크 키로 설정합니다.
## RCP Joiner ## ---------------- > dataset networkkey 1234c0de7ab51234c0de7ab51234c0de Done > dataset commit active Done
데이터 세트가 올바르게 설정되었는지 확인합니다.
## RCP Joiner ## ---------------- > dataset Network Key: 1234c0de7ab51234c0de7ab51234c0de
RCP 조이너가 '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 커미셔너로 돌아가 라우터 및 하위 테이블을 확인하여 두 기기가 동일한 네트워크에 속해 있는지 확인합니다. RLOC16을 사용하여 RCP 조이너를 식별합니다.
## 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 조이너의 메시 로컬 주소 (RCP 조이너의 ipaddr
출력에서 가져온 메시 로컬 주소)를 핑하여 연결을 확인합니다.
## 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
이제 다음 토폴로지 다이어그램에 표시된 대로 두 노드로 구성된 스레드 네트워크가 있습니다.
토폴로지 다이어그램
Codelab의 나머지 부분을 진행하면서 네트워크 상태가 변경될 때마다 새로운 스레드 토폴로지 다이어그램이 표시됩니다. 노드 역할은 다음과 같이 표시됩니다.
라우터는 항상 오각형이고 최종 기기는 항상 원입니다. 각 노드의 숫자는 당시 각 노드의 현재 역할과 상태에 따라 CLI 출력에 표시된 라우터 ID 또는 하위 ID를 나타냅니다.
9. FTD 조이너 커미셔닝
이제 세 번째 스레드 기기를 'codelab' 네트워크에 추가해 보겠습니다. 이번에는 더 안전한 인밴드 커미셔닝 프로세스를 사용하고 FTD 조이너만 참여하도록 허용합니다.
FTD Joiner에서 eui64
를 가져와 FTD 커미셔너가 이를 식별할 수 있도록 합니다.
## FTD Joiner ## ---------------- > eui64 2f57d222545271f1 Done
FTD 커미셔너에서 커미셔너를 시작하고 참여할 수 있는 기기의 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 커미셔너에서 방금 설정한 조이너 사용자 인증 정보로 조이너 역할을 시작합니다.
## FTD Joiner ## ---------------- > ifconfig up Done > joiner start J01NME Done
1분 이내에 인증 성공 확인이 표시됩니다.
## FTD Joiner ## ---------------- > Join success
FTD 조이너가 'codelab' 네트워크에 가입하도록 스레드를 가져오고 상태와 RLOC16을 즉시 확인합니다.
## FTD Joiner ## ---------------- > thread start Done > state child Done > rloc16 0c02 Done
기기의 IPv6 주소를 확인합니다. ALOC가 없습니다. 이 기기는 리더가 아니며 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 커미셔너로 즉시 전환하고 라우터 및 하위 테이블을 확인하여 'codelab' 네트워크에 기기가 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 | > 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 조이너가 엔드 기기 (하위)로 네트워크에 연결되었습니다. 업데이트된 토폴로지는 다음과 같습니다.
10. 실제 대화목록
이 Codelab의 스레드 기기는 라우터 지원 최종 기기 (REED)라는 특정 종류의 전체 스레드 기기 (FTD)입니다. 즉, 라우터 또는 최종 기기로 작동할 수 있으며 최종 기기에서 라우터로 승격될 수 있습니다.
스레드는 최대 32개의 라우터를 지원할 수 있지만 라우터 수를 16~23개로 유지하려고 합니다. REED가 최종 기기 (하위)로 연결되고 라우터 수가 16개 미만이면 2분 이내의 임의 시간 후에 라우터로 자동 승격됩니다.
FTD 조이너를 추가한 후 스레드 네트워크에 자녀가 두 명 있는 경우 2분 이상 기다린 후 FTD 커미셔너에서 라우터 및 자녀 테이블을 다시 확인합니다.
## 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 조이너 (확장 MAC = e6cdd2d93249a243
)가 라우터로 승격되었습니다. RLOC16이 다릅니다 (0c02
대신 b800
). 이는 RLOC16이 기기의 라우터 ID와 하위 ID를 기반으로 하기 때문입니다. 엔드 기기에서 라우터로 전환되면 라우터 ID와 하위 ID 값이 변경되고 RLOC16도 변경됩니다.
FTD Joiner에서 새 상태와 RLOC16을 확인합니다.
## FTD Joiner ## ---------------- > state router Done > rloc16 b800 Done
FTD 조이너 다운그레이드
라우터에서 엔드 기기로 FTD 조이너를 수동으로 다운그레이드하여 이 동작을 테스트할 수 있습니다. 상태를 child로 변경하고 RLOC16을 확인합니다.
## FTD Joiner ## ---------------- > state child Done > rloc16 0c03 Done
FTD 커미셔너로 돌아가면 이제 FTD 조이너가 하위 테이블 (ID = 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
인 라우터로 다시 전환됩니다.
리더 삭제
리더는 모든 스레드 라우터 중에서 자체적으로 선출됩니다. 즉, 현재 리더가 스레드 네트워크에서 삭제되면 다른 라우터 중 하나가 새 리더가 됩니다.
FTD 커미셔너에서 스레드를 종료하여 스레드 네트워크에서 삭제합니다.
## FTD Commissioner ## ---------------------- > thread stop Done > ifconfig down Done
2분 이내에 FTD Joiner가 새로운 스레드 리더가 됩니다. FTD 조이너의 상태와 IPv6 주소를 확인하여 다음을 확인합니다.
## 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
하위 테이블을 확인합니다. 새 RLOC16이 있습니다. ID와 확장 MAC으로 표시된 RCP 조이너입니다. 스레드 네트워크를 함께 유지하기 위해 FTD 커미셔너에서 FTD 조이너로 상위 라우터를 전환했습니다. 이로 인해 RCP 조이너의 새 RLOC16이 생성됩니다 (라우터 ID가 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 커미셔너 다시 연결
노드가 두 개인 스레드 네트워크는 재미가 없습니다. FTD 커미셔너를 다시 온라인 상태로 만들어 보겠습니다.
FTD 커미셔너에서 스레드를 다시 시작합니다.
## FTD Commissioner ## ---------------------- > ifconfig up Done > thread start Done
2분 이내에 '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
스레드 네트워크가 다시 세 개의 노드로 구성됩니다.
11. 문제 해결
서로 다른 터미널 또는 화면 창에서 여러 기기로 스레드 네트워크를 관리하는 것은 복잡할 수 있습니다. 문제가 발생하면 다음 도움말을 사용하여 네트워크 또는 워크스페이스의 상태를 '재설정'하세요.
화면
구성에서 길을 잃은 경우 (화면 창이 너무 많거나 화면 내 화면이 있는 경우) 명령줄에서 screen -ls
가 No Sockets found
를 출력할 때까지 Ctrl+a → k를 사용하여 화면 창을 계속 종료하세요. 그런 다음 각 기기의 화면 창을 다시 만듭니다. 화면이 종료되어도 기기 상태가 유지됩니다.
스레드 노드
스레드 네트워크 토폴로지가 이 Codelab에 설명된 대로가 아니거나 노드가 어떤 이유로 연결이 끊어지는 경우 (예: 노드를 구동하는 Linux 머신이 절전 모드로 전환됨) 스레드를 중단하고 네트워크 사용자 인증 정보를 지우고 스레드 네트워크 만들기 단계부터 다시 시작하는 것이 좋습니다.
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. 멀티캐스트 사용
멀티캐스트는 한 번에 여러 기기에 정보를 전달하는 데 사용됩니다. 스레드 네트워크에서는 범위에 따라 다양한 기기 그룹에서 멀티캐스트를 사용할 수 있도록 특정 주소가 예약됩니다.
IPv6 주소 | 범위 | 배송지 |
| 링크-로컬 | 모든 FTD 및 MED |
| 링크-로컬 | 모든 FTD 및 보더 라우터 |
| 메시 로컬 | 모든 FTD 및 MED |
| 메시 로컬 | 모든 FTD 및 보더 라우터 |
이 Codelab에서는 테두리 라우터를 사용하지 않으므로 두 FTD 및 MED 멀티캐스트 주소에 집중해 보겠습니다.
링크-로컬
링크 로컬 범위는 단일 무선 전송 또는 단일 '홉'으로 연결할 수 있는 모든 스레드 인터페이스로 구성됩니다. 네트워크 토폴로지에 따라 ff02::1
멀티캐스트 주소에 대한 핑에 응답하는 기기가 결정됩니다.
FTD 커미셔너에서 ff02::1
를 핑합니다.
## FTD Commissioner ## ---------------------- > ping ff02::1 > 8 bytes from fe80:0:0:0:e4cd:d2d9:3249:a243: icmp_seq=2 hlim=64 time=9ms
네트워크에 다른 두 기기 (FTD 조이너 및 RCP 조이너)가 있지만 FTD 커미셔너는 FTD 조이너의 링크 로컬 주소 (LLA)에서 하나의 응답만 수신했습니다. 즉, FTD 조이너는 FTD 커미셔너가 단일 홉으로 연결할 수 있는 유일한 기기입니다.
이제 FTD Joiner에서 ff02::1
를 핑합니다.
## 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
로 끝남)는 FTD 커미셔너의 LLA이고 두 번째 주소 (943b
로 끝남)는 RCP 조이너의 LLA입니다.
즉, FTD 조이너가 FTD 커미셔너와 RCP 조이너에 모두 직접 연결되어 토폴로지가 확인됩니다.
메시 로컬
메시 로컬 범위는 동일한 스레드 네트워크 내에서 연결할 수 있는 모든 스레드 인터페이스로 구성됩니다. ff03::1
멀티캐스트 주소에 대한 핑에 대한 응답을 살펴보겠습니다.
FTD 커미셔너에서 ff03::1
를 핑합니다.
## 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
로 끝남)에서, 다른 하나는 RCP 조이너의 메시 로컬 EID (ML-EID, d55f
로 끝남)에서 수신했습니다. 메시 로컬 범위가 전체 스레드 네트워크를 포함하기 때문입니다. 기기가 네트워크의 어디에 있든 ff03::1
주소를 구독합니다.
FTD Joiner에서 ff03::1
를 핑하여 동일한 동작을 확인합니다.
## 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
두 ping 출력에서 RCP Joiner의 응답 시간을 확인합니다. RCP 조이너가 FTD 커미셔너에 도달하는 데 걸린 시간 (68ms)이 FTD 조이너에 도달하는 데 걸린 시간 (23ms)보다 훨씬 깁니다. FTD 조이너의 경우 홉이 하나인 반면 FTD 커미셔너에 도달하려면 홉이 두 개여야 하기 때문입니다.
또한 메시 로컬 멀티캐스트 핑이 RCP 조이너가 아닌 두 FTD에 대해서만 RLOC로 응답한 것을 알 수 있습니다. FTD는 네트워크 내 라우터이고 RCP는 최종 기기이기 때문입니다.
RCP 조이너의 상태를 확인하여 다음을 확인합니다.
## RCP Joiner ## ---------------- > state child
13. UDP로 메시지 보내기
OpenThread에서 제공하는 애플리케이션 서비스 중 하나는 전송 계층 프로토콜인 사용자 데이터그램 프로토콜 (UDP)입니다. OpenThread를 기반으로 빌드된 애플리케이션은 UDP API를 사용하여 스레드 네트워크의 노드 간에 또는 외부 네트워크 (예: 스레드 네트워크에 보더 라우터가 있는 경우 인터넷)의 다른 기기에 메시지를 전달할 수 있습니다.
UDP 소켓은 OpenThread CLI를 통해 노출됩니다. 이를 사용하여 두 FTD 간에 메시지를 전달해 보겠습니다.
FTD Joiner의 메시 로컬 EID 주소를 가져옵니다. 이 주소는 스레드 네트워크 내 어디에서나 연결할 수 있으므로 사용됩니다.
## 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 커미셔너로 전환하고 UDP를 시작한 후 ML-EID를 사용하여 FTD 조이너에서 설정한 소켓에 연결합니다.
## 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. 축하합니다.
실제 스레드 네트워크가 생성되었습니다.
이제 다음 사항을 알게 되었습니다.
- 스레드 기기 유형, 역할, 범위의 차이점
- 스레드 기기가 네트워크 내에서 상태를 관리하는 방식
- UDP를 사용하여 노드 간에 간단한 메시지를 전달하는 방법
다음 단계
이 Codelab을 기반으로 다음 실습을 해 보세요.
ot-cli-mtd
바이너리를 사용하여 FTD 조이너 보드를 MTD로 다시 플래시하고 라우터로 업그레이드되거나 리더가 되려고 시도하지 않는지 확인합니다.- 네트워크에 기기를 더 추가하고 (다른 플랫폼 시도) 라우터 및 하위 테이블과 멀티캐스트 주소에 대한 핑을 사용하여 토폴로지를 스케치합니다.
- pyspinel을 사용하여 NCP 제어
- OpenThread 보더 라우터를 사용하여 NCP를 보더 라우터로 변환하고 스레드 네트워크를 인터넷에 연결합니다.
추가 자료
openthread.io 및 GitHub에서 다음을 비롯한 다양한 OpenThread 리소스를 확인하세요.
- 지원되는 플랫폼 - OpenThread를 지원하는 모든 플랫폼을 알아봅니다.
- OpenThread 빌드: OpenThread 빌드 및 구성에 관한 자세한 내용
- 스레드 기본사항: 이 Codelab에 나온 모든 스레드 개념을 다룹니다.
참조: