Criar uma rede Thread com placas nRF52840 e OpenThread

1. Introdução

26b7f4f6b3ea0700.png

O OpenThread lançado pelo Google é uma implementação de código aberto do protocolo de rede Thread®. O Google Nest lançou o OpenThread para disponibilizar a tecnologia usada nos produtos Nest a desenvolvedores e acelerar o desenvolvimento de produtos para a casa conectada.

A especificação Thread define um protocolo de comunicação sem fio confiável, seguro e de baixo consumo de energia entre dispositivos com base em IPv6 para aplicações domésticas. O OpenThread implementa todas as camadas de rede Thread, incluindo IPv6, 6LoWPAN, IEEE 802.15.4 com segurança MAC, estabelecimento de link de malha e roteamento de malha.

Neste codelab, você vai programar o OpenThread em hardware real, criar e gerenciar uma rede Thread e transmitir mensagens entre nós.

4806d16a8c137c6d.jpeg

O que você vai aprender

  • Como criar e gravar binários da CLI OpenThread em placas de desenvolvimento
  • Como criar um RCP com uma máquina Linux e uma placa de desenvolvimento
  • Comunicação com um RCP usando o daemon OpenThread e ot-ctl
  • Gerenciar manualmente nós do Thread com o GNU Screen e a CLI do OpenThread
  • Comissionamento seguro de dispositivos em uma rede Thread
  • Como o multicast IPv6 funciona
  • Como transmitir mensagens entre nós de thread com UDP

O que é necessário

Hardware:

  • 3 placas de desenvolvimento Nordic Semiconductor nRF52840
  • 3 cabos USB para micro USB para conectar os quadros
  • Uma máquina Linux com pelo menos três portas USB

Software:

  • Conjunto de ferramentas GNU
  • Ferramentas de linha de comando Nordic nRF5x
  • Software Segger J-Link
  • OpenThread
  • Git

2. Primeiros passos

Simulação do OpenThread

Antes de começar, faça o codelab de simulação do OpenThread para se familiarizar com os conceitos básicos do Thread e a CLI do OpenThread.

Terminais de porta serial

Você precisa saber se conectar a uma porta serial usando um terminal. Este codelab usa o GNU Screen e apresenta uma visão geral do uso, mas é possível usar qualquer outro software de terminal.

Máquina Linux

Este codelab foi criado para usar uma máquina Linux baseada em i386 ou x86 como host de um dispositivo Thread de coprocessador de rádio (RCP) e para atualizar todas as placas de desenvolvimento do Thread. Todas as etapas foram testadas no Ubuntu 14.04.5 LTS (Trusty Tahr).

Placas Nordic Semiconductor nRF52840

Este codelab usa três placas nRF52840 PDK.

a6693da3ce213856.png

Usamos o SEGGER J-Link para programar as placas nRF52840, que têm módulos JTAG integrados. Instale isso na sua máquina Linux.

Faça o download do pacote adequado para sua máquina e instale-o no local correto. No Linux, é /opt/SEGGER/JLink.

Instalar as ferramentas de linha de comando nRF5x

Com as ferramentas de linha de comando nRF5x, é possível gravar os binários do OpenThread nas placas nRF52840. Instale o build nRF5x-Command-Line-Tools-<OS> adequado na sua máquina Linux.

Coloque o pacote extraído na pasta raiz ~/.

Instalar a cadeia de ferramentas GNU do ARM

A cadeia de ferramentas GNU ARM é usada para criar.

Recomendamos colocar o arquivo extraído em /opt/gnu-mcu-eclipse/arm-none-eabi-gcc/ na sua máquina Linux. Siga as instruções de instalação no arquivo readme.txt do arquivo.

Tela de instalação (opcional)

O Screen é uma ferramenta simples para acessar dispositivos conectados por uma porta serial. Este codelab usa o Screen, mas você pode usar qualquer aplicativo de terminal de porta serial.

$ sudo apt-get install screen

3. Clonar repositórios

OpenThread

Clone e instale o OpenThread. Os comandos script/bootstrap garantem que a cadeia de ferramentas esteja instalada e que o ambiente esteja configurado corretamente:

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

Crie o daemon OpenThread:

$ script/cmake-build posix -DOT_DAEMON=ON

Agora você já pode criar e gravar o OpenThread nas placas nRF52840.

4. Configurar o RCP Joiner

Criar e atualizar

Crie o exemplo do OpenThread nRF52840 com o Joiner e a funcionalidade USB nativa. Um dispositivo usa a função de associador para ser autenticado e comissionado com segurança em uma rede Thread. O USB nativo permite o uso do USB CDC ACM como um transporte serial entre o nRF52840 e o host.

Sempre limpe o repositório de builds anteriores executando rm -rf build primeiro.

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

Acesse o diretório com o binário RCP do OpenThread e converta para o formato hexadecimal:

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

Conecte o cabo USB à porta de depuração micro USB ao lado do pino de alimentação externa na placa nRF52840 e conecte-o à máquina Linux. Defina a chave nRF power source na placa nRF52840 como VDD. Quando conectado corretamente, o LED5 fica aceso.

20a3b4b480356447.png

Se esta for a primeira placa conectada à máquina Linux, ela vai aparecer como porta serial /dev/ttyACM0. Todas as placas nRF52840 usam ttyACM como identificador da porta serial.

$ ls /dev/ttyACM*
/dev/ttyACM0

Anote o número de série da placa nRF52840 usada para o RCP:

c00d519ebec7e5f0.jpeg

Acesse o local das ferramentas de linha de comando nRFx e faça o flash do arquivo hexadecimal RCP do OpenThread na placa nRF52840 usando o número de série dela. Se você não incluir a flag --verify, uma mensagem de aviso vai aparecer informando que o processo de atualização pode falhar sem erro.

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

A seguinte saída é gerada em caso de sucesso:

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.

Marque o quadro como "RCP" para não confundir as funções do quadro depois.

Conectar ao USB nativo

Como o build do RCP do OpenThread permite o uso do USB CDC ACM nativo como um transporte serial, use a porta nRF USB na placa nRF52840 para se comunicar com o host RCP (máquina Linux).

Desconecte a extremidade micro USB do cabo USB da porta de depuração da placa nRF52840 gravada e reconecte-a à porta micro USB nRF USB ao lado do botão RESET. Defina o interruptor Fonte de alimentação nRF como USB.

46e7b670d2464842.png

Iniciar o daemon OpenThread

No design do RCP, use o daemon OpenThread para se comunicar com o dispositivo Thread e gerenciá-lo. Inicie ot-daemon com a flag detalhada -v para ver a saída do registro e confirmar que ele está em execução:

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

Quando bem-sucedido, o ot-daemon no modo detalhado gera uma saída semelhante a esta:

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

Deixe essa janela de terminal aberta para que os registros de ot-daemon possam ser visualizados.

Use ot-ctl para se comunicar com o nó RCP. O ot-ctl usa a mesma CLI que o app OpenThread CLI. Portanto, é possível controlar os nós ot-daemon da mesma maneira que os outros dispositivos Thread simulados.

Em uma segunda janela de terminal, inicie ot-ctl:

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

Verifique o state do nó 2 (o nó RCP) que você iniciou com ot-daemon:

> state
disabled
Done

5. Configurar os FTDs

Os outros dois nós do Thread usados neste codelab são dispositivos Thread completos (FTDs, na sigla em inglês) no design padrão de sistema em um chip (SoC, na sigla em inglês). Um dispositivo funciona como o comissário, para autenticar e comissionar dispositivos com segurança nessa rede. O outro dispositivo funciona como um conector que o comissário pode autenticar na rede Thread.

Criar e atualizar

Crie o exemplo de FTD do OpenThread para a plataforma nRF52840 com as funções de comissário e participante ativadas:

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

Navegue até o diretório com o binário da CLI do dispositivo de thread completo (FTD) do OpenThread e converta-o para o formato hexadecimal:

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

Conecte o cabo USB à porta micro USB ao lado do conector de alimentação externa na placa nRF52840 e conecte-o à máquina Linux. Se o RCP ainda estiver conectado à máquina Linux, a nova placa vai aparecer como porta serial /dev/ttyACM1. Todas as placas nRF52840 usam ttyACM como identificador da porta serial.

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

Como antes, observe o número de série da placa nRF52840 usada para o FTD:

c00d519ebec7e5f0.jpeg

