Hi Nordic team!
I haven't been able to implement the joiner functionality on a Thread network with nrf52840. I'm using the nRF52840-DK as the leader. For the DK, I follow the steps on: https://nrfconnectdocs.nordicsemi.com/ncs/latest/nrf/protocols/thread/overview/commissioning.html#setting-up-the-commissioner, and it seems to work fine. It creates the network:
uart:~$ > ot dataset ot dataset Active Timestamp: 1 Channel: 17 Channel Mask: 0x07fff800 Ext PAN ID: d0202f6f8e59cab3 Mesh Local Prefix: fd5a:79d7:d8b9:9faa::/64 Network Key: 006ba3ba39b20cc0ee05c2828a5f1ba3 Network Name: OpenThread-eb5e PAN ID: 0xeb5e PSKc: 457127fa04c419a51e02a8c0a0c8e618 Security Policy: 672 onrc 0 Done
Then, on a nrf52840 chip, which I debug through J-Link, I use the following code:
static const char *THREAD_JOINER_PSKD = "KULD55P";
static void joiner_callback(otError aError, void *aContext)
{
ARG_UNUSED(aContext);
if (aError == OT_ERROR_NONE)
{
LOG_INF("Joining successful");
}
else
{
LOG_ERR("Joining failed: %d", aError);
}
}
static void on_thread_state_changed(otChangedFlags flags, void *user_data)
{
ARG_UNUSED(user_data);
if (flags & OT_CHANGED_THREAD_ROLE)
{
switch (otThreadGetDeviceRole(openthread_get_default_instance()))
{
case OT_DEVICE_ROLE_CHILD:
LOG_INF("Thread role changed: CHILD");
break;
case OT_DEVICE_ROLE_ROUTER:
LOG_INF("Thread role changed: ROUTER");
break;
case OT_DEVICE_ROLE_LEADER:
LOG_INF("Thread role changed: LEADER");
break;
case OT_DEVICE_ROLE_DISABLED:
LOG_INF("Thread role changed: DISABLED");
break;
case OT_DEVICE_ROLE_DETACHED:
LOG_INF("Thread role changed: DETACHED");
break;
default:
LOG_INF("Thread role changed: UNKNOWN");
break;
}
}
if (flags & OT_CHANGED_JOINER_STATE)
{
otJoinerState joiner_state = otJoinerGetState(openthread_get_default_instance());
LOG_INF("Joiner state changed: %s", otJoinerStateToString(joiner_state));
}
}
static struct openthread_state_changed_callback ot_state_chaged_cb = {
.otCallback = on_thread_state_changed};
void thread_init(){
otInstance *ot = openthread_get_default_instance();
if (!ot)
{
LOG_ERR("No valid OpenThread instance");
return;
}
else
{
LOG_INF("ot default instance ok..");
}
openthread_state_changed_callback_register(&ot_state_chaged_cb);
LOG_INF("registered callback...");
// 3. enable Ipv6
if (!otIp6IsEnabled(ot))
{
otIp6SetEnabled(ot, true);
LOG_INF("IPv6 enabled");
}
else
{
LOG_INF("otIp6IsEnabled not enabled ok...");
}
LOG_INF("Commissioned=%d", otDatasetIsCommissioned(ot));
LOG_INF("Role=%d", otThreadGetDeviceRole(ot));
LOG_INF("IPv6=%d", otIp6IsEnabled(ot));
errorCode = otJoinerStart(
ot,
THREAD_JOINER_PSKD,
NULL,
NULL,
NULL,
NULL,
NULL,
joiner_callback,
NULL);
if (errorCode != OT_ERROR_NONE)
{
LOG_ERR("otJoinerStart failed: %d", errorCode);
return -1;
}
}
I commented out the rest of the code just to debug the Thread code, so I'm only using these lines.
This is my prj.conf
# Enable OpenThread CONFIG_OPENTHREAD=y CONFIG_OPENTHREAD_FTD=y #CONFIG_OPENTHREAD_COAP=y CONFIG_OPENTHREAD_JOINER=y CONFIG_OPENTHREAD_JOINER_AUTOSTART=n CONFIG_MPSL=y CONFIG_IEEE802154=y # Same network Master Key for client and server #CONFIG_OPENTHREAD_NETWORKKEY="00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff" #CONFIG_MBEDTLS_SHA1_C=n #CONFIG_FPU=y # Increase main stack size to meet networking requirements CONFIG_SHELL_STACK_SIZE=5000 CONFIG_MAIN_STACK_SIZE=10000 # UART CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y # Logging CONFIG_LOG=y CONFIG_RTT_CONSOLE=n CONFIG_USE_SEGGER_RTT=y CONFIG_UART_CONSOLE=n CONFIG_LOG_BACKEND_RTT=y CONFIG_LOG_BACKEND_RTT_MODE_BLOCK=y CONFIG_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE=256 CONFIG_LOG_BACKEND_RTT_RETRY_CNT=16 CONFIG_LOG_BACKEND_RTT_RETRY_DELAY_MS=1 CONFIG_LOG_BACKEND_SHOW_COLOR=n CONFIG_LOG_MODE_DEFERRED=y CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=10 CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096 CONFIG_SEGGER_RTT_PRINTF_BUFFER_SIZE=256 CONFIG_SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL=y CONFIG_CONSOLE=n #CONFIG_OPENTHREAD_DEBUG=y #CONFIG_OPENTHREAD_LOG_LEVEL_DEBG=y #NVS CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_NVS=y CONFIG_NVS_LOG_LEVEL_DBG=y CONFIG_REBOOT=y CONFIG_MPU_ALLOW_FLASH_WRITE=y
I use *ot commissioner start* and *ot commissioner joiner add * KULD55P*, and it works ok. I can confirm with the table that is waiting on the joiner.
These are the logs:
00> *** Booting nRF Connect SDK v3.3.0-ba167d9f3db4 *** 00> *** Using Zephyr OS v4.3.99-fd9204a02d52 *** 00> [00:00:00.028,167] <inf> main: start main 00> [00:00:00.028,167] <inf> thread_main: ot default instance ok.. 00> [00:00:00.028,198] <inf> thread_main: registered callback... 00> [00:00:00.028,656] <inf> thread_main: IPv6 enabled 00> [00:00:00.028,747] <inf> thread_main: Commissioned=0 00> [00:00:00.028,747] <inf> thread_main: Role=0 00> [00:00:00.028,778] <inf> thread_main: IPv6=1 00> [00:00:00.030,029] <inf> thread_main: Joiner state changed: Discover 00> [00:00:00.030,090] <inf> main: Main initialization completed
My problem is that it stays in discover, and that's it. The joiner callback never gets called, and nothing happens on the DK side neither.
Is there an example of how to implement the joiner method correctly? I also tried the discover method, but it's the same problem.
Thanks a lot in advance