For fuck's sake

This commit is contained in:
2025-12-25 21:28:59 +01:00
parent ce6a2b9185
commit 1e86f97113
41689 changed files with 4655 additions and 14185374 deletions

View File

@@ -0,0 +1,2 @@
CompileFlags:
Remove: [-f*, -m*]

View File

@@ -0,0 +1,13 @@
ARG DOCKER_TAG=latest
FROM espressif/idf:${DOCKER_TAG}
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN apt-get update -y && apt-get install udev -y
RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
CMD ["/bin/bash", "-c"]

View File

@@ -0,0 +1,21 @@
{
"name": "ESP-IDF QEMU",
"build": {
"dockerfile": "Dockerfile"
},
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension",
"espressif.esp-idf-web"
]
}
},
"runArgs": ["--privileged"]
}

78
esp32-thread/border-router/.gitignore vendored Normal file
View File

@@ -0,0 +1,78 @@
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Directory metadata
.directory
# Temporary files
*~
*.swp
*.swo
*.bak
*.tmp
# Log files
*.log
# Build artifacts and directories
**/build/
build/
*.o
*.a
*.out
*.exe # For any host-side utilities compiled on Windows
# ESP-IDF specific build outputs
*.bin
*.elf
*.map
flasher_args.json # Generated in build directory
sdkconfig.old
sdkconfig
# ESP-IDF dependencies
# For older versions or manual component management
/components/.idf/
**/components/.idf/
# For modern ESP-IDF component manager
managed_components/
# If ESP-IDF tools are installed/referenced locally to the project
.espressif/
# CMake generated files
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
install_manifest.txt
CTestTestfile.cmake
# Python environment files
*.pyc
*.pyo
*.pyd
__pycache__/
*.egg-info/
dist/
# Virtual environment folders
venv/
.venv/
env/
# Language Servers
.clangd/
.ccls-cache/
compile_commands.json
# Windows specific
Thumbs.db
ehthumbs.db
Desktop.ini
# User-specific configuration files
*.user
*.workspace # General workspace files, can be from various tools
*.suo # Visual Studio Solution User Options
*.sln.docstates # Visual Studio

View File

@@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "ESP-IDF",
"compilerPath": "${config:idf.toolsPathWin}\\tools\\riscv32-esp-elf\\esp-14.2.0_20241119\\riscv32-esp-elf\\bin\\riscv32-esp-elf-gcc.exe",
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
"includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**"
],
"browse": {
"path": [
"${config:idf.espIdfPath}/components",
"${config:idf.espIdfPathWin}/components",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
}
],
"version": 4
}

View File

@@ -0,0 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
},
{
"type": "espidf",
"name": "Launch",
"request": "launch"
}
]
}

View File

@@ -0,0 +1,19 @@
{
"C_Cpp.intelliSenseEngine": "default",
"idf.espIdfPathWin": "C:\\Users\\Laurent\\esp\\v5.5.1\\esp-idf",
"idf.pythonInstallPath": "C:\\Users\\Laurent\\.espressif\\tools\\idf-python\\3.11.2\\python.exe",
"idf.openOcdConfigs": [
"board/esp32h2-builtin.cfg"
],
"idf.portWin": "COM4",
"idf.toolsPathWin": "C:\\Users\\Laurent\\.espressif",
"idf.customExtraVars": {
"IDF_TARGET": "esp32h2"
},
"clangd.path": "C:\\Users\\Laurent\\.espressif\\tools\\esp-clang\\esp-19.1.2_20250312\\esp-clang\\bin\\clangd.exe",
"clangd.arguments": [
"--background-index",
"--query-driver=**",
"--compile-commands-dir=c:\\Users\\Laurent\\Desktop\\board-mate\\esp32-thread\\border-router\\build"
]
}

View File

@@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(border-router)

View File

