/// <summary> /// Handler for Mac sdu confirmations /// </summary> private void MacDataConfirmHandler( IMacDataSap sender, Byte msduHandle, MacEnum mStatus) { MessageContext.Context context = _messageContext.GetContext(msduHandle); if (context == null) return; Status status = Status.Success; if (mStatus != MacEnum.Success) { status = Status.Error; if (!context.useExtAddr && mStatus != MacEnum.Congested) { // if network is congested, avoid route repairs causing additional traffic Trace.Print("Link failure for 0x" + HexConverter.ConvertUintToHex(context.nextHopShort, 4)); _routingTable.HandleLinkFailure(context.nextHopShort); } } if (context.dataHandler != null) context.dataHandler.Invoke(_net, context.dataSduHandle, status); _messageContext.ReleaseContext(context); }
private void UpdateTarget() { string s = "Current nodes: "; target = 0; UInt16 targetNode = 1; lock (_statusLock) { for (int i = 0; i < _status.Length; i++) { if (i > 0) { s += ", "; } s += "0x" + HexConverter.ConvertUintToHex(_status[i].addr, 4); if (_status[i].addr == targetNode) { target = _status[i].addr; } } } _monitor.Print(s); if (target == 0) { _monitor.Print("Not sending any data"); } else { _monitor.Print("Sending data to 0x" + HexConverter.ConvertUintToHex(target, 4)); } }
public override string ToString() { return("RouteError [HopsLeft: " + HopsLeft + ", TargetAddr: 0x" + HexConverter.ConvertUintToHex(TargetAddr, 4) + ", OriginatorAddr: 0x" + HexConverter.ConvertUintToHex(OriginatorAddr, 4) + ", UnreachableAddr: 0x" + HexConverter.ConvertUintToHex(UnreachableAddr, 4) + "]"); }
public override string ToString() { return("AddressReply [HopsLeft: " + HopsLeft + ", BrokerAddr: 0x" + HexConverter.ConvertUintToHex(BrokerAddr, 4) + ", DeviceAddr: 0x" + HexConverter.ConvertUint64ToHex(DeviceAddr, 16) + ", ShortAddr: 0x" + HexConverter.ConvertUintToHex(ShortAddr, 4) + ", DiscoveryInterval: " + DiscoveryInterval + "]"); }
/// <summary> /// Returns textual representation /// </summary> /// <returns>textual repressentation</returns> public override string ToString() { string description = "CoordinatorRealignment ["; description += "panId: " + HexConverter.ConvertUintToHex(panId, 4); description += ", coordinatorShortAddr: " + HexConverter.ConvertUintToHex(coordinatorShortAddr, 4); description += ", channel: " + channel.ToString(); description += ", shortAddr: " + HexConverter.ConvertUintToHex(shortAddr, 4); description += "]"; return(description); }
void phy_DataIndicationDump(IPhyDataSap sender, Frame frame, byte linkQuality) { string s = "recv: "; for (int i = 0; i < frame.LengthDataUsed; i++) { byte b = frame.ReadByte(i); s += HexConverter.ConvertUintToHex(b, 2) + " "; } Debug.Print(s); Frame.Release(ref frame); }
public void Status(NodeStatus[] status) { Print("Status update"); if (status != null) { for (int i = 0; i < status.Length; i++) { Print("0x" + HexConverter.ConvertUintToHex(status[i].addr, 4) + ":"); if (status[i].txBps > 0) { Print(" TX: " + status[i].txBps.ToString() + " bytes/s"); } if (status[i].neighbors == null || status[i].neighbors.Length == 0) { Print(" no neighbors"); } else { for (int j = 0; j < status[i].neighbors.Length; j++) { Print(" neighbor 0x" + HexConverter.ConvertUintToHex(status[i].neighbors[j].addr, 4) + ": LQI " + status[i].neighbors[j].lqi); } } if (status[i].traffic == null || status[i].traffic.Length == 0) { Print(" no traffic"); } else { for (int j = 0; j < status[i].traffic.Length; j++) { Print(" traffic from 0x" + HexConverter.ConvertUintToHex(status[i].traffic[j].addr, 4) + ": " + status[i].traffic[j].rxBps + " bytes/sec"); } } } } }
public override string ToString() { string res; if (IsRequest) { res = "RouteRequest"; } else { res = "RouteReply"; } return(res + " [HopsLeft: " + HopsLeft + ", HopCount: " + HopCount + ", MinLQI: " + MinLQI + ", SeqNo: " + SeqNo + ", TargetAddr: 0x" + HexConverter.ConvertUintToHex(TargetAddr, 4) + ", OriginatorAddr: 0x" + HexConverter.ConvertUintToHex(OriginatorAddr, 4) + "]"); }
public override string ToString() { string res = "NeighborhoodDiscovery ["; if (Neighbours != null) { int length = Neighbours.Length; for (int i = 0; i < length; i++) { if (i > 0) { res += ", "; } res += "[Address: 0x" + HexConverter.ConvertUintToHex(Neighbours[i].Address, 4) + ", LQI: " + Neighbours[i].Lqi + "]"; } } res += "]"; return(res); }
/// <summary> /// allocate a short address /// </summary> /// <param name="extAddr">the extended address of the target node</param> /// <param name="shortAddr">the allocated short address</param> /// <returns>true on success</returns> public virtual bool AllocateAddress(UInt64 extAddr, out UInt16 shortAddr) { lock (_addresses) { int bucket = (int)(extAddr % cBuckets); // lookup old addr ArrayList list = _addresses.data[bucket]; Mapping mapping; int count = list.Count; for (int i = 0; i < count; i++) { mapping = (Mapping)list[i]; if (mapping.extAddr == extAddr) { shortAddr = mapping.shortAddr; return(true); } } // allocate new addr if (_addresses.nextAddr > cLastAddr) { shortAddr = 0; return(false); } shortAddr = _addresses.nextAddr++; // store addr mapping = new Mapping(); mapping.extAddr = extAddr; mapping.shortAddr = shortAddr; list.Add(mapping); Trace.Print("Allocating short address 0x" + HexConverter.ConvertUintToHex(shortAddr, 4) + " for device 0x" + HexConverter.ConvertUint64ToHex(extAddr, 16)); return(true); } }
private void ScanHandlerJoinRequest( object sender, Status status, ScanResult[] networks) { _logicalChannel = 0; _channelPage = 0; if (status == Status.Success) { // find properties of target network UInt16[] neighborAddr; status = FindNetwork(out neighborAddr); if (status == Status.Success) { Trace.Print("Joining network on Pan Id=0x" + HexConverter.ConvertUintToHex(_panId, 4) + ", logicalChannel=" + _logicalChannel + ", channelPage=" + _channelPage); _net.Routing.Start(_panId, false, _logicalChannel, _channelPage, neighborAddr, StartHandlerJoinRequest); return; } } StartHandlerJoinRequest(null, status, 0); }
/// <summary> /// Updates timeouts in routing table. Deletes entries with expired deletion timer. /// After changing some timer externally, set _timerEvent /// </summary> private void TimerThread() { int nextTimeout = int.MaxValue; while (true) { DateTime start = DateTime.Now; if (nextTimeout == cInfiniteTimeout) { _timerEvent.WaitOne(); } else { _timerEvent.WaitOne((int)nextTimeout, false); } if (_timerThreadExit) { break; } TimeSpan tsElapsed = DateTime.Now - start; int timeElapsed = tsElapsed.Milliseconds + 1000 * (tsElapsed.Seconds + 60 * tsElapsed.Minutes); // max wait time is in minutes, less than an hour lock (_lock) { // each entry gets checked periodically after cRouteTimeout: // if neither "routeInUse" nor "broadcastActive" is set, entry is deleted // else: flags are reset and timer gets restarted // if "routeInUse" is true, a route request is performed to refresh the route // else: the next hop is set to invalid nextTimeout = cInfiniteTimeout; int i = 0; while (i < _table.Count) { Entry entry = _table[i] as Entry; if (entry.timeOutSet > 0) { entry.timeOutLeft = entry.timeOutSet; entry.timeOutSet = 0; // timer is running; } else { if (entry.timeOutLeft <= timeElapsed) { // timeout bool routeInUse = entry.routeInUse; bool broadcastActive = entry.broadcastActive; entry.routeInUse = false; entry.broadcastActive = false; if (routeInUse && !entry.routePending) { Trace.Print("Refreshing route to 0x" + HexConverter.ConvertUintToHex(entry.targetAddr, 4)); entry.routePending = true; entry.requestRetryCnt = cRouteRequestRetryCnt + 1; } if (entry.routePending) { if (entry.requestRetryCnt > 0) { // retry route request Trace.Print("Sending route request for 0x" + HexConverter.ConvertUintToHex(entry.targetAddr, 4) + " for timeout"); entry.requestRetryCnt--; entry.timeOutLeft = cRouteRequestWaitTime; _routing.RouteRequest(entry.targetAddr); } else { entry.routePending = false; // give up ClearPendingMessages(entry); } } else { if (routeInUse || broadcastActive) { // keep entry Trace.Print("Invalidating route to 0x" + HexConverter.ConvertUintToHex(entry.targetAddr, 4) + " for timeout"); entry.nextHopAddr = cInvalidAddr; entry.timeOutLeft = cRouteTimeout; } else { // delete entry Trace.Print("Removing route for 0x" + HexConverter.ConvertUintToHex(entry.targetAddr, 4) + " for timeout"); RemoveEntry(i); continue; // keep i } } } else { // update timer entry.timeOutLeft -= timeElapsed; } } // update timeout if (entry.timeOutLeft < nextTimeout) { nextTimeout = entry.timeOutLeft; } i++; } } } }
public override string ToString() { switch (status) { case Status.AssociationSuccessful: return("AssociationResponse [status: AssociationSuccessful, shortAddr: " + HexConverter.ConvertUintToHex(shortAddr, 4) + "]"); case Status.PanAtCapacity: return("AssociationResponse [status: PanAtCapacity]"); case Status.PanAccessDenied: return("AssociationResponse [status: PanAccessDenied]"); default: return("AssociationResponse [unknown status]"); } }
public override string ToString() { return("MeshHeader [HopsLeft: " + HopsLeft + ", OriginatorAddr: 0x" + HexConverter.ConvertUintToHex(originatorAddress, 4) + ", FinalAddress: 0x" + HexConverter.ConvertUintToHex(finalAddress, 4) + "]"); }
public void TestCommon() { // GetFrameHeaders { int mtu, head, tail; phy.GetMtuSize(out mtu, out head, out tail); Assert(mtu == 127); Assert(head == 2); Assert(tail == 0); } // Capabilities { bool res; phy.IsCapabilitySupported(Capabilities.AddressFilter, out res); Assert(res == true); phy.IsCapabilitySupported(Capabilities.AutoAck, out res); Assert(res == true); phy.IsCapabilitySupported(Capabilities.AutoFcs, out res); Assert(res == true); phy.IsCapabilitySupported(Capabilities.PowerOff, out res); Assert(res == true); } phy.SetPower(true); // GetDeviceAddress { UInt64 mac; phy.GetDeviceAddress(out mac); String s = String.Empty; for (int i = 0; i < 8; i++) { if (i > 0) { s += ":"; } s += HexConverter.ConvertUintToHex((UInt32)((mac >> i * 8) & 0xFF), 2); } Debug.Print(s); } // GetRequest { Status status; PibValue value; // constants phy.GetRequest(PibAttribute.phyChannelsSupported, out status, out value); Assert(status == Status.Success); int[] res = value.IntArray; Assert(res != null); Assert(res.Length == 1); Assert((res[0] & 0xF8000000) == 0); // page 0 for (int i = 0; i <= 27; i++) { bool val = (res[0] & (1 << i)) != 0; bool expected = (i >= 11 && i <= 26); Assert(val == expected); } phy.GetRequest(PibAttribute.phyCCAMode, out status, out value); Assert(status == Status.Success); Assert(value.Int == 3); phy.GetRequest(PibAttribute.phyCurrentPage, out status, out value); Assert(status == Status.Success); Assert(value.Int == 0); phy.GetRequest(PibAttribute.phyMaxFrameDuration, out status, out value); Assert(status == Status.Success); Assert(value.Int == 1064); phy.GetRequest(PibAttribute.phySHRDuration, out status, out value); Assert(status == Status.Success); Assert(value.Int == 40); phy.GetRequest(PibAttribute.phySymbolsPerOctet, out status, out value); Assert(status == Status.Success); Assert(value.Float == 8); // defaults phy.GetRequest(PibAttribute.phyCurrentChannel, out status, out value); Assert(status == Status.Success); Assert(value.Int == 11); phy.GetRequest(PibAttribute.phyTransmitPower, out status, out value); Assert(status == Status.Success); Assert(value.Int == -1); } // SetRequest { // constants Status status; PibValue value = new PibValue(); int[] res = new int[1]; res[0] = 256; value.IntArray = res; phy.SetRequest(PibAttribute.phyChannelsSupported, value, out status); Assert(status == Status.ReadOnly); value.Int = 0; phy.SetRequest(PibAttribute.phyCCAMode, value, out status); Assert(status == Status.ReadOnly); phy.SetRequest(PibAttribute.phyMaxFrameDuration, value, out status); Assert(status == Status.ReadOnly); phy.SetRequest(PibAttribute.phySHRDuration, value, out status); Assert(status == Status.ReadOnly); phy.SetRequest(PibAttribute.phySymbolsPerOctet, value, out status); Assert(status == Status.ReadOnly); // page phy.SetRequest(PibAttribute.phyCurrentPage, value, out status); Assert(status == Status.Success); value.Int = 1; phy.SetRequest(PibAttribute.phyCurrentPage, value, out status); Assert(status == Status.InvalidParam); // channel for (int i = 0; i < 27; i++) { value.Int = i; phy.SetRequest(PibAttribute.phyCurrentChannel, value, out status); if (i >= 11 && i <= 26) { Assert(status == Status.Success); phy.GetRequest(PibAttribute.phyCurrentChannel, out status, out value); Assert(status == Status.Success); Assert(value.Int == i); } else { Assert(status == Status.InvalidParam); } } // power value.Int = -100; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.InvalidParam); value.Int = -32; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.Success); phy.GetRequest(PibAttribute.phyTransmitPower, out status, out value); Assert(status == Status.Success); value.Int = 1; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.Success); phy.GetRequest(PibAttribute.phyTransmitPower, out status, out value); Assert(status == Status.Success); Assert(value.Int == 0); // max CC tx power value.Int = 64; phy.SetRequest(PibAttribute.phyTransmitPower, value, out status); Assert(status == Status.InvalidParam); } phy.SetPower(false); }
public void Run(AutoResetEvent stopEvent) { UInt64 extAddr; _net.GetDeviceAddress(out extAddr); _monitor.Print("Device address is 0x" + HexConverter.ConvertUint64ToHex(extAddr, 16)); _monitor.Print("Frame structure: mtu=" + _mtu + ", head=" + _head + ", tail=" + _tail); UInt16 panId = 0x6366; AutoResetEvent callback = new AutoResetEvent(false); bool started = false; UInt16 shortAddr = 0; Byte logicalChannel = 0; Byte channelPage = 0; #if MICROFRAMEWORK _coordinator = false; #else _coordinator = true; #endif _monitor.Print("attempting to start network layer"); while (!started) { if (_coordinator) { _monitor.Print("StartRequest for PanId=0x" + HexConverter.ConvertUint64ToHex(panId, 4)); _net.StartRequest(panId, delegate( object sender, Status status, UInt16 _shortAddr, Byte _logicalChannel, Byte _channelPage) { _monitor.Print("StartConfirm: " + status.ToString()); if (status == Status.Success) { shortAddr = _shortAddr; logicalChannel = _logicalChannel; channelPage = _channelPage; started = true; } callback.Set(); }); } else { _monitor.Print("JoinRequest for PanId=0x" + HexConverter.ConvertUint64ToHex(panId, 4)); _net.JoinRequest(panId, delegate( object sender, Status status, UInt16 _shortAddr, Byte _logicalChannel, Byte _channelPage) { _monitor.Print("JoinConfirm: " + status.ToString()); if (status == Status.Success) { shortAddr = _shortAddr; logicalChannel = _logicalChannel; channelPage = _channelPage; started = true; } callback.Set(); }); } callback.WaitOne(); } _monitor.Print("network is running, logicalChannel=" + logicalChannel + ", channelPage=" + channelPage + ", shortAddr=0x" + HexConverter.ConvertUintToHex(shortAddr, 4)); _testMode = true; StartSink(); if (_coordinator) { StartSource(); } if (stopEvent != null) { stopEvent.WaitOne(); } else { for (; ;) { Thread.Sleep(60 * 1000); } } StopSource(); StopSink(); }
/// <summary> /// Returns a string representation of the object /// </summary> /// <returns>a string represetnation</returns> public override string ToString() { string description = fcs.ToString(); description += ", seqNo: " + seqNo.ToString(); AddressingMode dstMode = fcs.DstAddrMode; AddressingMode srcMode = fcs.SrcAddrMode; switch (dstMode) { case AddressingMode.None: description += ", no dst"; break; case AddressingMode.Reserved: description += ", bad dst"; break; case AddressingMode.Short: description += ", dstPanId: " + dstPanId.ToString(); description += ", dstAddrShort: " + HexConverter.ConvertUintToHex(dstAddrShort, 4); break; case AddressingMode.Extended: description += ", dstPanId: " + dstPanId.ToString(); description += ", dstAddrExt: " + HexConverter.ConvertUint64ToHex(dstAddrExt, 16); break; default: description += ", bad dst"; break; } switch (srcMode) { case AddressingMode.None: description += ", no src"; break; case AddressingMode.Reserved: description += ", bad src"; break; case AddressingMode.Short: if (!fcs.PanIdCompression) { description += ", srcPanId: " + srcPanId.ToString(); } description += ", srcAddrShort: " + HexConverter.ConvertUintToHex(srcAddrShort, 4); break; case AddressingMode.Extended: if (!fcs.PanIdCompression) { description += ", srcPanId: " + srcPanId.ToString(); } description += ", srcAddrExt: " + HexConverter.ConvertUint64ToHex(srcAddrExt, 16); break; default: description += ", bad src"; break; } // FIXME: secHeader return(description); }
private void DataIndicationHandler( object sender, UInt16 source, UInt16 targetShortAddr, Frame frame) { lock (_msgReport) { Message msg = (Message)frame.ReadByte(0); switch (msg) { case Message.Data: { if (_testMode) { _monitor.Print("received frame from 0x" + HexConverter.ConvertUintToHex(source, 4) + ", sduHandle=" + frame.ReadByte(1) + ", len=" + frame.LengthDataUsed + " bytes"); } for (int i = 0; i < _msgReport.nodeCount; i++) { if (_msgReport.nodes[i].addr == source) { _msgReport.nodes[i].rxBps += (UInt32)frame.LengthDataUsed; return; } } if (_msgReport.nodeCount < _msgReport.nodes.Length) { _msgReport.nodes[_msgReport.nodeCount].addr = source; _msgReport.nodes[_msgReport.nodeCount].rxBps = (UInt32)frame.LengthDataUsed; _msgReport.nodeCount++; } break; } case Message.Report: { MsgReport rep = new MsgReport(); if (rep.ReadFromFrame(frame)) { if (_testMode) { _monitor.Print("Report from node 0x" + HexConverter.ConvertUintToHex(source, 4) + ":"); for (int i = 0; i < rep.nodeCount; i++) { _monitor.Print(" " + rep.nodes[i].rxBps + " bytes per second from 0x" + HexConverter.ConvertUintToHex(rep.nodes[i].addr, 4)); } } if (_coordinator) { StatusHandleReport(source, rep); } } break; } case Message.Neighbors: { MsgNeighbors neigh = new MsgNeighbors(); if (neigh.ReadFromFrame(frame)) { if (_testMode) { _monitor.Print("Neighbors from node 0x" + HexConverter.ConvertUintToHex(source, 4) + ":"); for (int i = 0; i < neigh.neighborCount; i++) { _monitor.Print(" 0x" + HexConverter.ConvertUintToHex(neigh.neighbors[i].shortAdr, 4) + ": " + neigh.neighbors[i].lqi); } } if (_coordinator) { StatusHandleNeighbors(source, neigh); } } break; } } } Frame.Release(ref frame); }
private void ScanHandlerStartRequest( object sender, Status status, ScanResult[] networks) { _logicalChannel = 0; _channelPage = 0; if (status == Status.Success) { // first check if there are nodes of target network already -> use same channel UInt16[] neighborAddr; status = FindNetwork(out neighborAddr); if (status == Status.NoNeighbor) { // perform ED scan bool found = true; byte energy = 0xff; // max AutoResetEvent callbackEvent = new AutoResetEvent(false); Trace.Print("Performing ED scan"); int length = _scanChannels.Length; for (int i = 0; i < length; i++) { UInt32 channels = (UInt32)_scanChannels[i]; UInt32 page = (channels >> 27); channels &= 0x07FFFFFF; // remove page // FIXME: how to select scanDuration? byte scanDuration = 5; _net.Mac.ScanRequest(ScanType.ED, channels, scanDuration, (byte)page, new SecurityOptions(), delegate( IMacMgmtSap senderDlgt, MacEnum statusDlgt, ScanType scanTypeDlgt, Byte channelPageDlgt, UInt32 unscannedChannelDlgt, byte[] energyDetectListDlgt, PanDescriptor[] panDescriptorListDlgt) { if (statusDlgt == MacEnum.Success && energyDetectListDlgt != null) { int idx = 0; for (int c = 0; c < 27; c++) { if ((channels & (1 << c)) > 0) { // channel 'c' was requested if (((unscannedChannelDlgt & (1 << c)) == 0) && // channel was measured (idx < energyDetectListDlgt.Length)) { // result is avaiable Trace.Print("channel " + c + ": energy level " + energyDetectListDlgt[idx]); if (energyDetectListDlgt[idx] < energy) { // result is better found = true; energy = energyDetectListDlgt[idx]; _logicalChannel = (byte)c; _channelPage = channelPageDlgt; } } idx++; } } } callbackEvent.Set(); }); callbackEvent.WaitOne(); } if (found) { status = Status.Success; Trace.Print("Starting new network on channel " + _logicalChannel + ", page " + _channelPage); } else { status = Status.Error; Trace.Print("ED scan failed"); } } if (status == Status.Success) { Trace.Print("Using Pan Id=0x" + HexConverter.ConvertUintToHex(_panId, 4) + ", logicalChannel=" + _logicalChannel + ", channelPage=" + _channelPage); _net.Routing.Start(_panId, true, _logicalChannel, _channelPage, null, StartHandlerStartRequest); return; } } // scanning failed StartHandlerStartRequest(null, status, 0); }
/// <summary> /// To send sdu from local node /// </summary> /// <param name="tgtAddrExt"></param> /// <param name="sduHandle"></param> /// <param name="sdu"></param> /// <param name="handler"></param> public void DataRequest( UInt16 targetAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler, bool isControlMsg) { lock (_lock) { int i = FindTargetAddr(targetAddr); Entry entry; if (i == -1) { // create new entry entry = AddEntry(targetAddr); } else { entry = _table[i] as Entry; } bool doRouteRequest = false; if (entry.nextHopAddr == cInvalidAddr || entry.routeHasError) { // no route to targetAddr // queue this message if (entry.pendingMessages.Count == cMaxPendingMsg) { // delete oldest waiting msg PendingMessage pmOld = (PendingMessage)entry.pendingMessages[0]; entry.pendingMessages.RemoveAt(0); _routing.DataRequestTimeout(targetAddr, pmOld.sduHandle, pmOld.handler, pmOld.isControlMsg); Frame.Release(ref pmOld.sdu); } PendingMessage pm = new PendingMessage(); pm.sdu = sdu; sdu = null; pm.sduHandle = sduHandle; pm.handler = handler; pm.isControlMsg = isControlMsg; entry.pendingMessages.Add(pm); doRouteRequest = true; } else { entry.routeInUse = true; _routing.DataRequest(targetAddr, entry.nextHopAddr, ref sdu, sduHandle, handler, isControlMsg); if (entry.routeHasError) { doRouteRequest = true; entry.routeHasError = false; } } if (doRouteRequest) { // initiate route request if (!entry.routePending) { // we haven't asked for a route yet, start now entry.routePending = true; entry.requestRetryCnt = cRouteRequestRetryCnt; entry.timeOutSet = cRouteRequestWaitTime; _timerEvent.Set(); Trace.Print("Sending route request for 0x" + HexConverter.ConvertUintToHex(entry.targetAddr, 4) + " for data"); _routing.RouteRequest(targetAddr); } // else: wait for ongoing request } } }
public override string ToString() { return("AddressRequest [HopsLeft: " + HopsLeft + ", BrokerAddr: 0x" + HexConverter.ConvertUintToHex(BrokerAddr, 4) + ", DeviceAddr: 0x" + HexConverter.ConvertUint64ToHex(DeviceAddr, 16) + "]"); }