UDP on openthread is not received

This example automatically create the thread network. Once the button is pressed every 3 second udp is sent. 

Issue is I am not receiving the packet on 2nd device. I am not seeing print from port_data_callback().

What am I missing? Thanks.

Using nrf52840 dongle, nrf connect 1.9.1

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <zephyr.h>
#include <dk_buttons_and_leds.h>
#include <logging/log.h>
#include <net/openthread.h>
#include <openthread/thread.h>
#include <openthread/udp.h>
#include <sys/printk.h>
#include <usb/usb_device.h>
#include <drivers/uart.h>

LOG_MODULE_REGISTER(coap_server, CONFIG_COAP_SERVER_LOG_LEVEL);

BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_shell_uart), zephyr_cdc_acm_uart),
	     "Console device is not ACM CDC UART device");

#define OT_CONNECTION_LED DK_LED1

static struct k_work udp_send_work;

static struct k_timer msg_timer;

const char buf[10] = "Hello\0";

otUdpSocket m_socket;

static void port_data_callback(void                * p_context,
                               otMessage           * p_message,
                               const otMessageInfo * p_message_info)
{
    LOG_INF("port_data_callback");
    // LOG_INF("ptr to msg = %08x",p_message);
}

static void init_udp() {
    otError error = otIp6SetEnabled(openthread_get_default_instance(), true);
    if( error ){
        LOG_ERR("otIp6SetEnabled = %u", error);
    }
    error = otUdpOpen(openthread_get_default_instance(), &m_socket, port_data_callback, NULL);
    if (error != OT_ERROR_NONE )
    {
        LOG_INF("otUdpOpen err = %u", error);
        return error;
    }
    else
    {
        LOG_INF("otUdpOpen SUCCESS!");
    }
}

otError send_udp(otUdpSocket *socket)
{
    otError error = OT_ERROR_NONE;

    otMessageInfo messageInfo;

    bool is_open = otUdpIsOpen(openthread_get_default_instance(), socket);
    if (is_open == false)
    {
    	LOG_INF("socket is not open!");
    }

    memset(&messageInfo, 0, sizeof(messageInfo));

    error = otIp6AddressFromString("ff03::1", &messageInfo.mPeerAddr);
    if (error != OT_ERROR_NONE )
    {
        LOG_INF("otIp6AddressFromString err = %u", error);
        return error;
    }
    messageInfo.mPeerPort = (uint16_t)1994;
    otMessageSettings settings;
    settings.mPriority=OT_MESSAGE_PRIORITY_NORMAL;
    settings.mLinkSecurityEnabled=true;

    otMessage *test_Message  = otUdpNewMessage(openthread_get_default_instance(), &settings);

    error = otMessageAppend(test_Message, buf, (uint16_t)strlen(buf));
    if (error != OT_ERROR_NONE )
    {
        LOG_INF("otMessageAppend err = %u", error);
        return error;
    }

    error = otUdpSend(openthread_get_default_instance(), socket, test_Message, &messageInfo);
    if(error != OT_ERROR_NONE)
    {
        LOG_ERR("otUdpSend err = %u",error);
        return error;
    }

     if(test_Message != NULL)
    {
        // otMessageFree(test_Message);
        LOG_INF("otMessageFree, to be added");
    }


    return error;
}

static void activate_udp_send(struct k_work *item)
{
	ARG_UNUSED(item);
	send_udp(&m_socket);
	k_timer_start(&msg_timer, K_SECONDS(3), K_NO_WAIT);

	LOG_INF("UDP send activated");
}

static void on_msg_timer_expiry(struct k_time *timer_id)
{
	ARG_UNUSED(timer_id);
	k_work_submit(&udp_send_work);
}

static void on_button_changed(uint32_t button_state, uint32_t has_changed)
{
	uint32_t buttons = button_state & has_changed;

	if (buttons & DK_BTN1_MSK) {
		k_work_submit(&udp_send_work);
	}
}

