基于Contiki OS与Cooja的IoT数字孪生网络拓扑构建及路由问题咨询
解决方案:Contiki/Cooja 强制数据包中转与中间节点代码实现
一、强制所有数据包经中间节点中转
1. 物理拓扑限制(最直接)
在Cooja中调整节点通信半径,从物理层面切断源节点与Sink的直接连接:
- 将3个源节点的
Radio Range设为仅能覆盖中间节点(比如50) - 将Sink节点的
Radio Range设为仅能覆盖中间节点(比如50) - 中间节点的
Radio Range设为足够覆盖源和Sink(比如100)
这样源节点只能向中间节点发包,Sink只能从中间节点收包,自然实现强制中转。
2. 路由协议层面限制(适合动态拓扑)
如果使用RPL协议,可通过过滤父节点强制源节点仅选择中间节点作为路由入口:
在源节点代码中添加父节点校验逻辑:
static void rpl_parent_filter(rpl_parent_t *old, rpl_parent_t *new) { if(new == NULL) return; // 中间节点的IPv6地址,根据你的拓扑配置修改 uip_ipaddr_t mid_node; uip_ip6addr(&mid_node, 0xfd00, 0, 0, 0, 0, 0, 0, 0x1); // 拒绝非中间节点的父节点请求 if(!uip_ipaddr_cmp(&new->addr, &mid_node)) { rpl_remove_parent(new, rpl_get_any_dag()); } } // 在节点初始化时注册回调 rpl_set_parent_callback(rpl_parent_filter);
二、可编译的中间节点代码示例
Contiki节点默认支持数据包转发,以下是两种常用协议的可运行代码:
基于RPL+UDP的中间节点代码
#include "contiki.h" #include "net/routing/routing.h" #include "net/netstack.h" #include "net/ipv6/simple-udp.h" #include "sys/log.h" #define LOG_MODULE "Middle Node" #define LOG_LEVEL LOG_LEVEL_INFO PROCESS(middle_node_proc, "Middle Node Process"); AUTOSTART_PROCESSES(&middle_node_proc); static struct simple_udp_connection udp_conn; static void udp_rx_handler(struct simple_udp_connection *c, const uip_ipaddr_t *sender, uint16_t sender_port, const uip_ipaddr_t *receiver, uint16_t receiver_port, const uint8_t *data, uint16_t len) { LOG_INFO("Forwarding data from source: %.*s\n", len, data); // Sink节点的IPv6地址,按需修改 uip_ipaddr_t sink_ip; uip_ip6addr(&sink_ip, 0xfd00, 0, 0, 0, 0, 0, 0, 0x2); simple_udp_sendto(&udp_conn, data, len, &sink_ip); } PROCESS_THREAD(middle_node_proc, ev, data) { PROCESS_BEGIN(); NETSTACK_ROUTING.init(); // 注册UDP连接,监听端口1234 simple_udp_register(&udp_conn, 1234, NULL, 1234, udp_rx_handler); while(1) { PROCESS_YIELD(); } PROCESS_END(); }
编译配置要求
在project-conf.h中启用RPL路由:
#define NETSTACK_ROUTING RPL_ROUTING #define RPL_CONF_MOP RPL_MOP_STORING_NO_MULTICAST
基于Rime协议的中间节点代码(低功耗场景)
#include "contiki.h" #include "net/rime/rime.h" #include "sys/log.h" #define LOG_MODULE "Middle Node" #define LOG_LEVEL LOG_LEVEL_INFO PROCESS(middle_node_proc, "Middle Node Process"); AUTOSTART_PROCESSES(&middle_node_proc); static struct multihop_conn multihop_conn; static void multihop_recv(struct multihop_conn *c, const linkaddr_t *from, const linkaddr_t *origin) { LOG_INFO("Forwarding data from %02x:%02x\n", origin->u8[0], origin->u8[1]); // Sink节点的物理地址,按需修改 linkaddr_t sink_addr; linkaddr_set_node_addr(&sink_addr, 0x0002); multihop_send(&multihop_conn, &sink_addr); } static const struct multihop_callbacks multihop_cbs = {multihop_recv}; PROCESS_THREAD(middle_node_proc, ev, data) { PROCESS_BEGIN(); multihop_open(&multihop_conn, 128, &multihop_cbs); while(1) { PROCESS_YIELD(); } PROCESS_END(); }
内容的提问来源于stack exchange,提问作者Shreya
相关产品推荐
相关产品推荐

