DQMH Consortium Toolkits Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

What is a good method that is used specifically for notifying other modules when any given module has started/restarted?

Solved!
Go to solution

In this article by Chris R. (https://delacor.com/rsvp-how-we-do-event-registration/), he explains how the Obtain Broadcast Events for Registration.vi can be used whether or not the module is already running (near the end of the article).  I would like some clarification about this part of that blog: "and then we can re-register for the actual valid refnums at some other time when we know the module is running".  I am unclear on the method, the HOW, some other module knows that the module is now running (was started or restarted after it was stopped).

 

Here is the situation that I have created that prompted this question:

 

  1. Module A is started and is the top-level of the application.
  2. Part of the startup of Module A is to start Modules B-G.
  3. Module C has events that are used by several other modules and is headless, in case that matters.
    1. All of these modules start after Module C and are properly registered for the events to/from Module C during the application startup.
  4. The application is up and running and everything is working great.
  5. At some point Module C is stopped (for whatever reason).  Other modules all properly handle the notification that Module C has stopped and they no longer have valid references to those events.
  6. Now Module D re-starts Module C.  (Module D is a user controlled module that is used to start/stop any headless modules within the application.)
  7. Now the other modules need to know that they can reregister for the events to/from Module C.

Would this simply be a Round Trip (Request + Broadcast) event?

 

Module D sends a request to notify Module A that it restarted Module C and then Module A broadcasts its own message that Module C was restarted.  Then any other modules that need to reregister for Module C's events will do so.  Is this a typical way to handle this type of situation?

 

 

0 Kudos
Message 1 of 16
(6,999 Views)

Or would it be better to change the architecture somewhat and have Module D not actually start Module C and instead just send a request to Module A to restart Module C?  Then Module A would restart Module C and then broadcast that it was restarted?

0 Kudos
Message 2 of 16
(6,993 Views)

I think I would let module A start module C, as you describe.

 

And maybe let A broadcast C‘s event refs? If the message datatype was generic (we have a „System Message“ that all of our modules implement, for example), your other modules would only habe to register for A‘s broadcasts statically. 




DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (The Future of Team-Based LabVIEW Development)


Message 3 of 16
(6,959 Views)

@doyles wrote:

Or would it be better to change the architecture somewhat and have Module D not actually start Module C and instead just send a request to Module A to restart Module C?  Then Module A would restart Module C and then broadcast that it was restarted?


Doyles,

This is more along the lines of how we have done it at Delacor. If module A is the one in charge of launching C and it has the communication with all the other modules, I would have D send a request to A to relaunch C. Then A would know who else to notify that C relaunch and those modules need re-register for the C broadcasts (if they need to).

 

Regards,

Fab

For an opportunity to learn from experienced developers / entrepeneurs (Steve, Joerg, and Brian amongst them):
Check out DSH Pragmatic Software Development Workshop!

DQMH Lead Architect * DQMH Trusted Advisor * Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor

Have you been nice to future you?
Message 4 of 16
(6,957 Views)

Thanks Joerg!

 

Could you explain your "System Message" a little bit more?  I'm not quite sure I understand what you mean.  Is this related to your method to dynamically load modules using wrappers for the common DQMH events?

 

BTW, I pulled your repository from your Git site.  Thank you very much for making that available.  Unfortunately, I don't have the later version installed to open that up.  I'm pretty sure I will understand what you mean by "System Message" once I open that up and take a look at that code.  For now however, I don't quite get it.

 

Thanks again,

 

Scott

 

 

0 Kudos
Message 5 of 16
(6,944 Views)

Hi Fab, Joerg, others,

 

Thinking some more on this, do you typically have a non-top-level module that is responsible for launching all common/reusable modules?

 

Using the example above for a more detailed scenario:

  • Currently I have the scenario described earlier.  My top-level Module A starts Module B-G.  If Module C needs to be restarted, a "Start Module C" request is sent from Module D to Module A.  Upon a successful Module C initialization, Module A will broadcast that "Module C has Started".  All modules that interface with Module C are registered to Module A for the "Module C Started" event.  When they receive the "Module C has Started" broadcast message from Module A, they will update their own event registration for Module C.
  • Some further details
    • Module B is my Data Logger Module and I plan on that being a reusable module.
    • Module C is my DAQ Module and I plan on that being a reusable module.
  • Because Module B & C are intended to be reused, I was thinking about having Module D be the only place that Module B or C (and any other reusable modules that I end up creating) are started, excluding the Test API VI's.  Once Module C successfully initializes, then Module D would broadcast that Module C has started, exactly as I am currently doing with Module A.  This would then use the same method of starting these modules every time they needed to start, regardless of the reason or who is starting them.
    • This would only apply to the common, reusable, Singleton modules. 

I wondered about this change in approach when I was adding in the Obtain Broadcast Events for Registration.vi for my top-level Main Module to most of my other modules.  I realized that a common launcher could prevent the OBEfR.vi from needing to be replaced in every new project - and all of those events needing to be relinked to the new top-level.  This would also mean that my top-level could be a simple VI as shown in the shipping example.  Right now, I need my top-level to be a module so that it can interface with the events of all of the other modules.  But before I go and make all of the changes necessary for that approach, I want to find out if I am on the right path or missing a big gotcha.

 

So, is the 3rd main bullet point above a typical approach, or am I coding myself into corner?

 

I have very little experience planning a project where all of the various project components are distinct, reusable modules/plug-ins/actors/etc.  From the start of this project I have had a difficult time outlining how all of the modules should interface with one another.  I have read the https://delacor.com/simple-dqmh-dos-and-donts/ article multiple times.  But that didn't translate into an understanding of applying those concepts in a real project.

 

Thanks in advance for any suggestions, comments, etc.

 

Scott

0 Kudos
Message 6 of 16
(6,931 Views)

@doyles wrote:

Could you explain your "System Message" a little bit more?  I'm not quite sure I understand what you mean.  Is this related to your method to dynamically load modules using wrappers for the common DQMH events?


Scott, we added a "generic" broadcast event to each module. As this event has the same name and datatype for every module, allows us to call it dynamically on each of our modules. This can be quite handy sometimes.

 

Bildschirmfoto 2018-10-02 um 23.26.26.png

 

We don't need that generic broadcasting message for the Demo Application you referred to which loads/starts modules dynamically, but I made use of it in the Generic Networking Modules.

 

(Caveat: I'll be reworking these public code repos in the next weeks to add features and tidy them up a lot - hopefully)




DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (The Future of Team-Based LabVIEW Development)


0 Kudos
Message 7 of 16
(6,926 Views)

@doyles wrote:

I realized that a common launcher could prevent the OBEfR.vi from needing to be replaced in every new project - and all of those events needing to be relinked to the new top-level. 


Here's my two cent: Your reusable modules should be oblivious of who called them, i.e. have no static linkage to their caller (parent). That would generally mean that the parent calls request VIs of the child, and the child broadcasts data that the parent registered for. 

 

Example: We have a generic, cloneable database module. Every module that needs DB connectivity - be it the top-level or any level - loads a private clone. It is thus statically linked to the database module. The database module doesn't know who it was called from. It will reply if requested, and it will broadcast status and error messages. The parent gets to decide wether it is interest in those broadcasts or not. 

 

Now, coming back to your question, the above scheme can be applied to multiple levels (a tree) of modules as well. If you haven't done so yet, read Sam Taggart's article on https://automatedenver.com/simple-dqmh-dos-donts/ where he talks about coupling, amongst other things.

 

Not sure if this is actually helping you, but here goes. As it is right now, we have three types of "main" VIs:

- On headless Real-Time systems, it's a small VI that calls all (top-level) modules and then sits there and does nothing but display logging events if run in the development environment

- On Real-Time systems with Embedded UI, it's a huge and ugly VI that also starts the top-level modules, but then hosts the whole UI (visualization and user input) of all modules because Embedded UI on Linux RT doesn't support sub panels 😞

- On Windows, we have the startup VI that you already mentioned, which loads modules dynamically from a configuration file which holds a list of module names/paths. 




DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (The Future of Team-Based LabVIEW Development)


0 Kudos
Message 8 of 16
(6,923 Views)

 


@joerg.hampel


Hi Joerg,

Thanks once again for responding.  I had to push a different project along for the past couple days, so I wasn't able to digest your responses until now.

 

My reusable modules are indeed oblivious of who called them.  They respond to requests and output their broadcasts in their own happy little world.  It is the modules that want to register to the requests/broadcasts from one of the reusable modules, and then regain registration after that module stops and restarts, that are tripping me up.  Specifically, after a module is already running, how does that module know when a different module has started?

 

I have obviously done a poor job of explaining my question because I am still essentially asking the same question. Here is the sequence of events that I am trying to understand:

  1. Module C is started.
  2. Module G is started and the events of Module C are properly registered during the startup of Module G.
  3. Both Modules are running fine for some period of time.  Module G is properly receiving the broadcasts from Module C.
  4. Then Module C is stopped.
  5. Module G receives the broadcast that Module C has stopped and acts accordingly.
  6. Now Module C is started (again).
  7. How does Module G know that Module C has started when its references to Module C are not valid?

The event references that Module G has for Module C are no longer valid.  So the Module C broadcasts, including the Module Did Init broadcast, cannot notify Module G that it has started.

 

For my Network Streams between my cRIO Target and Windows Host, if the connection is lost, they periodically poll for a valid connection.  Is that the typical method used to establish those communication linkages between modules?

 

Thanks,

 

Scott 

 

 

0 Kudos
Message 9 of 16
(6,903 Views)

One thing that I just realized is that I think that I am envisioning these modules as having more of a client/server relationships versus parent/child or caller/callee.  I guess that is the kind of connection method that I am interested in within the DQMH framework.  The method to reconnect after a disconnect.

 

Does a client/server relationship break the tree type of structure that Sam recommends?  Are DAQ and Data Logger type of modules typically one of the exceptions to the tree structure that he mentions?

 

Thanks, 

 

Scott

 

 

0 Kudos
Message 10 of 16
(6,902 Views)