Я пытаюсь создать пограничный маршрутизатор Openthread, используя ESP32S3 в качестве хоста и ESP32H2 в качестве радиомодема.
Я использовал ESP32C6 с ot-cli для имитации соединения.
Я могу подключить оба, используя один и тот же набор данных, но не могу «автоматически подключиться» с помощью соединения.
Если я вручную устанавливаю panid, канал и сетевой ключ, все работает хорошо.
Я получаю это регистрируется в моем BR:
I (34569) esp_ot_br: Role attached (4) → start Commissioner
I(34569) OPENTHREAD: Commissioner--: Sent LeaderPetition
I(34579) OPENTHREAD: Commissioner--: State: disabled -> petition
I (34579) esp_ot_br: Commissioner petitioning for network leader
I(34579) OPENTHREAD: Commissioner--: start commissioner OpenThread Commissioner
I (34579) esp_ot_br: otCommissionerStart -> 0
I(34579) OPENTHREAD: MeshCoPLeader-: Received LeaderPetition
I(34579) OPENTHREAD: MeshCoPLeader-: Sent LeaderPetition response
I(34579) OPENTHREAD: Commissioner--: Received LeaderPetition response
I(34579) OPENTHREAD: Commissioner--: State: petition -> active
I (34589) esp_ot_br: Commissioner active (window 600s)
I(34589) OPENTHREAD: Commissioner--: Sent CommissionerSet to leader
I(34589) OPENTHREAD: Commissioner--: Added Joiner (any, J01NME)
I (34589) esp_ot_br: CommissionerAddJoiner -> 0
I(35089) OPENTHREAD: Commissioner--: Sent CommissionerSet to leader
I(35089) OPENTHREAD:[I] Commissioner--: Added Joiner (any, J01NME)
I (35089) esp_ot_br: Re-sent CommissionerAddJoiner -> 0
I(35089) OPENTHREAD:[I] NetworkData---: Sent CommissionerSet response
Мой комиссионер кажется в порядке, но я получаю сообщение «Ошибка присоединения» после отправки joiner start J01NME с помощью joiner... иногда по таймауту, иногда не найден.
Вот мой код, развернутый на ESP32S3, с комиссионером:
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems
* SPDX-License-Identifier: Apache-2.0
*/
#include
#include
#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 "openthread/dataset.h"
#include "openthread/commissioner.h"
#include "openthread/joiner.h"
#include "openthread/coap.h"
#include "openthread/coap_secure.h"
#include "esp_openthread_types.h"
#include "esp_openthread_netif_glue.h"
#include "esp_openthread_lock.h"
#include "esp_ot_config.h"
#include "esp_ot_ota_commands.h"
#include "esp_ot_wifi_cmd.h"
#include "esp_spiffs.h"
#include "esp_vfs_eventfd.h"
#include "mdns.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "openthread/logging.h"
#define TAG "esp_ot_br"
/* -------------------------------------------------------------------------- */
/* OpenThread Platform Config */
/* -------------------------------------------------------------------------- */
static esp_openthread_platform_config_t s_openthread_platform_config = {
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
};
/* -------------------------------------------------------------------------- */
/* CoAP Simple Resource */
/* -------------------------------------------------------------------------- */
static void coap_handle_test(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo)
{
otInstance *ins = (otInstance *)aContext;
otCoapCode code = otCoapMessageGetCode(aMessage);
bool isGet = (code == OT_COAP_CODE_GET);
ESP_LOGI(TAG, "CoAP %s /test from [%02x%02x:%02x%02x:...]", isGet ? "GET" : "REQ",
aMsgInfo->mPeerAddr.mFields.m8[0], aMsgInfo->mPeerAddr.mFields.m8[1],
aMsgInfo->mPeerAddr.mFields.m8[2], aMsgInfo->mPeerAddr.mFields.m8[3]);
if (isGet) {
otMessage *resp = otCoapNewMessage(ins, NULL);
if (resp) {
otCoapMessageInitResponse(resp, aMessage,
OT_COAP_TYPE_NON_CONFIRMABLE,
OT_COAP_CODE_CONTENT);
otCoapMessageAppendContentFormatOption(resp, OT_COAP_OPTION_CONTENT_FORMAT_TEXT_PLAIN);
// ➜ marqueur de payload
otCoapMessageSetPayloadMarker(resp);
const char *payload = "hello-from-esp32-s3";
otMessageAppend(resp, payload, strlen(payload));
otError err = otCoapSendResponse(ins, resp, aMsgInfo);
ESP_LOGI(TAG, "CoAP /test response -> %d", err);
if (err != OT_ERROR_NONE) otMessageFree(resp);
}
}
}
static void coap_response_handler(void *aContext, otMessage *aMessage,
const otMessageInfo *aMessageInfo, otError aResult)
{
if (aResult == OT_ERROR_NONE) {
char payload[64] = {0};
otMessageRead(aMessage, otMessageGetOffset(aMessage), payload, sizeof(payload) - 1);
ESP_LOGI("COAP_CLIENT", "Response from [%x:%x:%x:%x]: %s",
aMessageInfo->mPeerAddr.mFields.m16[0],
aMessageInfo->mPeerAddr.mFields.m16[1],
aMessageInfo->mPeerAddr.mFields.m16[2],
aMessageInfo->mPeerAddr.mFields.m16[3],
payload);
} else {
ESP_LOGW("COAP_CLIENT", "Request failed: %d", aResult);
}
}
void coap_send_get_to_joiner(otInstance *ins, const char *addr_str)
{
otMessageInfo msgInfo;
otMessage *msg;
otError error;
otIp6Address destAddr;
memset(&msgInfo, 0, sizeof(msgInfo));
otIp6AddressFromString(addr_str, &destAddr);
msgInfo.mPeerAddr = destAddr;
msgInfo.mPeerPort = OT_DEFAULT_COAP_PORT;
msg = otCoapNewMessage(ins, NULL);
otCoapMessageInit(msg, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_GET);
otCoapMessageGenerateToken(msg, 2);
otCoapMessageAppendUriPathOptions(msg, "test");
otCoapMessageSetPayloadMarker(msg);
error = otCoapSendRequest(ins, msg, &msgInfo, coap_response_handler, NULL);
ESP_LOGI("COAP_CLIENT", "CoAP GET sent to %s -> %d", addr_str, error);
}
static otCoapResource s_coap_test_resource = {
.mUriPath = "test",
.mHandler = coap_handle_test,
.mContext = NULL,
.mNext = NULL,
};
static void log_active_dataset(otInstance *instance)
{
otOperationalDataset dataset;
otError error;
esp_openthread_lock_acquire(portMAX_DELAY);
error = otDatasetGetActive(instance, &dataset);
esp_openthread_lock_release();
if (error != OT_ERROR_NONE) {
ESP_LOGW(TAG, "No active dataset found (error %d)", error);
return;
}
ESP_LOGI(TAG, "------ Active Dataset ------");
ESP_LOGI(TAG, "Channel: %d", dataset.mChannel);
ESP_LOGI(TAG, "PAN ID: 0x%04X", dataset.mPanId);
ESP_LOGI(TAG, "Network Name: %s", dataset.mNetworkName.m8);
char buf[OT_EXT_PAN_ID_SIZE * 2 + 1] = {0};
for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++)
sprintf(&buf[i * 2], "%02X", dataset.mExtendedPanId.m8[i]);
ESP_LOGI(TAG, "Extended PAN ID: %s", buf);
buf[0] = 0;
for (int i = 0; i < OT_PSKC_MAX_SIZE; i++)
sprintf(&buf[i * 2], "%02X", dataset.mPskc.m8[i]);
ESP_LOGI(TAG, "PSKc: %s", buf);
buf[0] = 0;
for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++)
sprintf(&buf[i * 2], "%02X", dataset.mNetworkKey.m8[i]);
ESP_LOGI(TAG, "Network Key: %s", buf);
ESP_LOGI(TAG, "-----------------------------");
}
/* -------------------------------------------------------------------------- */
/* Commissioner Callbacks */
/* -------------------------------------------------------------------------- */
static void commissioner_state_cb(otCommissionerState aState, void *aContext)
{
otInstance *ins = (otInstance *)aContext;
switch (aState) {
case OT_COMMISSIONER_STATE_DISABLED:
ESP_LOGI(TAG, "Commissioner disabled");
break;
case OT_COMMISSIONER_STATE_PETITION:
ESP_LOGI(TAG, "Commissioner petitioning for network leader");
break;
case OT_COMMISSIONER_STATE_ACTIVE:
ESP_LOGI(TAG, "Commissioner active (window 600s)");
esp_openthread_lock_acquire(portMAX_DELAY);
{
otError e = otCommissionerAddJoiner(ins, NULL, "J01NME", 600);
ESP_LOGI(TAG, "CommissionerAddJoiner -> %d", e);
}
esp_openthread_lock_release();
vTaskDelay(pdMS_TO_TICKS(500));
esp_openthread_lock_acquire(portMAX_DELAY);
{
// Reforcer la mise à jour du CommissionerSet vers le Leader
otError e2 = otCommissionerAddJoiner(ins, NULL, "J01NME", 600);
ESP_LOGI(TAG, "Re-sent CommissionerAddJoiner -> %d", e2);
}
esp_openthread_lock_release();
break;
}
}
static void commissioner_joiner_cb(otCommissionerJoinerEvent aEvent,
const otJoinerInfo *aJoinerInfo,
const otExtAddress *aJoinerId,
void *aContext)
{
char eui64_str[OT_EXT_ADDRESS_SIZE * 2 + 1] = {0};
if (aJoinerId) {
for (int i = 0; i < OT_EXT_ADDRESS_SIZE; i++) {
sprintf(&eui64_str[i * 2], "%02X", aJoinerId->m8[i]);
}
}
switch (aEvent) {
case OT_COMMISSIONER_JOINER_CONNECTED:
ESP_LOGI(TAG, "Joiner connected: %s", eui64_str);
break;
case OT_COMMISSIONER_JOINER_FINALIZE:
ESP_LOGI(TAG, "Joiner finalize: %s", eui64_str);
break;
case OT_COMMISSIONER_JOINER_START:
ESP_LOGI(TAG, "Joiner start: %s", eui64_str);
break;
default:
ESP_LOGW(TAG, "Joiner event %d for %s", aEvent, eui64_str);
}
}
/* -------------------------------------------------------------------------- */
/* State Change Callback */
/* -------------------------------------------------------------------------- */
static void state_changed_cb(otChangedFlags flags, void *ctx)
{
static bool s_commissioner_started = false;
if ((flags & OT_CHANGED_THREAD_ROLE) && !s_commissioner_started) {
otInstance *ins = (otInstance *)ctx;
esp_openthread_lock_acquire(portMAX_DELAY);
otDeviceRole r = otThreadGetDeviceRole(ins);
esp_openthread_lock_release();
if (r == OT_DEVICE_ROLE_LEADER || r == OT_DEVICE_ROLE_ROUTER) {
ESP_LOGI(TAG, "Role attached (%d) → start Commissioner", r);
ESP_LOGI(TAG, "Current channel: %d", otLinkGetChannel(ins));
esp_openthread_lock_acquire(portMAX_DELAY);
otError e = otCommissionerStart(ins, commissioner_state_cb, commissioner_joiner_cb, ins);
esp_openthread_lock_release();
ESP_LOGI(TAG, "otCommissionerStart -> %d", e);
if (e == OT_ERROR_NONE) s_commissioner_started = true;
}
}
}
/* -------------------------------------------------------------------------- */
/* OpenThread Worker */
/* -------------------------------------------------------------------------- */
static void ot_task_worker(void *ctx)
{
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
esp_netif_t *openthread_netif = esp_netif_new(&cfg);
assert(openthread_netif != NULL);
ESP_ERROR_CHECK(esp_openthread_init(&s_openthread_platform_config));
// ESP_ERROR_CHECK(esp_openthread_border_router_init()); // enable BR services
esp_openthread_lock_acquire(portMAX_DELAY);
ESP_ERROR_CHECK(esp_netif_attach(openthread_netif,
esp_openthread_netif_glue_init(&s_openthread_platform_config)));
esp_openthread_lock_release();
otInstance *instance = esp_openthread_get_instance();
/* Clean start */
esp_openthread_lock_acquire(portMAX_DELAY);
(void)otThreadSetEnabled(instance, false);
(void)otIp6SetEnabled(instance, false);
esp_openthread_lock_release();
/* Dataset setup */
esp_openthread_lock_acquire(portMAX_DELAY);
otOperationalDataset dataset;
otError ds_ret = otDatasetGetActive(instance, &dataset);
esp_openthread_lock_release();
if (ds_ret != OT_ERROR_NONE) {
ESP_LOGW(TAG, "No active dataset, creating new one…");
otOperationalDataset ds = {0};
ds.mActiveTimestamp.mSeconds = 1;
ds.mChannel = 11;
ds.mPanId = 0x2345;
static const uint8_t xpan[OT_EXT_PAN_ID_SIZE] =
{0xDE,0xAD,0xBE,0xEF,0x00,0x11,0x22,0x33};
memcpy(ds.mExtendedPanId.m8, xpan, OT_EXT_PAN_ID_SIZE);
const char *networkName = "BEE_AGD";
strncpy((char *)ds.mNetworkName.m8, networkName, sizeof(ds.mNetworkName.m8)-1);
static const uint8_t nwkKey[OT_NETWORK_KEY_SIZE] =
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
memcpy(ds.mNetworkKey.m8, nwkKey, OT_NETWORK_KEY_SIZE);
otIp6NetworkPrefix mlp = {.m8={0xfd,0x00,0xca,0xfe,0xba,0xbe,0x00,0x00}};
memcpy(ds.mMeshLocalPrefix.m8, mlp.m8, OT_MESH_LOCAL_PREFIX_SIZE);
const char *passphrase = "C0mm-Pass";
otPskc pskc;
esp_openthread_lock_acquire(portMAX_DELAY);
otError e_pskc = otDatasetGeneratePskc(passphrase, &ds.mNetworkName,
&ds.mExtendedPanId, &pskc);
if (e_pskc == OT_ERROR_NONE) {
memcpy(&ds.mPskc, &pskc, sizeof(pskc));
ds.mComponents.mIsPskcPresent = true;
}
esp_openthread_lock_release();
ds.mComponents.mIsActiveTimestampPresent = true;
ds.mComponents.mIsChannelPresent = true;
ds.mComponents.mIsPanIdPresent = true;
ds.mComponents.mIsExtendedPanIdPresent = true;
ds.mComponents.mIsNetworkNamePresent = true;
ds.mComponents.mIsNetworkKeyPresent = true;
ds.mComponents.mIsMeshLocalPrefixPresent = true;
esp_openthread_lock_acquire(portMAX_DELAY);
otError err = otDatasetSetActive(instance, &ds);
esp_openthread_lock_release();
if (err != OT_ERROR_NONE)
ESP_LOGE(TAG, "Failed to set active dataset: %d", err);
}
log_active_dataset(instance);
/* Log dataset info */
esp_openthread_lock_acquire(portMAX_DELAY);
bool commissioned = otDatasetIsCommissioned(instance);
otLinkModeConfig lm = otThreadGetLinkMode(instance);
esp_openthread_lock_release();
ESP_LOGI(TAG, "Dataset commissioned: %s", commissioned ? "YES" : "NO");
ESP_LOGI(TAG, "LinkMode: rx=%d, devType=%d, netData=%d",
lm.mRxOnWhenIdle, lm.mDeviceType, lm.mNetworkData);
esp_openthread_lock_acquire(portMAX_DELAY);
otSetStateChangedCallback(instance, state_changed_cb, instance);
esp_openthread_lock_release();
/* Enable IPv6 + Thread */
esp_openthread_lock_acquire(portMAX_DELAY);
ESP_ERROR_CHECK(otIp6SetEnabled(instance, true));
vTaskDelay(pdMS_TO_TICKS(100));
otError e_th = otThreadSetEnabled(instance, true);
esp_openthread_lock_release();
if (e_th == OT_ERROR_NONE)
ESP_LOGI(TAG, "Thread starting…");
else
ESP_LOGE(TAG, "Failed to enable Thread: %d", e_th);
/* --------------------- CoAP server start ---------------------- */
esp_openthread_lock_acquire(portMAX_DELAY);
otError e1 = otCoapStart(instance, OT_DEFAULT_COAP_PORT);
if (e1 == OT_ERROR_NONE) {
s_coap_test_resource.mContext = instance;
otCoapAddResource(instance, &s_coap_test_resource);
ESP_LOGI(TAG, "CoAP server up on /test (udp/5683)");
} else {
ESP_LOGE(TAG, "otCoapStart failed: %d", e1);
}
esp_openthread_lock_release();
/* --------------------------------------------------------------- */
ESP_LOGI(TAG, "Mainloop start");
esp_openthread_launch_mainloop();
}
/* -------------------------------------------------------------------------- */
/* app_main */
/* -------------------------------------------------------------------------- */
void app_main(void)
{
esp_vfs_eventfd_config_t eventfd_config = {.max_fds = 3};
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());
ESP_ERROR_CHECK(mdns_init());
ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br"));
/* 12k stack for OT mainloop */
xTaskCreate(ot_task_worker, "ot_br_main", 12288, NULL, 5, NULL);
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... openthread
Пограничный маршрутизатор ESP32 с открытой резьбой ⇐ C++
Программы на C++. Форум разработчиков
-
Anonymous
1761145047
Anonymous
Я пытаюсь создать пограничный маршрутизатор Openthread, используя ESP32S3 в качестве хоста и ESP32H2 в качестве радиомодема.
Я использовал ESP32C6 с ot-cli для имитации соединения.
Я могу подключить оба, используя один и тот же набор данных, но не могу «автоматически подключиться» с помощью соединения.
Если я вручную устанавливаю panid, канал и сетевой ключ, все работает хорошо.
Я получаю это регистрируется в моем BR:
I (34569) esp_ot_br: Role attached (4) → start Commissioner
I(34569) OPENTHREAD:[I] Commissioner--: Sent LeaderPetition
I(34579) OPENTHREAD:[I] Commissioner--: State: disabled -> petition
I (34579) esp_ot_br: Commissioner petitioning for network leader
I(34579) OPENTHREAD:[I] Commissioner--: start commissioner OpenThread Commissioner
I (34579) esp_ot_br: otCommissionerStart -> 0
I(34579) OPENTHREAD:[I] MeshCoPLeader-: Received LeaderPetition
I(34579) OPENTHREAD:[I] MeshCoPLeader-: Sent LeaderPetition response
I(34579) OPENTHREAD:[I] Commissioner--: Received LeaderPetition response
I(34579) OPENTHREAD:[I] Commissioner--: State: petition -> active
I (34589) esp_ot_br: Commissioner active (window 600s)
I(34589) OPENTHREAD:[I] Commissioner--: Sent CommissionerSet to leader
I(34589) OPENTHREAD:[I] Commissioner--: Added Joiner (any, J01NME)
I (34589) esp_ot_br: CommissionerAddJoiner -> 0
I(35089) OPENTHREAD:[I] Commissioner--: Sent CommissionerSet to leader
I(35089) OPENTHREAD:[I] Commissioner--: Added Joiner (any, J01NME)
I (35089) esp_ot_br: Re-sent CommissionerAddJoiner -> 0
I(35089) OPENTHREAD:[I] NetworkData---: Sent CommissionerSet response
Мой комиссионер кажется в порядке, но я получаю сообщение «Ошибка присоединения» после отправки joiner start J01NME с помощью joiner... иногда по таймауту, иногда не найден.
Вот мой код, развернутый на ESP32S3, с комиссионером:
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems
* SPDX-License-Identifier: Apache-2.0
*/
#include
#include
#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 "openthread/dataset.h"
#include "openthread/commissioner.h"
#include "openthread/joiner.h"
#include "openthread/coap.h"
#include "openthread/coap_secure.h"
#include "esp_openthread_types.h"
#include "esp_openthread_netif_glue.h"
#include "esp_openthread_lock.h"
#include "esp_ot_config.h"
#include "esp_ot_ota_commands.h"
#include "esp_ot_wifi_cmd.h"
#include "esp_spiffs.h"
#include "esp_vfs_eventfd.h"
#include "mdns.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "openthread/logging.h"
#define TAG "esp_ot_br"
/* -------------------------------------------------------------------------- */
/* OpenThread Platform Config */
/* -------------------------------------------------------------------------- */
static esp_openthread_platform_config_t s_openthread_platform_config = {
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
};
/* -------------------------------------------------------------------------- */
/* CoAP Simple Resource */
/* -------------------------------------------------------------------------- */
static void coap_handle_test(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo)
{
otInstance *ins = (otInstance *)aContext;
otCoapCode code = otCoapMessageGetCode(aMessage);
bool isGet = (code == OT_COAP_CODE_GET);
ESP_LOGI(TAG, "CoAP %s /test from [%02x%02x:%02x%02x:...]", isGet ? "GET" : "REQ",
aMsgInfo->mPeerAddr.mFields.m8[0], aMsgInfo->mPeerAddr.mFields.m8[1],
aMsgInfo->mPeerAddr.mFields.m8[2], aMsgInfo->mPeerAddr.mFields.m8[3]);
if (isGet) {
otMessage *resp = otCoapNewMessage(ins, NULL);
if (resp) {
otCoapMessageInitResponse(resp, aMessage,
OT_COAP_TYPE_NON_CONFIRMABLE,
OT_COAP_CODE_CONTENT);
otCoapMessageAppendContentFormatOption(resp, OT_COAP_OPTION_CONTENT_FORMAT_TEXT_PLAIN);
// ➜ marqueur de payload
otCoapMessageSetPayloadMarker(resp);
const char *payload = "hello-from-esp32-s3";
otMessageAppend(resp, payload, strlen(payload));
otError err = otCoapSendResponse(ins, resp, aMsgInfo);
ESP_LOGI(TAG, "CoAP /test response -> %d", err);
if (err != OT_ERROR_NONE) otMessageFree(resp);
}
}
}
static void coap_response_handler(void *aContext, otMessage *aMessage,
const otMessageInfo *aMessageInfo, otError aResult)
{
if (aResult == OT_ERROR_NONE) {
char payload[64] = {0};
otMessageRead(aMessage, otMessageGetOffset(aMessage), payload, sizeof(payload) - 1);
ESP_LOGI("COAP_CLIENT", "Response from [%x:%x:%x:%x]: %s",
aMessageInfo->mPeerAddr.mFields.m16[0],
aMessageInfo->mPeerAddr.mFields.m16[1],
aMessageInfo->mPeerAddr.mFields.m16[2],
aMessageInfo->mPeerAddr.mFields.m16[3],
payload);
} else {
ESP_LOGW("COAP_CLIENT", "Request failed: %d", aResult);
}
}
void coap_send_get_to_joiner(otInstance *ins, const char *addr_str)
{
otMessageInfo msgInfo;
otMessage *msg;
otError error;
otIp6Address destAddr;
memset(&msgInfo, 0, sizeof(msgInfo));
otIp6AddressFromString(addr_str, &destAddr);
msgInfo.mPeerAddr = destAddr;
msgInfo.mPeerPort = OT_DEFAULT_COAP_PORT;
msg = otCoapNewMessage(ins, NULL);
otCoapMessageInit(msg, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_GET);
otCoapMessageGenerateToken(msg, 2);
otCoapMessageAppendUriPathOptions(msg, "test");
otCoapMessageSetPayloadMarker(msg);
error = otCoapSendRequest(ins, msg, &msgInfo, coap_response_handler, NULL);
ESP_LOGI("COAP_CLIENT", "CoAP GET sent to %s -> %d", addr_str, error);
}
static otCoapResource s_coap_test_resource = {
.mUriPath = "test",
.mHandler = coap_handle_test,
.mContext = NULL,
.mNext = NULL,
};
static void log_active_dataset(otInstance *instance)
{
otOperationalDataset dataset;
otError error;
esp_openthread_lock_acquire(portMAX_DELAY);
error = otDatasetGetActive(instance, &dataset);
esp_openthread_lock_release();
if (error != OT_ERROR_NONE) {
ESP_LOGW(TAG, "No active dataset found (error %d)", error);
return;
}
ESP_LOGI(TAG, "------ Active Dataset ------");
ESP_LOGI(TAG, "Channel: %d", dataset.mChannel);
ESP_LOGI(TAG, "PAN ID: 0x%04X", dataset.mPanId);
ESP_LOGI(TAG, "Network Name: %s", dataset.mNetworkName.m8);
char buf[OT_EXT_PAN_ID_SIZE * 2 + 1] = {0};
for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++)
sprintf(&buf[i * 2], "%02X", dataset.mExtendedPanId.m8[i]);
ESP_LOGI(TAG, "Extended PAN ID: %s", buf);
buf[0] = 0;
for (int i = 0; i < OT_PSKC_MAX_SIZE; i++)
sprintf(&buf[i * 2], "%02X", dataset.mPskc.m8[i]);
ESP_LOGI(TAG, "PSKc: %s", buf);
buf[0] = 0;
for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++)
sprintf(&buf[i * 2], "%02X", dataset.mNetworkKey.m8[i]);
ESP_LOGI(TAG, "Network Key: %s", buf);
ESP_LOGI(TAG, "-----------------------------");
}
/* -------------------------------------------------------------------------- */
/* Commissioner Callbacks */
/* -------------------------------------------------------------------------- */
static void commissioner_state_cb(otCommissionerState aState, void *aContext)
{
otInstance *ins = (otInstance *)aContext;
switch (aState) {
case OT_COMMISSIONER_STATE_DISABLED:
ESP_LOGI(TAG, "Commissioner disabled");
break;
case OT_COMMISSIONER_STATE_PETITION:
ESP_LOGI(TAG, "Commissioner petitioning for network leader");
break;
case OT_COMMISSIONER_STATE_ACTIVE:
ESP_LOGI(TAG, "Commissioner active (window 600s)");
esp_openthread_lock_acquire(portMAX_DELAY);
{
otError e = otCommissionerAddJoiner(ins, NULL, "J01NME", 600);
ESP_LOGI(TAG, "CommissionerAddJoiner -> %d", e);
}
esp_openthread_lock_release();
vTaskDelay(pdMS_TO_TICKS(500));
esp_openthread_lock_acquire(portMAX_DELAY);
{
// Reforcer la mise à jour du CommissionerSet vers le Leader
otError e2 = otCommissionerAddJoiner(ins, NULL, "J01NME", 600);
ESP_LOGI(TAG, "Re-sent CommissionerAddJoiner -> %d", e2);
}
esp_openthread_lock_release();
break;
}
}
static void commissioner_joiner_cb(otCommissionerJoinerEvent aEvent,
const otJoinerInfo *aJoinerInfo,
const otExtAddress *aJoinerId,
void *aContext)
{
char eui64_str[OT_EXT_ADDRESS_SIZE * 2 + 1] = {0};
if (aJoinerId) {
for (int i = 0; i < OT_EXT_ADDRESS_SIZE; i++) {
sprintf(&eui64_str[i * 2], "%02X", aJoinerId->m8[i]);
}
}
switch (aEvent) {
case OT_COMMISSIONER_JOINER_CONNECTED:
ESP_LOGI(TAG, "Joiner connected: %s", eui64_str);
break;
case OT_COMMISSIONER_JOINER_FINALIZE:
ESP_LOGI(TAG, "Joiner finalize: %s", eui64_str);
break;
case OT_COMMISSIONER_JOINER_START:
ESP_LOGI(TAG, "Joiner start: %s", eui64_str);
break;
default:
ESP_LOGW(TAG, "Joiner event %d for %s", aEvent, eui64_str);
}
}
/* -------------------------------------------------------------------------- */
/* State Change Callback */
/* -------------------------------------------------------------------------- */
static void state_changed_cb(otChangedFlags flags, void *ctx)
{
static bool s_commissioner_started = false;
if ((flags & OT_CHANGED_THREAD_ROLE) && !s_commissioner_started) {
otInstance *ins = (otInstance *)ctx;
esp_openthread_lock_acquire(portMAX_DELAY);
otDeviceRole r = otThreadGetDeviceRole(ins);
esp_openthread_lock_release();
if (r == OT_DEVICE_ROLE_LEADER || r == OT_DEVICE_ROLE_ROUTER) {
ESP_LOGI(TAG, "Role attached (%d) → start Commissioner", r);
ESP_LOGI(TAG, "Current channel: %d", otLinkGetChannel(ins));
esp_openthread_lock_acquire(portMAX_DELAY);
otError e = otCommissionerStart(ins, commissioner_state_cb, commissioner_joiner_cb, ins);
esp_openthread_lock_release();
ESP_LOGI(TAG, "otCommissionerStart -> %d", e);
if (e == OT_ERROR_NONE) s_commissioner_started = true;
}
}
}
/* -------------------------------------------------------------------------- */
/* OpenThread Worker */
/* -------------------------------------------------------------------------- */
static void ot_task_worker(void *ctx)
{
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
esp_netif_t *openthread_netif = esp_netif_new(&cfg);
assert(openthread_netif != NULL);
ESP_ERROR_CHECK(esp_openthread_init(&s_openthread_platform_config));
// ESP_ERROR_CHECK(esp_openthread_border_router_init()); // enable BR services
esp_openthread_lock_acquire(portMAX_DELAY);
ESP_ERROR_CHECK(esp_netif_attach(openthread_netif,
esp_openthread_netif_glue_init(&s_openthread_platform_config)));
esp_openthread_lock_release();
otInstance *instance = esp_openthread_get_instance();
/* Clean start */
esp_openthread_lock_acquire(portMAX_DELAY);
(void)otThreadSetEnabled(instance, false);
(void)otIp6SetEnabled(instance, false);
esp_openthread_lock_release();
/* Dataset setup */
esp_openthread_lock_acquire(portMAX_DELAY);
otOperationalDataset dataset;
otError ds_ret = otDatasetGetActive(instance, &dataset);
esp_openthread_lock_release();
if (ds_ret != OT_ERROR_NONE) {
ESP_LOGW(TAG, "No active dataset, creating new one…");
otOperationalDataset ds = {0};
ds.mActiveTimestamp.mSeconds = 1;
ds.mChannel = 11;
ds.mPanId = 0x2345;
static const uint8_t xpan[OT_EXT_PAN_ID_SIZE] =
{0xDE,0xAD,0xBE,0xEF,0x00,0x11,0x22,0x33};
memcpy(ds.mExtendedPanId.m8, xpan, OT_EXT_PAN_ID_SIZE);
const char *networkName = "BEE_AGD";
strncpy((char *)ds.mNetworkName.m8, networkName, sizeof(ds.mNetworkName.m8)-1);
static const uint8_t nwkKey[OT_NETWORK_KEY_SIZE] =
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
memcpy(ds.mNetworkKey.m8, nwkKey, OT_NETWORK_KEY_SIZE);
otIp6NetworkPrefix mlp = {.m8={0xfd,0x00,0xca,0xfe,0xba,0xbe,0x00,0x00}};
memcpy(ds.mMeshLocalPrefix.m8, mlp.m8, OT_MESH_LOCAL_PREFIX_SIZE);
const char *passphrase = "C0mm-Pass";
otPskc pskc;
esp_openthread_lock_acquire(portMAX_DELAY);
otError e_pskc = otDatasetGeneratePskc(passphrase, &ds.mNetworkName,
&ds.mExtendedPanId, &pskc);
if (e_pskc == OT_ERROR_NONE) {
memcpy(&ds.mPskc, &pskc, sizeof(pskc));
ds.mComponents.mIsPskcPresent = true;
}
esp_openthread_lock_release();
ds.mComponents.mIsActiveTimestampPresent = true;
ds.mComponents.mIsChannelPresent = true;
ds.mComponents.mIsPanIdPresent = true;
ds.mComponents.mIsExtendedPanIdPresent = true;
ds.mComponents.mIsNetworkNamePresent = true;
ds.mComponents.mIsNetworkKeyPresent = true;
ds.mComponents.mIsMeshLocalPrefixPresent = true;
esp_openthread_lock_acquire(portMAX_DELAY);
otError err = otDatasetSetActive(instance, &ds);
esp_openthread_lock_release();
if (err != OT_ERROR_NONE)
ESP_LOGE(TAG, "Failed to set active dataset: %d", err);
}
log_active_dataset(instance);
/* Log dataset info */
esp_openthread_lock_acquire(portMAX_DELAY);
bool commissioned = otDatasetIsCommissioned(instance);
otLinkModeConfig lm = otThreadGetLinkMode(instance);
esp_openthread_lock_release();
ESP_LOGI(TAG, "Dataset commissioned: %s", commissioned ? "YES" : "NO");
ESP_LOGI(TAG, "LinkMode: rx=%d, devType=%d, netData=%d",
lm.mRxOnWhenIdle, lm.mDeviceType, lm.mNetworkData);
esp_openthread_lock_acquire(portMAX_DELAY);
otSetStateChangedCallback(instance, state_changed_cb, instance);
esp_openthread_lock_release();
/* Enable IPv6 + Thread */
esp_openthread_lock_acquire(portMAX_DELAY);
ESP_ERROR_CHECK(otIp6SetEnabled(instance, true));
vTaskDelay(pdMS_TO_TICKS(100));
otError e_th = otThreadSetEnabled(instance, true);
esp_openthread_lock_release();
if (e_th == OT_ERROR_NONE)
ESP_LOGI(TAG, "Thread starting…");
else
ESP_LOGE(TAG, "Failed to enable Thread: %d", e_th);
/* --------------------- CoAP server start ---------------------- */
esp_openthread_lock_acquire(portMAX_DELAY);
otError e1 = otCoapStart(instance, OT_DEFAULT_COAP_PORT);
if (e1 == OT_ERROR_NONE) {
s_coap_test_resource.mContext = instance;
otCoapAddResource(instance, &s_coap_test_resource);
ESP_LOGI(TAG, "CoAP server up on /test (udp/5683)");
} else {
ESP_LOGE(TAG, "otCoapStart failed: %d", e1);
}
esp_openthread_lock_release();
/* --------------------------------------------------------------- */
ESP_LOGI(TAG, "Mainloop start");
esp_openthread_launch_mainloop();
}
/* -------------------------------------------------------------------------- */
/* app_main */
/* -------------------------------------------------------------------------- */
void app_main(void)
{
esp_vfs_eventfd_config_t eventfd_config = {.max_fds = 3};
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());
ESP_ERROR_CHECK(mdns_init());
ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br"));
/* 12k stack for OT mainloop */
xTaskCreate(ot_task_worker, "ot_br_main", 12288, NULL, 5, NULL);
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79795871/esp32-border-router-openthread[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия