Author Topic: How to wait for data with Synchronous Bluetooth Client  (Read 15404 times)

mcmalburg

  • Guest
How to wait for data with Synchronous Bluetooth Client
« on: July 13, 2016, 07:56:11 PM »
For my PC-based Bluetooth project, I'm using a wclSyncClient.  It works great,  however there are times when I need to wait for my connected device to respond to a command and send data back to the PC.  What is the best way to wait for available bytes?

Below is a bit of my code.  This resides on the application's main (UI) thread.  My real question is: what do I put in the "wait" loop?

I think  I need to "Sleep" or "DoEvents" in order to give the wclsyncClient a chance to update its incoming data.  The "DoEvents" seems to do the best job at getting updated buffer status, but it is causing me problems with the user interface.  (For example, the user can close the application, and the "DoEvents" will handle it in the middle of of Bluetooth polling.)  Thus, I'm not feeling very good about using DoEvents.

What should I put in the "while loop" to give the wclsyncClient a chance to update?

Thanks,

   - Mark


------- CODE SNIPPET ----------------



   private wclSyncClient wclsyncClient;

   wclsyncClient = new wcl.wclSyncClient();
   wclsyncClient.OnDisconnect += new System.EventHandler(OnBluetoothDisconnect);
   wclsyncClient.OnConnect += new wcl.wclConnectEventHandler(OnBluetoothConnect);

   wclsyncClient.BluetoothParams.Address = strBluetoothDeviceAddress;
   wclsyncClient.BluetoothParams.Radio = Radio;
   wclsyncClient.BluetoothParams.Service = wcl.wclUUIDs.SerialPortServiceClass_UUID;
   wclsyncClient.Transport = wcl.wclTransport.trBluetooth;

   nWCLErrorCode = wclsyncClient.Connect();




   public Boolean WaitForBytes(int nBytes, int nTimeoutMSEC)
   {
      StopWatch sw = new StopWatch();
      sw.Start();

      // Here is the "wait" loop
      while ((wclsyncClient.DataSize < nBytes) && (sw.ElapsedMsec < nTimeoutMSEC))
      {
         Thread.Sleep(10);
         // Application.DoEvents();
      }

      return (wclsyncClient.DataSize >= nBytes);

   }

Offline Mike Petrichenko

  • Bluetooth Framework Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 3675
  • Karma: 1000
    • Wireless Communication Libraries
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #1 on: July 13, 2016, 10:58:10 PM »
Hello,

DoEvents is exactly when you need in this case. However in such scenarious you should use async wclClient.

mcmalburg

  • Guest
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #2 on: July 13, 2016, 11:26:55 PM »
Thanks for the reply, Mike,

My challenge is that I want the user interface to be "locked" while waiting for response bytes to be available over the Bluetooth interface.  A "DoEvents' allows the user to do things while waiting.  Thus, I was hoping a simple "Sleep" then a re-poll would allow the data to appear.  Is there a way to manually force the wclSyncClient to "re-check" data buffer"?  That way I could achieve the refreshing of "DataSize" in a modal/synchronous manner (while the UI waits).

    - Mark


Offline Mike Petrichenko

  • Bluetooth Framework Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 3675
  • Karma: 1000
    • Wireless Communication Libraries
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #3 on: July 13, 2016, 11:42:10 PM »
Unfortunately no, but:

1. Create separate thread and use NativeWindow class there to process messages (and provide message loop).
2. Use wclClient in this thread
3. Create event in main thread and pass it into communication thread
4. When something happened in communication thread set event.
5. Lock your UI thread when need to wait on this event.

mcmalburg

  • Guest
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #4 on: July 28, 2016, 12:41:25 PM »
In re-thinking this, I realize that I don't need to wait for bytes.  I didn't notice the fact that the wclsyncClient has it's own timeout that I should be able to rely on.

My application needs to periodically read a sensor and provide a live display.  The sensor returns a variable length string terminated with a carriage return. 

Along with the live display, there are several other user interface items in my application that cause interaction with the Bluetooth device.   To prevent multiple commands and responses from getting crossed over Bluetooth I'm using a "wclSyncClient" - the goal is to ensure that one command/response pair is complete before sending the next command.  The wclsyncClient should be exactly what I need.  I'm relying on the "wclsyncClient.Read" and the fact that is should be waiting for a response (with an associated timeout).  However, the wclsyncClient.Read seems to be letting other messages through... as if it isn't really synchronous.

Quite often, I'm finding the "FormClosing" event being handled in the midst of a "wclsyncClient.Read".  That would imply that the sync client isn't all that synchronous.  It also puts me in a situation where the wclsyncClient is closed while in the middle of the wclsyncClient.Read. Thus hanging the application.



Here's a bit of code as an example.  Note: this isn't my actual compiled code. This is just to show the concept of what I'm trying to do:

      private void timerHeartbeat_Tick(object sender, EventArgs e)
      {
         timerHeartbeat.Enabled = false;

         byte[] array = Encoding.ASCII.GetBytes("READ");
         wclsyncClient.Write(array, (UInt32)array.Length);

         String strValue = GetString(100);

         timerHeartbeat.Enabled = true;
      }

      private String GetString(uint uTimeoutMSEC)
      {
         int nResult;
         List<Byte> bList = new List<Byte>();
         Byte bTest = (Byte)'\n';

         do
         {
            nResult = wclsyncClient.Read(ref byteCurrent, ref nSize, uTimeoutMSEC);
            if (nResult == wcl.wclErrors.WCL_E_SUCCESS)
            {
               if (byteCurrent[0] == bTest)
               {
                  bFound = true;
               }
               else
               {
                  bList.Add(byteCurrent[0]);
               }
            }
         } while (!bFound && (nResult == wcl.wclErrors.WCL_E_SUCCESS));

         // return as much of the string that was found
         Byte[] bArray = bList.ToArray();
   
         return ASCIIEncoding.ASCII.GetString(bArray);
      }

      private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
      {
         // Here's the problem... this occurs in the middle of the GetString's execution
         //    thus closing the client and causing the GetString reading to hang
         wclsyncClient.Disconnect();
      }


So... is the wclsyncClient.Read really synchronous?  How can I prevent events from interrupting my string reading?

Thanks,

   - Mark


Offline Mike Petrichenko

  • Bluetooth Framework Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 3675
  • Karma: 1000
    • Wireless Communication Libraries
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #5 on: July 28, 2016, 12:51:33 PM »
Hi,

wcSyncClient based on wclClient and uses the same methods internally. So yes other even can still be generated.

All you need to implement your task is simple state machine. What is much better than blicking UI.

mcmalburg

  • Guest
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #6 on: July 28, 2016, 12:57:07 PM »
Wow... you really do provide fast responses. Thank you for that.

I'm not familiar with "state machines".   Rather than dig into this topic and learn it from scratch - is there a WCL example using this approach?  If not - do you have any hints regarding getting this solved quickly?

Thanks again.

Offline Mike Petrichenko

  • Bluetooth Framework Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 3675
  • Karma: 1000
    • Wireless Communication Libraries
Re: How to wait for data with Synchronous Bluetooth Client
« Reply #7 on: July 28, 2016, 01:17:17 PM »
WCL itself is good example of state machine.

Good start point is https://en.wikipedia.org/wiki/State_pattern

 

Sitemap 1 2 3 4 5 6 7