⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disseminationengineimplp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
#include <DisseminationEngine.h>

/*
 * Copyright (c) 2006 Arch Rock Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the
 *   distribution.
 * - Neither the name of the Arch Rock Corporation nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE
 *
 */

/**
 * The DisseminationEngineImplP component implements the dissemination
 * logic.
 *
 * See TEP118 - Dissemination for details.
 * 
 * @author Gilman Tolle <gtolle@archrock.com>
 * @version $Revision: 1.1 $ $Date: 2007/09/14 00:22:18 $
 */

module DisseminationEngineImplP {
  provides interface StdControl;

  uses {
    interface DisseminationCache[uint16_t key];
    interface TrickleTimer[uint16_t key];
    interface StdControl as DisseminatorControl[uint16_t id];

    interface AMSend;
    interface Receive;

    interface AMSend as ProbeAMSend;
    interface Receive as ProbeReceive;

    interface Leds;
  }
}
implementation {

  enum { NUM_DISSEMINATORS = uniqueCount("DisseminationTimerC.TrickleTimer") };

  message_t m_buf;
  bool m_running;
  bool m_bufBusy;

  void sendProbe( uint16_t key );
  void sendObject( uint16_t key );

  command error_t StdControl.start() {
    uint8_t i;
    for ( i = 0; i < NUM_DISSEMINATORS; i++ ) {
      call DisseminatorControl.start[ i ]();
    }
    m_running = TRUE;
    return SUCCESS;
  }

  command error_t StdControl.stop() {
    uint8_t i;
    for ( i = 0; i < NUM_DISSEMINATORS; i++ ) {
      call DisseminatorControl.stop[ i ]();
    }
    m_running = FALSE;
    return SUCCESS;
  }

  event error_t DisseminationCache.start[ uint16_t key ]() {
    error_t result = call TrickleTimer.start[ key ]();
    call TrickleTimer.reset[ key ]();
    return result;
  }

  event error_t DisseminationCache.stop[ uint16_t key ]() {
    call TrickleTimer.stop[ key ]();
    return SUCCESS;
  }

  event void DisseminationCache.newData[ uint16_t key ]() {

    if ( !m_running || m_bufBusy ) { return; }

    sendObject( key );
    call TrickleTimer.reset[ key ]();
  }

  event void TrickleTimer.fired[ uint16_t key ]() {

    if ( !m_running || m_bufBusy ) { return; }

    sendObject( key );
  }

  void sendProbe( uint16_t key ) {
    dissemination_probe_message_t* dpMsg = 
      (dissemination_probe_message_t*) call ProbeAMSend.getPayload( &m_buf, sizeof(dissemination_probe_message_t));
    if (dpMsg != NULL) {
      m_bufBusy = TRUE;
      
      dpMsg->key = key;
      
      call ProbeAMSend.send( AM_BROADCAST_ADDR, &m_buf,
			     sizeof( dissemination_probe_message_t ) );
    }
  }

  void sendObject( uint16_t key ) {
    void* object;
    uint8_t objectSize = 0;
    
    dissemination_message_t* dMsg = 
      (dissemination_message_t*) call AMSend.getPayload( &m_buf, sizeof(dissemination_message_t) );
    if (dMsg != NULL) {
      m_bufBusy = TRUE;
      
      dMsg->key = key;
      dMsg->seqno = call DisseminationCache.requestSeqno[ key ]();
      
      if ( dMsg->seqno != DISSEMINATION_SEQNO_UNKNOWN ) {
	object = call DisseminationCache.requestData[ key ]( &objectSize );
	if ((objectSize + sizeof(dissemination_message_t)) > 
	    call AMSend.maxPayloadLength()) {
	  objectSize = call AMSend.maxPayloadLength() - sizeof(dissemination_message_t);
	}
	memcpy( dMsg->data, object, objectSize );
      }      
      call AMSend.send( AM_BROADCAST_ADDR,
			&m_buf, sizeof( dissemination_message_t ) + objectSize );
    }
  }

  event void ProbeAMSend.sendDone( message_t* msg, error_t error ) {
    m_bufBusy = FALSE;
  }

  event void AMSend.sendDone( message_t* msg, error_t error ) {
    m_bufBusy = FALSE;
  }

  event message_t* Receive.receive( message_t* msg, 
				    void* payload, 
				    uint8_t len ) {

    dissemination_message_t* dMsg = 
      (dissemination_message_t*) payload;

    uint16_t key = dMsg->key;
    uint32_t incomingSeqno = dMsg->seqno;
    uint32_t currentSeqno = call DisseminationCache.requestSeqno[ key ]();

    if ( !m_running ) { return msg; }

    if ( currentSeqno == DISSEMINATION_SEQNO_UNKNOWN &&
	 incomingSeqno != DISSEMINATION_SEQNO_UNKNOWN ) {

      call DisseminationCache.storeData[ key ]
	( dMsg->data, 
	  len - sizeof( dissemination_message_t ),
	  incomingSeqno );
      
      call TrickleTimer.reset[ key ]();
      return msg;
    }

    if ( incomingSeqno == DISSEMINATION_SEQNO_UNKNOWN &&
	 currentSeqno != DISSEMINATION_SEQNO_UNKNOWN ) {

      call TrickleTimer.reset[ key ]();
      return msg;
    }

    if ( (int32_t)( incomingSeqno - currentSeqno ) > 0 ) {

      call DisseminationCache.storeData[key]
	( dMsg->data, 
	  len - sizeof(dissemination_message_t),
	  incomingSeqno );
      dbg("Dissemination", "Received dissemination value 0x%08x,0x%08x @ %s\n", (int)key, (int)incomingSeqno, sim_time_string());
      call TrickleTimer.reset[ key ]();

    } else if ( (int32_t)( incomingSeqno - currentSeqno ) == 0 ) {
      
      call TrickleTimer.incrementCounter[ key ]();

    } else {

      // Still not sure which of these is the best. Immediate send for now.
      sendObject( key );
      // call TrickleTimer.reset[ key ]();

    }

    return msg;
  }

  event message_t* ProbeReceive.receive( message_t* msg, 
					 void* payload, 
					 uint8_t len) {
    
    dissemination_probe_message_t* dpMsg = 
      (dissemination_probe_message_t*) payload;

    if ( !m_running ) { return msg; }

    if ( call DisseminationCache.requestSeqno[ dpMsg->key ]() != 
	 DISSEMINATION_SEQNO_UNKNOWN ) {    
      sendObject( dpMsg->key );
    }

    return msg;
  }
  
  default command void* 
    DisseminationCache.requestData[uint16_t key]( uint8_t* size ) { return NULL; }

  default command void 
    DisseminationCache.storeData[uint16_t key]( void* data, 
						uint8_t size, 
						uint32_t seqno ) {}

  default command uint32_t 
    DisseminationCache.requestSeqno[uint16_t key]() { return DISSEMINATION_SEQNO_UNKNOWN; }

  default command error_t TrickleTimer.start[uint16_t key]() { return FAIL; }

  default command void TrickleTimer.stop[uint16_t key]() { }

  default command void TrickleTimer.reset[uint16_t key]() { }

  default command void TrickleTimer.incrementCounter[uint16_t key]() { }

  default command error_t DisseminatorControl.start[uint16_t id]() { return FAIL; }
  default command error_t DisseminatorControl.stop[uint16_t id]() { return FAIL; }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -