/// <summary>
        /// Method to receive async
        /// </summary>
        /// <param name="client">the udp client</param>
        /// <returns>the result task</returns>
        private async Task ReceiveAsync(UdpClient client, Action <FritzDevice> deviceCallback)
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 1900);

            // delay for 20 seconds
            Task waitTask = Task.Delay(TimeSpan.FromSeconds(10));

            var getDeviceInfoTasks = new List <Task <Tr64Description> >();

            Dictionary <IPAddress, FritzDevice> discovered = new Dictionary <IPAddress, FritzDevice>();

            var tr64DataReader = new Tr64DataReader();

            while (!waitTask.IsCompleted)
            {
                var receiveTask = SafeReceiveAsync(client);

                // check wat for tasks
                Task finishedTask = await Task.WhenAny(receiveTask, waitTask);

                if (finishedTask == receiveTask)
                {
                    UdpReceiveResult result = await receiveTask;

                    // if there is data in buffer read and pars it
                    if (result.Buffer != null && result.Buffer.Length > 0)
                    {
                        string response = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length);

                        // create device by endpoint data
                        FritzDevice device = FritzDevice.ParseResponse(result.RemoteEndPoint.Address, response);
                        if (!discovered.ContainsKey(result.RemoteEndPoint.Address))
                        {
                            if (device != null && device.Location != null && device.Location.Scheme != "unknown")
                            {
                                // fetch the device info
                                deviceCallback?.Invoke(device);
                                getDeviceInfoTasks.Add(tr64DataReader.ReadDeviceInfoAsync(device));
                                discovered.Add(result.RemoteEndPoint.Address, device);
                            }
                        }
                    }
                }
            }

            if (getDeviceInfoTasks.Count > 0)
            {
                foreach (var task in getDeviceInfoTasks)
                {
                    try
                    {
                        var description = await task;
                        description.Device.ParseTR64Desc(description.Data);
                    } catch (FritzDeviceException e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
            }
        }
        /// <summary>
        /// Creates a single <see cref="FritzDevice"/>.
        /// </summary>
        /// <param name="address">The address the device can be found under.</param>
        /// <returns>The ready-to-use device.</returns>
        /// <exception cref="FritzDeviceException">Thrown if a device can not be created or if the data is incomplete.</exception>
        public async Task <FritzDevice> CreateDeviceAsync(IPAddress address)
        {
            var locationBuilder = new UriBuilder("http", address.ToString(), _dataQueryPort);
            var device          = new FritzDevice(address, locationBuilder.Uri);
            var tr64Reader      = new Tr64DataReader();

            var tr64Data = await tr64Reader.ReadDeviceInfoAsync(device);

            device.ParseTR64Desc(tr64Data.Data);
            return(device);
        }