📄 networkc.nc
字号:
} } } return err_MessageSendFailed; } /** Called (by TupleRouter) whenever an epoch ends */ command void Network.endOfEpoch() { //HACK : Parent reselect interval in terms of epochs on all queries //may not be the best metric as it will cause reselection to happen //faster for higher epoch rates / more queries mSendCount++; } /* Send a 'query' message -- query messages contain information about queries that should be sent to neighbors in the network. 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_UnknownError if transmission fails. */ command TinyDBError Network.sendQueryMessage(TOS_MsgPtr msg) { NetworkMessage *nw = (NetworkMessage *)msg->data; 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; } /* 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 from) { 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(from, kMSG_LEN, msg) == SUCCESS) { return err_NoError; } else { mRadio = FALSE; return err_MessageSendFailed; } } return err_MessageSendFailed; } //write a message out over the uart command result_t Network.sendUart(char *msg, uint8_t amid) { if (!mUart /*&& !mRadio*/) { mUart = TRUE; memcpy(&mDbg.data, msg, kMSG_LEN); if (call DebugMsg.send(TOS_UART_ADDR,kMSG_LEN,&mDbg)) { return err_NoError; } else { mUart = FALSE; return err_MessageSendFailed; } } else return err_MessageSendFailed; } /* Called when the network component has finished delivering a message. */ result_t sendDone(TOS_MsgPtr msg) { 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 signal Network.outputDone(msg, mAmId); } 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); } } else { mRetryCnt = 0; return sendDone(msg); } return SUCCESS; } event result_t SendDataMsg.sendDone(TOS_MsgPtr msg, result_t success) { //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); if ((!success || !msg->ack) && mRetryCnt-- > 0) { if (call SendDataMsg.send(TOS_BCAST_ADDR, kMSG_LEN, msg) != SUCCESS) { mRetryCnt = 0; return sendDone(msg); } } else { mRetryCnt = 0; return sendDone(msg); } return SUCCESS; } event result_t SendQueryRequest.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg); } event result_t DebugMsg.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg); } event result_t SchemaMsg.sendDone(TOS_MsgPtr msg, result_t success) { return sendDone(msg); } /* 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) { return TRUE; } 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(msg); } else { //forward without processing in centralized approach call Network.sendDataMessage(msg); } } return msg; } /* 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(msg); return msg; } /* 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(msg); } else if (nw->hdr.senderid != TOS_UART_ADDR) //give mote a chance to look at it event though it wasn't addressed locally signal Network.snoopedSub(msg, kDATA_MESSAGE_ID, mParentIx[rootId] != PARENT_UNKNOWN && nw->hdr.senderid == mRelatives[mParentIx[rootId]]); return msg; } /* Intercept schema command messages so that they can be forwarded from the root out to the rest of the nodes */ event TOS_MsgPtr RcvSchemaMsg.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; } /* 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; for (i=0; i < NUM_ROOTS; i++) { if (mRoots[i] != UNKNOWN_ROOT && mParentIx[mRoots[i]] == idx) return TRUE; } return FALSE; } //make this link look less attractive, as a result of a dropped //message or a failed ack! void degradeLinkQuality(short neighborId) { int i; for (i = 0; i < NUM_RELATIVES; i++) { if (mRelatives[i] == neighborId) { mCommProb[i] = mCommProb[i] - (mCommProb[i] >> NACKALPHA); break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -