TestNetworkC.nc

/**
 * TestNetworkC exercises the basic networking layers, collection and
 * dissemination. The application samples DemoSensorC at a basic rate
 * and sends packets up a collection tree. The rate is configurable
 * through dissemination. The default send rate is every 10s.
 *
 * See TEP118: Dissemination and TEP 119: Collection for details.
 */

#include <Timer.h>
#include "TestNetwork.h"
#include "CtpDebugMsg.h"

module TestNetworkC {
  uses interface Boot;
  uses interface SplitControl as RadioControl;
  uses interface SplitControl as SerialControl;
  uses interface StdControl as RoutingControl;  //路由控制
  uses interface StdControl as DisseminationControl;  //分发控制
  uses interface DisseminationValue<uint32_t> as DisseminationPeriod; //分发周期
  uses interface Send;                    //普通的Send
  uses interface Leds;
  uses interface Read<uint16_t> as ReadSensor;
  uses interface Timer<TMilli>;
  uses interface RootControl;
  uses interface Receive;                 //普通的Receive
  uses interface AMSend as UARTSend;
  uses interface CollectionPacket;        //???
  uses interface CtpInfo;
  uses interface CtpCongestion;
  uses interface Random;
  uses interface Queue<message_t *>;      //FIFO队列,每一个元素是message_t *类型,用于对串口的发送
  uses interface Pool<message_t>;         //池子,每一个元素是message_t类型
  uses interface CollectionDebug;
  uses interface AMPacket;
  uses interface Packet as RadioPacket;
}
implementation {
  message_t packet;
  //message_t uartpacket;
  //message_t * recvPtr = &uartpacket;
  //uint8_t msglen;
  bool sendBusy = FALSE;
  bool uartbusy = FALSE;
  //bool firstTimer = TRUE;
  uint16_t seqno;         //包的序列号
  enum {
    SEND_INTERVAL = 8192  //发送间隔
  };

  task void uartEchoTask();

	event void ReadSensor.readDone(error_t err, uint16_t val) { }

  event void Boot.booted() {
    call SerialControl.start(); //启动串口
  }

  event void SerialControl.startDone(error_t err) {
    call RadioControl.start();  //串口启动完毕后,启动射频
  }

  event void RadioControl.startDone(error_t err) {
    if (err != SUCCESS) {
      call RadioControl.start();  //射频启动失败,则重新启动
    } else {
      call DisseminationControl.start();  //开启分发
      call RoutingControl.start();        //开启路由
      if (TOS_NODE_ID % 500 == 0) {       //如果节点id是0
				call RootControl.setRoot();       //把自己设置成根节点
      }
      seqno = 0;                          //消息包的序列号初始化为0
      call Timer.startOneShot(call Random.rand16() & 0x01ff); //定时器只运行一个周期,然后关闭
    }
  }

  event void RadioControl.stopDone(error_t err) {}
  event void SerialControl.stopDone(error_t err) {}

  void failedSend() {
    dbg("App", "%s: Send failed.\n", __FUNCTION__);
    call CollectionDebug.logEvent(NET_C_DBG_1);
  }

  void sendMessage() {
    TestNetworkMsg * msg;
    uint16_t metric;        //度量
    am_addr_t parent = 0;

		msg = (TestNetworkMsg *)call Send.getPayload(&packet, sizeof(TestNetworkMsg));  //获取有效载荷的指针
    call CtpInfo.getParent(&parent);
    call CtpInfo.getEtx(&metric);

    msg->source = TOS_NODE_ID;  //写入消息源节点id
    msg->seqno = seqno;         //写入消息包序列号
    msg->data = 0xCAFE;         //消息包有效数据标记
    msg->parent = parent;
    msg->hopcount = 0;
    msg->metric = metric;

    if (call Send.send(&packet, sizeof(TestNetworkMsg)) != SUCCESS) { //如果发送失败
      failedSend();
      call Leds.led0On();
      dbg("TestNetworkC", "%s: Transmission failed.\n", __FUNCTION__);
    } else {  //发送成功
      sendBusy = TRUE;
      seqno++;                  //每次消息包序列号自增1
      dbg("TestNetworkC", "%s: Transmission succeeded.\n", __FUNCTION__);
    }
  }

  event void Timer.fired() {
    uint32_t nextInt;
    dbg("TestNetworkC", "TestNetworkC: Timer fired.\n");
    nextInt = call Random.rand32() % SEND_INTERVAL;   //使产生的随机数在[0, SEND_INTERVAL)内
    nextInt += SEND_INTERVAL >> 1;  //给一个正向的偏移量SEND_INTERVAL/2
    call Timer.startOneShot(nextInt); //重新开启定时器一个周期,周期为nextInt(有点像递归)
    if (!sendBusy)
			sendMessage();
  }

  event void Send.sendDone(message_t * m, error_t err) {
    if (err != SUCCESS) { //如果发送失败
      call Leds.led0On();
    }
    sendBusy = FALSE; //发送完毕,置不忙
    dbg("TestNetworkC", "Send completed.\n");
  }

  event void DisseminationPeriod.changed() {	//捕捉到分发周期改变了
    const uint32_t * newVal;
		newVal = call DisseminationPeriod.get();  //获取载有分发周期数据的指针
    call Timer.stop();  //停止定时器
    call Timer.startPeriodic(*newVal);  //重新启动定时器,周期为新的分发周期
  }

  event message_t * Receive.receive(message_t * msg, void * payload, uint8_t len) { //获取消息包事件
    static uint16_t prevSeq = 0;
    static uint8_t firstMsg = 0;   //bool类型的变量,标记是不是第一个接收到的包
    uint16_t nowSeq;

    dbg("TestNetworkC", "Received packet at %s from node %hhu.\n",
			sim_time_string(), call CollectionPacket.getOrigin(msg));
    call Leds.led1Toggle();

    if (call CollectionPacket.getOrigin(msg) == 1) {  //???
      nowSeq = call CollectionPacket.getSequenceNumber(msg);
      if (firstMsg == 1) {    //如果当前不是第一个消息包,即第一个消息包之前已经收到了
				if (nowSeq - prevSeq > 1) { //出现掉包的标志,因为相邻的包的序列号是连续的(相差1)
	  			call Leds.led2On();                                             //见变量seqno
				}
      } else {    //收到了消息包,则置1
				firstMsg = 1;
      }
      prevSeq = nowSeq; //将序列号备份一下
    }
    //如果池子不空,并且队列还没有满
    if (!call Pool.empty() && call Queue.size() < call Queue.maxSize()) {
      message_t * tmp = call Pool.get();  //获取池子中一个message_t元素的指针,暂存
      call Queue.enqueue(msg);  //将该消息包的指针放入串口队列(见函数参数)
      if (!uartbusy) {          //如果串口不忙
        post uartEchoTask();    //布置串口发送任务
      }
      return tmp;
    }
    return msg;
 }

 task void uartEchoTask() {     //串口发送任务
   dbg("Traffic", "Sending packet to UART.\n");
   if (call Queue.empty()) {    //如果串口队列为空
     return;
   } else if (!uartbusy) {      //否则如果串口不忙
     message_t * msg = call Queue.dequeue();  //从串口队列头部获取一个消息包的指针
     dbg("Traffic", "Sending packet to UART.\n");
     if (call UARTSend.send(0xffff, msg, call RadioPacket.payloadLength(msg)) == SUCCESS) { //发送该消息包
       uartbusy = TRUE;
     } else {       //发送失败,则做记录
     	 call CollectionDebug.logEventMsg(NET_C_DBG_2,
			 		call CollectionPacket.getSequenceNumber(msg),
					call CollectionPacket.getOrigin(msg),
					call AMPacket.destination(msg));
     }
   }
 }

  event void UARTSend.sendDone(message_t * msg, error_t error) {  //串口发送完毕事件
    dbg("Traffic", "UART send done.\n");
    uartbusy = FALSE;             //置串口不忙
    call Pool.put(msg);           //将该消息包的指针指向的元素放入池子中
    if (!call Queue.empty()) {    //如果串口队列中还有元素
      post uartEchoTask();
    } else {
      //        call CtpCongestion.setClientCongested(FALSE);
    }
  }

  /* Default implementations for CollectionDebug calls.
   * These allow CollectionDebug not to be wired to anything if debugging
   * is not desired. */

	default command error_t CollectionDebug.logEvent(uint8_t type) {
    return SUCCESS;
  }

  default command error_t CollectionDebug.logEventSimple(uint8_t type, uint16_t arg) {
    return SUCCESS;
  }

	default command error_t CollectionDebug.logEventDbg(uint8_t type, uint16_t arg1, uint16_t arg2, uint16_t arg3) {
    return SUCCESS;
  }

	default command error_t CollectionDebug.logEventMsg(uint8_t type, uint16_t msg, am_addr_t origin, am_addr_t node) {
    return SUCCESS;
  }

	default command error_t CollectionDebug.logEventRoute(uint8_t type, am_addr_t parent, uint8_t hopcount, uint16_t metric) {
    return SUCCESS;
  }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值