10-01-2018 03:46 PM - edited 10-02-2018 09:19 AM
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:
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?
Solved! Go to Solution.
10-01-2018 04:09 PM
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?
10-02-2018 01:22 AM
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® (Developer Experience that makes you smile )
10-02-2018 01:23 AM
@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
10-02-2018 09:18 AM
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
10-02-2018 01:54 PM
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:
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
10-02-2018 04:36 PM - edited 01-12-2019 04:59 AM
@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.
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® (Developer Experience that makes you smile )
10-02-2018 05:11 PM - edited 10-02-2018 05:22 PM
@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® (Developer Experience that makes you smile )
10-05-2018 04:54 PM
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:
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
10-05-2018 04:55 PM
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