Distributed Control & Automation Framework (DCAF)

cancel
Showing results for 
Search instead for 
Did you mean: 

DCAF Blog: Reloading New Configurations Without Stopping the Main VI

This is my first of what I hope to be many documents providing more detail on specific aspects or capabilities of the framework. Throughout these posts I plan to outline capabilities that exist today, known limitations, and ideas for future improvement.

Today's Capabilities

DCAF provides an API for every engine plugin that can be used to control the engine's state. DCAF also ships with two sample projects that demonstrate different approaches to using that API.

The first approach found in the 'Basic Execution Template' sample project simply reads from a configuration file, initializes all engines, starts them, checks their status, and waits for a user to stop the program.

Basic Execution Template.PNG


This template could be modified to allow a user to reload a configuration file without stopping the Main VI by doing something as simple as putting a While Loop around the entire application. Instead of stopping when a user presses the stop button, the code would instead reload the configuration from file and start again. If that file contained new configuration information, the application would use that information instead.

A more elegant approach to supporting this functionality is demonstrated in the 'DCAF Execution Service' sample project. This sample project runs a background loop that communicates using the Asynchronous Message Communication (AMC) library to handle all interactions with engines on the target. This example allows users to send messages to this service telling it to start, stop, or reinitialize the system from the file. It also allows a user to change the state of various engines independently.

The ability to reload configurations without stopping the main program or rebooting the target is a powerful tool for embedded applications. It allows parameters and other functionality to be quickly tweaked and modified, saving valuable development time. It may also be possible to reinitialize engines on the target without affecting other code running in parallel (code not plugged into DCAF).

Limitations

There are two main limitations to this capability. The first limitation is that this approach likely won't work if the modifications to the configuration involved adding or changing the plugin modules to execute. This is because all plugin modules must be present in memory before the file can be loaded, and if you are using a 'Module Includes VI' to place those modules in memory, then changes to that VI will require stopping the main application entirely to change the required module dependencies.

The second limitation is that the engines must first enter their safe-state and then stop before they can load a new configuration. There is currently no on-the-fly mechanism for changing behavior immediately between execution periods of an engine that stays in the Run state. The amount of downtime will depend on how long it takes a particular configuration to close and then reinitialize, but may finish in as little as a few seconds.

Ideas for Improvement

There are plenty of ways to improve on this functionality without requiring significant changes to the core of the framework. Note that these are simply ideas that have been thrown around and are not on a development roadmap of any kind. If you are reading this and are interesting in implementing one of these ideas, please let us know!

First, the limitation of needing to change the 'Module Includes VI' to change plugin dependencies for a particular configuration could be addressed by building each plugin into its own package of executable code using either a Source Distribution or a Packed Project Library. This would give the main application the power to load VI dependencies dynamically from disk and make a truly modular application. Of course properly building this compiled code can be challenging; it must be done for each OS that it needs to run on, and must be rebuilt and revalidated every time the code changes. This would require a lot of extra work and infrastructure to do for every plugin in the framework.

Second, the limitation on first stopping an engine before changing a configuration could also be addressed. Technically it is possible for an engine to load up and start executing a new plugin module on the fly as long as that module uses the same channel interface as the previous module. The engine allocates all data for each module before the run state, and statically maps data from a module's channels during initialization. Instead of over-complicating the core engine, another way to accomplish this would be to create a module that itself calls other modules. The container module could internally decide which plugin module it wants to call, and could potentially do so between iterations of the engine loop. This container module could even support selecting between multiple different plugin modules, and could load new modules from disk on the fly, as long as all of the modules shared the same Channel interface.

One final idea for improvement would be to better integrate the 'Reload' functionality with the Configuration Editor. There are multiple ways to accomplish this. One way would be to have a standard set of code on a target that allows a configuration editor to connect and send messages to it. The editor could then send down a new configuration as well as the messages to the target to reload that configuration. Doing this in a standard way could help make this feature more robust and reduce code duplication across various DCAF projects.

Let me know in the comments below if you have questions or more to add on the capabilities, limitations, or ideas for improvement. I'd also love to get feedback on how to improve posts like this in the future as well as any new topics that may be of interest.

0 Kudos
Message 1 of 3
(4,474 Views)

Burt,

 

A very nicely written article!

 

Pardon me for being a DCAF newbie.

 

I am looking for an architecture where we can allow the application user to reconfigure the devices and restart the application.

Let's say that the system is comprised of N subsystems and each subsystem is comprised of serial Device1 and serial Device2. The user needs to be able to:

 

1. Configure for N subsystems, and

2. Reconfigure for a different brand of Device1 or Device2.

 

Ideally, I'd like to be able to let the user do this without having to have knowledge of the parameters that would need to be re-mapped to change the number of subsystems or brand of devices.

 

It seems to me that the reloading you have described above may be sufficient for our purposes, but it also seems that DCAF requires that the configuration file be manipulated via the DCAF Editor.

 

Is there a  way to provide a user with an easy way to configure the number of subsystems or change brands of devices without requiring them to have skills with the DCAF architecture?

 

Further, how can I code the UI so it knows to dynamically accommodate the new changes (i.e. display a different number of subsystems) without having to recode the UI?

0 Kudos
Message 2 of 3
(3,211 Views)

Hi Wireman, actually this is not correct: "seems that DCAF requires that the configuration file is manipulated via the DCAF Editor". One of the nice things with DCAF is that we are not using any special API for the editor, anything that can be done n the editor can be done programmatically. In DCAF each module contains 3 classes, the runtime, that works based on the configuration, the configuration class that basically stores this configuration and has methods to saving and loading it to file and the UI Node, that is just a UI to interact that just gives a simple UI to configure the module.
Technically you could just use the runtime class and configuration class and create a completely custom editor.
Automapping is something the editor won't do by default but if you establish a naming conventions on your tags you can make your UI to configure itself.
Now here there are different options, one is you create a generic device class. In this, you define which are the channels (what is shared with the engine is) which in general would be the same regardless of the brand, and then in here, you choose which runtime would run. This decision of the runtime could be as simple as having 1 runtime and just decide which one you include or having multiple runtimes and just select which one you are going to use based on the configuration. In other words, you would share 1 configuration and 1 UI for multiple runtimes.
The other option is you could look into the scaling module, in here there is a main level module and based on your configuration it chooses a submodule.
Best Regards

Benjamin C
Principal Systems Engineer // CLA // CLED
0 Kudos
Message 3 of 3
(3,192 Views)