Navegue até o local das ferramentas de linha de comando nRFx e faça o flash do arquivo hexadecimal FTD da CLI OpenThread na placa nRF52840 usando o número de série dela:

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

Nomeie o quadro como "Comissário".

Conectar ao USB nativo

Como o build FTD do OpenThread permite o uso do USB CDC ACM nativo como um transporte serial, você precisa usar a porta nRF USB na placa nRF52840 para se comunicar com o host RCP (máquina Linux).

Desconecte a extremidade micro USB do cabo USB da porta de depuração da placa nRF52840 gravada e reconecte-a à porta micro USB nRF USB ao lado do botão RESET. Defina o interruptor Fonte de alimentação nRF como USB.

46e7b670d2464842.png

Verificar build

Verifique se o build foi bem-sucedido acessando a CLI OpenThread usando o GNU Screen em uma janela de terminal.

$ screen /dev/ttyACM1

Na nova janela, pressione "Return" algumas vezes no teclado para abrir o prompt da CLI OpenThread >. Ative a interface IPv6 e verifique os endereços:

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

Use Ctrl+a →

d para desanexar da tela da CLI do FTD Commissioner e voltar ao terminal do Linux para que a próxima placa possa ser atualizada. Para reentrar na CLI a qualquer momento, use screen -r na linha de comando. Para conferir uma lista de telas disponíveis, use screen -ls:

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

Configurar o FTD Joiner

Repita o processo acima para gravar a terceira placa nRF52840 usando o build ot-cli-ftd.hex atual. Quando terminar, reconecte a placa ao PC usando a porta USB nRF e defina a chave fonte de alimentação nRF como VDD.

Se os outros dois nós estiverem conectados à máquina Linux quando esta terceira placa for conectada, ela vai aparecer como porta serial /dev/ttyACM2:

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

Nomeie o quadro como "Joiner".

Ao verificar usando o Screen, em vez de criar uma nova instância do Screen na linha de comando, reconecte-se à instância atual e crie uma nova janela nela (que você usou para o comissário da FTD):

$ screen -r

Crie a nova janela no Screen com Ctrl+a → c.

Um novo prompt de linha de comando vai aparecer. Acesse a CLI do OpenThread para o FTD Joiner:

$ screen /dev/ttyACM2

Nessa nova janela, pressione "Return" algumas vezes no teclado para abrir o prompt > da CLI OpenThread. Ative a interface IPv6 e verifique os endereços:

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

Agora que a CLI do FTD Joiner está na mesma instância do Screen que o FTD Commissioner, é possível alternar entre eles usando Ctrl+a → n.

Use Ctrl+a →

d a qualquer momento para sair da tela.

6. Configuração da janela do terminal

De agora em diante, você vai alternar entre dispositivos Thread com frequência. Por isso, verifique se todos estão ativos e acessíveis. Até agora, usamos a tela para acessar os dois FTDs, e essa ferramenta também permite a tela dividida na mesma janela do terminal. Use isso para ver como um nó reage a comandos emitidos em outro.

O ideal é ter quatro janelas disponíveis:

  1. Serviço / registros do ot-daemon
  2. RCP Joiner via ot-ctl
  3. Comissário do FTD pela CLI do OpenThread
  4. FTD Joiner via CLI do OpenThread

Se você quiser usar sua própria configuração ou ferramenta de terminal / porta serial, pule para a próxima etapa. Configure as janelas do terminal para todos os dispositivos da maneira que funcionar melhor para você.

Usar a tela

Para facilitar o uso, inicie apenas uma sessão do Screen. Você já deve ter um da configuração dos dois FTDs.

Todos os comandos no Screen começam com Ctrl+a.

Comandos básicos da tela:

Reanexar à sessão do Screen (na linha de comando)

screen -r

Sair da sessão do Screen

Ctrl+a → d

Criar uma nova janela na sessão da tela

Ctrl+a → c

Alternar entre janelas na mesma sessão da tela

Ctrl+a → n (para frente)Ctrl+a → p (para trás)

Encerrar a janela atual na sessão da tela

Ctrl+a → k

Tela dividida

Com o Screen, é possível dividir o terminal em várias janelas:

f1cbf1258cf0a5a.png

Os comandos em screen são acessados usando Ctrl+a. Todos os comandos precisam começar com essa combinação de teclas de acesso.

