📄 networkm.nc
字号:
uint8_t rootId = 0; bool amRoot = checkRoot(msg, &rootId); mMsg = msg; mAmId = kQUERY_MESSAGE_ID; if (!mRadio) { mRadio = TRUE; initHeader(&nw->hdr, amRoot, rootId); mRetryCnt = QUERY_RETRIES; if (call SendQueryMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) == SUCCESS) { call Leds.redToggle(); return err_NoError; } else { mIdx--; //failed to send -- undo counter mRadio = FALSE; return err_MessageSendFailed; } } return err_MessageSendFailed; }#ifdef kQUERY_SHARING command QueryRequestMessagePtr Network.getQueryRequestPayLoad(TOS_MsgPtr msg) { return (QueryRequestMessagePtr)&((NetworkMessage*)msg->data)->data[0]; } /* Send a request for a query message to neighbors REQUIRES: msg is a message buffer of which the first entry is of type DbMsgHdr SIGNALS: TINYDB_NETWORK_SUB_MSG_SEND_DONE after message is sent, unless an error is returned. RETURNS: err_NoError if no error err_MessageSendFailed if transmission fails. */ command TinyDBError Network.sendQueryRequest(TOS_MsgPtr msg, uint16_t to) { NetworkMessage *nw = (NetworkMessage *)msg->data; uint8_t rootId = 0; bool amRoot = checkRoot(msg, &rootId); mMsg = msg; mAmId = kQUERY_REQUEST_MESSAGE_ID; if (!mRadio) { mRadio = TRUE; initHeader(&nw->hdr, amRoot, rootId); if (call SendQueryRequest.send(to, kMSG_LEN, msg) == SUCCESS) { return err_NoError; } else { mRadio = FALSE; return err_MessageSendFailed; } } return err_MessageSendFailed; }#endif /* Called when the network component has finished delivering a message. */ result_t sendDone(TOS_MsgPtr msg, result_t success) { dbg(DBG_USR1,"SEND DONE \n"); if (mUart && msg == &mDbg) { //if we finished sending a message over the uart mUart = FALSE; } else if (mRadio) { //might not have been us that send the message! mRadio = FALSE; if (!mLocal && !mWasCommand) { //message sent on behalf of some other component switch (mAmId) { case kDATA_MESSAGE_ID: signal Network.sendDataDone(msg, success); break; case kQUERY_MESSAGE_ID: signal Network.sendQueryDone(msg, success); break; case kQUERY_REQUEST_MESSAGE_ID: signal Network.sendQueryRequestDone(msg, success); break; } } else if (mWasCommand) { //command message that has been sent, now must be executed // XXX, ignore command return value for now call CommandUse.invokeMsg(&mDbg, NULL, &errorNo); mWasCommand = FALSE; } else { mLocal = FALSE; } } return SUCCESS; } event result_t SendQueryMsg.sendDone(TOS_MsgPtr msg, result_t success) { if ((!success || !msg->ack) && mRetryCnt-- > 0) { if (call SendQueryMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) != SUCCESS) { mRetryCnt = 0; return sendDone(msg, FAIL); } } else { mRetryCnt = 0; return sendDone(msg, success && msg->ack); } return SUCCESS; } event result_t SendDataMsg.sendDone(TOS_MsgPtr msg, result_t success) { uint8_t rootId = 0; bool amRoot = checkRoot(msg, &rootId); //disabled link degredation for now -- this would be a way to work //around asymmetric links, but it adds a lot of instability //if (!msg->ack) degradeLinkQuality(((NetworkMessage *)msg->data)->hdr.parentid); //since root sends over uart, don't update contention since acks dont work on root if (!amRoot) { if (!msg->ack) call NetworkMonitor.updateContention(TRUE, ACK_FAILURE); else call NetworkMonitor.updateContention(FALSE,0); } if ((!success || !msg->ack) && mRetryCnt-- > 0) { if (call SendDataMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) != SUCCESS) { mRetryCnt = 0; return sendDone(msg, FAIL); } } else { mRetryCnt = 0; return sendDone(msg, success && msg->ack); } return SUCCESS; } event result_t SendQueryRequest.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg, success); }#ifdef kSTATUS event result_t SendStatusMessage.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg, success); }#endif event result_t DebugMsg.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg, success); } event result_t SchemaMsg.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg, success); }#ifdef kSUPPORTS_EVENTS event result_t EventMsg.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg, success); }#endif /* Check a message for CRC and to see if we've already ack'd it... Return true if the messsage should be rejected. */ bool filterMessage(TOS_MsgPtr msg, bool checkRecent ) { if (msg->crc == 0) { call NetworkMonitor.updateContention(TRUE,CRC_FAILURE); return TRUE; } else call NetworkMonitor.updateContention(FALSE,0); if (checkRecent) { NetworkMessage *nw = (NetworkMessage *)msg->data; long id = (((long)nw->hdr.senderid) << 16) + nw->hdr.idx; short i; if ( nw->hdr.senderid == TOS_UART_ADDR) return FALSE; //don't filter root messages for (i = 0; i < NUM_RECENT_MSGS; i++) { if (mRecentMsgs[i] == id) { return TRUE; } } mRecentMsgs[mNextMsg++] = id; if (mNextMsg == NUM_RECENT_MSGS) mNextMsg = 0; //circular buffer } return FALSE; } /* Event that's fired when a query message arrives */ event TOS_MsgPtr RcvQueryMsg.receive(TOS_MsgPtr msg) { NetworkMessage *nw = (NetworkMessage *)msg->data; uint8_t rootId = 0; if (filterMessage(msg,TRUE)) return msg; checkRoot(msg, &rootId); if (processHeader(nw->hdr,QUERY_TYPE,rootId)) { //only log messages we're actually processing if (!mCentralized) { signal Network.querySub(call Network.getQueryPayLoad(msg)); } else { //forward without processing in centralized approach call Network.sendDataMessage(msg); } } return msg; }#ifdef kQUERY_SHARING /* Event thats fired when a request for a query arrives from a neighbor */ event TOS_MsgPtr RcvRequestMsg.receive(TOS_MsgPtr msg) { NetworkMessage *nw = (NetworkMessage *)msg->data; uint8_t rootId = 0; if (filterMessage(msg,FALSE)) return msg; checkRoot(msg, &rootId); processHeader(nw->hdr, QUERY_TYPE,rootId); //ignore return rest -- always handle these signal Network.queryRequestSub(call Network.getQueryRequestPayLoad(msg)); return msg; }#endif /* Event that's fired when a network data item arrives */ event TOS_MsgPtr RcvDataMsg.receive(TOS_MsgPtr msg) { NetworkMessage *nw = (NetworkMessage *)msg->data; uint8_t rootId; bool amRoot; if (filterMessage(msg,TRUE)) return msg; amRoot = checkRoot(msg, &rootId); if (amRoot && nw->hdr.senderid == TOS_UART_ADDR) { //was this heartbeat from root? if (!mRadio /*&& !mUart*/) { mRadio = TRUE; mLocal = TRUE; initHeader(&nw->hdr, TRUE, rootId); call Leds.redToggle(); if (call SendDataMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) == FAIL) { mIdx--; //reuse this index, since we failed to forward this message mRadio = FALSE; mLocal = FALSE; } } } //root sends data messages heartbeats -- ignore them if (processHeader(nw->hdr,DATA_TYPE,rootId) && nw->hdr.senderid != mRoots[rootId]) { signal Network.dataSub(call Network.getDataPayLoad(msg)); } else if (nw->hdr.senderid != TOS_UART_ADDR) //give mote a chance to look at it even though it wasn't addressed locally signal Network.snoopedSub(call Network.getDataPayLoad(msg), mParentIx[rootId] != PARENT_UNKNOWN && nw->hdr.senderid == mRelatives[mParentIx[rootId]], nw->hdr.senderid); return msg; }#ifdef kSUPPORTS_EVENTS /** Intercept schema event messages and execute the event */ event TOS_MsgPtr RcvEventMsg.receive(TOS_MsgPtr msg) { bool amRoot,shouldResend; uint8_t rootId; if (filterMessage(msg,FALSE)) return msg; amRoot = checkRoot(msg, &rootId); shouldResend = ((struct EventMsg *)(msg->data))->fromBase; ((struct EventMsg *)(msg->data))->fromBase = FALSE; if ((amRoot || shouldResend) && !mRadio) { mLocal = TRUE; //don't notify higher levels about the completion of this send mRadio = TRUE; if (call EventMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) != SUCCESS) { mLocal = FALSE; mRadio = FALSE; } } call EventUse.signalEventMsg(msg); return msg; }#endif /** Intercept schema command messages so that they can be forwarded from the root out to the rest of the nodes */ event TOS_MsgPtr RcvCommandMsg.receive(TOS_MsgPtr msg) { uint8_t rootId; bool amRoot; //bool shouldResend; if (filterMessage(msg,FALSE)) return msg; amRoot = checkRoot(msg, &rootId); //shouldResend = ((struct CommandMsg *)(msg->data))->fromBase; //((struct CommandMsg *)(msg->data))->fromBase = FALSE; //forward the message if ((amRoot /*|| shouldResend*/) && !mRadio) { mWasCommand = TRUE; //note that we'll need to executed the command later mRadio = TRUE; if (call SchemaMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) == SUCCESS) { memcpy(&mDbg, msg, sizeof(TOS_Msg)); //save off command for later execution. } else { //failure mWasCommand = FALSE; mRadio = FALSE; } } else { // XXX ignore command return values for now call Leds.greenToggle(); call CommandUse.invokeMsg(msg, NULL, &errorNo); } return msg; }#ifdef kSTATUS /* Event that's fired when a status request message arrives */ event TOS_MsgPtr RcvStatusMessage.receive(TOS_MsgPtr msg) { short numqs,i; StatusMessage *smsg; if (filterMessage(msg,FALSE)) return msg; if (!mRadio) { smsg = (StatusMessage *)&(mDbg.data); mLocal = TRUE; //don't notify higher levels about the completion of this send mRadio = TRUE; numqs = call QueryProcessor.numQueries(); if (numqs > kMAX_QUERIES) numqs = kMAX_QUERIES; smsg->numQueries = numqs; for (i = 0; i < numqs; i++) { uint8_t qid = (uint8_t)((call QueryProcessor.getQueryIdx(i))->qid); dbg(DBG_USR2, "i = %d, qid = %d\n", i, qid ); smsg->queries[i] = qid; } if (call SendStatusMessage.send(TOS_UART_ADDR, kMSG_LEN, &mDbg) != SUCCESS) { mLocal = FALSE; mRadio = FALSE; } } return msg; }#endif /* Maintain the local header information */ void initHeader(DbMsgHdr *header, bool amRoot, uint8_t rootId) { header->senderid = TOS_LOCAL_ADDRESS; if (!amRoot) { header->parentid = mRelatives[mParentIx[rootId]]; header->level = myLevel(rootId); } else { header->parentid = 0; header->level = 0; } header->idx = mIdx++; //if (header->idx < 0) // overflow! //header->idx = mIdx = 0; // TOS_CALL_COMMAND(GET_TIME)(&header->sendtime); } // handle case where parent is unknown. // parent becomes the sender of this msg void tinydbParentInit(DbMsgHdr header, short clockCnt, uint8_t rootId) { // short curtime; mParentIx[rootId] = 0; // put parent in 1st slot in relatives array mRelOccupiedBits = 0x1; // 1 slot occupied: slot 0 mRelatives[0] = header.senderid; // sender is parent mLastIdxRelative[0] = header.idx; mCommProb[0] = 0xff; // ignore 1st message in stats mRelLevel[rootId][0] = header.level; //synchronize time with new parent (unless parent is root!) // if (MY_LEVEL != 1 // && mRelatives[mParentIx] == header.senderid) { // curtime = header.sendtime + TIME_OF_FLIGHT; // XXXX not sure that time sync works right! // TOS_CALL_COMMAND(SET_TIME)(curtime); //} dbg(DBG_USR1,"%d: parent is %d\n", TOS_LOCAL_ADDRESS, header.senderid); } // loop through all parents (for all roots) and check if the specified index is // a prent. bool isParent(uint8_t idx) { short i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -