Get the live data on TCP server from UWP (UPDATED)

2019-03-01 07:19发布

问题:

Below is one method that basically sends the data to TCP Server.

         UPDATE BEGINS HERE: 
 //////////////////////////////////
 private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format)
    {
        // BT_Code: For the purpose of this sample, this function converts only UInt32 and
        // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them.
        byte[] data;
        CryptographicBuffer.CopyToByteArray(buffer, out data);
        if (format != null)
        {
            if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4)
            {
                return BitConverter.ToInt32(data, 0).ToString();
            }
            else if (format.FormatType == GattPresentationFormatTypes.Utf8)
            {
                try
                {
                    return Encoding.UTF8.GetString(data);
                }
                catch (ArgumentException)
                {
                    return "(error: Invalid UTF-8 string)";
                }
            }
            else
            {
                // Add support for other format types as needed.
                return "Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer);
            }
        }
        else if (data != null)
        {
            // We don't know what format to use. Let's try some well-known profiles, or default back to UTF-8.
            if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement))
            {
                try
                { 
                    ///////LOOK HERE/////
                    **string b = ParseHeartRateValue(data).ToString();
                    TrySend(b); 
                    //return "Heart Rate: " + ParseHeartRateValue(data).ToString();
                    return "Heart Rate: " + b;** 
                }
                catch (ArgumentException)
                {
                    return "Heart Rate: (unable to parse)";
                }
            }
            else if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel))
            {
                try
                {
                    // battery level is encoded as a percentage value in the first byte according to
                    // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml
                    return "Battery Level: " + data[0].ToString() + "%";
                }
                catch (ArgumentException)
                {
                    return "Battery Level: (unable to parse)";
                }
            }
            // This is our custom calc service Result UUID. Format it like an Int
            else if (selectedCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid))
            {
                return BitConverter.ToInt32(data, 0).ToString();
            }
            // No guarantees on if a characteristic is registered for notifications.
            else if (registeredCharacteristic != null)
            {
                // This is our custom calc service Result UUID. Format it like an Int
                if (registeredCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid))
                {
                    return BitConverter.ToInt32(data, 0).ToString();
                }
            }
            else
            {
                try
                {
                    return "Unknown format: " + Encoding.UTF8.GetString(data);
                }
                catch (ArgumentException)
                {
                    return "Unknown format";
                }
            }
        }
        else
        {
            return "Empty data received";
        }
        return "Unknown format";
    }
        ///////// END OF UPDATE //////


 private async void TrySend(string data)

    {
        // Create the StreamSocket and establish a connection to the echo server.

        StreamSocket socket = new StreamSocket();
        try
        {
            var streamSocket = new Windows.Networking.Sockets.StreamSocket();
            {
                //The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
                var hostName = new Windows.Networking.HostName("127.0.0.1");
                await streamSocket.ConnectAsync((new Windows.Networking.HostName("127.0.0.1")), "9999");

                // Send a request to the echo server.
                using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
                {
                    using (var streamWriter = new StreamWriter(outputStream))
                    {
                        while (true)
                        {
                            await streamWriter.WriteLineAsync(data);
                            await streamWriter.FlushAsync();
                        }

                        //await streamWriter.WriteLineAsync(data);
                        //await streamWriter.FlushAsync();
                    }
                }
            }
        }
        catch (Exception)
        {
        }
    }

And here is my TCP Server code that receives the data:

 public class EchoServer {
public static void Main() {
    TcpListener listener = null;

    try
    {
        listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9999);
        listener.Start();
        Console.WriteLine("TCP Server Has Started....");
        while (true)
        {
            Console.WriteLine("                                           ");
            Console.WriteLine("Waiting for incoming client connections....");
            Console.WriteLine("                                           ");
            Console.WriteLine("A message will display below once the client starts and establishes a connection ");
            TcpClient client = listener.AcceptTcpClient();
            Console.WriteLine("                                              ");
            Console.WriteLine("Okay, Accepting Client connection now");
            Console.WriteLine("                                       ");
            Console.WriteLine("Accepted new client connection.....");
            StreamReader reader = new StreamReader(client.GetStream());
            StreamWriter writer = new StreamWriter(client.GetStream());
            string s = string.Empty;
            while (!(s = reader.ReadLine()).Equals("Exit") || (s == null)) {
                Console.WriteLine("From client -> " + s);
                writer.WriteLine("From server -> " + s);
                writer.Flush();
            }
            reader.Close();
            writer.Close();
            client.Close();
        }



    } catch (Exception e)
    {
        Console.WriteLine(e);

    } finally
    {
        if (listener != null)
        {
            listener.Stop();
        }
    }

  }
}

Now, the data I am trying to get are the heart rates and it changes every two seconds. However on TCP server I only get the first recorded value of a heart rate and it keeps repeating instead of getting new one.

There is a similar post I saw here on stackoverflow : UWP TCP receive data continuously

and someone suggested to use while loop which I did as you can see in the code. Are there any other suggestions on what should I do?

Thanks

回答1:

while (true)
{
    await streamWriter.WriteLineAsync(data);
    await streamWriter.FlushAsync();
}

The while(true) will keep repeating, meaning that it will always send 'data' at its current value. This is what causes your issue.

In my opinion, you should keep a connection to your TCP server open outside of your 'TrySend' method, and use this method only to send the data. This way you won't need to use this loop.

EDIT :

Try this :

private async void CharacteristicReadButton_Click()
    {
    while(true)
    {
            // BT_Code: Read the actual value from the device by using Uncached.
            GattReadResult result = await selectedCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);
            if (result.Status == GattCommunicationStatus.Success)
            {


                string formattedResult = FormatValueByPresentation(result.Value, presentationFormat);
                rootPage.NotifyUser($"Read result: {formattedResult}", NotifyType.StatusMessage);

                //string formattedResult = FormatValueByPresentation(result.Value, presentationFormat);
                //rootPage.NotifyUser($"Read result: {formattedResult}", NotifyType.StatusMessage);
            }
            else
            {
                rootPage.NotifyUser($"Read failed: {result.Status}", NotifyType.ErrorMessage);
            }
        }
    }