Se você seguiu o codelab exatamente, terá duas janelas (FTD Commissioner, FTD Joiner) na mesma instância de tela. Para dividir a tela entre os dois, primeiro insira sua sessão do Screen atual:

$ screen -r

Você precisa estar em um dos dispositivos FTD. Siga estas etapas na tela:

  1. Ctrl+a → S para dividir a janela horizontalmente
  2. Ctrl+a → Tab para mover o cursor para a nova janela em branco
  3. Ctrl+a → n para alternar essa nova janela para a próxima
  4. Se for igual à janela de cima, pressione Ctrl+a → n novamente para ver o outro dispositivo FTD.

Agora os dois estão visíveis. Alterne entre eles usando Ctrl+a → Tab. Recomendamos que você renomeie cada janela com Ctrl+a → A para evitar confusão.

Uso avançado

Para dividir ainda mais a tela em quadrantes e ver os registros ot-daemon e o RCP Joiner ot-ctl, esses serviços precisam ser iniciados na mesma instância de tela. Para isso, pare ot-daemon e saia de ot-ctl. Depois, reinicie os dois em novas janelas do Screen (Ctrl+a → c).

Essa configuração não é necessária e fica como um exercício para o usuário.

Divida e navegue entre as janelas com os seguintes comandos:

Criar nova janela

Ctrl+a → c

Dividir janela verticalmente

Ctrl+a →

Dividir a janela horizontalmente

Ctrl+a → S

Ir para a próxima janela mostrada

Ctrl+a → Tab

Mudar a janela mostrada para frente ou para trás

Ctrl+a → n ou p

Renomear a janela atual

Ctrl+a → A

Saia do Screen a qualquer momento com Ctrl+a → d e reconecte com screen -r na linha de comando.

Para mais informações sobre o Screen, consulte a referência rápida do GNU Screen.

7. Criar a rede Thread

Agora que você tem todas as janelas e telas do terminal configuradas, vamos criar nossa rede Thread. No FTD Commissioner, crie um novo conjunto de dados operacionais e confirme-o como o ativo. O conjunto de dados operacional é a configuração da rede Thread que você está criando.

## 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

Anote a chave de rede 1234c0de7ab51234c0de7ab51234c0de, que será usada mais tarde.

Faça o commit desse conjunto de dados como o ativo:

> dataset commit active
Done

Ative a interface IPv6:

> ifconfig up
Done

Iniciar a operação do protocolo de conversa:

> thread start
Done

Depois de um momento, verifique o estado do dispositivo. Ele precisa ser o líder. Também anote o RLOC16 para referência futura.

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

> state
leader
Done
> rloc16
0c00
Done

Verifique os endereços IPv6 do dispositivo:

## 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)

A rede "codelab" agora fica visível quando é verificada em outros dispositivos Thread.

Em ot-ctl no RCP Joiner:

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

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

Na CLI do OpenThread no FTD Joiner:

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

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

Se a rede "codelab" não aparecer na lista, tente digitalizar novamente.

8. Adicionar o RCP Joiner

O Thread Commissioning não está ativo na rede. Isso significa que precisamos adicionar o RCP Joiner à rede Thread que acabamos de criar usando um processo de comissionamento fora da banda.

No FTD Commissioner, anotamos a chave de rede, por exemplo, 1234c0de7ab51234c0de7ab51234c0de. Se você precisar pesquisar a chave de rede novamente, execute o seguinte comando no FTD Commissioner:

## FTD Commissioner ##

> dataset networkkey
1234c0de7ab51234c0de7ab51234c0de
Done

Em seguida, no RCP Joiner, defina a chave de rede do conjunto de dados ativo como a chave de rede do comissário do FTD:

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

> dataset networkkey 1234c0de7ab51234c0de7ab51234c0de
Done
> dataset commit active
Done

Verifique se o conjunto de dados está configurado corretamente.

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

> dataset
Network Key: 1234c0de7ab51234c0de7ab51234c0de

Abra o Thread para que o RCP Joiner entre na rede "codelab". Aguarde alguns segundos e verifique o estado, o RLOC16 e os endereços 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

Anote o endereço IPv6 local da malha (fdc0:de7a:b5c0:0:66bf:99b9:24c0:d55f aqui), que será usado mais tarde.

