Jump to content

[LVTN] Messenger Library


Recommended Posts

James,

This may have been answered before, so forgive me if it has.

The actor model you use ensures sequential execution of the Event Structure and State Machine. This means the state machine can complete its task(s) without interference from the event structure, because the event structure literally cannot react to any incoming messages until the state machine completes its stack and yields execution.

But what if you have a case where this is unhelpful? For example, consider that the state machine is in the middle of a series of state changes, controlling hardware and taking measurements, when an Emergency Stop message comes in. I would want the emergency stop message to be received and reacted upon immediately, with the event structure being able to inform the state machine that it needs to take into account this emergency stop state, change its task list (stack) and instead put hardware in a safe state with immediate effect.

Currently I don't see a way to do that without the state machine yielding to the event structure at regular intervals (every 100ms for example), which requires some uncomfortable coding styles. I could, for example, let the state machine yield to the event structure with a status flag set in the shift register that the Timeout Case uses to recognise a need to return to the state machine. This would give the event structure a chance to look at incoming messages and react. But what if a benign message comes in that would normally be held back until after the state machine was finished? Suddenly it gets processed and dealt with too soon. This is why it's important not to yield to the event structure before the state machine is ready to process new requests.

Alternatively I somehow use a notification style message within the state machine itself, enabling the possibility of checking an Emergency State notification at regular intervals within the state machine, preventing the need to yield to the event structure. But this notifier would have to be populated from outside the actor, because the event structure is not free to create the notification. This means we now have external source able to directly influence a privately scoped state machine, bypassing the controlling event structure and defeating the primary principle of the actor's stacked structure. Or do we let this fly because we're just using it for emergency notifiers?

Your counsel is greatly sought, my friend.

Link to comment

I few other methods for you to consider:

1) a separate "helper loop": in this, the main loop of the template is a "manager", with a separate loop inside the actor doing the work.  The "worker" can be controlled by non-actorish ways (such as an Abort Notifier) by the Manager, which is always capable of handling new messages coming in.  This encapsulates the non-actor communication, keeping it local (and understandable).  I likely addition to this is a "job queue", to hold the list of actions that the manager queues up for the worker.  Here is where one can have job priority, or cancelable jobs.  Note that this is different from the "action stack" (what you called a "state machine").   These are different things that are too often combined.

2) Have a "Sequence actor" that does the long actions, which can't itself be aborted, but which acts on hardware via short-to-execute synchronous Request-Reply messages to separate hardware actors.  Send the "abort" messages to the hardware actors, putting them into a safe-mode state where they reply to action requests with errors.  The first such error message causes the "Sequence actor" to end it's sequence (using standard error-chaining logic).   Note that if your stop really is an emergency then this bypassing of your complex higher-level logic to talk directly to low-level hardware actors is actually a lot safer and more easily testable.

3) An asynchronous version of (2), where the "Sequence actor" uses Async Request-Reply for interaction with the Hardware actors.  Less flexible than (2), but more properly actorish, in that the Sequence actor is always able to handle messages.

I actually don't mind your abort notifier triggered from outside the actor.  This is, as you say, bending the rules for a limited and clear purpose, and for the special case of aborting.

 

Unfortunately, though, you're dealing with the problem of "state" (true "state", not the actions of a so-called "QSM") and that isn't ever easy.  

  • Like 1
Link to comment

Interesting - these offerings are significant effort. I was hoping for something simpler, but I wonder perhaps if the use of a 'globalised' notifier is the solution I need. As you state, it's for a limited and clearly defined purpose.

I'd be interested to see suggestion 1, (the helper loop, with the main actor template becoming the manager of an internalised worker), provided as another template option from the scripting tools. 

Thanks for the advice James - professional as always!

Link to comment
  • 2 weeks later...

Hello James,

Since I started using the framework I started having trouble with the so called Infinite Reset of Death during shutting down of the application (executable). The cause of the problem is not the messenger library, and now there is a way to deal with this problem as explained here:

http://www.labviewcraftsmen.com/blog/not-so-infinite-reset-of-death

