如何通过脚本实现所有节点输出指定内容时停止Contiki仿真
解决所有节点至少输出一次'ok'后停止仿真的问题
嘿,我来帮你搞定这个问题!先说说你之前两种代码为啥不行:
为啥之前的代码无效?
- 无效代码1的问题:你定义的
test是单个节点的局部变量,每个节点的test都是独立的——比如节点1的test最多只会加到1,节点2的也是如此,永远不可能达到10,所以WAIT_UNTIL(test == 10)永远不会触发。 - 无效代码2的问题:逻辑完全矛盾,一个节点的
id不可能同时等于1、2……10,这个条件永远是false,自然没法停止仿真。
可行解决方案(无需指定节点总数优先)
核心思路是用全局共享变量来追踪所有已经输出过'ok'的节点,因为单个节点的局部变量无法跨节点统计状态。以下是两种靠谱的实现方式:
方案1:自动识别总节点数(推荐)
如果你的仿真环境支持获取全局节点总数(比如提供simulation.getNodeCount()这类API),可以用Set来存已完成的节点ID,等Set的大小等于总节点数时停止:
// 仅在第一个节点初始化全局集合,避免重复创建 if (id === 1) { global.completedNodes = new Set(); } // 当前节点输出'ok'时,将自身ID加入全局集合(自动去重,避免重复计数) if (msg.equals('ok')) { global.completedNodes.add(id); } // 获取总节点数(根据你的仿真工具调整API,比如有的工具是`getNodeCount()`) const totalNodeNum = simulation.getNodeCount(); // 等待所有节点都加入集合后停止仿真 WAIT_UNTIL(global.completedNodes.size === totalNodeNum); log.testOK();
方案2:无需提前知道总节点数
如果没法直接获取总节点数,可以先让所有节点注册自己,再统计完成情况:
// 仅在第一个节点初始化全局变量 if (id === 1) { global.allNodes = new Set(); // 存所有节点ID global.completedNodes = new Set(); // 存已输出'ok'的节点ID } // 每个节点先注册自己,确保所有节点都被统计 global.allNodes.add(id); // 当前节点首次输出'ok'时,加入完成集合 if (msg.equals('ok') && !global.completedNodes.has(id)) { global.completedNodes.add(id); } // 等待完成集合的大小等于所有节点的数量 WAIT_UNTIL(global.completedNodes.size === global.allNodes.size); log.testOK();
关键注意点
- 全局变量的初始化一定要只执行一次(比如让
id=1的节点来做),避免重复创建导致数据混乱; - 用
Set而不是普通计数器,是为了避免同一个节点多次输出'ok'时重复计数,保证每个节点只被统计一次。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

