Bluetooth module driver advice

Dec 30, 2011 at 3:06 PM
I need you advice for Bluetooth module driver. 
This module can be set as in Bluetooth host(server) mode or client mode. 
Each mode has its own functions like "Search" in client mode and "set friendly name" in host mode.
Mixing these functions together is going to be confusing for .NET Gadgeteer users.
So do you think it is wise to create two drivers, one for client mode and one for host mode in a way that we have to Bluetooth modules in the designer and user can pick the one they need in the application.
Or is there a way for example to add a new properties member to the Bluetooth module in the designer like "Mode" that can be set to "Client" or "Host" then th euser choose the mode in the designer before starting coding?

Coordinator
Jan 3, 2012 at 10:24 AM

Hi all,

Happy New Year!

Joe, the pattern you describe (to have two separate software classes for a hardware module that has two distinct modes of operation) is an interesting idea.  The advantage is that once you have the instance, you get only the available API.  The disadvantages are that the user might be confused about having two module options in the designer view (this is the only module that does that) and the user might find it hard to discover which choice is right (they have to pick a type in the designer before seeing its API) or to know when to switch between the two.  

The alternative pattern  I would suggest is to have a single class with two sub-classes, e.g.:

 public class Bluetooth : GTM.Module
    {
        // Note: A constructor summary is auto-generated by the doc builder.
        /// <summary></summary>
        /// <param name="socketNumber">The socket that this module is plugged in to.</param>
        public Bluetooth(int socketNumber)
        {
            // implement this
        }

        private object _lock = new Object();

        private Client _client;
        public Client ClientMode
        {
            get {
                lock(_lock)
                {
                    if (_host != null) throw new InvalidOperationException("Cannot use both Client and Host modes for Bluetooth module");
                    if (_client == null) _client = new Client(this);
                    return _client;
                }
            }
        }

        private Host _host;
        public Host HostMode
        {
            get
            {
                lock (_lock)
                {
                    if (_client != null) throw new InvalidOperationException("Cannot use both Client and Host modes for Bluetooth module");
                    if (_host == null) _host = new Host(this);
                    return _host;
                }
            }
        }


        public class Client
        {
            internal Client(Bluetooth bluetooth)
            {
                // implement me
            }
            // implement client API
        }

        public class Host
        {
            internal Host(Bluetooth bluetooth)
            {
                // implement me
            }

            // implement host API
        }
    }

Then when users type "bluetooth." they would see the HostMode and ClientMode in the intellisense dropdown and go via one of these.   It would be important to make it clear to the users via the XML comments that only one mode is usable at a time.  This separates the APIs clearly, but with only one module in the designer view, though it does impose an overhead on the user of another field dereference each time the module is called (bluetooth.HostMode.X instead of bluetooth.X) though of course a savvy user could declare "Bluetooth.Host btHost = bluetooth.HostMode;" and use btHost if they wished.

We do a similar thing in the GTM.DisplayModule abstract class where WPFWindow and SimpleGraphics are two options (though we don't stop you using both but the behaviour might be strange!)

I would lean to the latter pattern (one class, two subclasses) but of course it is up to you (and you may want to try implementing both and seeing how they turn out/getting more feedback).

A lot of the work that's gone into .NET Gadgeteer is about self-explanatory and usable APIs, and it's great to see that you are also taking such care about this.

Ta
James

Jan 3, 2012 at 10:00 PM

Thank you James for the advice.

 

Jan 16, 2012 at 8:24 PM

I agree with James.. I like the exposed designer property approach and would have expected that as a Visual Studio user and their other designers.. I've just started using the module and was able to get into trouble a few times... I think it would be great to have a grouped set for each set of the commands so you could tell the bluetooth module, to issue a particular serial command or maybe even a series of commands based on the patterns in the seeed doc... 

For example if you were in client mode it would be nice to be able to say bluetooth.ClientModeCommand(ClientCommands.Connect, "00,00,00,00,00,00") and that would send the appropriate serial command to connect to the remote bluetooth host at that address... or throw an exception if your not in client mode.

Another thing to look out for are pitfalls that can get you in trouble.. Being a new user I made the mistake of sending the serial command to set the baud rate to 115400?, but the baud is locked to 38400 in the module code currently... That makes the module unusable immediately after you issue the command and once you do this it's essentially "broken".  You have to close the serial ( bluetooth.serial.close() ), set the baud to the higher rate, and then open the serial and set the slower baud rate, just to get it to work again!  Long story short is some way to prevent this through the bluetooth module implementation, or don't hardcode the baud rate if that's not needed..

I don't have the doc's infront of me so I'm kind of adlibing, but I've started modeling this out (thinking it was completely roll-your-own), and I'm excited to see your giving it the thought and asking for input!

Not sure what your timing is, but I'm still planning to roll one up and I'll share my code once complete, using what James suggested as well..

Craig