@@ -0,0 +1,276 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- |
# OpenThread Border Router Example
## Overview
This example demonstrates an [OpenThread border router](https://openthread.io/guides/border-router).
The ESP Thread Border Router SDK provides extra components and examples for putting the ESP Thread Border Router solution into production:
* [ESP Thread Border Router Docs](https://docs.espressif.com/projects/esp-thread-br)
* [ESP Thread Border Router Repo](https://github.com/espressif/esp-thread-br)
## How to use example
### Hardware Required
#### **Wi-Fi based Thread Border Router**
By default, two SoCs are required to run this example:
* An ESP32 series Wi-Fi SoC (ESP32, ESP32-C, ESP32-S, etc) loaded with this ot_br example.
* An IEEE 802.15.4 SoC (ESP32-H2) loaded with [ot_rcp](../ot_rcp) example.
* Another IEEE 802.15.4 SoC (ESP32-H2) loaded with [ot_cli](../ot_cli) example.
Connect the two SoCs via UART, below is an example setup with ESP32 DevKitC and ESP32-H2 DevKitC:
![thread_br](image/thread-border-router-esp32-esp32h2.jpg)
ESP32 pin | ESP32-H2 pin
----------|-------------
GND | G
GPIO4 | TX
GPIO5 | RX
The example could also run on a single SoC which supports both Wi-Fi and Thread (e.g., ESP32-C6), but since there is only one RF path in ESP32-C6, which means Wi-Fi and Thread can't receive simultaneously, it has a significant impact on performance. Hence the two SoCs solution is recommended.
#### **Ethernet based Thread Border Router**
Similar to the previous Wi-Fi based Thread Border Route setup, but a device with Ethernet interface is required, such as [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-ethernet-kit.html) or [ESP32-P4-Function-EV-Board](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html).
#### **ESP32-P4 using Wi-Fi Co-Processor**
This example can also be run using Wi-Fi using the ESP32-P4, which does not natively support Wi-Fi, by incorporating the ESP-Hosted component to enable Wi-Fi connectivity for the ESP32-P4 through a ESP32-C6 co-processor. You may refer to the [ESP-Hosted-MCU documentation](https://github.com/espressif/esp-hosted-mcu/blob/main/docs/esp32_p4_function_ev_board.md) for more information about ESP-Hosted.
If you are using the ESP32-P4-Function-EV-Board, you may refer to the [OpenThread Border Router Example](https://github.com/espressif/esp-thread-br/tree/main/examples/basic_thread_border_router) for running a Wi-Fi based Thread Border Router.
### Configure the project
```
idf.py menuconfig
```
OpenThread Command Line is enabled with UART as the default interface. Additionally, USB JTAG is also supported and can be activated through the menuconfig:
```
Component config → ESP System Settings → Channel for console output → USB Serial/JTAG Controller
```
In order to run the example on single SoC which supports both Wi-Fi and Thread, the option `CONFIG_ESP_COEX_SW_COEXIST_ENABLE` and option `CONFIG_OPENTHREAD_RADIO_NATIVE` should be enabled. The two options are enabled by default for ESP32-C6 target.
Two ways are provided to setup the Thread Border Router in this example:
- Auto Start
Enable `OPENTHREAD_BR_AUTO_START`, configure the `CONFIG_EXAMPLE_WIFI_SSID` and `CONFIG_EXAMPLE_WIFI_PASSWORD` with your access point's ssid and psk.
The device will connect to Wi-Fi and form a Thread network automatically after boot up.
- Manual mode
Disable `OPENTHREAD_BR_AUTO_START` and enable `OPENTHREAD_CLI_ESP_EXTENSION`. `wifi` command will be added for connecting the device to the Wi-Fi network.
If the `CONFIG_EXAMPLE_CONNECT_ETHERNET` option is enabled, the device will connect to `Ethernet`, form a Thread network and act as a Ethernet based Thread Border Router.
### Build, Flash, and Run
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT build flash monitor
```
If the `OPENTHREAD_BR_AUTO_START` option is enabled, The device will be connected to the configured Wi-Fi and Thread network automatically then act as the border router.
Otherwise, you need to manually configure the networks with CLI commands.
`wifi` command can be used to configure the Wi-Fi network.
```bash
> wifi
--wifi parameter---
connect
-s : wifi ssid
-p : wifi psk
---example---
join a wifi:
ssid: threadcertAP
psk: threadcertAP : wifi connect -s threadcertAP -p threadcertAP
state : get wifi state, disconnect or connect
---example---
get wifi state : wifi state
Done
```
To join a Wi-Fi network, please use the `wifi connect` command:
```bash
> wifi connect -s threadcertAP -p threadcertAP
ssid: threadcertAP
psk: threadcertAP
I (11331) wifi:wifi driver task: 3ffd06e4, prio:23, stack:6656, core=0
I (11331) system_api: Base MAC address is not set
I (11331) system_api: read default base MAC address from EFUSE
I (11341) wifi:wifi firmware version: 45c46a4
I (11341) wifi:wifi certification version: v7.0
..........
I (13741) esp_netif_handlers: sta ip: 192.168.3.10, mask: 255.255.255.0, gw: 192.168.3.1
W (13771) wifi:<ba-add>idx:0 (ifx:0, 02:0f:c1:32:3b:2b), tid:0, ssn:2, winSize:64
wifi sta is connected successfully
Done
```
To get the state of the Wi-Fi network:
```bash
> wifi state
connected
Done
```
For forming the Thread network, please refer to the [ot_cli_README](../ot_cli/README.md).
## Example Output
```bash
I (2729) esp_netif_handlers: example_connect: sta ip: 192.168.1.100, mask: 255.255.255.0, gw: 192.168.1.1
I (2729) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.1.100
I (3729) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:266f:28ff:fe80:2920, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (3729) example_connect: Connected to example_connect: sta
I (3739) example_connect: - IPv4 address: 192.168.1.100
I (3739) example_connect: - IPv6 address: fe80:0000:0000:0000:266f:28ff:fe80:2920, type: ESP_IP6_ADDR_IS_LINK_LOCAL
......
I(8139) OPENTHREAD:[INFO]-MLE-----: AttachState ParentReqReeds -> Idle
I(8139) OPENTHREAD:[NOTE]-MLE-----: Allocate router id 50
I(8139) OPENTHREAD:[NOTE]-MLE-----: RLOC16 fffe -> c800
I(8159) OPENTHREAD:[NOTE]-MLE-----: Role Detached -> Leader
```
## Bidirectional IPv6 connectivity
The border router will automatically publish the prefix and the route table rule to the Wi-Fi network via ICMPv6 router advertisement packages.
### Host configuration
The automatically configure your host's route table rules you need to set these sysctl options:
Please replace `wlan0` with the real name of your Wi-Fi network interface.
```
sudo sysctl -w net/ipv6/conf/wlan0/accept_ra=2
sudo sysctl -w net/ipv6/conf/wlan0/accept_ra_rt_info_max_plen=128
```
For mobile devices, the route table rules will be automatically configured after iOS 14 and Android 8.1.
### Testing IPv6 connectivity
Now in the Thread end device, check the IP addresses:
```
> ipaddr
fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5
fdde:ad00:beef:0:0:ff:fe00:c402
fdde:ad00:beef:0:ad4a:9a9a:3cd6:e423
fe80:0:0:0:f011:2951:569e:9c4a
```
You'll notice an IPv6 global prefix with only on address assigned under it. This is the routable address of this Thread node.
You can ping this address on your host:
``` bash
$ ping fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5
PING fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5(fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5) 56 data bytes
64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=1 ttl=63 time=459 ms
64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=2 ttl=63 time=109 ms
64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=3 ttl=63 time=119 ms
64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=4 ttl=63 time=117 ms
```
## Service discovery
The newly introduced service registration protocol([SRP](https://datatracker.ietf.org/doc/html/draft-ietf-dnssd-srp-10)) allows devices in the Thread network to register a service. The border router will forward the service to the Wi-Fi network via mDNS.
### Publish the service using SRP
Now we'll publish the service `my-service._test._udp` with hostname `test0` and port 12345
```
> srp client host name test0
Done
> srp client host address fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5
Done
> srp client service add my-service _test._udp 12345
Done
> srp client autostart enable
Done
```
This service will also become visible on the Wi-Fi network:
```bash
$ avahi-browse -r _test._udp -t
+ enp1s0 IPv6 my-service _test._udp local
= enp1s0 IPv6 my-service _test._udp local
hostname = [test0.local]
address = [fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5]
port = [12345]
txt = []
+ enp1s0 IPv4 my-service _test._udp local
= enp1s0 IPv4 my-service _test._udp local
hostname = [test0.local]
address = [fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5]
port = [12345]
txt = []
```
### Discovery delegate
First, the service `testhost._test._udp` need to be published using `avahi-publish-service` on the Wi-Fi network(for example Host).
```bash
$ avahi-publish-service testhost _test._udp 12345 test=1 dn="aabbbb"
```
Then get the border router's OMR prefix global unicast address(or ML-EID), and configure it on the Thread end device.
On the border router:
```
> ipaddr
fdde:ad00:beef:0:0:ff:fe00:fc10
fd9b:347f:93f7:1:1003:8f00:bcc1:3038
fdde:ad00:beef:0:0:ff:fe00:fc00
fdde:ad00:beef:0:0:ff:fe00:b800
fdde:ad00:beef:0:f891:287:866:776
fe80:0:0:0:77:bca6:6079:785b
Done
```
On the Thread end device:
```
> dns config fd9b:347f:93f7:1:1003:8f00:bcc1:3038
(or
> dns config fdde:ad00:beef:0:f891:287:866:776)
Done
```
Now the service published on the Host can be discovered on the Thread end device.
```
> dns resolve FA001208.default.service.arpa.
DNS response for FA001208.default.service.arpa. - fdde:ad00:beef:cafe:b939:26be:7516:b87e TTL:120
Done
> dns browse _test._udp.default.service.arpa.
DNS browse response for _test._udp.default.service.arpa.
testhost
Port:5683, Priority:0, Weight:0, TTL:120
Host:FA001208.default.service.arpa.
HostAddress:fdde:ad00:beef:cafe:b939:26be:7516:b87e TTL:120
TXT:[test=31, dn=616162626262] TTL:120
Done
> dns service testhost _test._udp.default.service.arpa.
DNS service resolution response for testhost for service _test._udp.default.service.arpa.
Port:5683, Priority:0, Weight:0, TTL:120
Host:FA001208.default.service.arpa.
HostAddress:fdde:ad00:beef:cafe:b939:26be:7516:b87e TTL:120
TXT:[test=31, dn=616162626262] TTL:120
Done
```

View File

@@ -0,0 +1,72 @@
dependencies:
espressif/esp_ot_cli_extension:
component_hash: 0720bca3c3d0b3ea33ee9c9830d51c4c25312cb2cf32408e681e12cd4539cfb1
dependencies:
- name: espressif/iperf
registry_url: https://components.espressif.com
require: private
version: ^0.1.0
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.3.5
espressif/iperf:
component_hash: f4c2beaae50478a626995130d2611c628b7a568cd0799022758c05658928410c
dependencies:
- name: idf
require: private
version: '>=4.3'
source:
registry_url: https://components.espressif.com
type: service
version: 0.1.4
espressif/led_strip:
component_hash: 28c6509a727ef74925b372ed404772aeedf11cce10b78c3f69b3c66799095e2d
dependencies:
- name: idf
require: private
version: '>=4.4'
source:
registry_url: https://components.espressif.com/
type: service
version: 2.5.5
espressif/mdns:
component_hash: 29e47564b1a7ee778135e17fbbf2a2773f71c97ebabfe626c8eda7c958a7ad16
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.9.1
idf:
source:
type: idf
version: 5.5.1
ot_led:
dependencies:
- name: espressif/led_strip
version: ^2.4.1
source:
path: C:\Users\Laurent\esp\v5.5.1\esp-idf\examples\openthread\ot_common_components\ot_led
type: local
version: '*'
protocol_examples_common:
dependencies: []
source:
path: C:\Users\Laurent\esp\v5.5.1\esp-idf\examples\common_components\protocol_examples_common
type: local
version: '*'
direct_dependencies:
- espressif/esp_ot_cli_extension
- espressif/mdns
- idf
- ot_led
- protocol_examples_common
manifest_hash: b321f20879c2db943f68f56bf58015445d174916b597518cabf177d0b1f03dc0
target: esp32h2
version: 2.0.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

View File

@@ -0,0 +1,4 @@
idf_component_register(SRCS "gps.c" "esp_ot_br.c"
PRIV_REQUIRES esp_psram openthread esp_coex esp_wifi nvs_flash
INCLUDE_DIRS "."
REQUIRES esp_http_client)

View File

@@ -0,0 +1,52 @@
menu "OpenThread Border Router Example"
config OPENTHREAD_BR_AUTO_START
bool 'Enable the automatic start mode in Thread Border Router.'
default n
help
If enabled, The Thread Border Router will connect to Wi-Fi with pre-configured
SSID and PSK, and then form a Thread network automatically. Otherwise, user need
to configure Wi-Fi and Thread manually.
config OPENTHREAD_SUPPORT_HW_RESET_RCP
bool 'Enable hardware RCP resetting'
default n
help
If enabled, the Thread Border Router will support hardware resetting the RCP
when processing RCP failure.
config OPENTHREAD_HW_RESET_RCP_PIN
int 'Pin to RCP reset'
depends on OPENTHREAD_SUPPORT_HW_RESET_RCP
default 7
menu "External coexist wire type and pin config"
config EXTERNAL_COEX_WIRE_TYPE
int "The wire_type of external coexist"
depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE
default 3
range 0 3
help
Select wire_type for external coexist, the wire_type define in external_coex_wire_t.
config EXTERNAL_COEX_REQUEST_PIN
int "The number of external coexist request pin"
depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 0)
default 0
config EXTERNAL_COEX_GRANT_PIN
int "The number of external coexist grant pin"
depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 1)
default 1
config EXTERNAL_COEX_PRIORITY_PIN
int "The number of external coexist priority pin"
depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE >= 2)
default 2
config EXTERNAL_COEX_TX_LINE_PIN
int "The number of external coexist tx_line pin"
depends on ESP_COEX_EXTERNAL_COEXIST_ENABLE && (EXTERNAL_COEX_WIRE_TYPE = 3)
default 3
endmenu # External coexist wire type and pin config
endmenu

View File

@@ -0,0 +1,227 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*
* OpenThread Border Router Example
*
* This example code is in the Public Domain (or CC0 licensed, at your option.)
*
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_check.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_openthread.h"
#include "esp_openthread_border_router.h"
#include "esp_openthread_cli.h"
#include "esp_openthread_lock.h"
#include "esp_openthread_netif_glue.h"
#include "esp_openthread_types.h"
#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
#include "esp_ot_cli_extension.h"
#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
#include "esp_ot_config.h"
#include "esp_ot_wifi_cmd.h"
#include "esp_vfs_dev.h"
#include "esp_vfs_eventfd.h"
#include "esp_wifi.h"
#include "mdns.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "hal/uart_types.h"
#include "openthread/error.h"
#include "openthread/logging.h"
#include "openthread/tasklet.h"
#include "gps.h"
#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE
#include "ot_led_strip.h"
#endif
#if CONFIG_OPENTHREAD_BR_AUTO_START
#include "example_common_private.h"
#include "protocol_examples_common.h"
#endif
#if !CONFIG_OPENTHREAD_BR_AUTO_START && CONFIG_EXAMPLE_CONNECT_ETHERNET
// TZ-1109: Add a menchanism for connecting ETH manually.
#error Currently we do not support a manual way to connect ETH, if you want to use ETH, please enable OPENTHREAD_BR_AUTO_START.
#endif
#define TAG "esp_ot_br"
#if CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP
#define PIN_TO_RCP_RESET CONFIG_OPENTHREAD_HW_RESET_RCP_PIN
static void rcp_failure_hardware_reset_handler(void)
{
gpio_config_t reset_pin_config;
memset(&reset_pin_config, 0, sizeof(reset_pin_config));
reset_pin_config.intr_type = GPIO_INTR_DISABLE;
reset_pin_config.pin_bit_mask = BIT(PIN_TO_RCP_RESET);
reset_pin_config.mode = GPIO_MODE_OUTPUT;
reset_pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
reset_pin_config.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&reset_pin_config);
gpio_set_level(PIN_TO_RCP_RESET, 0);
vTaskDelay(pdMS_TO_TICKS(10));
gpio_set_level(PIN_TO_RCP_RESET, 1);
vTaskDelay(pdMS_TO_TICKS(30));
gpio_reset_pin(PIN_TO_RCP_RESET);
}
#endif
#if CONFIG_EXTERNAL_COEX_ENABLE
static void ot_br_external_coexist_init(void)
{
esp_external_coex_gpio_set_t gpio_pin = ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG();
esp_external_coex_set_work_mode(EXTERNAL_COEX_LEADER_ROLE);
ESP_ERROR_CHECK(esp_enable_extern_coex_gpio_pin(CONFIG_EXTERNAL_COEX_WIRE_TYPE, gpio_pin));
}
#endif /* CONFIG_EXTERNAL_COEX_ENABLE */
static void ot_task_worker(void *aContext)
{
esp_openthread_platform_config_t config = {
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
};
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
esp_netif_t *openthread_netif = esp_netif_new(&cfg);
assert(openthread_netif != NULL);
// Initialize the OpenThread stack
ESP_ERROR_CHECK(esp_openthread_init(&config));
ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&config)));
esp_openthread_lock_acquire(portMAX_DELAY);
#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
// The OpenThread log level directly matches ESP log level
(void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL);
#endif // CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
#if CONFIG_OPENTHREAD_CLI
esp_openthread_cli_init();
#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
esp_cli_custom_command_init();
#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
esp_openthread_cli_create_task();
#endif // CONFIG_OPENTHREAD_CLI
esp_openthread_lock_release();
// Run the main loop
esp_openthread_launch_mainloop();
// Clean up
esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif);
esp_vfs_eventfd_unregister();
vTaskDelete(NULL);
}
void ot_br_init(void *ctx)
{
#if CONFIG_OPENTHREAD_CLI_WIFI
ESP_ERROR_CHECK(esp_ot_wifi_config_init());
#endif
#if CONFIG_OPENTHREAD_BR_AUTO_START
#if CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET
bool wifi_or_ethernet_connected = false;
#else
#error No backbone netif!
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI
char wifi_ssid[32] = "";
char wifi_password[64] = "";
if (esp_ot_wifi_config_get_ssid(wifi_ssid) == ESP_OK) {
ESP_LOGI(TAG, "use the Wi-Fi config from NVS");
esp_ot_wifi_config_get_password(wifi_password);
} else {
ESP_LOGI(TAG, "use the Wi-Fi config from Kconfig");
strcpy(wifi_ssid, CONFIG_EXAMPLE_WIFI_SSID);
strcpy(wifi_password, CONFIG_EXAMPLE_WIFI_PASSWORD);
}
if (esp_ot_wifi_connect(wifi_ssid, wifi_password) == ESP_OK) {
wifi_or_ethernet_connected = true;
} else {
ESP_LOGE(TAG, "Fail to connect to Wi-Fi, please try again manually");
}
#endif
#if CONFIG_EXAMPLE_CONNECT_ETHERNET
ESP_ERROR_CHECK(example_ethernet_connect());
wifi_or_ethernet_connected = true;
#endif
#endif // CONFIG_OPENTHREAD_BR_AUTO_START
#if CONFIG_EXTERNAL_COEX_ENABLE
ot_br_external_coexist_init();
#endif // CONFIG_EXTERNAL_COEX_ENABLE
ESP_ERROR_CHECK(mdns_init());
ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br"));
esp_openthread_lock_acquire(portMAX_DELAY);
#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE
ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance()));
#endif
#if CONFIG_OPENTHREAD_BR_AUTO_START
if (wifi_or_ethernet_connected) {
esp_openthread_set_backbone_netif(get_example_netif());
ESP_ERROR_CHECK(esp_openthread_border_router_init());
#if CONFIG_EXAMPLE_CONNECT_WIFI
esp_ot_wifi_border_router_init_flag_set(true);
#endif
otOperationalDatasetTlvs dataset;
otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset);
ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL));
} else {
ESP_LOGE(TAG, "Auto-start mode failed, please try to start manually");
}
#endif // CONFIG_OPENTHREAD_BR_AUTO_START
esp_openthread_lock_release();
vTaskDelete(NULL);
}
void app_main(void)
{
// Used eventfds:
// * netif
// * task queue
// * border router
size_t max_eventfd = 3;
#if CONFIG_OPENTHREAD_RADIO_NATIVE || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
// * radio driver (A native radio device needs a eventfd for radio driver.)
// * SpiSpinelInterface (The Spi Spinel Interface needs a eventfd.)
// The above will not exist at the same time.
max_eventfd++;
#endif
#if CONFIG_OPENTHREAD_RADIO_TREL
// * TREL reception (The Thread Radio Encapsulation Link needs a eventfd for reception.)
max_eventfd++;
#endif
esp_vfs_eventfd_config_t eventfd_config = {
.max_fds = max_eventfd,
};
ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
#if CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP
esp_openthread_register_rcp_failure_handler(rcp_failure_hardware_reset_handler);
#endif
xTaskCreate(ot_task_worker, "ot_br_main", 8192, xTaskGetCurrentTaskHandle(), 5, NULL);
xTaskCreate(ot_br_init, "ot_br_init", 6144, NULL, 4, NULL);
}

View File

@@ -0,0 +1,140 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*
* OpenThread Border Router Example
*
* This example code is in the Public Domain (or CC0 licensed, at your option.)
*
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#include "esp_coexist.h"
#include "esp_openthread_types.h"
#if CONFIG_OPENTHREAD_RADIO_NATIVE
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_NATIVE, \
}
#elif CONFIG_OPENTHREAD_RADIO_SPINEL_UART
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_UART_RCP, \
.radio_uart_config = { \
.port = 1, \
.uart_config = \
{ \
.baud_rate = 460800, \
.data_bits = UART_DATA_8_BITS, \
.parity = UART_PARITY_DISABLE, \
.stop_bits = UART_STOP_BITS_1, \
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \
.rx_flow_ctrl_thresh = 0, \
.source_clk = UART_SCLK_DEFAULT, \
}, \
.rx_pin = 4, \
.tx_pin = 5, \
}, \
}
#else
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_SPI_RCP, \
.radio_spi_config = { \
.host_device = SPI2_HOST, \
.dma_channel = 2, \
.spi_interface = \
{ \
.mosi_io_num = 11, \
.sclk_io_num = 12, \
.miso_io_num = 13, \
}, \
.spi_device = \
{ \
.cs_ena_pretrans = 2, \
.input_delay_ns = 100, \
.mode = 0, \
.clock_speed_hz = 2500 * 1000, \
.spics_io_num = 10, \
.queue_size = 5, \
}, \
.intr_pin = 8, \
}, \
}
#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
#if CONFIG_IDF_TARGET_ESP32C2 && CONFIG_XTAL_FREQ_26
#define HOST_BAUD_RATE 74880
#else
#define HOST_BAUD_RATE 115200
#endif
#if CONFIG_OPENTHREAD_CONSOLE_TYPE_UART
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
{ \
.host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \
.host_uart_config = { \
.port = 0, \
.uart_config = \
{ \
.baud_rate = HOST_BAUD_RATE, \
.data_bits = UART_DATA_8_BITS, \
.parity = UART_PARITY_DISABLE, \
.stop_bits = UART_STOP_BITS_1, \
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \
.rx_flow_ctrl_thresh = 0, \
.source_clk = UART_SCLK_DEFAULT, \
}, \
.rx_pin = UART_PIN_NO_CHANGE, \
.tx_pin = UART_PIN_NO_CHANGE, \
}, \
}
#elif CONFIG_OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
{ \
.host_connection_mode = HOST_CONNECTION_MODE_CLI_USB, \
.host_usb_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(), \
}
#endif
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
{ \
.storage_partition_name = "nvs", \
.netif_queue_size = 10, \
.task_queue_size = 10, \
}
#if CONFIG_EXTERNAL_COEX_ENABLE
#if CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_1
#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \
{ \
.request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \
}
#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_2
#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \
{ \
.request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \
.grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \
}
#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_3
#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \
{ \
.request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \
.priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \
.grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \
}
#elif CONFIG_EXTERNAL_COEX_WIRE_TYPE == EXTERNAL_COEXIST_WIRE_4
#define ESP_OPENTHREAD_DEFAULT_EXTERNAL_COEX_CONFIG() \
{ \
.request = CONFIG_EXTERNAL_COEX_REQUEST_PIN, \
.priority = CONFIG_EXTERNAL_COEX_PRIORITY_PIN, \
.grant = CONFIG_EXTERNAL_COEX_GRANT_PIN, \
.tx_line = CONFIG_EXTERNAL_COEX_TX_LINE_PIN, \
}
#endif
#endif // CONFIG_EXTERNAL_COEX_ENABLE

View File

@@ -0,0 +1,111 @@
#include "gps.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "esp_http_client.h"
#include <string.h>
#include <stdlib.h>
#define GPS_UART_NUM UART_NUM_1
#define GPS_TX_PIN 4
#define GPS_RX_PIN 5
#define BUF_SIZE 1024
static uint8_t gps_buffer[BUF_SIZE];
void init_gps() {
const uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(GPS_UART_NUM, &uart_config);
uart_set_pin(GPS_UART_NUM, GPS_TX_PIN, GPS_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(GPS_UART_NUM, BUF_SIZE, 0, 0, NULL, 0);
}
// Convertit NMEA "ddmm.mmmm" + N/S/E/W en degrés décimaux
double nmea_to_decimal(const char* nmea_coord, const char direction) {
double raw = atof(nmea_coord);
int degrees = (int)(raw / 100);
double minutes = raw - (degrees * 100);
double decimal = degrees + minutes / 60.0;
if (direction == 'S' || direction == 'W') decimal = -decimal;
return decimal;
}
char* gps_to_json(char* gps_data) {
static char json[128];
double latitude = 0.0;
double longitude = 0.0;
if (gps_data && strncmp(gps_data, "$GPGGA,", 7) == 0) {
char* fields[15];
int i = 0;
char gps_copy[BUF_SIZE];
strncpy(gps_copy, gps_data, BUF_SIZE - 1);
gps_copy[BUF_SIZE - 1] = '\0';
char* token = strtok(gps_copy, ",");
while (token && i < 15) {
fields[i++] = token;
token = strtok(NULL, ",");
}
if (i >= 6 && fields[2][0] != '\0' && fields[4][0] != '\0') {
latitude = nmea_to_decimal(fields[2], fields[3][0]);
longitude = nmea_to_decimal(fields[4], fields[5][0]);
}
}
// Créer le JSON avec des valeurs valides même si GPS pas fixé
snprintf(json, sizeof(json), "{\"data\":{\"latitude\":%.6f,\"longitude\":%.6f}}",
latitude, longitude);
return json;
}
char* read_gps() {
int len = uart_read_bytes(GPS_UART_NUM, gps_buffer, BUF_SIZE - 1, 100 / portTICK_PERIOD_MS);
if (len > 0) {
gps_buffer[len] = '\0';
return (char*)gps_buffer;
}
return NULL;
}
void send_gps_data(const char* server_url, const char* json)
{
if (!json) return;
ESP_LOGI(TAG, "Sending JSON: %s", json);
esp_http_client_config_t config = { .url = server_url };
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_method(client, HTTP_METHOD_POST);
esp_http_client_set_post_field(client, json, strlen(json));
esp_http_client_set_header(client, "Content-Type", "application/json");
esp_http_client_perform(client);
esp_http_client_cleanup(client);
}
void send_position_task(void *pvParameters)
{
const char* position_endpoint = "http://192.168.15.117:5000/devices/notify-position";
while (1) {
char* json;
char* raw_data = read_gps();
if (raw_data) {
char* json = gps_to_json(raw_data);
send_gps_data(position_endpoint, json);
} else {
ESP_LOGI(TAG, "NO GPS DATA");
}
vTaskDelay(25000 / portTICK_PERIOD_MS);
}
}

View File

@@ -0,0 +1,11 @@
#include "driver/uart.h"
#define GPS_UART_NUM UART_NUM_1
#define GPS_TX_PIN 4
#define GPS_RX_PIN 5
void init_gps(void);
char* read_gps(void);
char* gps_to_json(char* gps_data);
void send_gps_data(const char* server_url, const char* json);
void send_position_task(void *pvParameters);

View File

@@ -0,0 +1,12 @@
## IDF Component Manager Manifest File
dependencies:
espressif/esp_ot_cli_extension:
version: "~1.3.0"
espressif/mdns: "^1.0.3"
## Required IDF version
idf:
version: ">=5.0"
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
ot_led:
path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led

View File

@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1900K,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1900K,

View File

@@ -0,0 +1,2 @@
CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP=y
CONFIG_OPENTHREAD_HW_RESET_RCP_PIN=6

View File

@@ -0,0 +1 @@
CONFIG_OPENTHREAD_BR_LIB_CHECK=y

View File

@@ -0,0 +1,3 @@
CONFIG_OPENTHREAD_RADIO_SPINEL_SPI=y
CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP=y
CONFIG_OPENTHREAD_HW_RESET_RCP_PIN=7

View File

@@ -0,0 +1,2 @@
CONFIG_EXTERNAL_COEX_ENABLE=y
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n

View File

@@ -0,0 +1,2 @@
CONFIG_OPENTHREAD_RADIO_NATIVE=y
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y

View File

@@ -0,0 +1 @@
CONFIG_OPENTHREAD_RADIO_TREL=y

View File

@@ -0,0 +1,2 @@
CONFIG_OPENTHREAD_RADIO_TREL=y
CONFIG_EXTERNAL_COEX_ENABLE=y

View File

@@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_TARGET_ESP32S3=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_OPENTHREAD_PLATFORM_MALLOC_CAP_SPIRAM=y
CONFIG_OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT=y

View File

@@ -0,0 +1,57 @@
#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
# end of Partition Table
#
# mbedTLS
#
CONFIG_MBEDTLS_CMAC_C=y
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y
# end of TLS Key Exchange Methods
CONFIG_MBEDTLS_ECJPAKE_C=y
# end of mbedTLS
#
# OpenThread
#
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_BORDER_ROUTER=y
CONFIG_OPENTHREAD_RADIO_SPINEL_UART=y
# end of OpenThread
#
# lwIP
#
CONFIG_LWIP_IPV6_FORWARD=y
CONFIG_LWIP_IPV6_NUM_ADDRESSES=12
CONFIG_LWIP_MULTICAST_PING=y
CONFIG_LWIP_NETIF_STATUS_CALLBACK=y
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM=y
CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y
CONFIG_LWIP_IPV6_AUTOCONFIG=y
# end of lwIP
#
# mDNS
#
CONFIG_MDNS_MULTIPLE_INSTANCE=y
# end of mDNS
# Example connect
CONFIG_EXAMPLE_CONNECT_THREAD=n
#
# ESP System Settings
#
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3584
# end of ESP System Settings

View File

@@ -0,0 +1,6 @@
# Enable BR auto start for Ethernet builds
CONFIG_OPENTHREAD_BR_AUTO_START=y
# Enable PPP support as a workaround to ensure LWIP thread-lib compatibility for Ethernet builds
CONFIG_LWIP_PPP_SUPPORT=y
CONFIG_LWIP_PPP_SERVER_SUPPORT=y

View File

@@ -0,0 +1,12 @@
#
# ESP PSRAM
#
CONFIG_SPIRAM=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
# end of ESP PSRAM
#
# OpenThread
#
CONFIG_OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT=y
# end of OpenThread