I used the methodology and it works very well! Now there is no more possibility for the resetting VI message that never goes away during shutting down of the application.

I hope users of the messenger framework find this useful.

 

Link to comment
  • 3 months later...

When updating Messenger Library from version1.8.3.82 to version 1.9.6.99, my application throws this error:

image.png.74513b9956fdf661a681b807adc0094c.png

Looking at the code I see the change that was made and comments pointing to here to explain the change:  https://labviewcoder.com/2016/07/06/quick-tip-asynchronously-launching-vis-the-right-way/

If I change Dynamic Launch Shell.vi on the block diagram back to a strictly typed VI reference, the error goes away.  What's gone wrong?  

The library has made my application development much easier, but I don't understand things well enough when an issue like this comes up.  For now my solution is to backdate the library to the previous version, but I'd like to understand what's happening.

 

Edited by dhendrix11
Link to comment

This is Issue 9, the trickiest problem in Messenger Library at the moment.   Can you try version 1.10.6, which is in the LAVA-CR (this has been submitted to the Tools Network and is working its way through the process.  There is no ideal solution but this is my best attempt.  Alternately, you can try renaming your Main:ActorNR to something else (assuming you don't need to launch it but are instead running it directly).

Link to comment

James,

Is it possible to glean information about the sender of a message? In my Actor I receive a message and it would be useful if I could learn some originator details, namely the Name of the Actor (VI Name perhaps). I wonder if it's possible to learn this info from the Reply to... indicator of a Read Reply Address call?

image.png.eb0a0b571ee6c72bc34a289594451d8e.png

A little bit of background - I want my actor to be smart enough to recognise where a message has come from. It's 'actor agnostic', except for one in particular, and if packets come from that one particular actor I want to perform additional tasks. I can't place additional information into the message itself, so I need this actor to be able to determine the source of the message automagically. Can we do that?

Link to comment

Does your receiving actor know the exact reply address that the special sender will use?  You can use addresses as unique identifiers with "equals".  There is a vi in the palettes that searches an array of addresses for the reply address on an incoming message.

Your design is different from ones I'm familiar with, so that may not be a good answer.

Link to comment

I was adding a 'quick' feature to my framework - in retrospect it wasn't the right approach so I've changed my tactic and now I have a better implementation that doesn't require this actor knowing the message origins.

I appreciate knowing now though that the addresses are directly identifiable, even if we cannot extract any information about the address from it.

Thanks James

Link to comment
  • 1 month later...

 

I PM'd James the following question regarding unit testing and the Messenger Library actors. He asked I repost it here so that he can answer publicly for the benefit of the community and it is documented with the rest of Messenger Library discussion.
 
Quote

Hi James, I have some thoughts/a question about the messenger library, actors, and testing. I have to create an "xcontrol" that involves an intensity chart and interlinked a histogram and I did a very quick test class with logic code right there on the actor block diagram. At the same time, I have been reading about and trying to put a foot into the door of unit testing. I found it conceptually hard to think of how to test the actor as I had written it. While working on the problem in general, I was browsing your augmented graph code. I noticed that there is zero low-level code and every "action" defers to a member vi of the graph class which encapsulates the actor data. I suppose this would be a step in the right direction to facilitate testing, because it clearly packages logic into defined methods. However, since I don't have much experience with testing, let alone for LabView, I feel at a loss trying to understand how to test these things when so many functions do things like modify cursor positions and such. That feels much more like side effects than logic. Would you might providing some insight into how you go about testing in LabVIEW, with attention to messenger library actors and classes? Thanks again for all that you do for the community.

 

Link to comment

I'm afraid I have no answer as how to test actual UI code, other than an actual set of tests done by a person.  That is quite a big problem.  However, I commonly do have business logic in some kind of subVI or class method, and that can be unit tested.   So for example, I can test if the "Save Data" and "Load Data" methods properly write/read the data, but I can't test if the "Save" and "Load" Menu items actually call those method correctly.  

One can, though, test the message-interaction of an actor in a Unit Test.   And one can use Queries to help do this quite easily, even if the actor, in actual use, is interacting much more asynchronously.  Below is a part of such a test of a ModbusTCP Server.  I included a diagram of the actor interactions at top (a secondary value of unit tests is that they allow one to demonstrate the use of a component in a simplified setup).  Note that I quickly made a simple message loop to stand in for the "Device", needed to handle some of the commands sent over Modbus (the actual actor that is the Device in the application is much more complicated).   

1639812413_ModbusTCPActorUnitTest.png.d52764d401f4fb4092d6e0ea00477330.png

Not shown, off the bottom of the screen, I use the Plasmionique Modbus Library as a test Modbus client to run a series of communication tests with the server.    

Note, though that this is an example of an Actor that involves no UI at all.   If it had UI elements, I could not test that automatically.

Link to comment
  • 3 weeks later...

Hello all - I am trying to figure out a way to use the TCP Messenger to create a PC client that can send messages to up to 52 remote cDAQs.  I used your simple TCP Client Server example to start off with and it works fine for a single cDAQ server.  The problem is that I do not want to have to launch 52 actors in my client code pointing to each of the 52 cDAQ IP addresses.  Is there a way to just send simple messages to the server without have to launch an actor or perhaps reuse an actor by programmatically pointing to the IP address I need to talk to at any given time?

Link to comment

I also need something that can handle situations where the cDAQ is not present or drops out and needs to be reconnected with.

I think I maybe trying to use the wrong tool for this application.  I might be better off with a topic based DDS that has inherent reconnect capability.

Link to comment

When you say cdaq, you mean normal cdaq or one of windows/rt cdaqs? Assuming windows/rt, maybe if you want some basic messages just set up a web service with a named queue to forward messages to. Then you don't need an actor, just call the http api directly (or spawn it as a task).

Link to comment

I am using cDAQ's with Linux RT but I suppose I could still use websockets, right?  In the meantime I am trying out on-the-fly creation of Messenger remote connections to my cDAQs.  It is not very fast ~50ms total transaction time per cDAQ but it might do since the command response side of things is more supervisory control of the overall system.  For status and data collection I am using RTI-DDS which is blazing fast. 

One concern I am having with Messenger is that on occasion I have seen the 50ms transaction times suddenly increase to 5000ms.  Shooting in the dark, I am wondering if it could have something to do with NI Service Locator sync between client and servers?

Anyway, it would be nice if the messenger library had the option of specifying static port numbers instead of service names.

Edited by viSci
Link to comment

Yeah websockets are easy, theres 12 libraries out there for setting them up using the tcp primitives.

50 ms delay could be nagle -- if its a closed network, 50 ms is at least 25 round trips, likely more.

One possibility for the long long delay is if you're using hostname rather than numeric IP address. The hostname lookup is a disaster for any networking code, at least on windows.

Link to comment

What about the port service name locator, could that be a problem as well?  I was planning on using RTI DDS for all network communications but the LabVIEW wrappers provided by RTI and now included in LV2018 have some shortcomings.  Things like no native support for command-reply, no events and issues with strings within a cluster that start with a numeric digit pushed me to consider Messenger...

Link to comment
8 hours ago, viSci said:

Things like no native support for command-reply, no events

I've never looked at rti-dds, but could you implement a "reply address" with it?  Instead of a blocking command-reply, you could do an async command-reply-continuation.  I talk about this messaging pattern in this GDevCon talk: https://youtu.be/HIuzY_Bs7BI (staring at 7:38).  

Regarding Event support, you can always write a reusable forwarding loop, which listens to an rti-dds whatever-they-call-it and posts the messages to a User Event.

I'm a believer in not cobling together different communication methods, and if I had your use case I would try and use only one package to implement it, adding capability if needed (though in my case that package would be Messenger Library, of course).

Edited by drjdpowell
Link to comment
15 hours ago, viSci said:

BTW, which websocket library would you recommend for command-reply use cases on a Linux RT target? 

I'm guessing shaun would say this one: https://lvs-tools.co.uk/software/websocket-api-labview-library/

But the one on vipm seems good enough to me. A lot of the others are only 1 half or the other.

Edited by smithd
Link to comment

Join the conversation

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

Guest
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.