You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Contiki Simple UDP API实现广播包回复的问题求助

Contiki中Node无法回复Root单播消息的问题排查与解决

问题场景

搭建了包含Root和Node两个mote的通信场景:

  • Root通过广播发送"Test"消息
  • Node接收广播后,以单播方式回复"OK"消息
  • 使用simple_udp API实现通信
  • 现象:Node能正常接收Root的广播消息,但无法发送回复的"OK"消息

问题分析与解决方案

结合代码来看,核心问题集中在调试信息缺失、等待时间不合理以及IP地址有效性验证不足,以下是针对性修复方案:

1. 优化等待时间,提升测试效率

原代码中Root设置了5分钟的等待时长,实际测试无需等待这么久,缩短为几秒即可避免不必要的等待。

2. 添加调试打印,明确消息流向

原回调函数仅打印端口和长度,无法直观确认回复是否发送/接收,新增调试打印可清晰追踪消息流转。

3. 验证设备IP地址,确保通信链路正常

添加IP地址打印逻辑,确认Root和Node已获取有效的链路本地/全局IP,避免因地址未初始化导致通信失败。

修改后的代码

Root代码

#include "contiki.h"
#include "lib/random.h"
#include "sys/ctimer.h"
#include "sys/etimer.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"

#include "simple-udp.h"
#include <stdio.h>
#include <string.h>

#define UDP_PORT 1234
#define DELAY   (CLOCK_SECOND) // 缩短为1秒单位

static struct etimer wait;
static struct simple_udp_connection connection;

static void receiver(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{
  printf("Root: Data received from ");
  uip_debug_ipaddr_print(sender_addr);
  printf(" on port %d, length %d\n", receiver_port, datalen);
  printf("Root: Received content: %.*s\n", datalen, data); // 打印收到的消息内容
}

PROCESS(Root_process, "Root process");
AUTOSTART_PROCESSES(&Root_process);

PROCESS_THREAD(Root_process, ev, data)
{
  PROCESS_BEGIN();

  // 打印自身IP地址,确认网络初始化状态
  uip_ipaddr_t *ipaddr = uip_ds6_get_global(ADDR_PREFERRED);
  if(ipaddr == NULL) {
    ipaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
  }
  printf("Root IP address: ");
  uip_debug_ipaddr_print(ipaddr);
  printf("\n");

  simple_udp_register(&connection, UDP_PORT, NULL, UDP_PORT, receiver);

  etimer_set(&wait, 5 * DELAY); // 等待5秒后发送广播
  PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&wait));

  uip_ipaddr_t broadcast;
  uip_create_linklocal_allnodes_mcast(&broadcast);
  printf("Root: Sending broadcast message\n");
  simple_udp_sendto(&connection, "Test", 4, &broadcast);

  while(1) {
    PROCESS_WAIT_EVENT();
  }

  PROCESS_END();
}

Node代码

#include "contiki.h"
#include "lib/random.h"
#include "sys/ctimer.h"
#include "sys/etimer.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"

#include "simple-udp.h"
#include <stdio.h>
#include <string.h>

#define UDP_PORT 1234

static struct simple_udp_connection connection;

static void receiver(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{
  printf("Node: Data received from ");
  uip_debug_ipaddr_print(sender_addr);
  printf(" on port %d, length %d\n", receiver_port, datalen);
  printf("Node: Received content: %.*s\n", datalen, data);

  // 添加发送调试打印,确认回复操作执行
  printf("Node: Sending reply to ");
  uip_debug_ipaddr_print(sender_addr);
  printf("\n");
  simple_udp_sendto(&connection, "OK", 2, sender_addr);
}

PROCESS(Node_process, "Node process");
AUTOSTART_PROCESSES(&Node_process);

PROCESS_THREAD(Node_process, ev, data)
{
  PROCESS_BEGIN();

  // 打印自身IP地址
  uip_ipaddr_t *ipaddr = uip_ds6_get_global(ADDR_PREFERRED);
  if(ipaddr == NULL) {
    ipaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
  }
  printf("Node IP address: ");
  uip_debug_ipaddr_print(ipaddr);
  printf("\n");

  simple_udp_register(&connection, UDP_PORT, NULL, UDP_PORT, receiver);

  while(1) {
    PROCESS_WAIT_EVENT();
  }

  PROCESS_END();
}

额外排查点

  • 确保两个mote处于同一无线覆盖范围内,信号强度正常
  • 检查Contiki网络栈配置,确认IPv6和UDP功能已正常开启
  • 若使用Cooja模拟器,检查模拟器的网络设置是否正确

内容的提问来源于stack exchange,提问作者Redha Bouakouk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:18:22