Пример #1
0
        static void MacBase_OnNeighborChange(IMAC macInstance, DateTime time)
        {
            var neighborList = MACBase.NeighborListArray();

            macInstance.NeighborList(neighborList);
            PrintNeighborList("\t\tNeighbor list CHANGE for Node [" + _macBase.MACRadioObj.RadioAddress + "]: ", neighborList);
        }
Пример #2
0
        public static void Send_ResetWave()
        {
            // If in a reset wave already, return.
            if (RoutingGlobal._color == Color.Red)
            {
                return;
            }

            // Refresh children table
            _children.CleanseChildrenTable();

            if (!_children.IsEmpty())
            {
                RoutingGlobal._color = Color.Red;
                var msgBytes = new byte[3];
                var size     = ComposeMessages.CreateResetMessage(msgBytes, (ushort)_resetMsgNum);
                MulticastToChildren(msgBytes, size);
                _distResetTimer.Change(120000, Timeout.Infinite); // 2 min timer. TODO: Make timeout interval contingent on distance from the reset wave origin
            }
            else
            {
                // Create status query to existing candidates
                var msgBytes = new byte[3];
                var size     = ComposeMessages.CreateStatusQueryMessage(msgBytes, (ushort)_statusMsgNum);

                // Multicast query to candidates
                if (MulticastToCandidates(msgBytes, size)) // If there are candidates
                {
                    // Wait for response
                    _statusResponseTimer.Change(10000, Timeout.Infinite); // 10 second timer

                    // Reset candidate table
                    ushort[] neighbors = MACBase.NeighborListArray();
                    CandidateTable.Initialize((byte)neighbors.Length);
                }
                else //Empty candidate table; set parent immediately
                {
                    // Set best node in candidate table as parent
                    RoutingGlobal.SetParent(false);

                    // Reset params
                    RoutingGlobal._color = Color.Green;
                    // Send "Add Parent" message to new parent
                    DistributedReset.Send_AddParent();
                    _statusMsgNum++;
                    _resetMsgNum++;
                }
            }
        }
Пример #3
0
        private static void RadioSend(string toSend)
        {
            var toSendByte   = Encoding.UTF8.GetBytes(HeaderRequest + toSend);
            var neighborList = MACBase.NeighborListArray();

            _macBase.NeighborList(neighborList);
            foreach (var theNeighbor in neighborList)
            {
                if (theNeighbor == 0)
                {
                    break;
                }
                Debug.Print("\tSending request message  \"" + toSend + "\" to " + theNeighbor);
                _macBase.Send(theNeighbor, toSendByte, 0, (ushort)toSendByte.Length);
            }
        }
Пример #4
0
            internal void CleanseChildrenTable()
            {
                ushort[] _neighborList = MACBase.NeighborListArray();
                _distResetPipe.NeighborList(_neighborList); // Get current neighborlist
                foreach (ushort c in _childrenList)
                {
                    if (Array.IndexOf(_neighborList, c) == -1)
                    {
#if DBG_VERBOSE
                        Debug.Print("--- CHILDREN LIST CLEANUP: Removing stale child: " + c + " ---");
#elif DBG_SIMPLE
                        Debug.Print("Removing stale child: " + c);
#endif
                        DropChild(c);
                    }
                }
            }
Пример #5
0
        public static void CleanseCandidateTable(MACPipe pipe)
        {
            ushort[] _neighborList = MACBase.NeighborListArray();
            pipe.NeighborList(_neighborList); // Get current neighborlist
            foreach (Candidate c in CandidateTable._candidateList)
            {
                ushort macID = c.GetMacID();
                if (Array.IndexOf(_neighborList, macID) == -1)
                {
#if DBG_VERBOSE
                    Debug.Print("--- CANDIDATE LIST CLEANUP: Removing stale candidate: " + macID + " ---");
#elif DBG_SIMPLE
                    Debug.Print("Removing stale candidate: " + macID);
#endif
                    CandidateTable.DropCandidate(macID);
                }
            }
        }
