Jump to content

[LVTN] Messenger Library


Recommended Posts

That's a standard technique I use all the time to prevent unwanted code coupling.  In fact I almost always do it if I have reason to pass the address of an actor.  I use either "Send" or "Actor" parent classes; there is no reason to use "Actor type 2".  With the Send class (the grandparent of all address classes) one also has the option of passing a TCP Messenger, allowing you to run C or D on a different machine.

  • Thanks 1
Link to comment

Note: I am considering uping Messenger Library's base LabVIEW version from 2013 to 2017.  This is to allow use adding actor templates that use JSONtext to do configuration, and to add VIMs to the palettes.  None of my clients use LabVIEW earlier than 2017.   Let me know if you use Messenger Library with LabVIEW earlier than 2017sp1 (sp1 fixed VIM bugs).

  • Like 1
Link to comment

Thank you for sharing your opinion on using parent classes for actor references to prevent unwanted code coupling! I will use Send class.

21 minutes ago, drjdpowell said:

Note: I am considering uping Messenger Library's base LabVIEW version from 2013 to 2017.  This is to allow use adding actor templates that use JSONtext to do configuration, and to add VIMs to the palettes.  None of my clients use LabVIEW earlier than 2017.   Let me know if you use Messenger Library with LabVIEW earlier than 2017sp1 (sp1 fixed VIM bugs).

That would be great, really looking forward to these changes.
____________________________________________________________________

If I ask too many question, please tell me! But I have another one. I use TCP messengers quite often to send messages and subscribe. That works perfect!
However today I tried to send a local queue in a message for the receiver to reply when asynchronous action is finished:

Untitled.png.72f250eb97d01d620d7b1344f2ad6048.png

The problem here is that I shared messenger references between 2 application instances which is not allowed.
This approach works in the same application instance.

I was wondering, is there a way to make the code above work across multiple application instances? I tried to create a TCP server instead of the
"action result" queue, but that doesn't seem to work.

Link to comment

This is basically this issue: https://bitbucket.org/drjdpowell/messenger-library/issues/32/clearer-way-to-pass-addresses-as-data-over

Addresses are all based on communication methods, such as a Queue, that don't work across application boundaries.   The TCP messengers get around this by replacing Reply addresses on messages with a special address that routes the reply back though the TCP connection.  So all the local-only communication methods will work remotely, but only for addresses passed as Reply addresses.  In your example, you are passing the address as data, not as the reply address.  Rather than Query, use Send, with your Queue as Reply address.  Use "read reply address" at the other end to get the address (actually now a "Route Back" address) and send your two messages to it.

  • Thanks 1
Link to comment
9 hours ago, drjdpowell said:

Note: I am considering uping Messenger Library's base LabVIEW version from 2013 to 2017.  This is to allow use adding actor templates that use JSONtext to do configuration, and to add VIMs to the palettes.  None of my clients use LabVIEW earlier than 2017.   Let me know if you use Messenger Library with LabVIEW earlier than 2017sp1 (sp1 fixed VIM bugs).

2017SP1 is fine for me. We have a generic configuration actor that uses JSON. Will be interested to compare your approach, if you include one in the toolkit.

Link to comment
  • 2 weeks later...
23 hours ago, Maksim Kuznetsov said:

Are you planning to return the "attachment" feature for the outer-envelope?
I remember using it for some time, but after installing the latest messenger library it seems to be gone.

It's badly documented, but it appears to be there for me, but in the "UseOuterEnvelopeLabel" vi (see below).  This is because that is where I envision it being useful, with a requestor attaching something to the reply. 

But you may be using the "Add Attachment" vi, directly.  This is still on disk, just not in the palettes.  I will add it back into the palettes (issue 5).

UseOuterEnvelopeLabel.png.70fa6b311e2294970113dacbcfc6442c.png

  • Like 1
Link to comment

 

On 8/26/2020 at 3:54 PM, Maksim Kuznetsov said:

Are you planning to return the "attachment" feature for the outer-envelope?

Can you show me how you use "Add Attachment"?  It's tricky to document its use, as I only use it as part of "Use Outer Envelope", and also because "Object Message" does double duty as "Outer Envelope" (as a Message is an object, then Object Message, when containing another Message, is acting like an outer envelope about that inner message).

Link to comment

My problem with the "Attachment" feature is that is difficult to come up with an intuitive API.  Just look quick example using a couple of Future Tokens to do one request-reply, with attached info.  Way too complicated, with four bits of info in the reply message (envelope label, attachment, inner message label, and inner message data).  This needs simplifying to be more than a niche feature.