De volta ao FTD Commissioner, confira as tabelas de roteador e secundárias para confirmar se os dois dispositivos fazem parte da mesma rede. Use o RLOC16 para identificar o 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

Envie um ping para o endereço local da malha do RCP Joiner (o endereço local da malha obtido na saída ipaddr do RCP Joiner) para verificar a conectividade:

## 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

Agora temos uma rede Thread com dois nós, ilustrada por este diagrama de topologia:

otcodelab_top01C_2nodes.png

Diagramas de topologia

Ao longo do restante do codelab, vamos mostrar um novo diagrama de topologia de encadeamento sempre que o estado da rede mudar. As funções de nó são indicadas da seguinte forma:

b75a527be4563215.png

Os roteadores são sempre pentágonos, e os dispositivos finais são sempre círculos. Os números em cada nó representam o ID do roteador ou o ID filho mostrado na saída da CLI, dependendo da função e do estado atuais de cada nó naquele momento.

9. Comissionar o FTD Joiner

Agora, vamos adicionar o terceiro dispositivo Thread à rede "codelab". Desta vez, vamos usar o processo de inclusão na banda mais seguro e permitir apenas a entrada do FTD Joiner.

No FTD Joiner, acesse o eui64 para que o comissário do FTD possa identificá-lo:

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

> eui64
2f57d222545271f1
Done

No FTD Commissioner, inicie o comissário e especifique o eui64 do dispositivo que pode participar, junto com a credencial de junção, por exemplo, J01NME. A credencial do participante é uma string específica do dispositivo com todos os caracteres alfanuméricos maiúsculos (0 a 9 e A a Y, exceto I, O, Q e Z para facilitar a leitura), com um comprimento entre 6 e 32 caracteres.

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

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

Mude para o FTD Joiner. Inicie a função de participante com a credencial que você acabou de configurar no comissário do FTD:

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

> ifconfig up
Done
> joiner start J01NME
Done

Em um minuto, você vai receber uma confirmação de autenticação bem-sucedida:

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

>
Join success

Inicie o Thread para que o FTD Joiner entre na rede "codelab" e verifique imediatamente o estado e o RLOC16:

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

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

Verifique os endereços IPv6 do dispositivo. Não há ALOC. Isso acontece porque esse dispositivo não é o líder nem tem uma função específica do Anycast que exige um 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)

Mude imediatamente para o FTD Commissioner e verifique as tabelas de roteador e criança para confirmar que existem três dispositivos na rede "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

Com base no RLOC16, o FTD Joiner se conectou à rede como um dispositivo final (filho). Esta é nossa topologia atualizada:

otcodelab_top01C_ed01.png

10. Conversa em ação

Os dispositivos Thread neste codelab são um tipo específico de dispositivo Thread completo (FTD, na sigla em inglês) chamado de dispositivo final qualificado para roteador (REED, na sigla em inglês). Isso significa que eles podem funcionar como um roteador ou um dispositivo final e podem se promover de um dispositivo final para um roteador.

O Thread pode oferecer suporte a até 32 roteadores, mas tenta manter o número entre 16 e 23. Se um REED se conectar como um dispositivo final (filho) e o número de roteadores for inferior a 16, ele será promovido automaticamente a um roteador após um período aleatório de até dois minutos.

Se você tinha duas crianças na rede Thread depois de adicionar o FTD Joiner, aguarde pelo menos dois minutos e verifique novamente as tabelas de roteador e criança no 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

O FTD Joiner (MAC estendido = e6cdd2d93249a243) se promoveu a um roteador. O RLOC16 é diferente (b800 em vez de 0c02) porque se baseia no ID do roteador e no ID filho de um dispositivo. Quando ele faz a transição de dispositivo final para roteador, os valores de ID do roteador e ID filho mudam, assim como o RLOC16.

otcodelab_top01C.png

Confirme o novo estado e o RLOC16 no FTD Joiner:

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

> state
router
Done
> rloc16
b800
Done

Fazer downgrade do FTD Joiner

Para testar esse comportamento, faça um downgrade manual do FTD Joiner de um roteador para um dispositivo final. Mude o estado para "child" e verifique o RLOC16:

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

> state child
Done
> rloc16
0c03
Done

