[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