Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Deploying Actors (classic PPL/Build concerns, sorry if a repeat)

Hi, I have been using LV Actors for many years, but the early years generated a lot of bad habits and poor use of OO principles, It was all very new to me. Therefore over the last few months I have tried to re-work my System with new interface classes leveraging 2020 to reduce coupling and correct some of the evolved mess I had created.

However, I needed to do a fair bit of work to get comfy with the interfaces and new structure and have not dedicated the time to deployment AGAIN... FYI Long term I want to develop a CI pipeline using Jenkins to automate build and test. We currently use Tagged code in the Dev environment on test machines, which is costly and prone to errors and potential for issues during testing.

Now I understand PPLs are the best route to a build, my real question is how to best organise the project(s), libraries etc to get functional PPLs. I have found and used LVSolutionBuilder which is awesome and works well... so far.

I have created a library for each interface (or group) and each actor in a main project, I have then created several sub projects for dynamic elements such as UIs and Tests etc. I have correctly handled these locations in the code too to distinguish PPL for source locations. 

But I keep hitting a road block of PPLs not building Error 1003 or getting it to build but issues running, not to mention the whole PPL of Actor FW.

So long question, long... am I doing things right or is this a stupid path and should change my plan/strategy and embrace EXE and Data folder concept etc?

 

Many Thanks in advance for any help!!

 

Neil 👍

0 Kudos
Message 1 of 13
(3,066 Views)

Hey Neil,

 

I have not used PPLs with Actors. But in a recent project when dealing with PPLs, I have found it to be much easier using LVSolutionBuilder for dealing with PPLs. On the issue that you are facing with Actor PPLs, I would suggest posting this in the LVSolutionBuilder's github issues page, preferably with a simple reproducible example.

------
Using LabVIEW since 2012. Certified LabVIEW & TestStand Architect
0 Kudos
Message 2 of 13
(3,015 Views)

Hi,

 

Thanks for the reply. I appreciate the help. I don't think this is an issue with LVSolution Builder more my code. I think I tracked down my problem to be circular dependencies in my PPL structure. I really am struggling to resolve them as I have interfaces (new proper labVIEW ones) that are used by Actors for messaging but they use Classes to encapsulate data which are shared by the Actors due to the interface messages so LVSolution builder cant resolve the build order.

I am wondering if this is my understanding of which items should be in what library/PPL to start with or a major design fault by using classes to encapsulate the message data etc.

Whatever it is I'm tearing my hair out and spending a lot of time failing to build 😓, that I should perhaps be spending on my code 🤔  .

Its all part of the process but this is mainly why I haven't had a proper build strategy with Actor before, along with the destruction of the IDE by having to pack the main Actor classes in to PPL too 😩.

 

Thanks again,

 

Neil.

0 Kudos
Message 3 of 13
(2,995 Views)

Hi Neil,

 

I've had some 'fun' with this issue in the past too, for me (in hindsight...) one of the best aspects of PPLs is that to build them you have to fix dependencies and figure out what needs what and break any circles.

 

I'm currently building my PPLs in 2019 (I started with Jenkins using LV2017) but I don't think your use of Interfaces is inherently the problem.

Guessing blindly, I'd say you probably need more libraries 😉

 

You can have some luck just building your PPLs 'by hand' to start with (using the LabVIEW Build Specifications and the right click > Build option) and then making sure that each next library depends on the .lvlibp instead of the .lvlib of its "upstream" libraries.

Take care to check the "Exclude Dependent PPLs" box (or whatever the actual label is).

In my case, I build all my PPLs into a single directory ("C:\LabVIEW Sources\PPLs\Current\blahblah.lvlibp").

 

 

Spoiler

I use the "Current" directory part to allow directory junctions (not symlinks on Windows) for multiple bitnesses, but since I designed this system AQ has published information about platform-dependent load path resolution, so if you want to run code in 32/64-bit on the same computer, I recommend reading that first and doing that instead (basically, put your PPLs in <vi.lib>/MyAwesomeCompany/PPLs/blahblah.lvlibp instead).

