public void ReceivedUnclaimedSynchronousCommandResponse(ZToolPacket packet) { if (packet is ZToolPacket srsp) { throw new NotImplementedException(); } }
/// <summary> /// An asynchronous command is received from the network. If it is an AF_INCOMING_MSG then /// pass the message on to any listeners. /// </summary> /// <param name="packet"></param> public void ReceivedAsynchronousCommand(ZToolPacket packet) { if (packet is AF_INCOMING_MSG msg) { if (_listeners.Count == 0) { _logger.Warn($"Received AF_INCOMING_MSG but no listeners. Message was from {msg.SrcAddr} and cluster {msg.ClusterId} to endpoint {msg.DstEndpoint}. Data: {msg}"); } else { _logger.Trace($"Received AF_INCOMING_MSG from {msg.SrcAddr} and cluster {msg.ClusterId} to endpoint {msg.DstEndpoint}. Data: {msg}"); } List <IApplicationFrameworkMessageListener> localCopy; lock (_listeners) { localCopy = new List <IApplicationFrameworkMessageListener>(); localCopy.AddRange(_listeners); } foreach (var listener in localCopy) { try { listener.Notify(msg); } catch (Exception e) { _logger.Error(e, "Error AF message listener notify"); } } } }
//public <REQUEST extends ZToolPacket, RESPONSE extends ZToolPacket> RESPONSE sendLocalRequest(REQUEST request) //{ // if (!WaitForNetwork()) // { // return null; // } // RESPONSE result = (RESPONSE)SendSynchronous(request); // if (result == null) // { // Log.Error("{} timed out waiting for synchronous local response.", request.GetType().Name); // } // return result; //} //public <REQUEST extends ZToolPacket, RESPONSE extends ZToolPacket> RESPONSE sendRemoteRequest(REQUEST request) //{ // if (!WaitForNetwork()) // { // return null; // } // RESPONSE result; // waitAndLock3WayConversation(request); // final BlockingCommandReceiver waiter = new BlockingCommandReceiver(ZToolCMD.ZDO_MGMT_PERMIT_JOIN_RSP, // _commandInterface); // Log.Verbose("Sending {}", request); // ZToolPacket response = SendSynchronous(request); // if (response == null) // { // Log.Error("{} timed out waiting for synchronous local response.", request.GetType().Name); // waiter.cleanup(); // return null; // } // else // { // Log.Error("{} timed out waiting for asynchronous remote response.", request.GetType().Name); // result = (RESPONSE)waiter.getCommand(TIMEOUT); // unLock3WayConversation(request); // return result; // } //} /// <summary> /// <paramref name="request"/> /// </summary> private void WaitAndLock3WayConversation(ZToolPacket request) { lock (_conversation3Way) { Type clz = request.GetType(); Thread requestor; while ((requestor = _conversation3Way[clz]) != null) { if (!requestor.IsAlive) { Log.Error("Thread {} whom requested {} DIED before unlocking the conversation"); Log.Debug("The thread {} who was waiting for {} to complete DIED, so we have to remove the lock"); _conversation3Way[clz] = null; break; } Log.Verbose("{Thread} is waiting for {Clz} to complete which was issued by {Requestor} to complete", new object[] { Thread.CurrentThread, clz, requestor }); try { _hardwareSync.Wait(); } catch (Exception ex) { Log.Error("Error in 3 way conversation: {Exception}", ex); } } _conversation3Way[clz] = Thread.CurrentThread; } }
public void testReceive() { ZToolPacket data = GetPacket("FE 07 45 83 00 00 00 00 00 10 C1 10"); ZigBeeApsFrame apsFrame = ZdoPowerDescriptor.Create(data); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("00 00 00 00 10 C1"), apsFrame.Payload); }
/// <summary> /// Sends asynchronous command. /// /// <param name="packet">the packet.</param> /// @throws IOException if IO exception occurs in packet sending. /// </summary> public void SendAsynchronousCommand(ZToolPacket packet) { byte value = (byte)(packet.CMD.Msb & 0xE0); if (value != 0x40) { throw new ArgumentException("You are trying to send a non AREQ packet. " + "Evaluated " + value + " instead of " + 0x40 + "\nPacket " + packet.GetType().Name + "\n" + packet); } SendPacket(packet); }
public void TestReceive() { ZToolPacket data = GetPacket("FE 12 45 82 00 00 00 00 00 00 40 0F 00 00 50 A0 00 01 00 A0 00 00 CB"); ZigBeeApsFrame apsFrame = ZdoNodeDescriptor.Create(data); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("00 00 00 00 00 40 0F 00 00 50 A0 00 01 00 A0 00 00"), apsFrame.Payload); }
public void ReceivedCommandResponse(ZToolPacket packet) { _logger.Trace(" {} received as synchronous command.", packet.GetType().Name); lock (packet) { OnResponseReceived?.Invoke(this, packet); // Do not set response[0] again. //response[0] = packet; //response.notify(); } }
public void TestReceive() { ZToolPacket data = GetPacket("FE 03 45 B4 E6 D2 00 C6"); ZigBeeApsFrame apsFrame = ZdoManagementLeave.Create(data); Assert.Equal(53990, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("D2 00"), apsFrame.Payload); }
public void TestReceive() { ZToolPacket data = GetPacket("FE 0D 45 C1 2A 2F 2A 2F F9 41 F6 02 00 4B 12 00 00 9C"); ZigBeeApsFrame apsFrame = ZdoEndDeviceAnnounce.Create(data); Assert.Equal(0x2f2a, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("2F 2A 2F F9 41 F6 02 00 4B 12 00 00"), apsFrame.Payload); }
public void TestReceive() { ZToolPacket data = GetPacket("FE 0B 45 B2 00 00 00 01 00 01 2A 2F 00 35 38 F4"); ZigBeeApsFrame apsFrame = ZdoManagementRouting.Create(data); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("00 00 01 00 01 2A 2F 00 35 38"), apsFrame.Payload); }
public void TestReceive() { ZToolPacket data = GetPacket("FE 15 45 FF 00 00 00 01 80 00 00 00 1B 00 5B 23 EB 09 00 4B 12 00 00 00 00 F6"); ZigBeeApsFrame apsFrame = ZdoCallbackIncoming.Create(data); Assert.Equal(0x8001, apsFrame.Cluster); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("1B 00 5B 23 EB 09 00 4B 12 00 00 00 00"), apsFrame.Payload); }
public void TestReceive2() { ZToolPacket data = GetPacket( "FE 18 45 84 21 A4 00 21 A4 12 02 04 01 01 00 00 02 00 00 03 00 03 05 00 06 00 08 00 C4"); ZigBeeApsFrame apsFrame = ZdoSimpleDescriptor.Create(data); Assert.Equal(42017, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("A4 00 21 A4 12 02 04 01 01 00 00 02 00 00 03 00 03 05 00 06 00 08 00"), apsFrame.Payload); }
public static ZigBeeApsFrame Create(ZToolPacket packet) { ZigBeeApsFrame apsFrame = new ZigBeeApsFrame(); apsFrame.Cluster = ZdoCommandType.GetValueByType(ZdoCommandType.CommandType.IEEE_ADDRESS_RESPONSE).ClusterId; apsFrame.DestinationEndpoint = 0; apsFrame.SourceAddress = BitConverter.ToUInt16(packet.Packet, 13); apsFrame.SourceEndpoint = 0; apsFrame.Profile = 0; apsFrame.Payload = packet.Packet.Skip(3).Take(packet.Packet[1]).ToArray(); return(apsFrame); }
public void TestReceive() { string packetString = "FE 08 45 85 00 00 00 00 00 02 02 01 C9"; ZToolPacket data = GetPacket(packetString); Assert.Equal(packetString, data.PacketString); ZigBeeApsFrame apsFrame = ZdoActiveEndpoint.Create(data); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData("00 00 00 00 02 02 01"), apsFrame.Payload); }
public static ZigBeeApsFrame Create(ZToolPacket packet) { ZigBeeApsFrame apsFrame = new ZigBeeApsFrame(); apsFrame.Cluster = ZdoCommandType.GetValueByType(ZdoCommandType.CommandType.SIMPLE_DESCRIPTOR_RESPONSE).ClusterId; apsFrame.DestinationEndpoint = 0; apsFrame.SourceAddress = (ushort)(packet.Packet[4] | (packet.Packet[5] << 8)); apsFrame.SourceEndpoint = 0; apsFrame.Profile = 0; Array.Copy(packet.Packet, 6, apsFrame.Payload, 0, packet.Packet.Length - 7); return(apsFrame); }
public void TestReceive() { ZToolPacket data = GetPacket( "FE 32 45 B1 00 00 00 02 00 02 14 D4 F1 02 00 4B 12 00 0B 88 DC 00 01 88 17 00 8F 22 15 02 01 3B 14 D4 F1 02 00 4B 12 00 EC A1 A5 01 00 8D 15 00 35 38 15 02 01 58 B5"); ZigBeeApsFrame apsFrame = ZdoManagementLqi.Create(data); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData( "00 00 02 00 02 14 D4 F1 02 00 4B 12 00 0B 88 DC 00 01 88 17 00 8F 22 15 02 01 3B 14 D4 F1 02 00 4B 12 00 EC A1 A5 01 00 8D 15 00 35 38 15 02 01 58"), apsFrame.Payload); }
public static ZigBeeApsFrame Create(ZToolPacket packet) { ZigBeeApsFrame apsFrame = new ZigBeeApsFrame(); apsFrame.Cluster = ZdoCommandType.GetValueByType(ZdoCommandType.CommandType.MANAGEMENT_LEAVE_RESPONSE).ClusterId; apsFrame.DestinationEndpoint = 0; apsFrame.SourceAddress = (ushort)(packet.Packet[4] | (packet.Packet[5] << 8)); apsFrame.SourceEndpoint = 0; apsFrame.Profile = 0; apsFrame.Payload = packet.Packet.Skip(5).Take(packet.Packet[1] - 1).ToArray(); return(apsFrame); }
public void TestReceive1() { ZToolPacket data = GetPacket( "FE 2E 45 84 00 00 00 00 00 28 01 04 01 00 00 00 00 10 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0F 00 0A 00 0C 00 15 00 00 01 01 01 CF"); ZigBeeApsFrame apsFrame = ZdoSimpleDescriptor.Create(data); Assert.Equal(0x0000, apsFrame.SourceAddress); Assert.Equal(0, apsFrame.Profile); Assert.Equal(0, apsFrame.DestinationEndpoint); Assert.Equal(GetPacketData( "00 00 00 00 28 01 04 01 00 00 00 00 10 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0F 00 0A 00 0C 00 15 00 00 01 01 01"), apsFrame.Payload); }
public static ZigBeeApsFrame Create(ZToolPacket packet) { ZigBeeApsFrame apsFrame = new ZigBeeApsFrame(); apsFrame.Cluster = (ushort)(packet.Packet[7] | (packet.Packet[8] << 8)); apsFrame.DestinationAddress = (ushort)(packet.Packet[11] | (packet.Packet[12] << 8)); apsFrame.DestinationEndpoint = 0; apsFrame.SourceAddress = (ushort)(packet.Packet[4] | (packet.Packet[5] << 8)); apsFrame.SourceEndpoint = 0; apsFrame.Profile = 0; apsFrame.Payload = packet.Packet.Skip(12).ToArray(); apsFrame.Payload = apsFrame.Payload.Take(apsFrame.Payload.Count() - 1).ToArray(); return(apsFrame); }
public void ReceivedAsynchronousCommand(ZToolPacket packet) { if (packet is ZDO_STATE_CHANGE_IND stateInd) { switch (stateInd.Status) { case DeviceState.Started_as_ZigBee_Coordinator: Log.Debug("Started as Zigbee Coordinator"); OnStateChanged?.Invoke(this, DriverStatus.NETWORK_READY); break; default: break; } } }
public static ZigBeeApsFrame Create(ZToolPacket packet) { ZigBeeApsFrame apsFrame = new ZigBeeApsFrame(); apsFrame.Cluster = (ushort)(packet.Packet[7] | (packet.Packet[8] << 8)); apsFrame.DestinationAddress = (ushort)(packet.Packet[11] | (packet.Packet[12] << 8)); apsFrame.DestinationEndpoint = 0; apsFrame.SourceAddress = (ushort)(packet.Packet[4] | (packet.Packet[5] << 8)); apsFrame.SourceEndpoint = 0; apsFrame.Profile = 0; apsFrame.ApsCounter = packet.Packet[10]; apsFrame.Payload = new byte[packet.Packet.Length - 13]; Array.Copy(packet.Packet, 13, apsFrame.Payload, 0, packet.Packet.Length - 14); return(apsFrame); }
public void ReceivedAsynchronousCommand(ZToolPacket packet) { _logger.Trace("Received a packet {} and waiting for {}", packet.CMD, _commandId); _logger.Trace("received {} {}", packet.GetType(), packet.ToString()); //if (packet.isError()) //{ // return; //} if ((ZToolCMD)packet.CMD.Value != _commandId) { _logger.Trace("Received unexpected packet: " + packet.GetType().Name); return; } lock (typeof(BlockingCommandReceiver)) { _commandPacket = packet; _logger.Trace("Received expected response: {}", packet.GetType().Name); Cleanup(); } }
/// <summary> /// Notifies listeners about asynchronous message. /// /// <param name="packet">the packet containing the message</param> /// </summary> private void NotifyAsynchronousCommand(ZToolPacket packet) { IAsynchronousCommandListener[] listeners; lock (_asynchrounsCommandListeners) { listeners = _asynchrounsCommandListeners.ToArray(); } Log.Debug("Received Async Cmd: {Packet}", packet); foreach (IAsynchronousCommandListener listener in listeners) { try { listener.ReceivedAsynchronousCommand(packet); } catch (Exception e) { Log.Error("Error in incoming asynchronous message processing: {Error}", e); } } }
/// <summary> /// Handle parsed packet. /// /// <param name="packet">the packet</param> /// </summary> public void HandlePacket(ZToolPacket packet) { DoubleByte cmdId = packet.CMD; switch (cmdId.Msb & 0xE0) { // Received incoming message which can be either message from dongle or remote device. case 0x40: Log.Debug("<-- Async incomming {Type} ({Packet})", packet.GetType().Name, ByteUtils.ToBase16(packet.Packet)); NotifyAsynchronousCommand(packet); break; // Received synchronous command response. case 0x60: Log.Debug("<-- Sync incomming {Type} ({Packet})", packet.GetType().Name, ByteUtils.ToBase16(packet.Packet)); NotifySynchronousCommand(packet); break; default: Log.Error("Received unknown packet. {Type}", packet.GetType().Name); break; } }
/// <summary> /// Release the lock held for the 3-way communication /// /// <paramref name="request"/> /// </summary> private void UnLock3WayConversation(ZToolPacket request) { Type clz = request.GetType(); Thread requestor; lock (_conversation3Way) { requestor = _conversation3Way[clz]; _conversation3Way[clz] = null; _hardwareSync.Set(); //Monitor.Pulse(_conversation3Way); } if (requestor == null) { Log.Error("LOCKING BROKEN - SOMEONE RELEASE THE LOCK WITHOUT LOCKING IN ADVANCE for {Clz}", clz); } else if (requestor != Thread.CurrentThread) { Log.Error("Thread {Thread} stolen the answer of {Clz} waited by {Requestor}", new object[] { Thread.CurrentThread, clz, requestor }); } }
/// <summary> /// Notifies listeners about synchronous command response. /// /// <param name="packet">the received packet</param> /// </summary> private void NotifySynchronousCommand(ZToolPacket packet) { DoubleByte cmdId = packet.CMD; lock (_synchronousCommandListeners) { ushort id = (ushort)(cmdId.Value & 0x1FFF); _synchronousCommandListeners.TryGetValue(id, out ISynchronousCommandListener listener); if (listener != null) { listener.ReceivedCommandResponse(packet); _synchronousCommandListeners.Remove(id); _commandListenerSync.Set(); } else { // Notify asynchronous command listeners of unclaimed asynchronous command responses. IAsynchronousCommandListener[] listeners; lock (_asynchrounsCommandListeners) { listeners = _asynchrounsCommandListeners.ToArray(); } foreach (IAsynchronousCommandListener asynchronousCommandListener in listeners) { try { asynchronousCommandListener.ReceivedUnclaimedSynchronousCommandResponse(packet); } catch (Exception e) { Log.Error("Error in incoming asynchronous message processing: {Error}", e); } } } } }
public void ReceivedCommandResponse(ZToolPacket packet) { Log.Verbose(" {Packet} received as synchronous command.", packet.GetType().Name); OnResponseReceived?.Invoke(this, packet); }
/** * Translates the ZigBee ZDO cluster packet into a ZTool RSP packet */ public ZToolPacket Translate() { ZToolPacket newPacket = null; byte[] frame; _logger.Trace("Translating ZDO cluster callback {ClusterId}", ClusterId); Type newPacketClass = ClusterToRSP[ClusterId.Value]; if (newPacketClass == null) { _logger.Error("Unhandled ZDO cluster callback {Cluster}", ClusterId); return(this); } else if (newPacketClass == typeof(ZDO_NWK_ADDR_RSP) || newPacketClass == typeof(ZDO_IEEE_ADDR_RSP)) { // The address responses don't need SrcAddr. NumAssocDev and StartIndex positions are reversed. // The new response frame is at least 13 bytes long. frame = new byte[Math.Max(Data.Length, 13)]; Array.Copy(Data, 0, frame, 0, Data.Length); // If RequestType == 1 there are two extra bytes in the frame if (Data.Length > 12) { frame[11] = Data[12]; // NumAssocDev frame[12] = Data[11]; // StartIndex } else { frame[11] = 0; frame[12] = 0; } } else { // Default frame translation, this works for most callbacks. // Get 2 extra bytes at the beginning to put source address into. frame = new byte[Data.Length + 2]; Array.Copy(Data, 0, frame, 2, Data.Length); frame[0] = SrcAddr.Lsb; frame[1] = SrcAddr.Msb; } try { //newPacket = Activator.CreateInstance(newPacketClass, frame); switch (ClusterId.Value) { case 0x0013: newPacket = new ZDO_END_DEVICE_ANNCE_IND(frame); break; case 0x8000: newPacket = new ZDO_NWK_ADDR_RSP(frame); break; case 0x8001: newPacket = new ZDO_IEEE_ADDR_RSP(frame); break; case 0x8002: newPacket = new ZDO_NODE_DESC_RSP(frame); break; case 0x8003: newPacket = new ZDO_POWER_DESC_RSP(frame); break; case 0x8004: newPacket = new ZDO_SIMPLE_DESC_RSP(frame); break; case 0x8005: newPacket = new ZDO_ACTIVE_EP_RSP(frame); break; case 0x8006: newPacket = new ZDO_MATCH_DESC_RSP(frame); break; case 0x8011: newPacket = new ZDO_USER_DESC_RSP(frame); break; case 0x8014: newPacket = new ZDO_USER_DESC_CONF(frame); break; case 0x8020: newPacket = new ZDO_END_DEVICE_BIND_RSP(frame); break; case 0x8021: newPacket = new ZDO_BIND_RSP(frame); break; case 0x8022: newPacket = new ZDO_UNBIND_RSP(frame); break; case 0x8031: newPacket = new ZDO_MGMT_LQI_RSP(frame); break; case 0x8034: newPacket = new ZDO_MGMT_LEAVE_RSP(frame); break; case 0x8036: newPacket = new ZDO_MGMT_PERMIT_JOIN_RSP(frame); break; } } catch (Exception e) { _logger.Error("Error constructing response packet {Exception}", e); return(this); } if (newPacket != null) { newPacket.FCS = this.FCS; } return(newPacket); }
public void ReceivedAsynchronousCommand(ZToolPacket packet) { switch (packet.Subsystem) { case ZToolPacket.CommandSubsystem.AF: return; case ZToolPacket.CommandSubsystem.ZDO: break; default: break; } ZigBeeApsFrame apsFrame = null; switch ((ZToolCMD)packet.CMD.Value) { case ZToolCMD.ZDO_MSG_CB_INCOMING: apsFrame = ZdoCallbackIncoming.Create(packet); break; case ZToolCMD.ZDO_IEEE_ADDR_RSP: apsFrame = ZdoIeeeAddress.Create(packet); break; case ZToolCMD.ZDO_END_DEVICE_ANNCE_IND: apsFrame = ZdoEndDeviceAnnounce.Create(packet); break; case ZToolCMD.ZDO_NODE_DESC_RSP: apsFrame = ZdoNodeDescriptor.Create(packet); break; case ZToolCMD.ZDO_POWER_DESC_RSP: apsFrame = ZdoPowerDescriptor.Create(packet); break; case ZToolCMD.ZDO_ACTIVE_EP_RSP: apsFrame = ZdoActiveEndpoint.Create(packet); break; case ZToolCMD.ZDO_SIMPLE_DESC_RSP: apsFrame = ZdoSimpleDescriptor.Create(packet); break; case ZToolCMD.ZDO_MGMT_LQI_RSP: apsFrame = ZdoManagementLqi.Create(packet); break; case ZToolCMD.ZDO_MGMT_RTG_RSP: apsFrame = ZdoManagementRouting.Create(packet); break; case ZToolCMD.ZDO_MGMT_LEAVE_RSP: apsFrame = ZdoManagementLeave.Create(packet); break; default: _logger.Debug($"Unhandled SerialPacket type {packet.CMD}"); break; } if (apsFrame != null) { _ZigBeeNetworkReceive.ReceiveCommand(apsFrame); return; } }
/// <summary> /// Sends synchronous command and adds listener. /// /// <param name="packet">the command packet</param> /// <param name="listener">the synchronous command response listener</param> /// <param name="timeoutMillis">the timeout</param> /// @throws IOException if IO exception occurs in packet sending /// </summary> public void SendSynchronousCommand(ZToolPacket packet, ISynchronousCommandListener listener, long timeoutMillis) { if (timeoutMillis == -1L) { _synchronousCommandListenerTimeouts[listener] = -1L; } else { long expirationTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + timeoutMillis; _synchronousCommandListenerTimeouts[listener] = expirationTime; } DoubleByte cmdId = packet.CMD; int value = (cmdId.Msb & 0xE0); if (value != 0x20) { throw new ArgumentException("You are trying to send a non SREQ packet as synchronous command. " + "Evaluated " + value + " instead of " + 0x20 + "\nPacket " + packet.GetType().Name + "\n" + packet); } CleanExpiredSynchronousCommandListeners(); if (_supportMultipleSynchrounsCommand) { lock (_synchronousCommandListeners) { ushort id = (ushort)(cmdId.Value & 0x1FFF); while (_synchronousCommandListeners.ContainsKey(cmdId.Value)) { try { Log.Verbose("Waiting for other request {Command} to complete", id); _commandListenerSync.Wait(500); CleanExpiredSynchronousCommandListeners(); } catch (Exception ignored) { } } _synchronousCommandListeners[id] = listener; } } else { lock (_synchronousCommandListeners) { ushort id = (ushort)(cmdId.Value & 0x1FFF); while (!(_synchronousCommandListeners.Count == 0)) { try { Log.Verbose("Waiting for other request to complete"); _commandListenerSync.Wait(500); CleanExpiredSynchronousCommandListeners(); } catch (Exception ignored) { } } Log.Verbose("Put synchronousCommandListeners listener for {Command} command", id); _synchronousCommandListeners[id] = listener; } } Log.Verbose("Sending SynchronousCommand {Packet} ", packet); SendPacket(packet); }