Пример #6
0
        private static void Reset_State(object state)
        {
#if DBG_VERBOSE
            Debug.Print("*** RESET WAVE TIMEOUT FIRED: Initiating completion wave# " + _resetMsgNum + " ***");
#elif DBG_SIMPLE
            Debug.Print("Initiating completion wave " + _resetMsgNum + "");
#endif
            Send_CompletionWave(_resetMsgNum);

            // Purge children table
            _children       = new ChildrenList();
            _completionMsgs = null;

            // Create status query to existing candidates
            var msgBytes = new byte[3];
            var size     = ComposeMessages.CreateStatusQueryMessage(msgBytes, (ushort)_statusMsgNum);

            // Multicast query to candidates
            if (MulticastToCandidates(msgBytes, size)) // If there are candidates
            {
                // Wait for response
                _statusResponseTimer.Change(10000, Timeout.Infinite); // 10 second timer

                // Reset candidate table
                ushort[] neighbors = MACBase.NeighborListArray();
                CandidateTable.Initialize((byte)neighbors.Length);
            }
            else //Empty candidate table; set parent immediately
            {
                // Set best node in candidate table as parent
                RoutingGlobal.SetParent(false);

                // Reset params
                RoutingGlobal._color = Color.Green;
                // Send "Add Parent" message to new parent
                DistributedReset.Send_AddParent();
                _statusMsgNum++;
            }

            _resetMsgNum++; // No more completion messages to be accepted beyond this point
        }
Пример #7
0
        /// <summary>
        /// Send a message to all neighbors
        /// </summary>
        /// <param name="mac"></param>
        /// <param name="message"></param>
        /// <param name="messageLength"></param>
        public static void Broadcast(IMAC mac, byte[] message, int messageLength)
        {
            var neighbors = MACBase.NeighborListArray();

            mac.NeighborList(neighbors);
#if !DBG_LOGIC
            PrintNeighborList(mac);
#endif

            var pipe = mac as MACPipe;

#if DBG_VERBOSE
            if (pipe != null)
            {
                PrintNumericVals("Broadcast (on MACPipe " + pipe.PayloadType + "): ", message, messageLength);
            }
            else
            {
                PrintNumericVals("Broadcast: ", message, messageLength);
            }
#endif
            foreach (var theNeighbor in neighbors)
            {
                if (theNeighbor == 0)
                {
                    continue;
                }
                var status = pipe.EnqueueToSend(theNeighbor, message, 0, (ushort)messageLength);

#if DBG_VERBOSE
                if (status != NetOpStatus.S_Success)
                {
                    Debug.Print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send status: " + status);
                }

                Debug.Print("\tSent to " + theNeighbor);
#elif DBG_SIMPLE
                Debug.Print("\tSent to " + theNeighbor + ", status: " + status);
#endif
            }
        }