1557895047_EnvelopewithAttachment2.png.6083d41ad3956dda79e851a3800a98ac.png

Link to comment
On 8/27/2020 at 5:28 PM, drjdpowell said:

Can you show me how you use "Add Attachment"?  It's tricky to document its use, as I only use it as part of "Use Outer Envelope", and also because "Object Message" does double duty as "Outer Envelope" (as a Message is an object, then Object Message, when containing another Message, is acting like an outer envelope about that inner message).

I have an OPC actor to which I can subscribe for channel data change events. Channels are strings. However after some time I realised that using strings was not that convenient, especially if one of the channel names changes. So, I decided to create an enum of all OPC channels and subscribed in the following way:

Subscription.PNG.7f50bd8080abe62ba1015f36eac9c247.PNG

This approach allowed me to leave the OPC actor unchanged. Then this is how I handle the events:

Handling.PNG.3f24fdd48bcb680df4b1d661821cb5e4.PNG

Now if need to change the OPC channel name, I can just change it in the typedef without touching anything else. Also writing/reading channels (separate messages supported by OPC actor) is convenient using an enum converted to string.

Edited by Maksim Kuznetsov
Link to comment
  • 1 month later...

I am trying to shift discussion of Messenger Library to a group at NI, as this conversation is at 12 pages and is hard to follow.

New post about a beta feature  for TCP that I am working on: https://forums.ni.com/t5/JDP-Science-Tools/New-Beta-feature-Reconnecting-TCP-Messenger/gpm-p/4092514#M5

Here's the image.  The idea is to have a persistent TCP Client connection that will try and reestablish itself if broken. 

822534739_2020-10-2015_09_33-ContextHelp.png.78975dd0f0582c0ec0d28bfff9305aaf.png

  • Thanks 2
Link to comment
  • 4 weeks later...

Note: I've also been thinking about UDP Messenger functionality, and am interested in people's use cases:

https://forums.ni.com/t5/JDP-Science-Tools/UDP-Messengers/m-p/4099792#M17

The use case I'm interested in is discoverability on the network.  So, allowing actors on different machines to announce their existence (ip address and port) via UDP, so that a TCP Messenger connection can then be established.  This could be built in to the new Reconnecting TCP Messengers.

Link to comment
2 hours ago, drjdpowell said:

Note: I've also been thinking about UDP Messenger functionality, and am interested in people's use cases:

https://forums.ni.com/t5/JDP-Science-Tools/UDP-Messengers/m-p/4099792#M17

The use case I'm interested in is discoverability on the network.  So, allowing actors on different machines to announce their existence (ip address and port) via UDP, so that a TCP Messenger connection can then be established.  This could be built in to the new Reconnecting TCP Messengers.

The major use case for UDP I would have is for COAPS (which, incidentally,  has service discovery rather than node discovery). Most node discovery methods require a known entry point (gateway, router, default port etc) and it's hard to get away from that that in a  reliable way across numerous network architectures.

Link to comment
2 hours ago, drjdpowell said:

Note: I've also been thinking about UDP Messenger functionality, and am interested in people's use cases:

https://forums.ni.com/t5/JDP-Science-Tools/UDP-Messengers/m-p/4099792#M17

The use case I'm interested in is discoverability on the network.  So, allowing actors on different machines to announce their existence (ip address and port) via UDP, so that a TCP Messenger connection can then be established.  This could be built in to the new Reconnecting TCP Messengers.

For this to be useful in my application, which is networked and takes advantage of the TCP Messenger, the UDP port would need to be configurable.

Also, our network admins have strict policies which could interfere with UDP. Although it's allowed, it can't cross certain hardware boundaries between networks. So although we can get TCP Messenger to cross networks, UDP would likely fail.

Edited by Thoric
Link to comment
On 11/17/2020 at 12:54 PM, Thoric said:

Also, our network admins have strict policies which could interfere with UDP. Although it's allowed, it can't cross certain hardware boundaries between networks. So although we can get TCP Messenger to cross networks, UDP would likely fail.

Another possible service-discovery design is a central broker; an actor with TCP Server at a known IP/Port that all services connect to to register their location, and to which clients connect to lookup services.

Link to comment
2 hours ago, drjdpowell said:

Another possible service-discovery design is a central broker; an actor with TCP Server at a known IP/Port that all services connect to to register their location, and to which clients connect to lookup services.

This is the standard way to do service discovery.

My "Dispatcher" implementation had a "broker" that ran on the local machine to act as a gateway to services that registered with it on that machine. External (or local) clients would then contact it to discover services and it would hand off comms to the service for direct communication. It behaved as a router rather than the usual broker and meant it didn't become a bottleneck for high speed transfers.

