locked
How to read from StreamSocket on RFComm bluetooth connection?

    Question

  • Hi, 

    I'm building an app which connects with a RFcomm bluetooth device. It connects successfuly and also writes successfuly.

    The device is configured to respond to certain strings. So if I write "test\r" it will respond "ok". The problem is, when I try to read from the Socket InputStream the app simply exits it´s thread, it writes this to output:

    The thread 0x40c has exited with code 0 (0x0).
    The thread 0x1de8 has exited with code 0 (0x0).

    Here is the code that is called on click button:

    if (rfCommService != null) { StreamSocket socket = new StreamSocket(); await socket.ConnectAsync(rfCommService.ConnectionHostName, rfCommService.ConnectionServiceName, SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication); writer = new DataWriter(socket.OutputStream); reader = new DataReader(socket.InputStream); // Write to Device writer.WriteString("test\r"); // Reads from Device uint s = await reader.LoadAsync(4); // Trying to read 4 bytes - Don´t know what put here!!! string data = reader.ReadString(s);

    System.Diagnostics.Debug.WriteLine(s); socket.Dispose(); }

    Any help is welcome.

    Thanks.

    Thursday, March 20, 2014 5:17 PM

Answers

  • You need to await writer.StoreAsync() to move the bytes out.  And for the length in the reader.LoadAsync(), try first setting reader.InputStreamOptions = InputStreamOptions.Partial, and then return "more" data (e.g., 1000 bytes).  The load will actually return when any data comes in.

    The networking API posters include sockets; download them here!


    Network Developer Experience Team (Microsoft)

    • Marked as answer by DevDoubts Thursday, March 20, 2014 6:33 PM
    Thursday, March 20, 2014 5:40 PM

All replies

  • You need to await writer.StoreAsync() to move the bytes out.  And for the length in the reader.LoadAsync(), try first setting reader.InputStreamOptions = InputStreamOptions.Partial, and then return "more" data (e.g., 1000 bytes).  The load will actually return when any data comes in.

    The networking API posters include sockets; download them here!


    Network Developer Experience Team (Microsoft)

    • Marked as answer by DevDoubts Thursday, March 20, 2014 6:33 PM
    Thursday, March 20, 2014 5:40 PM
  • Great!

    Thanks for the quick reply!

    I put the await writer.StoreAsync() and it resolved my main problem! Thanks very much. Just for learning purposes, why I have to put this? To make sure it has writen all?

    On the other side, I was expecting the string data to be filled with "ok" but it prints "4". Should I convert it to something in order to get the data from the stream?

    Thanks a lot!

    Thursday, March 20, 2014 5:51 PM
  • Please, 

    disregard my comments on the ouput. I was printing the wrong var. The content is right. 

    You solved my problem. Thanks again. 

    ps: If you could just reply to my question "for learning purposes" would be great!

    Best regards.

    Thursday, March 20, 2014 5:56 PM
  • A good mental model of DataWriter is that it accumulates a bunch of data, and then writes it out.  DataWriter won't try to second-guess you about what a "bunch" is; you get to specify it by calling StoreAsync() at the right times.

    One big reason for doing this is to support Datagram sockets correctly.  With a datagram socket, the buffer boundaries deeply matter: each "bunch of data" becomes a single packet that's sent out.

     

    Network Developer Experience Team (Microsoft)

    Friday, March 21, 2014 7:30 PM
  • Thanks a lot!
    Friday, March 21, 2014 10:55 PM
  • How do you handle a null data that coming from the reader? My app keeps force closing when it receive null data. Here is my code:

    int i = 0;
    
            private async void ReceiveData()
            {
                if (socket != null)
                {
                    uint s = await dataReader.LoadAsync(1);
                    string data = dataReader.ReadString(s);    
                    Debug.WriteLine(s);
                    if (data=="X")
                    {
                        i++;    
                    }
                    if (data == null)
                    {
                        // what should I put here?
                    }
                    txtMessage.Text = i.ToString();
                }
            }

    Tuesday, June 10, 2014 9:13 AM
  • Hi Aufar, I think you should open another thread to post this so other people would see and respond to you question. 

    Anyway, the answer depends on what you want to do in case of the data is null. Maybe a simple return statement will do, or maybe you want to decrement (--i) or maybe you would like to re-access the readstring method again. Then you would have to put this read inside a loop (while for example) and read a number of times to try and get the data from the stream.

    Does that help?

    Regards.

    Tuesday, June 10, 2014 5:16 PM
  • In this case I want the dataReader keep reading the incoming data even if the data is null (no data received) and wait until it gets the next incoming data. How would you do that?

    I've tried return but still doesn't work.

    Wednesday, June 11, 2014 10:43 AM
  • Would be something like that:

    int i = 0;
    
    private async void ReceiveData()
    {
    	if (socket != null)
    	{
    		while(true)
    		{
    			uint s = await dataReader.LoadAsync(1);
    			string data = dataReader.ReadString(s);    
    			Debug.WriteLine(s);
    			if (data=="X")
    			{
    				i++;    
    				// break while if found something -- maybe you have another criteria like wait for some specific character
    				break;
    			}
    			if (data == null)
    			{
    				// continue while if null
    				continue;
    			}
    			txtMessage.Text = i.ToString();					
    		}
    		
    	}
    }

    Does that help?

    Thursday, June 12, 2014 1:08 PM
  • I tried your code but turns out my app still crash.

    xception has been thrown by the target of an invocation. ---> System.Exception: The operation identifier is not valid.

       at Windows.Storage.Streams.DataReader.LoadAsync(UInt32 count)
       at HeartbeatPhoneApp.HeartbeatPivot.<ReceiveData>d__7.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__0(Object state)
       --- End of inner exception stack trace ---

    Saturday, June 14, 2014 6:44 AM
  • The exception: System.Exception: The operation identifier is not valid. Usually means that a method async is called twice or more before the first call has been finished. It´s like when It returns, as it got called again in the middle of an async operation.

    Try calling only once your ReceiveData() method. If it does not help you, I suggest you place a new thread on the forum so more people can help with this issue.

    Regards!

    Sunday, June 15, 2014 3:29 AM