otcodelab_top01C_ed02.png

De volta ao FTD Commissioner, o FTD Joiner vai aparecer na tabela secundária (ID = 3). Ele pode até estar nos dois durante a transição:

## 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

Depois de algum tempo, ele voltará para um roteador com um RLOC de b800.

otcodelab_top01C.png

Remover o líder

O líder é escolhido entre todos os roteadores de linha de execução. Isso significa que, se o líder atual for removido da rede Thread, um dos outros roteadores vai se tornar o novo líder.

No FTD Commissioner, desative o Thread para removê-lo da rede Thread:

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

> thread stop
Done
> ifconfig down
Done

Em dois minutos, o FTD Joiner se torna o novo líder da linha de execução. Verifique o estado e os endereços IPv6 do FTD Joiner para verificar:

## 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

Verifique a tabela filha. Há um novo RLOC16. Este é o RCP Joiner, conforme indicado pelo ID e pelo MAC estendido. Para manter a rede Thread unida, ele mudou os roteadores principais, do FTD Commissioner para o FTD Joiner. Isso resulta em um novo RLOC16 para o RCP Joiner, porque o ID do roteador mudou de 3 para 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

Talvez seja necessário aguardar alguns minutos para que o RCP Joiner seja anexado ao FTD Joiner como um filho. Verifique o estado e o RLOC16 para confirmar que:

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

> state
child
> rloc16
b801

Reconecte o comissário do FTD

Uma rede Thread com dois nós não é muito divertida. Vamos trazer o comissário da FTD de volta à Internet.

No FTD Commissioner, reinicie o Thread:

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

> ifconfig up
Done
> thread start
Done

Em dois minutos, ele se reconecta automaticamente à rede "codelab" como um dispositivo final e se promove a um roteador.

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

> state
router
Done

Verifique as tabelas de roteador e secundárias no FTD Joiner para verificar:

## 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

Nossa rede Thread consiste em três nós novamente.

11. Solução de problemas

Gerenciar uma rede Thread com vários dispositivos em diferentes janelas de terminal ou tela pode ser complicado. Use estas dicas para "redefinir" o estado da rede ou do seu espaço de trabalho se encontrar problemas.

Tela

Se você se perder na configuração (muitas janelas de tela ou telas dentro de telas), continue fechando as janelas com Ctrl+a → k até que não haja mais nenhuma e screen -ls na linha de comando mostre No Sockets found. Em seguida, recrie as janelas de tela para cada dispositivo. Os estados do dispositivo são mantidos mesmo quando a tela é encerrada.

Nós de conversas

Se a topologia da rede Thread não for como descrito neste codelab ou se os nós forem desconectados por algum motivo (talvez porque a máquina Linux que os alimenta entrou em modo de espera), é melhor desativar o Thread, limpar as credenciais da rede e começar de novo na etapa Criar a rede Thread.

Para redefinir os FTDs:

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

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

O RCP pode ser redefinido da mesma forma via ot-ctl:

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

> thread stop
Done
> ifconfig down
Done
> factoryreset
Done

12. Como usar o multicast

O multicast é usado para comunicar informações a um grupo de dispositivos de uma só vez. Em uma rede Thread, endereços específicos são reservados para uso de multicast com diferentes grupos de dispositivos, dependendo do escopo.

Endereço IPv6

Escopo

Entregue em

ff02::1

Link-local

Todas as FTDs e MEDs

ff02::2

Link-local

Todos os FTDs e roteadores de borda

ff03::1

Mesh-Local

Todas as FTDs e MEDs

ff03::2

Mesh-Local

Todos os FTDs e roteadores de borda

Como não estamos usando um roteador de borda neste codelab, vamos nos concentrar nos dois endereços multicast FTD e MED.

O escopo local de link inclui todas as interfaces do Thread acessíveis por uma única transmissão de rádio ou um único "salto". A topologia de rede determina quais dispositivos respondem a um ping no endereço multicast ff02::1.

Envie um ping para ff02::1 do Comissário da FTD:

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

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

Há dois outros dispositivos na rede (FTD Joiner e RCP Joiner), mas o FTD Commissioner só recebeu uma resposta, do endereço local de link (LLA) do FTD Joiner. Isso significa que o FTD Joiner é o único dispositivo que o FTD Commissioner pode alcançar com um único salto.