Your framework would be a good match for the above implementation since it already has all the publish, subscribe and routing features, IIRC.

Edited by ShaunR
Link to comment
  • 1 month later...

Hi James (and Messenger Library fans),

on page 2 of this thread you made a post showing a reconfigurable analysis pipeline. Would you mind explaining how you handled data transfer between the different analysis actors? I plan to start playing with this today, but would not mind some hints from the master. I am interested in doing something similar for really high data rates and the data transfer has been a sticking point for me.

I do think that standard queues in the actor data would be the way do go, but the specific protocol for linking up the queues has me in a quandry. My idea is to have each actor be in charge of it's input queue, which it then passes to its parent actor upon instantiation. On the opposite end, each actor would receive one (or possibly even multiple-- your example does show branching) output queues during its initialization, which could be changed during runtime with a message from the parent actor.

Another issue I have contemplated is doing something like a queue swap while there is still data waiting to be processed. I am thinking of giving the processing loop two states: idle and processing. Any changes to the pipeline must occur during an idle state and the transition from processing to idle be driven by a flag passed along with the data saying "I am the last one in this batch" which ensures that the queue is empty before messing with it. This flag would be set by the DAQ process either when it reaches the natural end of the acquisition or is told to stop by its parent. Of course a lossy hard-stop command that involves flushing the queue could also be implemented.

Hopefully I didn't botch putting my ideas into words. Looking forward to your input. I will try to report back with some code when I have it.

Edited by Conner P.
Link to comment

The target system is for optical coherence tomography. We are pulling 2048 wide U16 arrays from a linescan camera spectrometer from a framegrabber using IMAQ. The line rate is 80khz. The data is naturally blocked into "b-scans" which are ~1024 pixels wide, but we want to increase this in the future. The IMAQ buffers reflect this. So we get a 1024x2048 U16 image every 13ms or 75 images per second. The images are then converted to doubles for processing due to the limits of the LV Analysis library. This means 1024x2048x8bytes = 16MB per 13ms or 1.2GB/s.

The processing includes linearization through interpolation and FFT. We could probably optimize the hell out of it using C++ but that isn't on the table.

At present we are pushing around the IMAQ references and using IPE to do the processing in place. Of course moving references around is not very heavy lifting, but since we aren't running on a RT system it is very much at the mercy of the OS and any delay quickly adds up and can lead to the IMAQ ring buffer overrunning.

Edited by Conner P.
Link to comment

It is difficult for me to give good advice without really understanding the project.  Some random thoughts:

Where are the performance bottlenecks?  The first thing I would do is prototype and benchmark the steps and get a feel for what are time-limiting, high-CPU steps.   Be wary of designing a complex custom communication pattern "for performance" before you understand what and where the performance issues are.  How long does it take to convert your IMAQ image into a DBL array, for example?  You might find that effort on a custom queue system is better spent on some other area.

Remember that you IMAQdx task is already an asynchronous actor-like thing, with a buffer of images.  I often see people placing importance on the loop "taking data" piping that data to an async analysis loop, when really the IMAQdx or DAQmx task is really the one taking data.

Also note the design pattern used by IMAQdx Events, where the "Frame Done" event doesn't contain the Image itself, but tells one that an image can be read from a separate queue (ring buffer).  If you find you need a custom queue for data, you could consider using this pattern.  I'd also try and experiment to see if I could have more than one loop pull different Frames off the IMAQ ring buffer at the same time, as this gets parallelism working as early as possible.

If you are working with reference data, either IMAQ images or DVRs, then 75 messages per second is not high, and I personally would just use the standard Messenger Library Actor Event-Notification Messages for passing references to the data, at least at first.  Design for simplicity and add complexity only later if your performance benchmarks show value in it.

 

Link to comment
  • 3 weeks later...
  • 8 months later...
On 8/13/2020 at 11:28 AM, drjdpowell said:

Note: I am considering uping Messenger Library's base LabVIEW version from 2013 to 2017.  This is to allow use adding actor templates that use JSONtext to do configuration, and to add VIMs to the palettes.  None of my clients use LabVIEW earlier than 2017.   Let me know if you use Messenger Library with LabVIEW earlier than 2017sp1 (sp1 fixed VIM bugs).

I am actual about to commit to making the next release in LaVIEW 2019, rather than 2017, as VIMs were very new in 2017 and both buggy and of limited capability.  

 

  • Like 2
Link to comment
  • 2 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.