节点的通信,是
tinyos的基础知识。最近在编写
程序的过程中,有一些体会,跟大家分享一下,下面以BlinkToRadio程序为例,将一些大家可能忽略的东西说说。
#include <Timer.h>
#include "BlinkToRadio.h"
configuration BlinkToRadioAppC {
}
implementation {
components MainC;
components LedsC;
components BlinkToRadioC as App;
components new TimerMilliC() as Timer0;
components ActiveMessageC;
components new AMSenderC(AM_BLINKTORADIOMSG);
components new AMReceiverC(AM_BLINKTORADIOMSG);
App.Boot -> MainC;
App.Leds -> LedsC;
App.Timer0 -> Timer0;
App.Packet->AMSenderC;
App.AMPacket->AMSenderC;
App.AMSend->AMSenderC;
App.AMControl->ActiveMessageC;
App.Receive->AMReceiverC;
}
在这个配置文件中,注意这两条语句:
components new AMSenderC(AM_BLINKTORADIOMSG);
components new AMReceiverC(AM_BLINKTORADIOMSG);
这里的AMSenderC,AMReceiverC中的参数,非常重要,一旦出错,就没办法进行节点通信。这里要注意,发送方使用AMSenderC组件提供AMSend接口,接收方使用的AMReceive组件提供的AMReceive接口,这两个组件都是通用组件,需要提供参数。如果发送方A使用这个组件将 数据发送给接收方B,这两个组件的参数必须相同。如果A使用的AMSenderC组件的参数,跟B使用的AMReceive组件的参数不同,则A发送的数据,B是接收不到的。
其实这个参数,就是发送的数据包头部的第八个字段:
dest addr link source addr msg len groupID handlerID
f ff 00 00 04 22 06
也就是那个handlerID的值,这个大家可以尝试一下,利用这种方式可以实现组播。
下面再看看这个模块文件:
#include <Timer.h>
#include "BlinkToRadio.h"
module BlinkToRadioC {
uses interface Boot;
uses interface Leds;
uses interface Timer<TMilli> as Timer0;
uses interface Packet;
uses interface AMPacket;
uses interface AMSend;
uses interface SplitControl as AMControl;
uses interface Receive;
}
implementation {
bool busy=FALSE;
message_t pkt;
uint16_t counter = 0;
event void Boot.booted() {
call AMControl.start();
}
event void AMControl.startDone(error_t err){
if(err==SUCCESS){
call Timer0.startPeriodic(TIMER_PERIOD_MILLI);
}
else{
call AMControl.start();
}
}
event void AMSend.sendDone(message_t* msg,error_t error){
if(&pkt==msg){
busy=FALSE;
}
}
event void AMControl.stopDone(error_t err){
}
event message_t* Receive.receive(message_t* msg,void* payload,uint8_t len){
if(len==sizeof(BlinkToRadioMsg)){
BlinkToRadioMsg* btrpkt=(BlinkToRadioMsg*)payload;
call Leds.set(btrpkt->counter);
}
return msg;
}
event void Timer0.fired() {
counter++;
if(!busy){
BlinkToRadioMsg* btrpkt=(BlinkToRadioMsg*)(call Packet.getPayload(&pkt,sizeof(BlinkToRadioMsg)));
btrpkt->nodeid=TOS_NODE_ID;
btrpkt->counter=counter;
if(call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS){
busy=TRUE;
}
}
}
}
前面已经说过了程序的执行流程,这里说一下下面这条语句:
call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS
这里send命令有三个参数,第二个是指向这个包的指针,这个指针的使用跟C是一样的,具体可以参考C里语法。nesC里的很多语法其实跟C相差不多的,有什么不确定的,如果查不到资料,可以按照C的方式处理。
#include <Timer.h>
#include "BlinkToRadio.h"
configuration BlinkToRadioAppC {
}
implementation {
components MainC;
components LedsC;
components BlinkToRadioC as App;
components new TimerMilliC() as Timer0;
components ActiveMessageC;
components new AMSenderC(AM_BLINKTORADIOMSG);
components new AMReceiverC(AM_BLINKTORADIOMSG);
App.Boot -> MainC;
App.Leds -> LedsC;
App.Timer0 -> Timer0;
App.Packet->AMSenderC;
App.AMPacket->AMSenderC;
App.AMSend->AMSenderC;
App.AMControl->ActiveMessageC;
App.Receive->AMReceiverC;
}
在这个配置文件中,注意这两条语句:
components new AMSenderC(AM_BLINKTORADIOMSG);
components new AMReceiverC(AM_BLINKTORADIOMSG);
这里的AMSenderC,AMReceiverC中的参数,非常重要,一旦出错,就没办法进行节点通信。这里要注意,发送方使用AMSenderC组件提供AMSend接口,接收方使用的AMReceive组件提供的AMReceive接口,这两个组件都是通用组件,需要提供参数。如果发送方A使用这个组件将 数据发送给接收方B,这两个组件的参数必须相同。如果A使用的AMSenderC组件的参数,跟B使用的AMReceive组件的参数不同,则A发送的数据,B是接收不到的。
其实这个参数,就是发送的数据包头部的第八个字段:
dest addr link source addr msg len groupID handlerID
f ff 00 00 04 22 06
也就是那个handlerID的值,这个大家可以尝试一下,利用这种方式可以实现组播。
下面再看看这个模块文件:
#include <Timer.h>
#include "BlinkToRadio.h"
module BlinkToRadioC {
uses interface Boot;
uses interface Leds;
uses interface Timer<TMilli> as Timer0;
uses interface Packet;
uses interface AMPacket;
uses interface AMSend;
uses interface SplitControl as AMControl;
uses interface Receive;
}
implementation {
bool busy=FALSE;
message_t pkt;
uint16_t counter = 0;
event void Boot.booted() {
call AMControl.start();
}
event void AMControl.startDone(error_t err){
if(err==SUCCESS){
call Timer0.startPeriodic(TIMER_PERIOD_MILLI);
}
else{
call AMControl.start();
}
}
event void AMSend.sendDone(message_t* msg,error_t error){
if(&pkt==msg){
busy=FALSE;
}
}
event void AMControl.stopDone(error_t err){
}
event message_t* Receive.receive(message_t* msg,void* payload,uint8_t len){
if(len==sizeof(BlinkToRadioMsg)){
BlinkToRadioMsg* btrpkt=(BlinkToRadioMsg*)payload;
call Leds.set(btrpkt->counter);
}
return msg;
}
event void Timer0.fired() {
counter++;
if(!busy){
BlinkToRadioMsg* btrpkt=(BlinkToRadioMsg*)(call Packet.getPayload(&pkt,sizeof(BlinkToRadioMsg)));
btrpkt->nodeid=TOS_NODE_ID;
btrpkt->counter=counter;
if(call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS){
busy=TRUE;
}
}
}
}
前面已经说过了程序的执行流程,这里说一下下面这条语句:
call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS
这里send命令有三个参数,第二个是指向这个包的指针,这个指针的使用跟C是一样的,具体可以参考C里语法。nesC里的很多语法其实跟C相差不多的,有什么不确定的,如果查不到资料,可以按照C的方式处理。