otcodelab_top02C_02_LL.png

Agora, dê um ping em ff02::1 no 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

Duas respostas! Ao verificar os endereços IPv6 dos outros dispositivos, podemos ver que o primeiro (terminado em 4b1d) é o LLA do comissário FTD, e o segundo (terminado em 943b) é o LLA do associador RCP.

otcodelab_top02C_02_LL02.png

Isso significa que o FTD Joiner está conectado diretamente ao FTD Commissioner e ao RCP Joiner, o que confirma nossa topologia.

Mesh-Local

O escopo local da rede mesh inclui todas as interfaces Thread acessíveis na mesma rede Thread. Vamos conferir as respostas a um ping no endereço multicast ff03::1.

Envie um ping para ff03::1 do Comissário da 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

Desta vez, o comissário da FTD recebeu duas respostas: uma do localizador de roteamento (RLOC, na sigla em inglês) do participante da FTD (terminado em b800) e outra do EID local da malha (ML-EID, na sigla em inglês) do participante do RCP (terminado em d55f). Isso acontece porque o escopo local da malha abrange toda a rede Thread. Não importa onde um dispositivo esteja na rede, ele será inscrito no endereço ff03::1.

otcodelab_top02C_02_ML.png

Faça um ping em ff03::1 no FTD Joiner para confirmar o mesmo comportamento:

## 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

Observe o tempo de resposta do RCP Joiner nas duas saídas de ping. O RCP Joiner levou muito mais tempo para alcançar o FTD Commissioner (68 ms) do que o FTD Joiner (23 ms). Isso acontece porque ele precisa fazer dois saltos para alcançar o comissário da FTD, em comparação com um salto para o associado da FTD.

Você também pode ter notado que o ping de multicast local da malha respondeu com o RLOC apenas para os dois FTDs, não para o RCP Joiner. Isso acontece porque os FTDs são roteadores na rede, enquanto o RCP é um dispositivo final.

Verifique o estado do RCP Joiner para confirmar:

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

> state
child

13. Enviar mensagens com UDP

Um dos serviços de aplicativo fornecidos pelo OpenThread é o protocolo de datagramas do usuário (UDP), um protocolo da camada de transporte. Um aplicativo criado no OpenThread pode usar a API UDP para transmitir mensagens entre nós em uma rede Thread ou para outros dispositivos em uma rede externa (como a Internet, se a rede Thread tiver um roteador de borda).

Os soquetes UDP são expostos pela CLI do OpenThread. Vamos usá-lo para transmitir mensagens entre os dois FTDs.

Encontre o endereço EID local da malha do FTD Joiner. Estamos usando esse endereço porque ele pode ser acessado de qualquer lugar na rede 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

Inicie o UDP e vincule-o a um soquete para qualquer endereço IPv6:

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

> udp open
Done
> udp bind :: 1212

Mude para o FTD Commissioner, inicie o UDP e conecte-se ao soquete configurado no FTD Joiner usando o ML-EID dele:

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

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

A conexão UDP precisa estar ativa entre os dois nós. Envie uma mensagem do comissário da FTD:

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

> udp send hellothere
Done

No FTD Joiner, a mensagem UDP foi recebida.

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

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

14. Parabéns!

Você criou uma rede Thread física.

b915c433e7027cc7.png

Agora você sabe:

  • a diferença entre tipos, funções e escopos de dispositivos Thread
  • como os dispositivos Thread gerenciam os estados na rede
  • como transmitir mensagens simples entre nós usando UDP

Próximas etapas

Com base neste codelab, faça os exercícios a seguir:

  • Refaça o flash da placa FTD Joiner como um MTD usando o binário ot-cli-mtd e observe que ela nunca faz upgrade para um roteador nem tenta se tornar o líder.
  • Adicione mais dispositivos (tente uma plataforma diferente!) à rede e esboce a topologia usando tabelas de roteador e filho, além de pings para os endereços multicast.
  • Use pyspinel para controlar o NCP
  • Converta o NCP em um roteador de borda usando o OpenThread Border Router e conecte sua rede Thread à Internet.

Leitura adicional

Confira openthread.io e GitHub para acessar vários recursos do OpenThread, incluindo:

Referência: