1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/**
* 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.
*
* @author Philip Levis
* @version $Revision: 1.11 $ $Date: 2010-01-14 21:53:58 $
*/
#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;
uses interface Leds;
uses interface Read<uint16_t> as ReadSensor;
uses interface Timer<TMilli>;
uses interface RootControl;
uses interface Receive;
uses interface AMSend as UARTSend;
uses interface CollectionPacket;
uses interface CtpInfo;
uses interface CtpCongestion;
uses interface Random;
uses interface Queue<message_t*>;
uses interface Pool<message_t>;
uses interface CollectionDebug;
uses interface AMPacket;
uses interface Packet as RadioPacket;
}
implementation {
task void uartEchoTask();
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
};
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) {
call RootControl.setRoot();
}
seqno = 0;
call Timer.startOneShot(call Random.rand16() & 0x1ff);
}
}
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 = (TestNetworkMsg*)call Send.getPayload(&packet, sizeof(TestNetworkMsg));
uint16_t metric;
am_addr_t parent = 0;
call CtpInfo.getParent(&parent);
call CtpInfo.getEtx(&metric);
msg->source = TOS_NODE_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++;
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;
nextInt += SEND_INTERVAL >> 1;
call Timer.startOneShot(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 = call DisseminationPeriod.get();
call Timer.stop();
call Timer.startPeriodic(*newVal);
}
uint8_t prevSeq = 0;
uint8_t firstMsg = 0;
event message_t*
Receive.receive(message_t* msg, void* payload, uint8_t len) {
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) {
if (firstMsg == 1) {
if (call CollectionPacket.getSequenceNumber(msg) - prevSeq > 1) {
call Leds.led2On();
}
} else {
firstMsg = 1;
}
prevSeq = call CollectionPacket.getSequenceNumber(msg);
}
if (!call Pool.empty() && call Queue.size() < call Queue.maxSize()) {
message_t* tmp = call Pool.get();
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;
}
}
|