/**
* 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;
}
}
TestNetworkC.nc
最新推荐文章于 2024-01-23 14:50:49 发布