static void on_thread_state_changed(uint32_t flags, void *context)
{
	struct openthread_context *ot_context = context;

	if (flags & OT_CHANGED_THREAD_ROLE) {
		switch (otThreadGetDeviceRole(ot_context->instance)) {
		case OT_DEVICE_ROLE_CHILD:
		case OT_DEVICE_ROLE_ROUTER:
		case OT_DEVICE_ROLE_LEADER:
			dk_set_led_on(OT_CONNECTION_LED);
			break;

		case OT_DEVICE_ROLE_DISABLED:
		case OT_DEVICE_ROLE_DETACHED:
		default:
			dk_set_led_off(OT_CONNECTION_LED);
			break;
		}
	}
}

void main(void)
{
	int ret;
	k_timer_init(&msg_timer, on_msg_timer_expiry, NULL);

	k_work_init(&udp_send_work, activate_udp_send);

	ret = dk_leds_init();
	if (ret) {
		LOG_ERR("Could not initialize leds, err code: %d", ret);
		goto end;
	}

	ret = dk_buttons_init(on_button_changed);
	if (ret) {
		LOG_ERR("Cannot init buttons (error: %d)", ret);
		goto end;
	}

#if DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_shell_uart), zephyr_cdc_acm_uart)
	const struct device *dev;
	uint32_t dtr = 0U;

	ret = usb_enable(NULL);
	if (ret != 0) {
		LOG_ERR("Failed to enable USB");
		return;
	}

	dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart));
	if (dev == NULL) {
		LOG_ERR("Failed to find specific UART device");
		return;
	}

	LOG_INF("Waiting for host to be ready to communicate");

	/* Data Terminal Ready - check if host is ready to communicate */
	while (!dtr) {
		ret = uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
		if (ret) {
			LOG_ERR("Failed to get Data Terminal Ready line state: %d",
				ret);
			continue;
		}
		k_msleep(100);
	}

	/* Data Carrier Detect Modem - mark connection as established */
	(void)uart_line_ctrl_set(dev, UART_LINE_CTRL_DCD, 1);
	/* Data Set Ready - the NCP SoC is ready to communicate */
	(void)uart_line_ctrl_set(dev, UART_LINE_CTRL_DSR, 1);
#endif

	openthread_set_state_changed_cb(on_thread_state_changed);
	openthread_start(openthread_get_default_context());
	init_udp();

end:
	return;
}

Parents
  • Actually, there was no error output of init function or send function. I wish otUdpOpen() function return error if thread network is not up.

    FInally, I found the issue by try and error with help of CLI example.

    One key piece was missed is : I should not be doing udp init before the thread network is up. Once I call the init function once both devices are part of openthread network, everything is fine.

    Thank you for the help.

Reply
  • Actually, there was no error output of init function or send function. I wish otUdpOpen() function return error if thread network is not up.

    FInally, I found the issue by try and error with help of CLI example.

    One key piece was missed is : I should not be doing udp init before the thread network is up. Once I call the init function once both devices are part of openthread network, everything is fine.

    Thank you for the help.

Children
  • Glad to hear that you figured it out!

    Do you mean that you only needed to set up the network before otUdpopen()? You didn't need to set it up to listen at a specific port number?

    Best regards,

    Edvin

  • Thead start -> wait for device to have their role in network -> udp open -> create buffer -> udp send

    Address and port is not needed in initiation stage in otUdpOpen but it needs in otUDPsend().

    Detailed:

    - otUdpOpen ~ In this function parameter otUdpSocket does not need to be initalize with values. It can be memset(&m_socket, 0, sizeof(otUdpSocket)); otUdpReceive also need to be passed so, response can be seen when it receives

     - otUdpSend ~ In this function parameter otMessageInfo, it need the address (in my case ff03::1) and port 1234

    Note: I suggest Nordic to add this as an example, I have seen lot of people struggled on same issue in devzone forums.

    Best,

    Swap

Related