Пример #8
0
        /// <summary>
        /// Send a message to all neighbors - moved here from SystemGlobal
        /// </summary>
        /// <param name="mac"></param>
        /// <param name="message"></param>
        /// <param name="messageLength"></param>
        public static void BroadcastBeacon(IMAC mac, byte[] message, int messageLength)
        {
            var neighbors = MACBase.NeighborListArray();

            mac.NeighborList(neighbors);
#if !DBG_LOGIC
            SystemGlobal.PrintNeighborList(mac);
#endif

            var pipe = mac as MACPipe;

#if DBG_VERBOSE
            if (pipe != null)
            {
                PrintNumericVals("Broadcast (on MACPipe " + pipe.PayloadType + "): ", message, messageLength);
            }
            else
            {
                PrintNumericVals("Broadcast: ", message, messageLength);
            }
#endif
            foreach (var theNeighbor in neighbors)
            {
                if (theNeighbor == 0)
                {
                    continue;
                }
                var status = pipe.EnqueueToSend(theNeighbor, message, 0, (ushort)messageLength);

                if (pipe.IsMsgIDValid(status))
                {
                    // Update link metrics
                    if (theNeighbor == Parent)
                    {
                        UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for parent " + theNeighbor + "; new value = " + GetNumTriesInCurrentWindow_Parent());
#endif
                    }
                    else
                    {
                        byte cindex = CandidateTable.findIndex(theNeighbor);
                        if (cindex < byte.MaxValue)
                        {
                            CandidateTable._candidateList[cindex].UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                            Debug.Print("Updated numTriesInCurrentWindow for candidate " + theNeighbor + "; new value = " + CandidateTable._candidateList[cindex].GetNumTriesInCurrentWindow());
#endif
                        }
                    }


#if DBG_VERBOSE
                    if (status != NetOpStatus.S_Success)
                    {
                        Debug.Print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send status: " + status);
                    }

                    Debug.Print("\tSent to " + theNeighbor);
#elif DBG_SIMPLE
                    Debug.Print("\tSent to " + theNeighbor + ", status: " + status);
#endif
                }
            }
        }
        /*CAUTION: Any change in the advanced heartbeat structure should be accounted for in variables
         * NetManagerGlobal.AdvHeartbeatFixedSize and NetManagerGlobal.EachNeighborInfoSize
         */
        private static void Send_AdvancedHeartbeat(object state)
        {
            ushort[] neighbors = MACBase.NeighborListArray();
            _neighborInfoManagerPipe.MACBase.MACNeighborList(neighbors);

            // Find the number of neighbors
            byte num_nbrs = 0;

            for (int i = 0; i < neighbors.Length; i++)
            {
                if (neighbors[i] == 0) // At the end
                {
                    break;
                }
                num_nbrs++;
            }

            if (num_nbrs == 0)
            {
                return;
            }

            _numBeat++;

            ushort[] valid_nbrs;
            byte[]   nbrStatus;
            ushort[] numSamplesRec;
            ushort[] numSyncSent;
            byte[]   avgRSSI;
            byte[]   ewrnp;
            byte[]   isAvailableForUpperLayers;

            // TODO: Make this if-else more compact
            if (num_nbrs <= NetManagerGlobal.MaxNeighborsPerHeartbeat) // Send all information
            {
                valid_nbrs                = new ushort[num_nbrs];
                nbrStatus                 = new byte[num_nbrs];
                numSamplesRec             = new ushort[num_nbrs];
                numSyncSent               = new ushort[num_nbrs];
                avgRSSI                   = new byte[num_nbrs];
                ewrnp                     = new byte[num_nbrs];
                isAvailableForUpperLayers = new byte[num_nbrs];

                // Initialize ewrnp array with maxEtx
                for (int i = 0; i < ewrnp.Length; i++)
                {
                    ewrnp[i] = RoutingGlobal.MaxEtx;
                }

                for (int i = 0; i < num_nbrs; i++)
                {
                    var      nbr_name = neighbors[i];
                    Neighbor nbr      = _neighborInfoManagerPipe.NeighborStatus(nbr_name);

                    valid_nbrs[i]    = nbr_name;
                    nbrStatus[i]     = (byte)nbr.NeighborStatus;
                    numSamplesRec[i] = nbr.NumOfTimeSamplesRecorded;
                    numSyncSent[i]   = nbr.NumTimeSyncMessagesSent;
                    avgRSSI[i]       = (byte)((nbr.ReceiveLink.AverageRSSI + nbr.SendLink.AverageRSSI)); // * 0.5;

                    int index = CandidateTable.findIndex(nbr_name);
                    if (RoutingGlobal.Parent == nbr_name)
                    {
                        ewrnp[i] = RoutingGlobal.GetPathEWRNP();
                    }
                    else if (index < byte.MaxValue)
                    {
                        ewrnp[i] = (byte)CandidateTable._candidateList[index].GetPathEWRNP();
                    }

                    isAvailableForUpperLayers[i] = nbr.IsAvailableForUpperLayers ? (byte)1 : (byte)0;
                }
            }
            else // Starting with the current head pointer, use neighbor list as a circular array to send out info for NetManagerGlobal.MaxNeighborsPerHeartbeat consecutive neighbors
            {
                valid_nbrs                = new ushort[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                nbrStatus                 = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                numSamplesRec             = new ushort[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                numSyncSent               = new ushort[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                avgRSSI                   = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                ewrnp                     = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];
                isAvailableForUpperLayers = new byte[NetManagerGlobal.MaxNeighborsPerHeartbeat];

                // Initialize ewrnp array with maxEtx
                for (int i = 0; i < ewrnp.Length; i++)
                {
                    ewrnp[i] = RoutingGlobal.MaxEtx;
                }

                for (int i = 0; i < NetManagerGlobal.MaxNeighborsPerHeartbeat; i++)
                {
                    // If current head pointer has a higher index than number of neighbors (owing to loss), restart at index 0; otherwise, start at current head pointer
                    circ_headptr = (circ_headptr < num_nbrs) ? (byte)(circ_headptr % num_nbrs) : (byte)0;
                    var      nbr_name = neighbors[circ_headptr];
                    Neighbor nbr      = _neighborInfoManagerPipe.NeighborStatus(nbr_name);

                    valid_nbrs[i]    = nbr_name;
                    nbrStatus[i]     = (byte)nbr.NeighborStatus;
                    numSamplesRec[i] = nbr.NumOfTimeSamplesRecorded;
                    numSyncSent[i]   = nbr.NumTimeSyncMessagesSent;
                    avgRSSI[i]       = (byte)((nbr.ReceiveLink.AverageRSSI + nbr.SendLink.AverageRSSI)); // * 0.5;

                    int index = CandidateTable.findIndex(nbr_name);
                    if (RoutingGlobal.Parent == nbr_name)
                    {
                        ewrnp[i] = RoutingGlobal.GetPathEWRNP();
                    }
                    else if (index < byte.MaxValue)
                    {
                        ewrnp[i] = (byte)CandidateTable._candidateList[index].GetPathEWRNP();
                    }

                    isAvailableForUpperLayers[i] = nbr.IsAvailableForUpperLayers ? (byte)1 : (byte)0;

                    circ_headptr = (byte)((circ_headptr + 1) % num_nbrs);
                }

                // Adjust circular buffer head pointer at the end
                circ_headptr = (byte)((circ_headptr + 1) % num_nbrs);
            }

#if DBG_DIAGNOSTIC
            SystemGlobal.PrintNumericVals("Neighbor names: ", valid_nbrs);
            SystemGlobal.PrintNumericVals("Neighbor status: ", nbrStatus);
            SystemGlobal.PrintNumericVals("Avg RSSI: ", avgRSSI);
            SystemGlobal.PrintNumericVals("Routing EWRNP: ", ewrnp);
            SystemGlobal.PrintNumericVals("# samples rcvd: ", numSamplesRec);
            SystemGlobal.PrintNumericVals("# timesync sent: ", numSyncSent);
            SystemGlobal.PrintNumericVals("Available for upper layers: ", isAvailableForUpperLayers);
            Debug.Print("Parent: " + RoutingGlobal.Parent);
            Debug.Print("");
#endif

            var size = NetManagerGlobal.MoteMessages.Compose.Heartbeat(NetManagerGlobal.MsgBytes, _neighborInfoManagerPipe.MACRadioObj.RadioAddress, (ushort)_numBeat, SystemGlobal.NodeType, RoutingGlobal.Parent, (byte)RoutingGlobal.GetPathEWRNP(), valid_nbrs, nbrStatus, numSamplesRec, numSyncSent, avgRSSI, ewrnp, isAvailableForUpperLayers, RoutingGlobal.Infinity);
            //var size = NetManagerGlobal.MoteMessages.Compose.Heartbeat(NetManagerGlobal.MsgBytes, _neighborInfoManagerPipe.MACRadioObj.RadioAddress, (ushort)_numBeat, SystemGlobal.NodeType, RoutingGlobal.Parent, (byte)RoutingGlobal.BestEtx, neighbors, nbrStatus, avgRSSI, ewrnp);
#if !DBG_LOGIC
            Debug.Print("NeighborInfo#" + _numBeat + " size: " + size);
#endif

            #region Uncomment when not using scheduler
            // If in a reset, do not forward TODO: Change this to "spray"
            if (RoutingGlobal._color == Color.Red)
            {
#if DBG_VERBOSE
                Debug.Print("\tIn a Reset wave... not forwarded");
#endif
                return;
            }

            // If parent is available, pass it on
            if (RoutingGlobal.IsParent)
            {
                var status = RoutingGlobal.SendToParent(_neighborInfoManagerPipe, NetManagerGlobal.MsgBytes, size);
                if (status != 999)
                {
                    RoutingGlobal.UpdateNumTriesInCurrentWindow_Parent(1);
#if !DBG_LOGIC
                    Debug.Print("Updated numTriesInCurrentWindow for Parent " + RoutingGlobal.Parent + "; new value = " + RoutingGlobal.GetNumTriesInCurrentWindow_Parent());
#endif
                    if (!_sentPacketSizes.Contains(status))
                    {
                        _sentPacketSizes.Add(status, size);
                    }
                }
                else //Retry once
                {
#if !DBG_LOGIC
                    Debug.Print("Retrying packet");
#endif
                    RoutingGlobal.CleanseCandidateTable(_neighborInfoManagerPipe);
                    Candidate tmpBest = CandidateTable.GetBestCandidate(false);
                    NetManagerGlobal.TempParent = tmpBest.GetMacID();
                    status = NetManagerGlobal.SendToTempParent(_neighborInfoManagerPipe, NetManagerGlobal.MsgBytes, size);
                    if (status != 999)
                    {
                        tmpBest.UpdateNumTriesInCurrentWindow(1);
#if !DBG_LOGIC
                        Debug.Print("Updated numTriesInCurrentWindow for TempParent " + NetManagerGlobal.TempParent + "; new value = " + tmpBest.GetNumTriesInCurrentWindow());
#endif
                        if (!_sentPacketSizes.Contains(status))
                        {
                            _sentPacketSizes.Add(status, size);
                        }
                    }
                }
            }
            #endregion
        }
Пример #10
0
        private static void DistResetStreamReceive(IMAC macBase, DateTime time, Packet packet)
        {
#if DBG_VERBOSE
            DebuggingSupport.PrintMessageReceived(macBase, "Distributed Reset");
#endif

            if (packet == null)
            {
                return;
            }
#if !DBG_LOGIC
            Debug.Print("\tRSSI: " + packet.RSSI + ", from " + packet.Src);
#endif

            var rcvPayloadBytes = packet.Payload;

            //var payload = new string(Encoding.UTF8.GetChars(rcvPayloadBytes));
#if DBG_VERBOSE
            SystemGlobal.PrintNumericVals("\tDistributed reset Rcv: ", rcvPayloadBytes);
#endif
            try
            {
                ushort[] neighbors = MACBase.NeighborListArray();


                var neighborStatus = _distResetPipe.NeighborStatus(packet.Src);
                if (neighborStatus == null)
                {
#if DBG_VERBOSE
                    Debug.Print("\t\t!!!!!!!!!!!!!!!!! Node " + packet.Src + " is not a Neighbor (MACBase.NeighborStatus returned null)");
#elif DBG_SIMPLE
                    Debug.Print("Sender not a neighbor.");
#endif
                    // If node in children table, drop it
                    if (Array.IndexOf(_children._childrenList, packet.Src) < -1)
                    {
                        _children.DropChild(packet.Src);
                    }

                    return;
                }
                //Debug.Print("\t\tFwd avg RSSI: " + neighborStatus.ReceiveLink.AverageRSSI + ", Rev avg RSSI: " + neighborStatus.SendLink.AverageRSSI);

                switch ((MessageIds)rcvPayloadBytes[0])
                {
                case MessageIds.AddParent:
#if !DBG_LOGIC
                    Debug.Print("\t>>> AddParent");
#endif
                    if (_children.AddChild(packet.Src))
                    {
#if DBG_VERBOSE
                        Debug.Print("+++ Added new child: " + packet.Src + " +++");
#elif DBG_SIMPLE
                        Debug.Print("Added new child: " + packet.Src);
#endif
                    }
                    else
                    {
#if DBG_VERBOSE
                        Debug.Print("@@@ Child already exists: " + packet.Src + " @@@");
#endif
                    }

                    return;

                case MessageIds.DropParent:
#if !DBG_LOGIC
                    Debug.Print("\t>>> DropParent");
#endif

                    if (_children.DropChild(packet.Src))
                    {
#if DBG_VERBOSE
                        Debug.Print("--- Dropped child: " + packet.Src + " ---");
#elif DBG_SIMPLE
                        Debug.Print("Dropped child: " + packet.Src);
#endif
                    }
                    else
                    {
#if DBG_VERBOSE
                        Debug.Print("@@@ Child does not exist: " + packet.Src + " @@@");
#endif
                    }

                    return;

                case MessageIds.Reset:
#if !DBG_LOGIC
                    Debug.Print("\t>>> ResetWave");
#endif
                    // Decode round number
                    ushort round_num;
                    ParseMessages.ParseResetMessage(rcvPayloadBytes, out round_num);

                    // Is this a legit reset wave?
                    if (RoutingGlobal._color == Color.Red || packet.Src != RoutingGlobal.Parent || round_num != _resetMsgNum)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! ILLEGAL RESET WAVE# " + round_num + ": Received from: " + packet.Src + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Illegal reset wave " + round_num + " from " + packet.Src);
#endif
                        return;
                    }

                    // Refresh children table
                    _children.CleanseChildrenTable();

                    if (_children.IsEmpty())     // Start completion wave if leaf node
                    {
#if DBG_VERBOSE
                        Debug.Print("*** LEAF NODE REACHED: Initiating completion wave# " + round_num + " ***");
#elif DBG_SIMPLE
                        Debug.Print("At leaf; initiating completion wave " + round_num);
#endif
                        Send_CompletionWave(round_num);

                        // Create status query to existing candidates
                        var msgBytes = new byte[3];
                        var size     = ComposeMessages.CreateStatusQueryMessage(msgBytes, (ushort)_statusMsgNum);

                        // Multicast query to candidates
                        if (MulticastToCandidates(msgBytes, size))     // If there are candidates
                        {
                            // Wait for response
                            _statusResponseTimer.Change(10000, Timeout.Infinite);     // 10 second timer

                            // Reset candidate table
                            CandidateTable.Initialize((byte)neighbors.Length);
                        }
                        else     //Empty candidate table; set parent immediately
                        {
                            // Set best node in candidate table as parent
                            RoutingGlobal.SetParent(false);

                            // Reset params
                            RoutingGlobal._color = Color.Green;
                            // Send "Add Parent" message to new parent
                            DistributedReset.Send_AddParent();
                            _statusMsgNum++;
                        }

                        _resetMsgNum++;
                    }
                    else
                    {
                        // Forward reset wave to own children
                        Send_ResetWave(rcvPayloadBytes);
                    }
                    return;

                case MessageIds.Completion:
#if !DBG_LOGIC
                    Debug.Print("\t>>> CompletionWave");
#endif
                    // Decode round number
                    ushort round;
                    ParseMessages.ParseCompletionMessage(rcvPayloadBytes, out round);

                    // Is this a legit completion wave?
                    int pos = Array.IndexOf(_children._childrenList, packet.Src);
                    if (RoutingGlobal._color != Color.Red || pos == -1 || round != _resetMsgNum)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! ILLEGAL COMPLETION WAVE# " + round + ": Received from: " + packet.Src + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Illegal completion wave " + round + " from " + packet.Src);
#endif
                        return;
                    }

                    _completionMsgs[pos] = true;

                    // Forward completion wave if received from all children
                    for (int i = 0; i < _completionMsgs.Length; i++)
                    {
                        if (!_completionMsgs[i])     // If not received from any child, return
                        {
                            return;
                        }
                    }

                    // Else, forward completion wave to parent
#if DBG_VERBOSE
                    Debug.Print("*** RECEIVED COMPLETION MESSAGES FROM ALL CHILDREN: initiating completion wave# " + round + " ***");
#elif DBG_SIMPLE
                    Debug.Print("All children responded; initiating completion wave " + round);
#endif
                    Send_CompletionWave(round);

                    // Purge children table
                    _children       = new ChildrenList();
                    _completionMsgs = null;
                    _distResetTimer.Change(Timeout.Infinite, Timeout.Infinite);

                    // Create status query to existing candidates
                    var msgBytes1 = new byte[3];
                    var size1     = ComposeMessages.CreateStatusQueryMessage(msgBytes1, (ushort)_statusMsgNum);

                    // Multicast query to candidates
                    if (MulticastToCandidates(msgBytes1, size1))     // If there are candidates
                    {
                        // Wait for response
                        _statusResponseTimer.Change(10000, Timeout.Infinite);     // 10 second timer

                        // Reset candidate table
                        CandidateTable.Initialize((byte)neighbors.Length);
                    }
                    else     //Empty candidate table; set parent immediately
                    {
                        // Set best node in candidate table as parent
                        RoutingGlobal.SetParent(false);

                        // Reset params
                        RoutingGlobal._color = Color.Green;
                        // Send "Add Parent" message to new parent
                        DistributedReset.Send_AddParent();
                        _statusMsgNum++;
                    }

                    _resetMsgNum++;
                    return;

                case MessageIds.StatusQuery:
#if !DBG_LOGIC
                    Debug.Print("\t>>> StatusQuery");
#endif
                    //If in a reset wave or no valid path, don't bother responding
                    if (RoutingGlobal._color == Color.Red || RoutingGlobal.BestEtx >= RoutingGlobal.Infinity)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! Not responding. Color: " + RoutingGlobal._color + ", BestEtx: " + RoutingGlobal.BestEtx + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Not responding. Color: " + RoutingGlobal._color + ", BestEtx: " + RoutingGlobal.BestEtx);
#endif
                        return;
                    }

                    // Decode round number
                    ushort status_msgnum;
                    ParseMessages.ParseStatusQueryMessage(rcvPayloadBytes, out status_msgnum);

                    // Send status response
                    var         msgBytes2 = new byte[5];
                    var         size2     = ComposeMessages.CreateStatusResponseMessage(msgBytes2, status_msgnum);
                    NetOpStatus status    = _distResetPipe.Send(RoutingGlobal.Parent, msgBytes2, 0, (ushort)size2);

                    return;

                case MessageIds.StatusResponse:
#if !DBG_LOGIC
                    Debug.Print("\t>>> StatusResponse");
#endif
                    ushort status_respnum;
                    Color  col;
                    byte   etx;
                    byte   pathEWRNP_B2N;

                    // Decode message
                    ParseMessages.ParseStatusResponseMessage(rcvPayloadBytes, out col, out etx, out status_respnum, out pathEWRNP_B2N);

                    // Is this a valid response?
                    if (status_respnum != _statusMsgNum)
                    {
#if DBG_VERBOSE
                        Debug.Print("!!! ILLEGAL STATUS RESPONSE# " + status_respnum + ": Received from: " + packet.Src + " !!!");
#elif DBG_SIMPLE
                        Debug.Print("Illegal status response " + status_respnum + " from " + packet.Src);
#endif
                        return;
                    }

                    byte tempEtx = (byte)(etx + 1);

                    // Add candidate if its offered etx exceeds _minEtx
                    if (tempEtx >= RoutingGlobal._minEtx)
                    {
                        CandidateTable.AddCandidate(packet.Src, 0, tempEtx, pathEWRNP_B2N, RoutingGlobal.MaxEtx);     // TODO: Add RSSI later
#if DBG_VERBOSE
                        Debug.Print("+++ Added new candidate: " + packet.Src + "; path length: " + tempEtx + " +++");
#elif DBG_SIMPLE
                        Debug.Print("New candidate " + packet.Src + ":[" + tempEtx + "]");
#endif
                    }
                    else
                    {
#if DBG_VERBOSE
                        Debug.Print("--- Not a candidate: " + packet.Src + "; path length: " + tempEtx + " ---");
#elif DBG_SIMPLE
                        Debug.Print("Not a candidate " + packet.Src + ":[" + tempEtx + "]");
#endif
                    }

                    return;

                default:
#if !DBG_LOGIC
                    Debug.Print("\tUnknown message received <" + rcvPayloadBytes[0] + ">");
#endif
                    break;
                }
            }
            catch (Exception e) { Debug.Print(e.StackTrace); }
        }
Пример #11
0
 internal ChildrenList()
 {
     _length       = 0;
     _childrenList = MACBase.NeighborListArray(); // Initialize array;
     _maxLength    = (byte)_childrenList.Length;
 }