9

I've been working with the SerialPort class a lot lately. Currently I'm trying to figure out the proper way to check if a device is connected to the comm port my application uses. Is there any proper way to check if a device is connected to the comm port? My current method is as follows:

            while (isReading == true)
            {
                try
                {
                    received += serialPort.ReadExisting();

                    if (received.Contains('>'))
                        isReading = false;
                }
                catch (Exception e)
                {

                }
                if (tick == 10000)
                    if (received == "")
                    {
                        Console.WriteLine("No Data Received. Device isn't connected.");
                        isReading = false;
                    }
                tick++;
            }
            Console.WriteLine(received);

It works but I feel it's a little hacky and unreliable. I can keep it if need be but I'd like it if there's a proper alternative to doing this.

Edit: I actually have to set the tick value to about 10,000 to ensure it's reliable. Otherwise I fail to receive data on occasion. Even setting it to 1000 or 5000 is unreliable. Even then, it's not guaranteed to be reliable across multiple machines.

DanteTheEgregore
  • 1,530
  • 5
  • 23
  • 44
  • Are you programming the device as well? – Rubixus Jul 11 '13 at 14:28
  • @Rubixus No. It's a medical device called a Fluke 5500A Multi-Product Calibrator. I'm not even changing the internal settings on it myself. – DanteTheEgregore Jul 11 '13 at 14:29
  • Does the device register a driver in the registry when it is plugged in? Is it a USB device? – Kcvin Jul 11 '13 at 14:32
  • @NETscape Nope. The 5500 doesn't. It's connected via an RS-232 connection. All I do is send commands via the SerialPort class or a terminal. – DanteTheEgregore Jul 11 '13 at 14:35
  • What is `tick`? If you use a `Stopwatch`, would that (`Stopwatch.Elapsed`) get rid of the dependency of the tick value based on the performance of your computer? See this http://stackoverflow.com/questions/1485839/high-performance-timer-vs-stopwatch – Kcvin Jul 11 '13 at 15:24
  • @NETscape It's a badly named integer value that I increment in the loop. – DanteTheEgregore Jul 11 '13 at 15:36
  • 1
    Then definitely look into using `Stopwatch` or `Timer`... you can then actually make sure `n` of milliseconds go by before you stop listening. – Kcvin Jul 11 '13 at 15:38

3 Answers3

13

I too need to work with serial ports, and believe me they are a pain. My method to check if a device is connected usually revolves around issuing a polling command. While you method may work, I cant help but be reluctant to use a while loop when an event will suffice.

The .NET serial port class offers some useful events:

Serial.DataReceived Serial.ErrorReceived and Serial.Write

Usually I would issue a polling command at a specified interval to ensure the device is connected. When the device responds it will fire the DataReceived event, and you can deal with the response accordingly (along with any other neccessary data). This can be used in conjunction with a simple Timer or incremented variable to time the response. Note you will need to set the ReadTimeout and WriteTimeout value appropriately. This, along with the ReadExisting and/or ReadLine method may be of use in your DataReceived event handler.

So, to summarize, (in pseudo code)

Send Polling command, Start Timer
Timer to CountDown for a specified time
If Timer fires, then assume no response
If DataRecieved fires (and expected response) assume connection
(of course handle any specific Exceptions (e.g TimeOutException, InvalidOperationException)
Simon
  • 9,197
  • 13
  • 72
  • 115
4

Unfortunately with serial ports, there's no proper way to determine if a certain device is connected. You could write a magic message that only your device would respond correctly to, but as described in this answer, this method could cause problems for other connected devices.

Ultimately, you just have to depend on the user selecting the correct port.

Also, if you happen to lose connection to the device, you would only know when you fail to read/write to it. In this case, just throw a LostConnection event.

Community
  • 1
  • 1
Rubixus
  • 757
  • 4
  • 11
  • If the device has a driver, you can identify the device using WMI queries as noted in my answer. This answer is misleading. If it doesn't have a driver, you can learn to write a driver, write it yourself, and detect the device. – Kcvin Jul 11 '13 at 14:43
  • 1
    @NETscape I don't believe the answer's misleading. He makes a great point. Serial Connections are extremely iffy. They can be rather difficult to work with. Drivers arent' really an option. – DanteTheEgregore Jul 11 '13 at 14:48
  • @Rubixus I have it deployed in applications right now for RS232 devices. They can work. – Kcvin Jul 11 '13 at 14:51
1

I would agree that is a hacky because any device could be connected and sending '>'; but that doesn't mean its your device.

Instead, be dynamic and use something like SerialPort.GetPortNames and WMI Queries to interrogate the devices plugged into the COM ports.

You could use this example as a starting point.

After reading documentation and examples, you should be able to create a list of all device information that registers drivers on the computer and their connected COM port.

Edit:

Since the device doesn't register itself, consider looking at the product drivers for Visual Studio that might make your job a lot easier.

Community
  • 1
  • 1
Kcvin
  • 5,073
  • 2
  • 32
  • 54
  • '>' Is just the token character signifying that the device is done issuing a command and everything's been written to the buffer. My current method for checking if the device is connected is by waiting a set amount of time and then checking if received contains anything more than just an empty string. The problem is that on a good computer, the tick value can increment 10,000 times before any data is received. It's not something I can easily be dependent on. – DanteTheEgregore Jul 11 '13 at 14:45
  • This method only works with USB serial devices, not RS232, which is what the OP specified. – Rubixus Jul 11 '13 at 14:47
  • @Rubixus That is the example I gave. You can use WMI queries with devices which have drivers installed. When the driver is installed, it will show up in your device manager. If its in your device manager, you can find it using WMI Queries. So your comment is also invalid. – Kcvin Jul 11 '13 at 14:49
  • @NETscape The example you gave specifies a serial COM with USB device, so of course that would be in the device manager. But direct RS232 ports are usually labeled as "Communications Port", no matter what device is connected. – Rubixus Jul 11 '13 at 14:55
  • 1
    True. Depending on the application use @ZachSmith, you could also buy a USB-RS232 converter and use my answer :] – Kcvin Jul 11 '13 at 14:57
  • 1
    Additionally, you can use some of the methods in my answer for process elimination to guiding the user towards selecting the correct device. – Kcvin Jul 11 '13 at 15:00
  • @NETscape Filtering the ports is a great idea when you know that the user will use the same type of port every time. I've worked on applications where the user may use a a direct RS232 port or a RS232-USB converter, in which case filtering would not work as well. – Rubixus Jul 11 '13 at 15:11
  • In my opinion, DB9 ports aren't really "default" connectors anymore in computers sold today. If you package your product with a USB-RS232 converter, then users will know to use it. Granted the converter has a driver, you could then disable the ability to try and use the application if the converter isn't detected on the computer. @ZachSmith the edit I provided with the driver link could be helpful and may come with functions written to help detect the device, like `Initialize`, `iviDmm`, or `Fetch`. http://www.ni.com/white-paper/4562/en – Kcvin Jul 11 '13 at 15:17