Data visualizer and logger

Company: Tekanero Client Undisclosed
Main development: 01.2013 - 09.2013
Type Desktop Application
Technologies Java, JavaFX, Swing, COM / Serial communication, Audio, Images


Introduction

This proejct greatly contributed to the formation of Tekanero. In early 2013 a long time entrepreneur got in touch with me to discuss his options regarding a 16-Bit Windows Application for one of their products. The software was used to read sensory values through a controller via a virtual COM port, record it and provie audio and visual feedback.

Please note: due to a non-compete agreement I cannot reveal the exact purpose or the niche this software was intended for. For this reason I have altered the demo application and screenshot to make it appear more generic and hide its exact purpose.

Need for a solution and first attempts

The product was still a good seller. Whiel the application worked well, it was not compatible with 64bit operating sysems. As this was the period when 64Bit Windows started to become common place a solution due.

One idea was to package the application in a Virtual Machine. While this worked initially, passing on the USB to serial connection would have posed too many difficulties for end users which were not necessarily very computer literate.
A better solution was to take the users operating system out of the equation and package everything on dedicated machines. As the application had extremely low system requirements, we took Thin Clients which were affordable and could be purpose built with ease. A great advantage of the chosen Thin Client series was its self-re-setting main drive, which made them resistant to viruses and user interference. Even though, it was intended as a temporary solution, it was well received and paved the way for a new product line.


The solution

Multiple monitor support

Multiple Monitor support

As the original software was written in Delphi, the client had originally intended to hire a Delphi specialist. The idea was to clone the original application using a newer Version of Delphi by updating the source code. Considering the old age of the Delphi version used, its outdated appearance and unfortunate lack of documentation, a redevelopment from ground up seemed most appropriate. This meant that we were able to modernize the entire user experience, introduce new features and make use of new technologies, all without adding much overhead in cost.

Modern User Experience:

The greatest change came with the new user interface which was radically redesigned. The development of “use case scenarios” and sketches was done together with the client to minimize miscommunication. The aim was to create an intuitive experience with minimum risks of user error while being quick to operate.
Some of the main UI features included:
  • Media player inspired controls
  • Auto-Save feature
  • Modern graphics and appearance
  • Dynamic window appearance which only displays relevant buttons and options
  • In UI explanation of technical elements (rather than relying on reading the manual)
  • Understandable error messages with suggestions
  • Multi monitor support, through ability to add separate windows

Features:

Apart from its undisclosed purpose, the software’s main task was to process sensory data which was fed from a controller. This data processing has been presented to the end user with 3 main modes:
  • Live data mode – displays and if wanted records incoming data.
  • Analytic mode – shows summary of a previous recording.
  • Playback mode – plays back a previous recording as if it were live data.

Live data mode

Live mode:
Shows live data coming from the sensors and allows them to be recorded. During recording the operator can add different types of flags to highlight events.

Analytic mode

Analytic mode:
Uses a different a Graph API which allows zooming in on desired section in graphs as well as exporting and printing them.
In the UI itself the user also has the ability to review timestamp flags, add a description and export the recording as a CSV file for review in Excel or other software.

Replay mode

 Replay mode:
Runs a live reply of a recording with the ability to fast forward or rewind. In addition the operator also has the ability to add further timestamp flags.

To allow customers their own data analysis, the ability to export recordings as CSV files was added. This allowed their use in Microsoft Excel, Matlab and other software as its relatively easy to parse. For a smooth transition from the previous software, reading support for its proprietary format was added as well.


Part of the data processing was to provide audio feedback that would play a tone depending on the sensors value. This was achived Midi synthesizer.
Another important function was to trigger events when a sensors value reached a set threshold (orange line in some of the screenshots). These were customizable and allowed either: tone generation through Midi using different instruments, music playback and other events.
Localisation was also added to reach global customers. An updated feature which largely helped me during development was the built in DEMO mode. During this mode, the software would imitate the connection with a controller and send simulated values through the now virtual sensors. Apart from being a good demo feature, it also aided me largely during development.


Challenges and technical details

When I started working on this application, some of the libraries and components were new to me. Two major unknowns where the serial protocol and the old file format which had to be reverse engineered as the original software code had very little documentation in it. To see whether the software was even feasible in Java, the first step was to develop proof of concept builds before main development could start.

Serial Protocol:

This was the most critical component, without this the software simply wouldn’t work. Though I have worked with TCP sockets in the past, COM ports were a novelty to me and would commonly use binary data transfer. This had the further unknown of not understanding the communications protocol.

Consequentially the first step was to understand how data was transferred between the application and the device. To do so, I used a COM port sniffer which would simply display all packets sent between the original application and the controller.
Once I knew what triggered the communication, I used calibrated potentionmeters to gather an understanding of the packet data. With the protocol reverse engineered, I could begin selecting a suitable library and start the first communication with the controller.
The last step was to refine the software which included automatic port selection, error handling and well threaded communication.

Time accuracy and performance:

The nature of this project required the software to record all data with accurate timing which would not be affected by user actions.

Particularly in Java, lag is easily introduced by loading large new objects which can use up CPU time and trigger a swap operation in the operating system. At the expense of RAM, one countermeasure was to load all commonly used objects and windows during launch. A splash screen with progress bar ensured to users that the application was functioning during long start ups (slow machines). A further advantage of this approach came in the reduction of runtime errors as large chunks of the application were validated during launch.

The second issue was the accuracy of standard timers:. I discovered that they tend to lag by a couple milliseconds across all platforms (Java, Delphi,...) and are further delayed by other processes. In long recordings this could mount up to whole seconds which was a real issue for some end users. Solving this was more complicated than it originally seemed. The first remedy was to use Threads, which was particularly important for timer triggered events. To further improve accuracy, I implemented a custom timer class that would monitor and correct itself. The last step was to ensure Graphs would plot data points true to their timestamps which also meant adding a timing track to recordings.

Simple data storage:

This application relies to a great extent on storing data persistently and parsing it for later use. This includes a large array of settings which go as far as Window positions and in their own way localization files. The most reliable technique has proven to be the use of key value pair files as they posed several advantages over other techniques such as XML, JSON or even the use of databases. As a developer they are easy to parse and store as they only need a few lines of code and don't need any 3rd party APIs. Their simplicity massively improves performance.
Also if values are set with a hard-coded default value, they offer an easy way of recovery if a loaded file is or some data in it is missing. In case a setting is preventing the user from using the application, they simply delete the settings file with the faulty parameters and essentially return that component back to factory settings. Upon application shut-down a new settings file will be written.
The last advantage is their human readability which tied with the mentioned failsafe, allows customers to edit parameters which are not listed in the UI.

Original Theme used Screenshot of the Nimbus User-Interface in its unmodified form.

Swing meets JavaFX:

During initial development I decided to play it safe and opted for the tried and tested Swing user interface which has remained popular till this day. However, being unhappy with the standard appearance I tried various Look and Feels. To achieve the design I wanted, I opted the Nimbus look and feel, modified the colour schemes, theme settings added my own icons and developed a number of custom components such as a slider with 2 knobs and a value marker inside of it.

JavaFX came into play during mid-development with the use of live graphs and multimedia components (images and audio). During this I have come across some quirks in Java which I documented in StackOverflow: One of these became my most appreciated solution.

Best practices:

In addition to the listed features, I have done my best to design this application following common best practises to avoid running into issues during development or in the future. These include but are not limited to:

  • Good code documentation
  • Systematic naming of classes, methods and variables
  • Heavy use of MVC to handle events such as:
    • Incoming sensor value which are used by (graphs, background monitors, plugins)
    • User actions in UI (eventHandlers)
    • Change of application mode
    • Change in settings
  • User files, settings and logs stored in operating systems user directory
  • Strict exception handling throughout application
  • Extensive testing before every new release
  • Detailed logging which also includes unhandled exceptions
  • Understandable error messages