If this all sounds like a lot of trouble and you're not interested in it (at least now), you can ignore it all. But consider if <vi.lib> is a suitable destination for your PPLs anyway, it might make migration in the future easier. Maybe.. 😕 

 

To have a bit more control over your builds on Jenkins, you might take a look at the Application Builder API. It seems this is an unpopular choice, but I really like it. The documentation(?) is a little hit and miss (/guesswork based on file name), but it allows you to generate the build specs during build time on Jenkins, and change whichever values you like to get stuff set up how you want.

I found it vital to building cRIO PPLs without pulling out all of my hair (but I'm not sure there aren't better solutions, just that this works for me and other things seemed very trying).

 

For me, the "easiest" solution to building the Actor Framework libraries whilst retaining some of the original decisions (split out Reply messages, etc) was to ditch AF_Debug entirely.

I copied all of the Actor Framework code out of vi.lib into a separate directory and made changes there, this involved cut/pasting the vi.lib stuff if I remember correctly to force it to relink and search, it was quite a pain but now it works nicely. (Obviously copy the original code back into vi.lib once you've finished).

I have two PPLs, "Actor Framework.lvlibp" and "AF_Messages.lvlibp", where the first is just the contents of the Actor Framework library, and AF_Messages is the rest (Reply, Time-Delayed, Batch, Self-Addressed and Report Error Msgs).

A more popular (as I guess from reading the forums) approach is to throw everything inside one library, and build that instead. You can keep AF_Debug in that case, but you still have to fight the library membership if I understand correctly.

I have a git repository with the two libraries I've created, and so I can easily rebuild it using Jenkins as desired.

If you build Actor Framework.lvlibp outside of vi.lib, you must (I think 😉 ) adjust "<LabVIEW 20xx>\resource\Framework\Providers\MessageMakerProvider\_Message Maker\_support\Inherits from an Actor.vi" in order to retain the scripting tools in the IDE.
My modified version is shown below:

cbutcher_0-1634030256936.png

 

This is because when you build the PPL in vi.lib, it has a mangled path but includes "vi.lib\ActorFramework\Actor\Actor.lvclass" at the end of the path for the Actor.lvclass class.

If you build it somewhere else, it doesn't!

 

If you show an example of your dependencies and libraries/classes, we might be able to give some suggestions about how they could be rearranged to remove circular dependencies (apologies if you already know how to do this, and are instead looking for motivation not to!)

 

Hopefully at least the point in this post about the VI modifications for the search path can fix the thing you describe as "destruction of the IDE". But maybe that's something else, in which case please explain it and I'll try figure out a solution.


GCentral
0 Kudos
Message 4 of 13
(2,989 Views)

Thanks cbutcher,

You have really given me a lot to think about and really appreciate the time you have taken to respond.

 

Can I ask for a few extra bits for clarification?

 


@cbutcher wrote:

Guessing blindly, I'd say you probably need more libraries 😉

I have a library for each Actor, Interface, Support Class (or group) I currently only have one main project for my Main Program and additional Projects for Dynamic elements UI and Tests etc. 

@cbutcher wrote:

You can have some luck just building your PPLs 'by hand' to start with (using the LabVIEW Build Specifications and the right click > Build option) and then making sure that each next library depends on the .lvlibp instead of the .lvlib of its "upstream" libraries.

Based on this statement though I think I will need to create a project for each and re-work post build of each upstream PPL, which is kind of why I tried to use LVsolution Builder to avoid this, am I taking this statement correctly?

 

@cbutcher wrote:

In my case, I build all my PPLs into a single directory ("C:\LabVIEW Sources\PPLs\Current\blahblah.lvlibp").

 

Is there value in the flat structure? I tried to maintain the Actor, plugin, support and interface segregation in the output, does it matter or will I cause more issues than I prevent lol?

 


@cbutcher wrote:

I copied all of the Actor Framework code out of vi.lib into a separate directory and made changes there, this involved cut/pasting the vi.lib stuff if I remember correctly to force it to relink and search, it was quite a pain but now it works nicely. (Obviously copy the original code back into vi.lib once you've finished).

I have two PPLs, "Actor Framework.lvlibp" and "AF_Messages.lvlibp", where the first is just the contents of the Actor Framework library, and AF_Messages is the rest (Reply, Time-Delayed, Batch, Self-Addressed and Report Error Msgs).

When you say relink and search do you mean in each project that referenced the new Actor framework? or something else?

 

I don't know if this will help much but here is a snip of my project explorer view.

I have highlighted a potential concern of a support Class utilised in messages (interface class) and Actor, since thinking about all of this I am wondering if this sort of problem/structure would be better resolved using an actor for Parameters and handling each parameter request as individual values? I will try with this link first to pre-build manually to see if it is a problem.

My design revolves around Parameters needing to be immutable so the class ingests the XML and stores in variant attributes, it is then supplied to the launched tests for reading. I could not figure out how to do this without send and wait messages for a centralised actor?!?

Project view.PNG

I haven't even got to the point of using Jenkins etc, I thought thought I knew how to program in LaBVIEW I know even less about Batch file, Jenkins and all that... I am at the stage of doubting the whole lot, top to bottom and my skills/understanding as a whole lol.

 

I have been here before, it is just know which is the route out not picking up a different spade and digging deeper Haha!

 

Thanks again 🙂

 

Really appreciate it.

 

Neil.

 

 

 

 

 

 

 



0 Kudos
Message 5 of 13
(2,984 Views)

Hi,

 

Further to the last I have tried as you described to create an Actor PPL from a completely different folder and cant get past the first issue adding it to a empty project.

I created a copy and new project and added the Actor Framework Library to be struck by conflict that create an un correctable locked link to vi.lib.

NeilA_0-1634036938984.png

Attempting to resolve conflicts doesnt have a selectable option

NeilA_2-1634037087219.png

All of the referenced items are in vi.lib...

 

Any Advice? Again fallen at the first hurdle lol!

 

 

0 Kudos
Message 6 of 13
(2,982 Views)

@NeilA wrote:

@cbutcher wrote:

You can have some luck just building your PPLs 'by hand' to start with (using the LabVIEW Build Specifications and the right click > Build option) and then making sure that each next library depends on the .lvlibp instead of the .lvlib of its "upstream" libraries.

Based on this statement though I think I will need to create a project for each and re-work post build of each upstream PPL, which is kind of why I tried to use LVsolution Builder to avoid this, am I taking this statement correctly?




Yes, that's my approach. I haven't got any personal experience with the LVSolutionBuilder, but I have heard some good things, so that might be an alternative.

However, if it never updates libraries in source to depend on upstream lvlibps, then I suspect it might not make it so obvious where you have dependency cycles, which might make it harder to solve your original issue.
In my case, the workflow (originally went like) goes something like:

  • I have Parent.lvlib and Child.lvlib (doesn't have to be class parent/child, but this naming might be clearer than "A" and "B"...)
  • I build Parent.lvlib using Parent.lvproj into C:\My\Location\Path\Parent.lvlibp
  • I go into Child.lvproj and update the dependencies to use C:\My\Location\Path\Parent.lvlibp, instead of lvlib (wherever that is).
    • LabVIEW has a "Replace With" dialog option now to make this easier (right click on lvlib in dependencies or project), that often works fairly well
    • I expect it doesn't work well when you change contents, most likely a problem when building ActorFramework.lvlibp or similar (where the library and the PPL might have different contents... oops)
  • I build Child.lvlib into C:\My\Location\Path\Parent.lvlibp, ensuring that I exclude dependent PPLs.

 


@NeilA wrote:

@cbutcher wrote:

In my case, I build all my PPLs into a single directory ("C:\LabVIEW Sources\PPLs\Current\blahblah.lvlibp").

Is there value in the flat structure? I tried to maintain the Actor, plugin, support and interface segregation in the output, does it matter or will I cause more issues than I prevent lol?




The most critical aspect of PPL paths is that the relative path between PPLs must remain the same.

Mark Yedinak and Yinhui Chen gave a presentation about this in some detail at NIWeek 2019. NIWeek 2019/Effectively Using Packed Project Libraries (wiki link) 

For me, a flat structure is a simple way to avoid this, but their presentation details a relative structure that they maintained at Zebra Technologies, if I remember correctly.

In any case, it isn't a requirement, just a simplification for me. If you like a more complicated structure, it's certainly possible. Just evaluate if it adds some value for you.

 


@NeilA wrote:

 


@cbutcher wrote:

I copied all of the Actor Framework code out of vi.lib into a separate directory and made changes there, this involved cut/pasting the vi.lib stuff if I remember correctly to force it to relink and search, it was quite a pain but now it works nicely. (Obviously copy the original code back into vi.lib once you've finished).

I have two PPLs, "Actor Framework.lvlibp" and "AF_Messages.lvlibp", where the first is just the contents of the Actor Framework library, and AF_Messages is the rest (Reply, Time-Delayed, Batch, Self-Addressed and Report Error Msgs).

When you say relink and search do you mean in each project that referenced the new Actor framework? or something else?




I mean when you try and create an Actor Framework.lvlib (not p) by copying out of vi.lib, everything will be a pain in the neck. From your next post, I'd guess you've already discovered this!

I'm going to respond to that one too after I've had a go at repeating the process, so I can write down which things I did in what order. Then you can try repeating it if you like.

Alternatively, copies of my PPLs (source from 2017 LabVIEW, built in 2019 LabVIEW, compatible with that and later versions via the build checkbox, 32-bit and debug enabled but no AF_Debug library) are attached.

 

Different approaches are described by Stefan Lemmens here:  How to build a PPL including Actor classes, messages and AF Debug 

and an overview is in this KB article: How to Inherit from an Actor That Is Inside a Packed Project Library? (see the first section, "Create a PPL from the Actor Framework").

The KB article also has some good points about using the PPL, probably worth a read if you haven't seen it before.

 

Regarding your image and description, I'm not quite sure which libraries contain which bits, so I'll guess and you can correct me...

  • ParametersInterface is an Interface that describes the things that can be done with a parameter? So things like "Apply Parameter.vi"?
  • ParametersParse is in the Interfaces folder, so I'm not sure, I'd have otherwise guessed code for taking the XML file you mentioned and producing an array of Parameter.lvclass objects?
  • Parameters.lvlib contains a Parameter(s?).lvclass which is created (one or more?) by the ParametersParse VIs and the XML file combination, and inherits from the ParametersInterface.
  • Controller contains an Actor which has one or more Parameter.lvclass objects, and makes use of them via the interface?

From that description, a few thoughts:

  • If you don't want Controller to depend on Parameters, use only ParameterInterface.lvclass in all of the Controller code, and then load the Parameters class in the Parse code via Get Default LV Class from Path (or whatever it's called). If you're careful with the design of the interface and the class, you can probably make the Parse code also only require the Interface (in principle, you should do this, and avoid any dependency in Controller or Parse on the Parameters.lvclass, but it might be more effort than required, remember you must avoid any block diagram constants of the Parameters.lvclass to do this)
  • Depending on the structure of the Controller behaviour, you could (to avoid Send and Wait for Reply)
    • Send "Load Parameters" to the ParametersParse Actor (if an Actor, guess so from the message mention). Then use a state machine or a boolean or something to say "Not yet loaded". In the "Do.vi" of "Send Parameters To Controller Msg" or whatever, set the boolean true (Parameters Loaded).
    • Make ParametersParse not an Actor, only synchronous dataflow code (simpler, might be a problem if very slow... but if you're waiting via Send and Wait anyway, no real difference)
    • If you need the parameters before you can run the tests, and you can start the tests from the controller, perhaps no need for complicated handling, add "Send Run Test Msg.vi" to "Update Parameters.vi" and then it will be called when ParametersParser uses "Send Update Parameters Msg.vi" to the Controller
    • probably lots of other things. But I'd be tempted by the second option, and consider the first based on the situation. Alternatively, just use send and wait, and be careful to avoid locking.

Re Jenkins, I think it's useful, but it adds complexity and if you're having problems with the PPLs alone (and the problems aren't related to multiple platforms) then I'd suggest the manual approach first, then move to Jenkins once the basic process is fixed.

You can also write VIs to build your PPLs, and run them manually on your computer, and then when you're happy use those directly on Jenkins-based workflows (I did this for a little bit, but it didn't last that long, the cRIO stuff kept messing me (well, my source libraries) up so had to "go big or go home", sort of thing).


GCentral
0 Kudos
Message 7 of 13
(2,960 Views)

And the promised list of my steps to extract a pair of PPLs without building in vi.lib.

Apologies for the lack of nice writing style, these are basically the notes I made whilst carrying out the process and I haven't made many adjustments to post here, except adding the bullets and some spacing + images (edited to add these, realise I forgot before) + headings.

I've used numbers in places to make it easier to ask questions if you want.

Prep

  • Copy "ActorFramework" from vilib to somewhere else (I used a separate disk)
  • Copy AF Debug from resource\AFDebug to somewhere else. This library will probably get totally screwed by the changes below, so good to have a copy to revert to the original easily.

 

Actor Framework.lvlibp

  1. Move contents of ActorFramework to a new working directory (C:\LabVIEW Sources\AF_Sources\ActorFramework)
  2. Move "Batch Msg", "Reply Msg", "Report Error Msg", "Self-Addressed Msg", "Time-Delayed Send Message" to side directory ("C:\LabVIEW Sources\AF_Sources\AF_Messages")
  3. Create a blank project in AF_Sources\ActorFramework
  4. Save project (in hope of saving sanity by simplifying save dialogs or crash problems) ("My Actor Framework.lvproj", name unimportant)
  5. Open Actor Framework.lvlib in this project (right click My Computer, Add, File)
    Mine loaded unexpectedly well here. I just checked the changed paths, it looked pretty good. A few items got broken, mostly by AF Debug.
  6. Save, Save All (Ctrl+Shift+S).
  7. Apparently don't ask why is Message Enqueuer in vi.lib in Dependencies. My LabVIEW crashed silently... 😞

The next few steps are probably very sub-optimal, but anyway...

  1. Open Init Actor Queues FOR TESTING ONLY.vi (IAQFTO)
  2. Resolve as many conflicts as pop up in favour of the local Actor Framework contents (not vi.lib). 
    Actor.lvclass dropped out of my library with conflicts.
  3. Delete the control and indicator in IAQFTO and then it should be possible to unload and reload the Actor.lvclass that actually exists (in same directory).
  4. Drag new controls from that class into the VI, rewire. Use Quick-Drop replace (Ctrl+P) to replace the two missing/broken VIs. (If you also create new controls, make sure to add them to the connector pane, I forgot this on the first attempt :/)
  5. Drag Actor.lvclass back into the library, save all.

Continued... (let's call this section 3?)

  1. Open Message.lvclass:Drop Message.vi, Message Enqueuer.lvclass:{Enqueue Critical,Enqueue}.vi (3 VIs, the ones that contain AF Debug calls and are given as "Why is this item in Dependencies?" for Time-Delay Override Options.ctl.
  2. Remove the Conditional Disable Structures containing AF Debug. Easiest way is to go to the default case, then right click and choose the Remove Conditional Disable Structure option. Remove any broken wires (Ctrl+B).
  3. Repeat the check for 'Why in deps' on TDOveride Options.ctl. Remove debug again from Actor.lvclass:{Actor,Receive Messsage}.vi
    The ctl should now drop out of dependencies, and AF Debug.lvlib moves into "Items in Memory"
  4. Save all, close, reload project. There should now be no dependencies outside of the folder you moved to ("C:\LabVIEW Sources\AF_Sources\ActorFramework") except "Error Cluster From Error Code.vi". Check this in the Files view of the project explorer.
  5. Add a PPL to the build specs.
    1. Choose the top level library (Actor Framework.lvlib)
    2. Set the destination directory ("C:\LabVIEW Sources\DummyPPLs") (probably you don't want this path for real 😉 )
    3. Choose to Enable debugging in Advanced, if you like. This is helpful even without the DETT support just for checking the contents, I mostly use the debug library during development despite increased size and presumably slower code.
    4. Check "Exclude dependent packed libraries" from "Additional Exclusions". This makes no difference here, but a good habit for this.
    5. Configure whatever you like in "Version Information".
    6. Generate Preview. You should see just the PPL in the directory you specified.
    7. Build.

Save project again. Celebrate, you're halfway done.

AF.png

 

AF_Messages

  1. Create a new blank project, "AF_Messages.lvproj", in "C:\LabVIEW Sources\AF_Sources\AF_Messages\" or wherever
  2. Save (for reasons above ;))
  3. Add > Folder (snapshot). Choose the current directory, with the subdirectories "Batch Msg", "Reply Msg", etc.
  4. When the missing search comes up, click browse (mine was for Message.lvclass first). Browse to your PPL created previously (C:\LabVIEW Sources\DummyPPLs\Actor Framework.lvlibp). Select the desired item (Message.lvclass).
  5. Repeat as required (check the name you're searching for carefully in the searching dialog before clicking browse, the visible part in the actual dialog after clicking browse is often too short to see clearly)
  6. When finished (I had 3 or 4 to browse for) check the changed paths ("Load Warning Summary") if desired. Or ignore...
    In my case (I don't know if it is deterministic, I guess maybe?) I had a mix of PPL and lvlib stuff in memory. Go figure.
  7. Save all
  8. Check why AF Debug is in dependencies (TDSM.vi, TDSM Core.vi). Go to those and remove the AF Debug stuff.
    • In the Time-Delayed Send Message.vi (not core) you'll have to be a bit cleverer to avoid a broken/void wire, just wire an empty string in the Conditional Disable Structure instead of the outputs of the AF Debug VI. It won't be used anyway.
  9. AF Debug moves to "Items in Memory".
    1. Right click on the Actor Framework.lvlib and choose Replace With.
    2. Select the PPL.
    3. Confirm in the "already exists in the project. It's current caller(s)... " dialog.
    4. Remove the extra files "AF_Messages.lvlps", "AF_Messages.aliases" from the project.
    5. Save all, close, reopen.
    6. I got a few more missing classes here, browse again and resave, close, reopen.
  10. Begin a tedious process of replacing lots of stuff in each message.

This basically involves opening broken VIs (in the classes, not the ones that get added outside the class), resolving the conflicts that pop up, ignoring the Browse search dialog (ignore all), then selecting items and choosing the equivalent item from the PPL using Quick-Drop and Ctrl+P to replace. An easily forgotten item is the message priority in Send Blah.vi
Having Context Help open and visible is useful, you're looking for items with the same name, but from the PPL.
When each is done, move it into the library (AF_Messages.lvlib)

 

I did them in the following order:
Time-Delayed Send Message (previously done).
Batch Msg (in Do.vi, you need the Message.lvclass:Do.vi in the loop. I couldn't get the Batch Msg class to replace at first, needed to go to class properties and fix inheritance)
Reply Msg
Report Error Msg (same issue as Batch with the class constant and control, retried after reload)
Self-Addressed Msg

 

Save all, close, reopen (just to be safe for me, actually it seemed fine at this point).
Only Actor Framework.lvlibp (PPL) and the Error Cluster from Error Code (in vi.lib) should be in Dependencies.


Move the classes out of the virtual folders (optional, but imo looks nicer). Not sure if it adjusts the load paths... I think only directory changes matter (not virtual folders).

AF_Messages.png

 


Add the Packed Library build spec. Make sure to tick the exclusion box (now it matters). Set the destination appropriately (same directory for me, easiest option).


Build.

???
Profit!

 

I had to fiddle with the original Actor Framework library after the first build of the Messages library, I'd accidentally broken some of the source VIs and linked them into the Actor Framework.lvlibp when adjusting the message priorities. So just open the two projects a couple of times and check you can repeatedly build both without problems. If not, figure out where they're mislinked (Why is this item in Dependencies?) and fix those call sites.

 

Finally, copy your backed-up ActorFramework and AFDebug directories back into vi.lib and resources, so that your installation isn't weird. Overwrite the AFDebug stuff (or just remove and replace, whichever).


GCentral
Message 8 of 13
(2,955 Views)