No ACL setup yet! Denying access to everyone.
en:edu:zmitac:s2:aih:projekt:studenci:openthread
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:edu:zmitac:s2:aih:projekt:studenci:openthread [2024/09/17 21:06] – blazkol203 | en:edu:zmitac:s2:aih:projekt:studenci:openthread [2024/09/18 20:58] (current) – blazkol203 | ||
|---|---|---|---|
| Line 2: | Line 2: | ||
| ===== Creating a Thread Network with the ESP Thread Border Router and ESP32H2 ===== | ===== Creating a Thread Network with the ESP Thread Border Router and ESP32H2 ===== | ||
| + | |||
| + | The following guide describes the necessary steps: https:// | ||
| + | |||
| + | ==== Example programs ==== | ||
| + | |||
| + | The example programs allow to configure and operate devices via the command line interface (CLI). | ||
| + | |||
| + | For the ESP Thread Border Router, two applications should be built: ot_rcp (device target - esp32h2) and basic_thread_border_router (device target - esp32s3).\\ | ||
| + | For the ESP32H2, only one application should be built: ot_cli (device target - esp32h2). | ||
| + | |||
| + | Before building the software, the menuconfig shoud be used to:\\ | ||
| + | - enable the commissioner feature for ESP Thread Border Router (basic_thread_border_router)\\ | ||
| + | //Component config > OpenThread > Enable Commissioner// | ||
| + | - enable the joiner feature for ESP32H2\\ | ||
| + | //Component config > OpenThread > Enable Joiner// | ||
| + | |||
| + | ==== Forming a mesh network ==== | ||
| + | |||
| + | We create a dataset on the ESP Thread Border Router using the following commands: | ||
| + | < | ||
| + | dataset init new | ||
| + | dataset commit active | ||
| + | </ | ||
| + | |||
| + | The entire dataset can be printed using the '' | ||
| + | |||
| + | In the next step, we bring up the IPv6 interface and the Thread protocol: | ||
| + | < | ||
| + | ifconfig up | ||
| + | thread start | ||
| + | </ | ||
| + | |||
| + | After a while, the device should change its status to " | ||
| + | |||
| + | In order to connect the ESP32H2 to the network, we can use the network key from the dataset generated on the ESP Thread Border Router: | ||
| + | < | ||
| + | dataset networkkey < | ||
| + | dataset commit active | ||
| + | </ | ||
| + | |||
| + | After that, we bringe up the IPv6 interface and the Thread protocol with '' | ||
| ===== Connecting the STM32WB55 to the Thread Network ===== | ===== Connecting the STM32WB55 to the Thread Network ===== | ||
| - | ===== Pinging | + | ==== Flashing the necessary firmware |
| + | |||
| + | The appropriate binary file (stm32wb5x_Thread_FTD_fw.bin) must be flashed for the Wireless Coprocessor using a tool like the STM32CubeProgrammer.\\ | ||
| + | It is available in github repository at the following link:\\ | ||
| + | https:// | ||
| + | The detailed procedure to change the Wireless Coprocessor binary (including install addresses) is available in the same repository: | ||
| + | |||
| + | ==== Example programs ==== | ||
| + | |||
| + | For the STM32WB55, the Thread_CLI_Cmd application can be found in the STM example programs | ||
| + | |||
| + | To establish a serial connection and send CLI commands, it is necessary to use an external application (e.g. PuTTY). | ||
| + | |||
| + | ==== Joining the network ==== | ||
| + | |||
| + | In addition to using the network key, it is possible to use the secure commissioning procedure to connect to the Thread network. | ||
| + | |||
| + | To connect the STM32WB55 to the network using commissioning we must enter the pskc and panid generated on the ESP Thread Border Router and bring up the IPv6 interface. | ||
| + | < | ||
| + | dataset pskc < | ||
| + | dataset panid < | ||
| + | dataset commit active | ||
| + | ifconfig up | ||
| + | </ | ||
| + | |||
| + | On the ESP Thread Border Router, we have to start the commissioner and specify the eui64 of the device that we want to join, along with the joiner credential: | ||
| + | < | ||
| + | commissioner start | ||
| + | commissioner joiner add < | ||
| + | </ | ||
| + | |||
| + | The Joiner Credential is a device-specific string of all uppercase alphanumeric characters (0-9 and A-Y, excluding I, O, Q and Z for readability), | ||
| + | |||
| + | On the STM32WB55, we start the joiner role with the previously set joiner credential: | ||
| + | < | ||
| + | joiner start <joiner credential> | ||
| + | </ | ||
| + | |||
| + | After a while, we should get confirmation of a successful authentication. | ||
| + | |||
| + | ===== Sending | ||
| + | |||
| + | The '' | ||
| + | To ping the selected node we use the appropriate command and Mesh-Local EID of the board we want to ping: '' | ||
| + | |||
| + | In order to send a message between two Thread devices with UDP we have to open udp and bind it on selected port on one board: | ||
| + | < | ||
| + | udp open | ||
| + | udp bind :: < | ||
| + | </ | ||
| + | |||
| + | Then send a message from the second board to MLE-ID address of the first board and previously selected port: | ||
| + | < | ||
| + | udp open | ||
| + | udp send < | ||
| + | </ | ||
| ===== Code samples ===== | ===== Code samples ===== | ||
| + | |||
| + | The following guide covers the basics of using the OpenThread API: https:// | ||
| + | The official documentation can be found at the following link: https:// | ||
| + | |||
| + | To make OpenThread API calls, it is necessary to initialize a static instance of the OpenThread library. In the ESP32H2 example, such an instance is returned by the '' | ||
| + | |||
| + | ==== Reacting to device role changes ==== | ||
| + | |||
| + | If we want to react whenever OpenThread instance state changes, we need to add following callback registration to our code: | ||
| + | |||
| + | < | ||
| + | otSetStateChangedCallback(esp_openthread_get_instance(), | ||
| + | </ | ||
| + | |||
| + | We also need to define a function that will be called after each state change: | ||
| + | |||
| + | < | ||
| + | void handleNetifStateChanged(uint32_t aFlags, void *aContext) | ||
| + | { | ||
| + | if ((aFlags & OT_CHANGED_THREAD_ROLE) != 0) | ||
| + | { | ||
| + | | ||
| + | |||
| + | | ||
| + | { | ||
| + | case OT_DEVICE_ROLE_LEADER: | ||
| + | case OT_DEVICE_ROLE_ROUTER: | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | case OT_DEVICE_ROLE_CHILD: | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | case OT_DEVICE_ROLE_DETACHED: | ||
| + | case OT_DEVICE_ROLE_DISABLED: | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The code above was written for the ESP32H2 platform, but in the Thread_CLI_Cmd example on STM32WB55 there exist similar functionality by default. | ||
| + | |||
| + | ==== Sending and receiving UDP messages ==== | ||
| + | When using UDP, we can define the port we want to use and also declare static variables such as socket, address or message payload. | ||
| + | |||
| + | < | ||
| + | #define UDP_PORT | ||
| + | |||
| + | static otUdpSocket sUdpSocket; | ||
| + | static const char UDP_DEST_ADDR[] = " | ||
| + | static const char UDP_PAYLOAD[] | ||
| + | </ | ||
| + | |||
| + | The following function can be used to initialize UDP: | ||
| + | |||
| + | < | ||
| + | void initUdp(otInstance *aInstance) | ||
| + | { | ||
| + | otSockAddr | ||
| + | |||
| + | memset(& | ||
| + | memset(& | ||
| + | |||
| + | listenSockAddr.mPort | ||
| + | |||
| + | otUdpOpen(aInstance, | ||
| + | otUdpBind(aInstance, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | We also define a function that will be called after receiving a message: | ||
| + | |||
| + | < | ||
| + | void handleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) | ||
| + | { | ||
| + | OT_UNUSED_VARIABLE(aContext); | ||
| + | OT_UNUSED_VARIABLE(aMessage); | ||
| + | OT_UNUSED_VARIABLE(aMessageInfo); | ||
| + | |||
| + | gpio_set_level(UDP_LED, | ||
| + | vTaskDelay(100); | ||
| + | gpio_set_level(UDP_LED, | ||
| + | vTaskDelay(100); | ||
| + | gpio_set_level(UDP_LED, | ||
| + | vTaskDelay(100); | ||
| + | gpio_set_level(UDP_LED, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | To send a UDP message we can use the following function: | ||
| + | |||
| + | < | ||
| + | void sendUdp(otInstance *aInstance) | ||
| + | { | ||
| + | otError | ||
| + | otMessage * | ||
| + | otMessageInfo messageInfo; | ||
| + | otIp6Address | ||
| + | |||
| + | memset(& | ||
| + | |||
| + | otIp6AddressFromString(UDP_DEST_ADDR, | ||
| + | messageInfo.mPeerAddr | ||
| + | messageInfo.mPeerPort | ||
| + | |||
| + | message = otUdpNewMessage(aInstance, | ||
| + | otEXPECT_ACTION(message != NULL, error = OT_ERROR_NO_BUFS); | ||
| + | |||
| + | error = otMessageAppend(message, | ||
| + | otEXPECT(error == OT_ERROR_NONE); | ||
| + | |||
| + | error = otUdpSend(aInstance, | ||
| + | |||
| + | exit: | ||
| + | if (error != OT_ERROR_NONE && message != NULL) | ||
| + | { | ||
| + | otMessageFree(message); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Here is an example of calling the above function inside a button interrupt from an STM32WB55 board. | ||
| + | |||
| + | < | ||
| + | void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) | ||
| + | { | ||
| + | if(GPIO_Pin == BUTTON_SW1_PIN) { | ||
| + | sendUdp(PtOpenThreadInstance); | ||
| + | } else { | ||
| + | __NOP(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
en/edu/zmitac/s2/aih/projekt/studenci/openthread.1726599988.txt.gz · Last modified: by blazkol203
