一、功能:
使用Tossim仿真两个节点相互通信的过程,也就是发送和接收数据的过程。两个节点通信,必须存在拓扑结构,信道也有噪声
二、功能逻辑实现:
BlinkToRadioC.nc
#include#include #include #include "BlinkToRadio.h" module BlinkToRadioC{ uses interface Boot; uses interface Leds; uses interface Timer as Timer0; uses interface Packet; uses interface AMSend; uses interface SplitControl as AMControl; uses interface Receive; } implementation{ uint16_t counter = 0; bool busy = FALSE; message_t pkt; //要发送的消息 event void Boot.booted(){ //硬件上电后调用 call AMControl.start(); //尽管可以把这些接口直接绑定到ActiveMessageC组件,但通常还是选择绑定AMSenderC组件。 //不过,必须使用ActiveMessageC组件的SplitControl接口来初始化无线模块 //开启这个组件和它的子组件 } event void AMControl.startDone(error_t err){ //AMControl.start()执行完成后signal的event,也就是要执行的代码 if(err==SUCCESS){ call Timer0.startPeriodic(TIMER_PERIOD_MILLI); dbg("Boot", "Application booted\n"); }else{ call AMControl.start(); } } //貌似是用到SplitControl 这个接口必须定义该函数 event void AMControl.stopDone(error_t err){ } event void AMSend.sendDone(message_t *msg,error_t error){ //AMSend.send()执行完后signal if(&pkt==msg){ //msg是packet中消息,这里与本地消息比较一下,看是否是自己发的消息 busy=FALSE; dbg("BlinkToRadioC", "%hhu mote send packet,time== %s.\n",TOS_NODE_ID,sim_time_string()); } } event void Timer0.fired(){ //Timer0到期后signal counter++; if(!busy){ BlinkToRadioMsg* btrpkt=(BlinkToRadioMsg*)(call Packet.getPayload(&pkt,NULL)); //获取一个Packet地址, //搞不懂为什么要这么多参数 btrpkt->nodeid=TOS_NODE_ID; //填充数据 btrpkt->counter=counter; if(call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS){ //将packet发送出去 //printf("send data\r\n"); busy=TRUE; } } } event message_t* Receive.receive(message_t *msg,void * payload,uint8_t len){ //接收到数据signal if(len==sizeof(BlinkToRadioMsg)){ BlinkToRadioMsg * btrpkt=(BlinkToRadioMsg *)payload; //数据保存在payload中 // call Leds.set(btrpkt->counter); dbg("BlinkToRadioC", "%hhu mote Receive packet,from node %hhu, counter= %hhu,time== %s.\n", TOS_NODE_ID,btrpkt->nodeid,btrpkt->counter, sim_time_string()); } return msg; } }
其实没什么,节点每个250ms发送一次数据,其余时间均处于接收状态,发送完和接收数据后都dbg一句话
三、仿真步骤
1、进入Blink 所在目录 “cd xxx/BlinkToRadio”
2、生成仿真框架,为后续的仿真做准备, 就像生成一个界面,等着你输入(命令或脚本)来交互 "make micaz sim" 目前仿真只支持micaz平台, 后面的"sim"代表生成仿真框架
3、编辑test.py
#!/usr/bin/env python #-*-coding:utf-8-*- #解决编码问题 from TOSSIM import * import sys t=Tossim([]) r=t.radio() #用于创建拓扑结构,通过r.add()创建链路 f=open("topo.txt","r") #拓扑结构所在文件,每一行代表一条链路 #每一行由三个数据组成:源节点,目标节点和增益(应该就是发射功率吧) lines=f.readlines() #下面这段只是打印拓扑结构,要不要无所谓 for line in lines: s = line.split() if (len(s)>0): print "",s[0],"",s[1],"",s[2]; r.add(int(s[0]),int(s[1]),float(s[2])) f=open("log.txt",'w'); t.addChannel("Boot",f) t.addChannel("BlinkToRadioC",f) #将BlinkToRadioC输出通道绑定到log.txt t.addChannel("BlinkToRadioC",sys.stdout) #将BlinkToRadioC输出绑定到标准输出,也就是屏幕 t.addChannel("Boot",sys.stdout) noise=open("meyer-heavy.txt","r") #信道噪声文件 lines=noise.readlines() for line in lines : #这个for和下面的for共同完成读取噪声文件并构造信道噪声模型,你可以深究,我看不懂 str= line.strip() if(str!=""): val=int(str) for i in range(1,3): t.getNode(i).addNoiseTraceReading(val) for i in range(1,3): print"Creating noise model for",i; t.getNode(i).createNoiseModel() t.getNode(1).bootAtTime(100001); #设置节点boot时间 t.getNode(2).bootAtTime(800008); for i in range(0,100): #让每个节点仿真100个事件 t.runNextEvent()
其中,topotxt内容如下
1 2 -54.0 2 1 -55.0
meyer-heavy.txt可以在tos/lib/tossim/noise目录下找到
4、运行test.py文件,进行仿真,结果如下
5、小结:
有点搞不懂,为什么第一条语句不是发送packet语句,而是接收呢?谁能给我答案
6、补充:
将逻辑功能代码改成如下,就比较好理解了:
BlinkToRadioC.nc
#include#include #include<string.h> #include "BlinkToRadio.h" module BlinkToRadioC{ uses interface Boot; uses interface Leds; uses interface Timer as Timer0; uses interface Packet; uses interface AMSend; uses interface SplitControl as AMControl; uses interface Receive; } implementation{ uint16_t counter = 0; bool busy = FALSE; message_t pkt; //要发送的消息 event void Boot.booted(){ //硬件上电后调用 call AMControl.start(); //尽管可以把这些接口直接绑定到ActiveMessageC组件,但通常还是选择绑定AMSenderC组件。 //不过,必须使用ActiveMessageC组件的SplitControl接口来初始化无线模块 //开启这个组件和它的子组件 } event void AMControl.startDone(error_t err){ //AMControl.start()执行完成后signal的event,也就是要执行的代码 if(err==SUCCESS){ call Timer0.startPeriodic(TIMER_PERIOD_MILLI); dbg("Boot", "Application booted\n"); }else{ call AMControl.start(); } } //貌似是用到SplitControl 这个接口必须定义该函数 event void AMControl.stopDone(error_t err){ } event void AMSend.sendDone(message_t *msg,error_t error){ //AMSend.send()执行完后signal if(&pkt==msg){ //msg是packet中消息,这里与本地消息比较一下,看是否是自己发的消息 busy=FALSE; //dbg("BlinkToRadioC", "%hhu mote send packet,time== %s.\n",TOS_NODE_ID,sim_time_string()); } } event void Timer0.fired(){ //Timer0到期后signal counter++; if(!busy){ BlinkToRadioMsg* btrpkt=(BlinkToRadioMsg*)(call Packet.getPayload(&pkt,NULL)); //获取一个Packet地址, //搞不懂为什么要这么多参数 btrpkt->nodeid=TOS_NODE_ID; //填充数据 btrpkt->counter=counter; if(call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS){ //将packet发送出去 dbg("BlinkToRadioC", "%hhu mote send packet,time== %s.\n",TOS_NODE_ID,sim_time_string()); //printf("send data\r\n"); busy=TRUE; } } } event message_t* Receive.receive(message_t *msg,void * payload,uint8_t len){ //接收到数据signal if(len==sizeof(BlinkToRadioMsg)){ BlinkToRadioMsg * btrpkt=(BlinkToRadioMsg *)payload; //数据保存在payload中 // call Leds.set(btrpkt->counter); dbg("BlinkToRadioC", "%hhu mote Receive packet,from node %hhu, counter= %hhu,time== %s.\n", TOS_NODE_ID,btrpkt->nodeid,btrpkt->counter, sim_time_string()); } return msg; } }
可以看到,其实就是将send packet时的dbg放到发送sendDone里面,而不是像第一次一样放到send函数里面,我想可能就是这边一点一点发,那边一点一点收,并不用等发完已经收完了,哎呀呀,纯属我瞎扯的,
大家可以自己想想,欢迎指点