Пограничный маршрутизатор ESP32 с открытой резьбойC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Пограничный маршрутизатор ESP32 с открытой резьбой

Сообщение Anonymous »

Я пытаюсь создать пограничный маршрутизатор 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»