01-08-2010 04:43 PM - edited 01-08-2010 04:44 PM
This installment gives an example of how to use the server template of the last installment to create a working server/daemon. This example is a simple string server used to localize a simple front panel. Before we get into the code, a few caveats are in order:
On to the code itself. Unzip the attached file to the directory of your choice and open the LabVIEW project. Open the top–level ExampleOfUse.vi and run it. Changing the selected language changes the displayed strings on the front panel. Clicking “OK” or “Cancel” will stop the VI. How does it work?
Open the front panel of ExampleOfUse.vi. Initialization consists of creating a stop user event, creating a server object, launching the server, querying it for the available languages, then updating the language selector. Public functions from the server are used for interaction with the server. A proper initialization would also select one of the valid values and set all the front panel strings (there is an easy way to do this for this example). For this example, we accept the default language value of “ENU”.
When the language value is changed, the server is queried for string values and the front panel controls are updated. A proper update routine would include subVIs to encapsulate update of the different types of controls. We are using public functions from the StringServer library to query for the string table entries. The StringServer handles reading the string tables and supplying the proper string.
Open the VI StringServer.lvlib:GetString.vi. This is a public function which uses the SendCommand.vi and GetResponse.vi to send the GetString command to the server and retrieve the response. It also handles data conversion to and from variants.
Now open StringServer.lvlib:Server.vi. Notice that the Initialize case has been populated and two commands have been added. These cases handle the string tables. The code before the actual task handler starts has been modified, as well. The command queue is stuffed with an Initialize command at the top of the queue to ensure that Initialize occurs before any other commands, thus preventing race conditions. The Initialize command queries for possible string tables, implemented as INI files, and fills in the local data structure with available localization values. The string tables are assumed to be in a directory named StringTables parallel to the calling code. They are also assumed to have name “StringTable_LCD.ini”, where LCD is the three–letter language code.
Two new commands have been added to the server compared to the template — GetString and GetLanguages. GetLanguages simply returns the language codes found during initialization. GetString checks to see if a language file has been loaded, loads it if not, then returns the string requested. If the language code is not found, it returns the string for the first language in the list. This could easily be modified to return the code for a specific, default, language.
This example stops the server using CloseServer.vi and closes the server references using Finalize.vi. These are public functions designed for this purpose.
Why would you want to use such a server/daemon instead of putting this code directly in your GUI VI? The main reasons are encapsulation, reusability, and maintenance. The code is encapsulated in a library and interaction is governed by the public VIs in the library. It can be used by multiple GUIs, should you have them, avoiding the task of rewriting the same code for each GUI. It also can be simply reused in other code by changing the string tables. Finally, the code itself can be upgraded and/or modified (e.g. changing the database format from INI files, to HDF, to SQL, as complexity increases) without effecting the interface or calling code. It makes maintenance much easier.
For those who are curious, the localization strings in this example were generated by talking to my nearest coworkers. We are a polyglot bunch.
This concludes my short series on dynamically calling VIs. If you have requests for a new topic, please let me know. I have lots of options...