Handle GPS data by two GPS Apps simultaneously

Given this situation: You have a GPS device that is connected to your computer (not handheld) via physical COM1. Now you want to use this data in two different applications, say: a Route Navigator and a GPS logger. You launch the Route Navigator, it’ll connect to the COM1 port and it’ll show you your position. Now, launch your GPS logger and try to connect on COM1. It’s not happening: that COM port is in use. You can connect to a COM port with only one application.

On a portable device, this is solved by installing a virtual COM port, which can be read by multiple applications simultaneously. Often, this is COM8 (so it is on my Windows Mobile 5 system). But what to do when you want this functionality on a normal pc?

XPort

Well, there is a very cool application that actually makes this possible. It’s called XPort. Just launch the application, hit “Find GPS”, select a virtual COM port in the right column and hit “Enable ports”. Now, you can connect with both applications to that selected virtual COM port. Or, you can select two virtual COM ports and have both applications connected on a different port.

There’s a little drawback. The application needs Administrative rights, so on your own computer at home it’ll work, but if you have to set this thing up on a terminal build in a truck and running Windows XP on which the GPS logger starts up silently and the Route Navigator launches in full screen, all automatically while a very limited user is logged on, XPort will be denied to launch the virtual COM ports since it should be run with administrative rights.

com0com

So we need an application that makes it possible to install the virtual COM ports as an administrator, then launch the mapping as a windows service.
I found com0com.
Using the application com0com, you can create virtual COM port pairs, each representing a virtual NULL Modem Cable. You can use the graphical interface, setupg or the commandline interface setupc. This last one can be used in scripts. I created three pairs, one for the Route Navigator, one for my software and one for later usage supposing that I might want to debug one day while the other apps are running. So my script looks like this:

setupc install 0 - PortName=COM14,EmuBR=yes
setupc change CNCA0 EmuBR=yes
setupc install 1 - PortName=COM15,EmuBR=yes
setupc change CNCA1 EmuBR=yes
setupc install 2 - PortName=COM16,EmuBR=yes
setupc change CNCA2 EmuBR=yes

This will create the following pairs:

CNCA0 <-> COM14
CNCA1 <-> COM15
CNCA2 <-> COM16

hub4com

Part of the project is hub4com that makes it possible to get the input from one COM port an route it to several others. The first example they give, is exactly that what I need.

You have a GPS device that connected to your computer via a phisical COM1 port and you’d like to handle its data by two GPS applications. You can do it this way:[..]

Following the rest of the example, while using COM6 as GPS COM port, CNCAx as virtual input, COM1x as virtual output, it showed me this on the commandline:

C:\com0com\>hub4com \\.\COM6 \\.\CNCA0 \\.\CNCA1 \\.\CNCA2
Open("\\.\COM6", baud=19200, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA0", baud=19200, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA1", baud=19200, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA2", baud=19200, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Route data COM6(0) --> CNCA0(1) CNCA1(2) CNCA2(2)
Route data CNCA0(1) --> COM6(0)
Route flow control COM6(0) --> CNCA0(1)
Route flow control CNCA0(1) --> COM6(0)
Started COM7(0)
Started CNCA0(1)
Started CNCA1(2)

When I now connect the GPS logger on COM5, I see a lot of trash appearing. The reason is that the baud rate doesn’t match. It’s very important to read from the COM port at the same rate as the device produces it’s data. The GPS receiver in my case has a speed of 9600 Bd, but as you can see in the console log, hub4com is reading it at 19200 Bd. Too fast, thus the trash.

Of course, hub4com provides a way to set the baud rate, option --baud=9600 is bringing it down and the output is now

C:\com0com>hub4com --baud=9600 \\.\COM6 \\.\CNCA0 \\.\CNCA1 \\.\CNCA2
Open("\\.\COM6", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA0", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA1", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA2", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Route data COM6(0) --> CNCA0(1) CNCA1(2) CNCA2(3)
Route data CNCA0(1) --> COM6(0)
Route flow control COM6(0) --> CNCA0(1)
Route flow control CNCA0(1) --> COM6(0)
Started COM6(0)
Started CNCA0(1)
Started CNCA1(2)
Started CNCA2(3)

Maybe it’s just me, but it took me a full day to understand what is happening now after reading and re-reading all information I could find. Launching the Route Navigator on COM14 will give you a GPS signal and launching the GPS logger on COM15 or COM16 will give you a signal as well. So far so good. Until you close the application on COM14. It doesn’t matter which one that is, Route Navigator or GPS logger, it all gives the same result. When the application on COM14 is closed, the signal is lost on COM14 and COM15. Although the configuration of all 3 ports are identically, the hub4com ReadMe states (adjusted to fit my example) that

It will send data received from COM6 port to CNCA0, CNCA1 and CNCA2 ports
and it will send data received from CNCA0 port to COM6 port.

As seen on the commandline:

Route data COM6(0) --> CNCA0(1) CNCA1(2) CNCA2(3)
Route data CNCA0(1) --> COM6(0)
Route flow control COM6(0) --> CNCA0(1)
Route flow control CNCA0(1) --> COM6(0)

The data is routed to all three COM ports, the “flow control” is applied from COM6 to CNCA0 and CNCA0 to COM6 (with CNCA0 the input for COM14). No flow control for the others is configured. So my only guess was to create a flow control to all others as well. One of the extended examples (got by issuing hub4com --help) stated this

  hub4com --route=All:All \\.\CNCB0 \\.\CNCB1 \\.\CNCB2
    - receive data from CNCB0 and send it to CNCB1 and CNCB2,
      receive data from CNCB1 and send it to CNCB0 and CNCB2,
      receive data from CNCB2 and send it to CNCB0 and CNCB1.

So that’s almost what I wanted to do. Assuming the syntax is consistent with, say, connect:

  --connect=<lstr>:<lstl>
      handle data sent to any port listed in <LstR>
      as data received by all ports listed in <LstL>.

(where I would have switched R and L by the way) and where --route=All:All says that "ports can talk to each other", I added the parameter --route=0:All to route all data always from 0 to the others, so from COM6 to COM14, COM15 and COM16:

C:\com0com>hub4com --baud=9600 --route=0:All \\.\COM6 \\.\CNCA0 \\.\CNCA1 \\.\CNCA2
Open("\\.\COM6", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA0", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA1", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Open("\\.\CNCA2", baud=9600, data=8, parity=no, stop=1, octs=on, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Route data COM6(0) --> CNCA0(1) CNCA1(2) CNCA2(3)
No route for flow control
Started COM6(0)
Started CNCA0(1)
Started CNCA1(2)
Started CNCA2(3)

With this setup the data always flows from COM6 to the others no matter which port is read or left unread.
It took me about four days to find out how com0com and hub4com work, mainly because there’s not much information about it. There are quite a few examples, but none of them are explained in detail.

I sure hope the developers are still maintaining this application, since it really does what it has to and works like a charm. I hope the lack of updates since December 2009 is just because the application works perfectly 🙂

My final command is this:

hub4com 
   --baud=9600 --route=0:All \\.\COM11
   --baud=9600 \\.\CNCA0
   --baud=9600 \\.\CNCA1
   --baud=9600 \\.\CNCA2

I added the --baud=9600 to all other Null cable entrances, but that’s more a leftover from my tests. I think it’s sufficient to add the parameter before the list of com ports.

Install as Windows Service

Once configured, the Virtual COM ports stay active until you remove them. However, you have to launch hub4com every time you have rebooted the computer. To solve that, I’ve used runassvc, which allows a silent install as well. Without parameters, the application launches a GUI in which you can enter the required values. With parameters, like opened through a bat file, it launches and enters the parameters you have defined. Then, when you use --quiet as parameter, the GUI doesn’t launch, but the service is installed and started. My command looks like this

RunAsSvc.exe 
   --install
   --displayname "hub4com"
   --description "Routes the GPS data from COM6 to virtual COM14, COM15 and COM16"
   --exe "C:\com0com\hub4com.exe"
   --params "--baud=9600 --route=0:All \\.\COM6 --baud=9600 \\.\CNCA0 --baud=9600 \\.\CNCA1 --baud=9600 \\.\CNCA2" 
   --workingdir "C:\com0com"
   --quiet

Now, even when the computer is rebooted, as soon as it has started and before any user has logged on, the system is running so every application is able to read one GPS device even if another is already accessing it. It was tested successfully on a Windows XP and even on a Windows 7 machine, although on the last one you have to boot the machine in Test configuration (bcdedit -set TESTSIGNING ON) otherwise the com0com drivers won’t load.

Used applications

The applications I used to set up this environment, are

Further reading

It is also possible to reroute the GPS data to a tcp port. Read Send GPS data over TCP how to do this.

10 Comments

  1. Murty
    July 21, 2010

    Sounds very interesting.. I should give it a try..

  2. Fabio
    September 16, 2010

    Really thank you! Your post helped me a lot. I was dealing with the lack of information just like you did in the past.

  3. Tony
    February 28, 2011

    Apparently I missed something. I did everything listed and I am getting
    Write lost CNCA0:5036, total 5036
    Write lost CNCA1:5036, total 5036
    etc….

  4. February 28, 2011

    @Tony
    Two questions:
    1. Does it work anyway? The logging sometimes looks like something goes wrong while everything works normally.
    2. If it doesn’t work, can you provide the entire command you’re executing and all the logging please?

  5. Tony
    March 2, 2011

    Yep I got it to work but the runassvc is not cooperating or obviously I am not using it correctly. When I run “RunAsSvc,exe” a dialog pops up. I give it the name and description then it asks for a executable path which I sully for the path to the “hub4com.exe” and then it has the parameters. I put in my parameters and it does not matter what I put there it does not show in the service that starts. I read above that if you do it and do not fill in the parameters “–baud9600 –route=0:All \\.\COM3\ \\.\CNCA0\ \\.\CNCA1\” (not using the quotes in the parameter file section) and supply the working directory (the directory where the hub4com.exe file lives). I have no clue where to put the –quiet parameter.

    When Windows XP boots the service starts but the “Path to executable” lists as the path to the “RunAsSvc.exe” file, not the “hub4com.exe” as I specified. It also has NOTHING in the parameter section.

    Now once I do this and it is obviously hosed, I can not delete it. I have to go through the registry to delete it.

    What am I doing wrong?
    Tony

  6. March 2, 2011

    The --quiet parameter is for commandline use. It makes RunAsSvc install the service without popping up the GUI

    Howerver, everything might be fine! If COM3 is the correct com port on your machine (where the physical GPS is located) then just try to connect on one of the virtual COM ports. It is normal to see something like
    “C:\com0com\runassvc\RunAsSvc.exe” -s {08CECC71-A9B1-417d-AB3A-F57A4C854E53}793835385
    as “Path to executable”!

    If it doesn’t work, copy that command I provided, paste it in a file named “installhub4com.bat” but remove the newlines (so that everything is on one line and make sure to replace COM6 to the correct COM (3?) port):

    RunAsSvc.exe --install --displayname "hub4com" ...

    then open that installhub4com.bat file, the installation should be done without popping up a GUI. You’ll notice “hub4com” appears in your services list. It should start automatically. Make sure that you don’t have any instance of hub4com running though, as well as any other service that reads from the physical COM port. If the port is in use (i.e. when you’re reading GPS data from it) at the time that hub4com is installed as service, it won’t be able to connect to the COM port and the service won’t start.

    Please make also sure to
    1. Reboot your PC first
    2. Always plug the GPS in the same USB port

    Please also note that — are actually two dashes, but the website makes one dash from it in this comment 🙂

    If you include a first line in the .bat file that says

    sc delete hub4com

    then the service will first be removed before RunAsSvc installs a new one

  7. Tony
    March 2, 2011

    Bert, You Da Man!!

    Doing it as as .bat was the key, I was trying to put the parameters in the GUI of the runassvc and obviously did not work. I went into the registry and clean up the just created by my attempts and created a .bat file you referred to (I obviously missed this in the original post). I put the .bat file in my Startup directory making sure the runassvc explicit path was set correctly and it starts each time I start my Toughbook. The GPS is internal to the laptop and used primarily for expedition services.
    Best regards
    Tony

  8. March 2, 2011

    if the .bat file contains the runassvc command, then this is not the way to go. If your .bat file contains the hub4com command, than that’s ok, but it’ll make a cmd window pop up every time.

    Anyway: this .bat file will install a windows service. The windows service will start at boot up. So there’s no need to put that .bat file in your Startup folder.

    Just make sure you don’t remove runassvc, com0com and hub4com and you should be fine by running the .bat once!

    • August 31, 2011

      Cool, thanks!
      It was only recently made, so no I didn’t knew that. Will try that shortly!

Comments are closed.