1

nesCコードに問題があります。私のコードでは、を使用して最初のパケットを送信しAMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))ます。

その後、機能でメッセージを受信するevent message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){と、応答が生成されて正常に送信されますが、他のノードは応答を受信できません。特に、DSRプロトコルの基本に従って、RREP応答を処理する必要があります。これは私のコードです:

implementation{


/**********************Variables used*****************************/
short phase = 0;
message_t packet;
bool locked;

event void Boot.booted(){
    dbg("Boot", "Node %hhu booted\n", TOS_NODE_ID);
    call AMControl.start(); 


}

  [cut]

event void MilliTimer.fired(){
    /*This contains the discovery message*/
    rd_message *rreq = NULL;

    if (phase == 0){
        //Route discovery phase
        rreq = (rd_message *) call Packet.getPayload(&packet, (int) NULL);


        if(call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) == SUCCESS){
        //locked = TRUE;

        }
        return;
    }

}


event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){
    rd_message *received_mex = NULL;  
    rd_message *reply_mex = NULL;

    int i,j;

    received_mex = (rd_message*) payload;   //cast to rd_message

      if (received_mex->type == RREQ){
          reply_mex = (rd_message*) call Packet.getPayload(&packet, (int) NULL);  //reply packet is created.
        if (received_mex->sender_id == TOS_NODE_ID){
          //The original sender received its RREQ. Stopping the forward procedure
          return bufPtr;   //FIXME: see if it's correct to return null here
        }

        //RREQ message case 1: I am not the receiver_id
        if (received_mex->receiver_id != TOS_NODE_ID){

        }
        else if (received_mex->receiver_id == TOS_NODE_ID){
          //I am the receiver of the RREQ message. I can now reply with a RREP

        }


        if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) == SUCCESS) {
                dbg("dsr", "packet sent\n");    
                //locked = TRUE;
            }
        else{
          dbg("dsr", "failed to send reply packet.\n");

        }


      }
      else if (received_mex->type == RREP){
       //DO SOMETHING WITH CHE NEW RECEIVED MESSAGE HERE

      }

    return bufPtr;


}


  event void AMSend.sendDone(message_t* bufPtr, error_t error) {
    if (&packet == bufPtr) {
      //locked = FALSE;
    }
  }

メッセージ交換呼び出しに焦点を合わせるために、コードからすべてのロジックを削除しました。誰かが私を助けてくれることを願っています...ありがとう。

4

1 に答える 1

4

TinyOS はほとんどすべての場所で所有権の規律に従います。どの時点でも、すべての「メモリ オブジェクト」 (メモリの一部、通常は変数全体または単一の配列要素) は、単一のモジュールによって所有されている必要があります。コマンド likesendは、その msg 引数の所有権を呼び出し元から呼び出し先に渡すと言われています。

コードの主な問題は、変数を 2 つの方法でReceive.receive使用している場合です。packet

  • 呼び出しによる発信パケットとしてcall AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))
  • 実行することにより、次の着信パケットのバッファとしてreturn bufPtr;

このコードの結果は予測できません (パケットを受信すると発信パケットが破損するため)。問題を解決するには、Pool<message_t>コンポーネントを使用する必要があります。あなたのようなプログラムの典型的な疑似コードは次のようなものです:

  1. 受信 (m):
  2. このメッセージを処理する必要がない場合は、m を返します
  3. フリー パケット リストが空の場合は、m を返します
  4. そうしないと
    1. プロセス/転送 m
    2. フリー パケット リストからエントリを返す

Pool<message_t>これは、通信を管理するためのフリー パケットのリストとして使用するモジュールの大まかな実装です。

module Foo
{
    /* this is our free packet list */
    uses interface Pool<message_t>;
    uses interface Receive;
    uses interface AMSend;
}

implementation
{

event void MilliTimer.fired()
{
    message_t *packet;
    /* get a free packet */
    packet = Pool.get();
    if (packet)
    {
        /* code to send the packet */
    }
}

event void AMSend.sendDone(message_t *msg, error_t error)
{
    /* the send function ended, put back the packet in the free packet pool */
    /* check here if msg was taken from Pool */
    call Pool.put(msg);
}

event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
{
    if (!haveToProcess(msg))
        return msg; // don't have to process this message
    if (Pool.empty())
        return msg; // memory exahusted;
    /* ... */
    /* code that processes the packet */
    call AMSend.send(AM_BROADCAST_ADDR, msg, sizeof(rd_message));
    /* return a free message_t* as buffer to store the next received packet */
    return Pool.get();
}

}

が気に入らない場合は、配列を循環バッファーとしてPool使用できます。その方法のヒントについてはmessage_tBaseStationコードを参照してください。

詳細については、TinyOS プログラミングの本、特にセクション 3.5.1 を読むことをお勧めします。

あなたのコメントについて:

return bufPtr;   //FIXME: see if it's correct to return null here

TinyOS は着信パケットを格納するために常にバッファーを必要とするため、受信イベントで戻ることはできません。NULL

于 2010-09-01T20:40:48.793 に答える