[Tinyos-contrib-commits]
CVS: tinyos-1.x/contrib/rincon/apps/MeshCollect/core
MeshAnalysisM.nc, NONE, 1.1 MeshAnalysis.h, NONE,
1.1 MeshManagerM.nc, NONE, 1.1 MeshTransferM.nc, NONE,
1.1 MeshAnalysisC.nc, NONE, 1.1
dmm
rincon at users.sourceforge.net
Thu Jul 27 16:38:27 PDT 2006
Update of /cvsroot/tinyos/tinyos-1.x/contrib/rincon/apps/MeshCollect/core
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18715/contrib/rincon/apps/MeshCollect/core
Added Files:
MeshAnalysisM.nc MeshAnalysis.h MeshManagerM.nc
MeshTransferM.nc MeshAnalysisC.nc
Log Message:
Added the MeshCollect component to CVS; Testing will continue on this component
--- NEW FILE: MeshAnalysisM.nc ---
/*
* Copyright (c) 2004-2006 Rincon Research Corporation.
* All rights reserved.
*
* Rincon Research will permit distribution and use by others subject to
* the restrictions of a licensing agreement which contains (among other things)
* the following restrictions:
*
* 1. No credit will be taken for the Work of others.
* 2. It will not be resold for a price in excess of reproduction and
* distribution costs.
* 3. Others are not restricted from copying it or using it except as
* set forward in the licensing agreement.
* 4. Commented source code of any modifications or additions will be
* made available to Rincon Research on the same terms.
* 5. This notice will remain intact and displayed prominently.
*
* Copies of the complete licensing agreement may be obtained by contacting
* Rincon Research, 101 N. Wilmot, Suite 101, Tucson, AZ 85711.
*
* There is no warranty with this product, either expressed or implied.
* Use at your own risk. Rincon Research is not liable or responsible for
* damage or loss incurred or resulting from the use or misuse of this software.
*/
/**
* After deploying a network, it's crucial to verify the
* network is set up correctly. This component helps do that.
*
* First, for the first X minutes of life, the component
* will attemp to send debug "analysis" type messages down the network
* to the base station. If the base station is connected to a computer,
* you will be able to gather the information about which nodes
* are connected together and their health. You can
* also listen in on the local network with an eavesdropper to verify
* which motes are connected together.
*
* After that functionality goes to sleep indefinitely, it's possible
* to request the same information from the network by walking by
* with a mote that's sending out single-hop analysis commands.
* The motes that hear the local analysis commands will respond with
* their current state through a multihop analysis message. This way,
* it's possible to construct a semi-realtime view of the network by
* walking around it and gathering the data locally or at the base station.
*
* Again, commands are sent to this component through Singlehop, and
* replies/analysis information is sent over Multihop.
*
* This component also serves as an example of how to use MeshCollect
*
*/
/**
* @author David Moss
*/
includes MeshAnalysis;
module MeshAnalysisM {
provides {
interface StdControl;
}
uses {
interface Timer as ReportTimer;
interface Transceiver as MultihopTransceiver;
interface Transceiver as SinglehopTransceiver;
interface Packet as MultihopPacket;
interface RouteControl;
interface RouteSelect;
interface State;
}
}
implementation {
/** The total number of times this mote has reported in */
uint8_t totalReports;
/** States */
enum {
S_IDLE = 0,
S_AUTOMATICALLY_REPORT,
};
/***************** Prototypes ****************/
task void startReporting();
task void reportIn();
/***************** StdControl Commands ****************/
command result_t StdControl.init() {
return SUCCESS;
}
command result_t StdControl.start() {
post startReporting();
return SUCCESS;
}
command result_t StdControl.stop() {
return SUCCESS;
}
/***************** ReportTimer Events ****************/
event result_t ReportTimer.fired() {
totalReports++;
if(totalReports > MAX_AUTOMATED_REPORTS) {
call State.toIdle();
call ReportTimer.stop();
}
post reportIn();
return SUCCESS;
}
/***************** SingleHopTransceiver Events ****************/
event result_t SinglehopTransceiver.radioSendDone(TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
event result_t SinglehopTransceiver.uartSendDone(TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
event TOS_MsgPtr SinglehopTransceiver.receiveRadio(TOS_MsgPtr m) {
switch(((MeshAnalysisMsg *) m->data)->cmd) {
case CMD_REPORT:
post reportIn();
break;
case CMD_ENABLE_ANALYSIS:
post startReporting();
break;
default:
break;
}
return m;
}
event TOS_MsgPtr SinglehopTransceiver.receiveUart(TOS_MsgPtr m) {
return m;
}
/***************** MultihopTransceiver Events ****************/
event result_t MultihopTransceiver.radioSendDone(TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
event result_t MultihopTransceiver.uartSendDone(TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
event TOS_MsgPtr MultihopTransceiver.receiveRadio(TOS_MsgPtr m) {
return m;
}
event TOS_MsgPtr MultihopTransceiver.receiveUart(TOS_MsgPtr m) {
return m;
}
/***************** RouteControl Events ****************/
event void RouteControl.connected(bool isConnected) {
}
/***************** Tasks ****************/
task void startReporting() {
if(!call State.requestState(S_AUTOMATICALLY_REPORT)) {
return;
}
totalReports = 0;
post reportIn();
call ReportTimer.start(TIMER_REPEAT, REPORT_DELAY);
}
/**
* Send a report of the health of this node to any local
* listeners, and the base station
*/
task void reportIn() {
TOS_Msg *tosPtr;
MeshAnalysisMsg *analysisMsg;
if((tosPtr = call MultihopTransceiver.requestWrite()) != NULL) {
analysisMsg = (MeshAnalysisMsg *) call MultihopPacket.getPayload(tosPtr, NULL);
analysisMsg->origin = TOS_LOCAL_ADDRESS;
analysisMsg->parent = call RouteControl.getParent();
analysisMsg->quality = call RouteControl.getQuality();
analysisMsg->depth = call RouteControl.getDepth();
analysisMsg->isActive = call RouteControl.isActive();
analysisMsg->cmd = REPLY_REPORT;
call MultihopTransceiver.sendRadio(0, sizeof(MeshAnalysisMsg));
}
}
}
--- NEW FILE: MeshAnalysis.h ---
/*
* Copyright (c) 2004-2006 Rincon Research Corporation.
* All rights reserved.
*
* Rincon Research will permit distribution and use by others subject to
* the restrictions of a licensing agreement which contains (among other things)
* the following restrictions:
*
* 1. No credit will be taken for the Work of others.
* 2. It will not be resold for a price in excess of reproduction and
* distribution costs.
* 3. Others are not restricted from copying it or using it except as
* set forward in the licensing agreement.
* 4. Commented source code of any modifications or additions will be
* made available to Rincon Research on the same terms.
* 5. This notice will remain intact and displayed prominently.
*
* Copies of the complete licensing agreement may be obtained by contacting
* Rincon Research, 101 N. Wilmot, Suite 101, Tucson, AZ 85711.
*
* There is no warranty with this product, either expressed or implied.
* Use at your own risk. Rincon Research is not liable or responsible for
* damage or loss incurred or resulting from the use or misuse of this software.
*/
/**
* 60 automated messages at 10 seconds between messages = 10 minutes of analysis.
*/
#ifndef REPORT_DELAY
#define REPORT_DELAY 10240
#endif
/**
* The maximum number of report messages to send out when automatic
* reporting is turned on.
*/
#ifndef MAX_AUTOMATED_REPORTS
#define MAX_AUTOMATED_REPORTS 60
#endif
typedef struct MeshAnalysisMsg {
uint16_t origin;
uint16_t parent;
uint16_t quality;
uint8_t depth;
bool isActive;
uint8_t cmd;
} MeshAnalysisMsg;
enum {
AM_MESHANALYSISMSG = 0xFA,
};
enum {
/** Get a single report from this mote */
CMD_REPORT = 0,
/** Start automated reporting, just like when the node is first powered on */
CMD_ENABLE_ANALYSIS = 1,
/** Single report from our mote */
REPLY_REPORT = 10,
/** No reply needed for enabling automated analysis */
};
--- NEW FILE: MeshManagerM.nc ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* Responsible for sending and receiving beacon messages
* for the continuous construction and maintenance of a
* collection network
*/
/**
* @author Gilman Tolle
* @author David Moss
*/
includes MeshCollect;
module MeshManagerM {
provides {
interface StdControl;
interface RouteSelect;
interface RouteControl;
}
uses {
interface Timer as NormalBeaconTimer;
interface Timer as QuickJoinTimer;
interface Transceiver as BeaconTransceiver;
interface State;
}
}
implementation {
/** TRUE if there is a valid route */
bool routeActive;
/** TRUE if this mote is a base station mote */
bool isBaseStation;
/** This mote's current selected parent */
uint16_t currentParent;
/** This mote's parent cost */
uint16_t currentParentCost;
/** This mote's current link quality estimate */
uint16_t currentLinkEst;
/** This mote's current depth in the network */
uint16_t currentHopCount;
/** Amount of update intervals that have passed since hearing a neighbor */
uint8_t lastResponseTime;
/** Current send message sequence number */
int16_t currentSeqNo;
/** The amount of time, in seconds, to send an update beacon */
uint16_t updateInterval;
/** The amount of time to delay before sending another quick join beacon */
uint16_t quickJoinInterval;
/** Local transmit packet history array index */
uint8_t recentLocalIndex;
/** Multihop origin history array index */
uint8_t recentOriginIndex;
/** Local transmit packet history send address array */
uint16_t recentLocalPacketSender[COLLECT_HISTORY_SIZE];
/** Local transmit packet history sequency number array */
int16_t recentLocalPacketSeqNo[COLLECT_HISTORY_SIZE];
/** Multihop origin address history */
uint16_t recentOriginPacketSender[COLLECT_HISTORY_SIZE];
/** Multihop origin sequence number history */
int16_t recentOriginPacketSeqNo[COLLECT_HISTORY_SIZE];
enum {
DEFAULT_BASE_STATION_ADDRESS = 0,
QUICKJOIN_INIT_TIME = 32,
QUICKJOIN_MAX_TIME = 16384,
DEFAULT_HOP_COUNT = 0xFFFF,
DEFAULT_PARENT_COST = 0x7FFF,
DEFAULT_LINK_EST = 0x7FFF,
DEFAULT_CURRENT_COST = 0xFFFE,
};
/**
* States
*/
enum {
S_IDLE = 0,
S_SENDING_BEACON,
};
/***************** Prototypes ****************/
uint16_t correlation(uint8_t val);
void sendBeacon(bool requestReply);
void continueQuickJoin();
void initializeParent();
void connected(bool isConnected);
task void startQuickJoin();
/***************** StdControl Commands ****************/
command result_t StdControl.init() {
int n;
recentLocalIndex = 0;
recentOriginIndex = 0;
for (n = 0; n < COLLECT_HISTORY_SIZE; n++) {
recentLocalPacketSender[n] = TOS_BCAST_ADDR;
recentLocalPacketSeqNo[n] = 0;
recentOriginPacketSender[n] = TOS_BCAST_ADDR;
recentOriginPacketSeqNo[n] = 0;
}
currentSeqNo = 0;
updateInterval = BEACON_PERIOD_SECONDS;
isBaseStation = (TOS_LOCAL_ADDRESS == DEFAULT_BASE_STATION_ADDRESS) || FORCE_BASE_STATION;
initializeParent();
return SUCCESS;
}
command result_t StdControl.start() {
lastResponseTime = 0;
call NormalBeaconTimer.start(TIMER_ONE_SHOT, 1024 * updateInterval);
if(!isBaseStation) {
post startQuickJoin();
}
return SUCCESS;
}
command result_t StdControl.stop() {
return SUCCESS;
}
/***************** RouteSelect Commands ****************/
/**
* Select a route and fill in all of the necessary routing
* information to a packet.
*
* @param msg Message to select route for and fill in routing information.
* @return SUCCESS if the route was selected succesfully. On FAIL the
* packet should not be sent.
*/
command result_t RouteSelect.selectRoute(TOS_MsgPtr msg, bool resend) {
int i;
TOS_CollectMsg *hopMsg = (TOS_CollectMsg *) msg->data;
if (hopMsg->originaddr != TOS_LOCAL_ADDRESS && !resend) {
// supress duplicate packets
for (i = 0; i < COLLECT_HISTORY_SIZE; i++) {
if ((recentLocalPacketSender[i] == hopMsg->sourceaddr) &&
(recentLocalPacketSeqNo[i] == hopMsg->seqno)) {
return FAIL;
}
}
recentLocalPacketSender[recentLocalIndex] = hopMsg->sourceaddr;
recentLocalPacketSeqNo[recentLocalIndex] = hopMsg->seqno;
recentLocalIndex = (recentLocalIndex + 1) % COLLECT_HISTORY_SIZE;
// supress multihop cycles and try to break out of it
for (i = 0; i < COLLECT_HISTORY_SIZE; i++) {
if ((recentOriginPacketSender[i] == hopMsg->originaddr) &&
(recentOriginPacketSeqNo[i] == hopMsg->originseqno)) {
currentParentCost = DEFAULT_PARENT_COST;
currentLinkEst = DEFAULT_LINK_EST;
currentParent = TOS_BCAST_ADDR;
currentHopCount = DEFAULT_HOP_COUNT;
connected(FALSE);
post startQuickJoin();
return FAIL;
}
}
recentOriginPacketSender[recentOriginIndex] = hopMsg->originaddr;
recentOriginPacketSeqNo[recentOriginIndex] = hopMsg->originseqno;
recentOriginIndex = (recentOriginIndex + 1) % COLLECT_HISTORY_SIZE;
}
if (!resend) {
hopMsg->seqno = currentSeqNo++;
}
hopMsg->sourceaddr = TOS_LOCAL_ADDRESS;
msg->addr = currentParent;
return SUCCESS;
}
/**
* Given a TOS_MstPtr, initialize its routing fields to a known
* state, specifying that the message is originating from this node.
* This known state can then be used by selectRoute() to fill in
* the necessary data.
*
* @param msg Message to select route for and fill in init data.
*/
command void RouteSelect.initializeFields(TOS_MsgPtr msg, uint8_t id) {
TOS_CollectMsg *hopMsg = (TOS_CollectMsg *) msg->data;
hopMsg->signature = COLLECT_SIGNATURE;
hopMsg->sourceaddr = TOS_LOCAL_ADDRESS;
hopMsg->originaddr = TOS_LOCAL_ADDRESS;
hopMsg->originseqno = currentSeqNo;
hopMsg->hopcount = currentHopCount;
}
/**
* Given a TinyOS message buffer, provide a pointer to the data
* buffer within it that an application can use as well as its
* length. Unlike the getBuffer of the Send interface, this can
* be called freely and does not modify the buffer.
*
* @param msg The message to get the data region of.
* @param length Pointer to a field to store the length of the data region.
* @return a pointer to the data region.
*/
command void *RouteSelect.getBuffer(TOS_MsgPtr msg, uint16_t *len) {
TOS_CollectMsg *hopMsg = (TOS_CollectMsg *) msg->data;
*len = sizeof(hopMsg->data);
return ((TOS_CollectMsg *) msg->data)->data;
}
/***************** RouteControl Commands ****************/
/**
* @return TRUE if there is a valid route.
*/
command bool RouteControl.isActive() {
return routeActive;
}
/**
* @return The address of the parent
*/
command uint16_t RouteControl.getParent() {
return currentParent;
}
/**
* @return A value between 0-256 where 256 represent the best
* goodness
*/
command uint8_t RouteControl.getQuality() {
return currentLinkEst;
}
/**
* Get this node's depth in the network
*
* @return The network depth.
*/
command uint8_t RouteControl.getDepth() {
return currentHopCount;
}
/**
* Get the previous hop sender for the given TOS_Msg
*
* @param msg Pointer to the TOS_Msg of interest
* @return the address of the sender.
*/
command uint16_t RouteControl.getSender(TOS_MsgPtr msg) {
return ((TOS_CollectMsg *) msg->data)->sourceaddr;
}
/**
* Set the routing componenets internal update interval.
*
* @param intervalInSeconds The duration, in seconds, of
* successive routing updates.
*/
command void RouteControl.setUpdateInterval(uint16_t intervalInSeconds) {
if(intervalInSeconds > 0) {
updateInterval = intervalInSeconds;
}
}
/**
* Queue a manual update of the routing state. This may or may
* not include the transmission of a message.
*/
command void RouteControl.manualUpdate() {
sendBeacon(TRUE);
}
/**
* Dynamically turn this mote into a base
* station that will collect data from the
* network and drain the data to its UART
* @param baseStation TRUE to turn this into a base station
* FALSE to make it a regular node in the network
*/
command void RouteControl.setBaseStation(bool baseStation) {
if(isBaseStation == baseStation) {
// Nothing needs to happen
return;
}
isBaseStation = baseStation;
initializeParent();
if(!isBaseStation) {
post startQuickJoin();
}
}
/**
* @return TRUE if this mote is a base station mote
*/
command bool RouteControl.isBaseStation() {
return isBaseStation;
}
/***************** Timer Events ****************/
event result_t NormalBeaconTimer.fired() {
lastResponseTime++;
if ((TOS_LOCAL_ADDRESS != 0) && (lastResponseTime > BEACON_TIMEOUT)) {
// We've lost the connection to our parent
currentParent = TOS_BCAST_ADDR;
currentParentCost = DEFAULT_PARENT_COST;
currentLinkEst = DEFAULT_LINK_EST;
currentHopCount = DEFAULT_HOP_COUNT;
connected(FALSE);
// Start the quick join, but don't immediately re-run it if it's not working:
lastResponseTime = 0;
post startQuickJoin();
}
sendBeacon(FALSE);
call NormalBeaconTimer.start(TIMER_ONE_SHOT, 1024 * updateInterval);
return SUCCESS;
}
event result_t QuickJoinTimer.fired() {
continueQuickJoin();
sendBeacon(TRUE);
return SUCCESS;
}
/***************** BeaconTransceiver Events ****************/
/**
* A message was sent over radio.
* @param m - a pointer to the sent message, valid for the duration of the
* event.
* @param result - SUCCESS or FAIL.
*/
event result_t BeaconTransceiver.radioSendDone(TOS_MsgPtr m, result_t result) {
call State.toIdle();
return SUCCESS;
}
/**
* A message was sent over UART.
* @param m - a pointer to the sent message, valid for the duration of the
* event.
* @param result - SUCCESS or FAIL.
*/
event result_t BeaconTransceiver.uartSendDone(TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
/**
* Received a message over the radio
* @param m - the receive message, valid for the duration of the
* event.
*/
event TOS_MsgPtr BeaconTransceiver.receiveRadio(TOS_MsgPtr m) {
TOS_CollectMsg *hopMsg = (TOS_CollectMsg *) m->data;
BeaconMsg *beaconPayload = (BeaconMsg *) hopMsg->data;
if(beaconPayload->requestReply) {
sendBeacon(FALSE);
}
if(isBaseStation) {
return m;
}
/*
* If the message is from my parent store the new link estimation
* Prevent cycles by checking the receive message's parent.
*/
if (hopMsg->sourceaddr == currentParent) {
if (beaconPayload->parent != TOS_LOCAL_ADDRESS) {
// This mote is my parent already and sent an update
lastResponseTime = 0;
currentParentCost = beaconPayload->cost;
currentLinkEst = correlation(m->strength);
currentHopCount = hopMsg->hopcount + 1;
connected(TRUE);
call QuickJoinTimer.stop();
} else {
// This mote has selected me as its parent; it is no longer my parent.
lastResponseTime = 0;
currentParentCost = DEFAULT_PARENT_COST;
currentLinkEst = DEFAULT_LINK_EST;
currentParent = TOS_BCAST_ADDR;
currentHopCount = DEFAULT_HOP_COUNT;
connected(FALSE);
post startQuickJoin();
}
} else {
/*
* If the message is not from my parent,
* compare the message's cost + link estimate to my current cost,
* switch if necessary. Make sure you don't pick a parent
* that creates a cycle.
*/
if ((beaconPayload->parent != TOS_LOCAL_ADDRESS)
&& (beaconPayload->parent != TOS_BCAST_ADDR)
&& ((uint32_t) beaconPayload->cost + (uint32_t) correlation(m->strength) <
((uint32_t) currentParentCost + (uint32_t) currentLinkEst)
- (((uint32_t) currentParentCost + (uint32_t) currentLinkEst) >> 2))) {
// This is my new parent
lastResponseTime = 0;
currentParent = hopMsg->sourceaddr;
currentParentCost = beaconPayload->cost;
currentLinkEst = correlation(m->strength);
currentHopCount = hopMsg->hopcount + 1;
connected(TRUE);
call QuickJoinTimer.stop();
}
}
return m;
}
/**
* Received a message over UART
* @param m - the receive message, valid for the duration of the
* event.
*/
event TOS_MsgPtr BeaconTransceiver.receiveUart(TOS_MsgPtr m) {
return m;
}
/***************** Tasks ****************/
task void startQuickJoin() {
quickJoinInterval = QUICKJOIN_INIT_TIME;
call QuickJoinTimer.start(TIMER_ONE_SHOT, quickJoinInterval);
}
/***************** Functions ****************/
void sendBeacon(bool requestReply) {
TOS_Msg *tosPtr;
TOS_CollectMsg *hopMsg;
BeaconMsg *beaconPayload;
if(!call State.requestState(S_SENDING_BEACON)) {
return;
}
if((tosPtr = call BeaconTransceiver.requestWrite()) != NULL) {
hopMsg = (TOS_CollectMsg *) tosPtr->data;
beaconPayload = (BeaconMsg *) hopMsg->data;
memset(tosPtr->data, 0, sizeof(tosPtr->data));
beaconPayload->parent = currentParent;
beaconPayload->cost = currentParentCost + currentLinkEst;
beaconPayload->requestReply = requestReply;
hopMsg->signature = COLLECT_SIGNATURE;
hopMsg->sourceaddr = TOS_LOCAL_ADDRESS;
hopMsg->originaddr = TOS_LOCAL_ADDRESS;
hopMsg->hopcount = currentHopCount;
hopMsg->originseqno = currentSeqNo;
hopMsg->seqno = currentSeqNo++;
call BeaconTransceiver.sendRadio(TOS_BCAST_ADDR, offsetof(TOS_CollectMsg, data) + sizeof(BeaconMsg));
}
}
void continueQuickJoin() {
quickJoinInterval *= 2;
if(quickJoinInterval <= QUICKJOIN_MAX_TIME) {
call QuickJoinTimer.start(TIMER_ONE_SHOT, quickJoinInterval);
}
}
uint16_t correlation(uint8_t v) {
uint16_t c = (80 - (v - 40));
c = (((c * c) >> 3) * c) >> 3;
return c;
}
/**
* Initialize the default parent properties
*/
void initializeParent() {
if (isBaseStation) {
currentParent = TOS_UART_ADDR;
currentParentCost = 0;
currentLinkEst = 0;
currentHopCount = 0;
connected(TRUE);
} else {
currentParent = TOS_BCAST_ADDR;
currentParentCost = DEFAULT_PARENT_COST;
currentLinkEst = DEFAULT_LINK_EST;
currentHopCount = DEFAULT_HOP_COUNT;
connected(FALSE);
}
}
/**
* Executed when our connection status changes
*/
void connected(bool isConnected) {
routeActive = isConnected;
signal RouteControl.connected(routeActive);
}
}
--- NEW FILE: MeshTransferM.nc ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
* MeshCollect is based on MultiHopLQI with some changes and a few improvements.
*
* Its goal is to setup and provide the ability to do data collection
* to a base station node for data exfiltration.
*
* It accepts messages from both applications and the network and does
* the necessary interception and forwarding.
*
* It interfaces to an algorithmic componenet via RouteSelect.
*/
/**
* @author Philip Buonadonna
* @author Alec Woo
* @author David Moss
*/
includes AM;
includes MeshCollect;
module MeshTransferM {
provides {
interface StdControl;
interface Transceiver as MultihopTransceiver[uint8_t id];
interface Packet as MultihopPacket;
}
uses {
interface Transceiver as SubTransceiver[uint8_t id];
interface Packet as SubPacket;
interface RouteControl;
interface RouteSelect;
}
}
implementation {
enum {
/** Maximum amount of times to retry sending a failed message */
MAX_RETRIES = 10,
};
/** The number of times the current send message hasn't received an ack */
uint8_t failCount;
/***************** Prototypes ****************/
/***************** StdControl Commands ****************/
command result_t StdControl.init() {
failCount = 0;
return SUCCESS;
}
command result_t StdControl.start() {
return SUCCESS;
}
command result_t StdControl.stop() {
return SUCCESS;
}
/***************** MultihopTransceiver Commands ****************/
/**
* Request a pointer to an empty TOS_Msg.data payload buffer.
* This will allocate one TOS_Msg to the requesting AM type.
* This message will be allocated to the requesting AM type until
* it is sent.
*
* You must call sendRadio(..) or sendUart(..) when finished
* to release the pointer and send the message.
*
* @return a TOS_MsgPtr to an allocated TOS_Msg if available,
* NULL if no buffer is available.
*/
command TOS_MsgPtr MultihopTransceiver.requestWrite[uint8_t id]() {
TOS_Msg *requestMsg;
if(!call RouteControl.isActive()) {
return NULL;
}
if((requestMsg = call SubTransceiver.requestWrite[id]()) != NULL) {
// The message is a reuse from the pool, so clear it.
call SubPacket.clear(requestMsg);
call RouteSelect.initializeFields(requestMsg, id);
// TODO this is CC1000 specific. We need a general up-to-date
// interface to enable ack's.
requestMsg->ack = 1;
return requestMsg;
} else {
return NULL;
}
}
/**
* Check if a TOS_Msg has already been allocated by
* the MultihopTransceiver from requestWrite(). Note that if a
* TOS_Msg is already allocated to the requesting AM type,
* calling requestWrite() again will return a pointer
* to the TOS_Msg that is already allocated.
* @return TRUE if requestWrite has been called and a TOS_Msg
* has been allocated to the current AM type.
*/
command bool MultihopTransceiver.isWriteOpen[uint8_t id]() {
return call SubTransceiver.isWriteOpen[id]();
}
/**
* Release and send the current contents of the payload buffer over
* the radio to the given address, with the given payload size.
* @param dest - the destination address
* @param size - the size of the structure inside the TOS_Msg payload.
* @return SUCCESS if the buffer will be sent. FAIL if no buffer
* had been allocated by requestWrite().
*/
command result_t MultihopTransceiver.sendRadio[uint8_t id](uint16_t dest, uint8_t payloadSize) {
uint8_t msgLength = offsetof(TOS_CollectMsg, data) + payloadSize;
if (msgLength > TOSH_DATA_LENGTH) {
msgLength = TOSH_DATA_LENGTH;
}
call RouteSelect.selectRoute(call SubTransceiver.requestWrite[id](), FALSE);
if(call RouteControl.getParent() == TOS_UART_ADDR) {
return call SubTransceiver.sendUart[id](msgLength);
} else {
return call SubTransceiver.sendRadio[id](call RouteControl.getParent(), msgLength);
}
}
/**
* Release and send the current contents of the payload buffer over
* UART with the given payload size. No address is needed.
* @param size - the size of the structure inside the TOS_Msg payload.
* @return SUCCESS if the buffer will be sent. FAIL if no buffer
* had been allocated by requestWrite().
*/
command result_t MultihopTransceiver.sendUart[uint8_t id](uint8_t payloadSize) {
return call SubTransceiver.sendUart[id](payloadSize);
}
/**
* Attempt to resend the last message sent by this AM type.
* If the message still exists in the pool and the attempt
* proceeds, SUCCESS will be signaled. Otherwise, FAIL will
* be signaled. In that case, the requesting module will have
* to reconstruct the message and try sending it again.
* @return SUCCESS if the attempt proceeds, and sendDone(..) will be signaled.
*/
command result_t MultihopTransceiver.resendRadio[uint8_t id]() {
// The message was already checked; seqno is off. Don't resend.
return FAIL;
}
/**
* @return TRUE if the requesting AM type is in the process of being sent.
*/
command bool MultihopTransceiver.isSending[uint8_t id]() {
return call SubTransceiver.isSending[id]();
}
/***************** Packet Events ****************/
/**
* Clear out this packet. Note that this is a deep operation and
* total operation: calling clear() on any layer will completely
* clear the packet for reuse.
*/
command void MultihopPacket.clear(TOS_MsgPtr msg) {
call SubPacket.clear(msg);
}
/**
* Return the length of the payload of msg. This value may be less
* than what maxPayloadLength() returns, if the packet is smaller than
* the MTU. If a communication component does not support variably
* sized data regions, then payloadLength() will always return
* the same value as maxPayloadLength().
*/
command uint8_t MultihopPacket.payloadLength(TOS_MsgPtr msg) {
return call SubPacket.payloadLength(msg) - offsetof(TOS_CollectMsg, data);
}
/**
* Return the maximum payload length that this communication layer
* can provide. Note that, depending on protocol fields, a
* given request to send a packet may not be able to send the
* maximum payload length (e.g., if there are variable length
* fields). Protocols may provide specialized interfaces
* for these circumstances.
*/
command uint8_t MultihopPacket.maxPayloadLength() {
return call SubPacket.maxPayloadLength() - offsetof(TOS_CollectMsg, data);
}
/**
* Return point to a protocol's payload region in a packet.
* If len is not NULL, getPayload will return the length of
* the payload in it, which is the same as the return value
* from payloadLength(). If a protocol does not support
* variable length packets, then *len is equal to
* maxPayloadLength().
*/
command void *MultihopPacket.getPayload(TOS_MsgPtr msg, uint8_t *len) {
*len = call MultihopPacket.payloadLength(msg);
return (((TOS_CollectMsg *) msg->data)->data);
}
/***************** SubTransceiver Events *****************/
/**
* A message was sent over radio.
* @param m - a pointer to the sent message, valid for the duration of the
* event.
* @param result - SUCCESS or FAIL.
*/
event result_t SubTransceiver.radioSendDone[uint8_t id](TOS_MsgPtr m, result_t result) {
if(((TOS_CollectMsg *) m->data)->signature != COLLECT_SIGNATURE) {
return SUCCESS;
}
if(!(m->ack) &&
m->addr != TOS_BCAST_ADDR &&
m->addr != TOS_UART_ADDR &&
failCount < MAX_RETRIES) {
failCount++;
call RouteSelect.selectRoute(m, TRUE);
call SubTransceiver.resendRadio[id]();
return SUCCESS;
}
failCount = 0;
if(((TOS_CollectMsg *) m->data)->originaddr == TOS_LOCAL_ADDRESS) {
signal MultihopTransceiver.radioSendDone[id](m, (failCount < MAX_RETRIES));
}
return SUCCESS;
}
/**
* A message was sent over UART.
* @param m - a pointer to the sent message, valid for the duration of the
* event.
* @param result - SUCCESS or FAIL.
*/
event result_t SubTransceiver.uartSendDone[uint8_t id](TOS_MsgPtr m, result_t result) {
signal MultihopTransceiver.radioSendDone[id](m, result);
return SUCCESS;
}
/**
* Received a message over the radio
* @param m - the receive message, valid for the duration of the
* event.
*/
event TOS_MsgPtr SubTransceiver.receiveRadio[uint8_t id](TOS_MsgPtr m) {
TOS_Msg *tosPtr;
if(((TOS_CollectMsg *) m->data)->signature == COLLECT_SIGNATURE
&& m->type != AM_BEACONMSG
&& m->addr != TOS_BCAST_ADDR) {
/*
* Reconfigure the receive message buffer to select a route
* Then request a new send message, memcpy the received msg
* to the send msg, and send it.
*/
if((tosPtr = call SubTransceiver.requestWrite[id]()) != NULL) {
call SubPacket.clear(tosPtr);
memcpy(tosPtr->data, m->data, m->length);
call RouteSelect.selectRoute(tosPtr, FALSE);
if(tosPtr->addr == TOS_UART_ADDR) {
call SubTransceiver.sendUart[id](m->length);
} else {
call SubTransceiver.sendRadio[id](call RouteControl.getParent(), m->length);
}
}
}
return m;
}
/**
* Received a message over UART
* @param m - the receive message, valid for the duration of the
* event.
*/
event TOS_MsgPtr SubTransceiver.receiveUart[uint8_t id](TOS_MsgPtr m) {
return m;
}
/***************** RouteControl Events ****************/
event void RouteControl.connected(bool isConnected) {
}
/***************** Functions ****************/
/***************** Defaults ****************/
default event result_t MultihopTransceiver.radioSendDone[uint8_t id](TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
default event result_t MultihopTransceiver.uartSendDone[uint8_t id](TOS_MsgPtr m, result_t result) {
return SUCCESS;
}
default event TOS_MsgPtr MultihopTransceiver.receiveRadio[uint8_t id](TOS_MsgPtr m) {
return m;
}
default event TOS_MsgPtr MultihopTransceiver.receiveUart[uint8_t id](TOS_MsgPtr m) {
return m;
}
}
--- NEW FILE: MeshAnalysisC.nc ---
/*
* Copyright (c) 2004-2006 Rincon Research Corporation.
* All rights reserved.
*
* Rincon Research will permit distribution and use by others subject to
* the restrictions of a licensing agreement which contains (among other things)
* the following restrictions:
*
* 1. No credit will be taken for the Work of others.
* 2. It will not be resold for a price in excess of reproduction and
* distribution costs.
* 3. Others are not restricted from copying it or using it except as
* set forward in the licensing agreement.
* 4. Commented source code of any modifications or additions will be
* made available to Rincon Research on the same terms.
* 5. This notice will remain intact and displayed prominently.
*
* Copies of the complete licensing agreement may be obtained by contacting
* Rincon Research, 101 N. Wilmot, Suite 101, Tucson, AZ 85711.
*
* There is no warranty with this product, either expressed or implied.
* Use at your own risk. Rincon Research is not liable or responsible for
* damage or loss incurred or resulting from the use or misuse of this software.
*/
/**
* After deploying a network, it's crucial to verify the
* network is set up correctly. This component helps do that.
*
* First, for the first X minutes of life, the component
* will attemp to send debug "analysis" type messages down the network
* to the base station. If the base station is connected to a computer,
* you will be able to gather the information about which nodes
* are connected together and their health. You can
* also listen in on the local network with an eavesdropper to verify
* which motes are connected together.
*
* After that functionality goes to sleep indefinitely, it's possible
* to request the same information from the network by walking by
* with a mote that's sending out single-hop analysis commands.
* The motes that hear the local analysis commands will respond with
* their current state through a multihop analysis message. This way,
* it's possible to construct a semi-realtime view of the network by
* walking around it and gathering the data locally or at the base station.
*
* Again, commands are sent to this component through Singlehop, and
* replies/analysis information is sent over Multihop.
*
* This component also serves as an example of how to use MeshCollect
*
*/
/**
* @author David Moss
*/
includes MeshAnalysis;
configuration MeshAnalysisC {
provides {
interface StdControl;
}
}
implementation {
components MeshAnalysisM, MeshCollectC, StateC, TimerC;
StdControl = MeshAnalysisM;
MeshAnalysisM.MultihopTransceiver -> MeshCollectC.MultihopTransceiver[AM_MESHANALYSISMSG];
MeshAnalysisM.SinglehopTransceiver -> MeshCollectC.SinglehopTransceiver[AM_MESHANALYSISMSG];
MeshAnalysisM.MultihopPacket -> MeshCollectC.MultihopPacket;
MeshAnalysisM.RouteControl -> MeshCollectC;
MeshAnalysisM.ReportTimer -> TimerC.Timer[unique("Timer")];
MeshAnalysisM.State -> StateC.State[unique("State")];
}
More information about the Tinyos-contrib-commits
mailing list