There is a library used by many projects called RXTX JAVA Communication API, which is an alternative to the ancient Javacomm. Using one of those projects I noticed that many operations went very slow when I had connected my Bluetooth adapter. What's going on?
Sometimes, with this kind of problem, the solution starts when you are able to find which triggers the problem. Often, we must accept these annoyances only because we are not able to describe why and when the problem occurs.
The problem exposed in this article makes reference to the Arduino IDE, editor for the language wiring used commonly with arduino boards. This IDE, source code and binaries for Mac, Windows and Linux are available from the link: http://www.arduino.cc.
The identification of the issue is based on two replicable conditions. Mysteriously, there were instances in which the development environment took more than ten seconds to appear, something unusual even considering that it is an application developed in Java.
I usually code in only one programmable board (Arduino) at the same time, so after the first delay everything else seemed to be ok with the uploads to the board. However when changing to another Arduino, trying to change the port number using the "Tools" menu presented another problem:
This operation was slow, very slow. The problem was triggered by accessing to the menu and not the selection of the port itself (submenu).
Already with enough clues to investigate, I first researched within the code of the environment. I usually prefer to check the binary files rather than the source code, although it is not the most direct way.
First, checking the Arduino program, written in Java to some extent allow operation across multiple platforms. We can start by quickly looking the Task Manager:
Dissection of the JAR files
As we already identify the root of this problem (the arduino environment), we must find the JAR file containing the problematic code. We can see some dependencies using Process Explorer (an enhanced Task Manager):
Now with DJ Java Decompiler we can look the main file of the IDE. This file is usually the biggest file inside each library:
We descompilamos and look for the section of the menu that comes to a standstill. In fact I'll give you a condensed version of the tale, first the home of the "Tools" menu:
The syntax provided by the decompiler can be strange, incorrect and unreadable. It is usually useful only for research or for example to have a better reference when editing should be performed directly on the bytecode.
Below follow many other menu options, none of them represents risk to cripple the program. In the list of "com" ports there is something suspicious:
And further down, the only suspect procedure:
The origin of the problem
The first question now appears on the Java code. In a previous instance I found that an error of the environment (in particular by making use of the option "Copy to forum") was a simple error checking:
Where you can see that the allocation should be after checking to not produce the classic errors ArrayIndexOutOfBoundsException:
(More information about this bug already corrected in the) Arduino Community Forum)
This question makes me to carefully review the code of procedure that obtains the list of available "com" ports.
The first attempt at solution
As in the obtaining of port lies the problem of slowness, and without even any Arduino board connected to the computer, the only possible guilty are virtual ports added by my bluetooth adapter and the physicists of the team. Can you imagine what would happen if I disable the bluetooth adapter thanks to the following video:
Well, we already have a first workaround. It's rustic, but programmatically disable the bluetooth adapter allow us to have an agile environment. In the video I use devcon, but initially the same effect would be achieved if we used the system (devmgmt.msc) Device Manager.
This utility allows you to manage remotely and locally a computer's hardware devices. Microsoft and is available as a Add-on here.
All of the first attempt at solution brings us to re-check the Java code...
Where does it come from CommPortIdentifier? How do you get those IDs? Why the the simple fact to obtain the name of the bluetooth virtual ports take so long?
The real solution
CommPortIdentifier it comes direct from the beginning of the file editor font:
And where is "gnu" namespace?, so light, of a library. They bet which?
Guess, now we continue digging.
I do not understand why, but it always gives me a particular taste investigate these applications by alternative routes. The funny thing is that in this case we have all the source code available, but mounted the stage of development to debug that code is undoubtedly much more effort that investigate quickly thanks to these beautiful tools are always in my "case" solutions.
Inside CommPortIdentifier.class We finally started to reach a way of escape from Java. It begins precisely here:
RXTXCommDriver our new adventure begins. An adventure full of new mysteries, away from the protective Java virtual machine, free, full of potential for not handled exceptions, Welcome to the universe of C.
The library beginning its name to RXTX implements a common communication interface serial port for various platforms, Linux, Windows, Mac, and even some more minority such as FreeBSD. Each implementation functions has its code for each platform and this shows the need to break the universality of an intermediate code, as soon as we approach to the physical world.
I previously rejected the existence of the program in Java source code. In this case, the C library sources)http://users.frii.com/jarvi/rxtx/) communication serial are worth gold. The problem now is in the file SerialImp.c:
"The fragment of code dedicated to the Windows platform can appreciate that we call cyclically to"Ret = serial_test ((char *) full_windows_name);” y “Ret = serial_test name ((char *));"in order to check if each port can be opened. In Windows, although it may not seem it, each port and device is also a file, and although the user interface keeps it as a secret full application layers on this abstraction, usually at low level continue to use resources as files without the scope of 'a class in particular device' which we are accustomed.
This means that within the path //./ We are referring to the local computer, on a resource in particular (this related to UNC Universal Name Convention, used as a notation of routes in Windows). Like this . / COM5 It will be, within our team, COM5 file, i.e. the representation of the five communications port. "All of this brief was to explain the details of the operating logic a bit of"serial_test“:
Simple or not?, if I get open filename, then return one, if I have an error return a zero.
... What is the problem with this logic?, apparently there is no problem because if a port is a file, if I can open it then that port there and as I do not know there are ports should I visit them polling port-by-port.
The first problem is in terms of synchronous and asynchronous behaviour)http://msdn.microsoft.com/en-us/library/aa365683(VS.85).aspx), I need to achieve to open port not blocked the following operations. However this is not so simple, the only fact to handle these (e.g. errors) responses asynchronously changed our scheme.
What then happens with virtual ports?
Windows tries to open them and as they are virtual ports, then the bluetooth adapter driver tries to communicate with the physical device was assigned to the port, for example a cell phone. As they take a while to respond, and if they take much is that they do not respond, the only effect of these virtual ports open entails a delay.
The real solution is almost materialized
"My first test then is to comment out the line of defense in"serial_test“. The result is that I can easily achieve that all possible ports and even the non-existent appear or simply that none appear as part of the options in the Arduino environment. This is already a good start.
Thanks to a code example)http://www.codeproject.com/KB/system/enumports.aspx) I discovered that there was another way to check the ports. This is a better continuation.
Windows NT allowed already from memorable times obtain all available ports without having to try to open any in particular. The trick is in the use of the function QueryDosDevice.
So our updated function is:
It is curious that although this solution works perfectly, for compatibility reasons diminished sees its maximum possible speed.
That is, if you give a look to the code above, appreciably with clarity in the sentence where [i] is used QueryDosDevice. The function serial_test asks once for each port, however QueryDosDevice It is the list of all the available instantly, without the need to go port to port.
Although at the moment I leave open the challenge to any avid reader, because for me, through operation to an immeasurable microsecond of notorious thirty seconds of waiting is enough.
The resulting library serves to solve this problem in any application that uses of CXR.
In our present case, just replace the file directory of the Arduino rxtxserial.dll for improvement:
Sometimes, the equivalence between to modify and repair something versus the existence of code source is not as crucial as you can imagine. Cunning and logic are large weapons that allow us to overcome many barriers.
In the case of the current document, I felt overwhelmed by moments when trying to understand the alien work, many different styles of programming put extra flavor to work trying to repair so insignificant as the current details.