Jump to content

PaulL

Members
  • Posts

    544
  • Joined

  • Last visited

  • Days Won

    17

Posts posted by PaulL

  1. I am designing an application upfront and am considering what is the BEST way to go….

    I haven't really worked too much on the solution yet but I have encountered similar cases before and I think it is a question with pretty general interest, so here goes....

    This application (which uses the DSC Module, by the way) will control ventilation doors (not important). Each door (at the moment) has exactly the same functionality, so…

    I designed a parent class (VentilationDoor) with child classes for each particular door. (Right now this class pretty much stores data about each door.)

    I designed a DoorController class and a UI.

    Now my current thinking is to put the child objects in an array and feed the array into a for loop that calls the DoorController and UI high-level methods (using VI server—or alternately deploying these as OPC servers—to get these to run in parallel for the different doors), resulting in an instantiation of DoorController and the UI for each object. Other solutions are possible--it may be a matter of picking the best design pattern. How would you do it? :)

    (I have attached a PDF of my current design class diagram but that is probably peripheral.)

    Paul

  2. For the record, NI support found the following:

    1) The problem only occurs if the method that calls the DataSocket function is wired with dynamic terminals. Rewiring these terminals as nondynamic (if possible) gets around the problem.

    If 1) is not possible (e.g., dynamic terminals are necessary) then

    2) use a wrapper VI around the DataSocket library VI. (This is a variation on 1 since the wrapper won't need dynamic terminals.)

    I implemented such wrappers with the same connector panes as far as possible as the DataSocket library VIs (I had to use variants as necessary, with a type conversion on the output of the read wrapper) and so far this has worked for me....

  3. I'm certainly no expert in software engineering but recently I've read:

    UML Distilled (3d ed.) by Martin Fowler. This book teaches how to model in the Unified Modeling Language (UML).

    I still had many questions, so to find out how UML fits in the design process (why and when to create UML artifacts, their relationship to Object-Oriented Analysis and Design, design patterns and principles, and the software design process itself--particularly the Unified Process) I read--and highly recommend--Applying UML and Patterns (3d ed.) by Craig Larman. This book offered the most complete picture I have found thus far.

    I found An Introduction to Object-Oriented Programming (3d ed. as well) by Timothy Budd helpful for wrapping my mind around some OOP concepts and challenges.

    Finally, More About Software Requirements: Thorny Issues and Practical Advice (Karl Wiegers) offered some useful guidelines on writing requirements effectively.

    I also read A Software Engineering Approach to LabVIEW (Conway and Watts) a while ago. It prompted me to start thinking about better software design principles. I think some of the books above have helped me to think still more clearly about effective software design, with an obvious emphasis on OOA/D.

    If I had to recommend just one of these to read it would definitely be Larman's book.

  4. QUOTE(Aristos Queue @ Jul 28 2007, 04:06 PM)

    I believe that you are meant to open and run

    ExecutionControl.lvclass:controlMainFlow.vi

    That is the main VI.

    Yes, that's the one! Sorry I didn't make that clear.

    I tried converting the shared variable name to text first (see attached) but this solution exhibits the same behavior. (A while back I encountered troubles using shared variable nodes inside classes, which is why I am using the DataSocket protocol anyway.)

  5. Can anyone suggestion suggest a cause, workaround, or method to diagnose the following problem?

    1) If I open LabVIEW and then my top-level VI and run the application, LabVIEW always crashes (a Windows error screen appears!) at an instance of a call to "DataSocket Open."

    2) If, however, after I open my top-level VI, force a recompile of the VIs in the hierarchy, and then run the application, everything works fine. (Note that if I then save all the files and then go back to method 1 LabVIEW still crashes.)

    A couple notes:

    The inputs to the DataSocket Open are the mode (Write), an error cluster, and, more importantly, a shared variable that comes from the private data of a LVOOP class. (A class method 'initialize' writes the shared variable to the class.)

    Broadly, the application flow to the point of the crash is initialize...deploy shared variable libraries...subscribe to shared variable events...open DataSocket connections to shared variables--and that is where the crash occurs (if I don't force a recompile).

    OK, I just created and attached a very simple example that exhibits the same crash behavior. (I didn't programmatically deploy the variable library in this example, but that isn't relevant.)

  6. QUOTE(Gavin Burnell @ Jul 19 2007, 10:35 AM)

    Uhhh, doesn't the application instance id always end up being set to the FF FF FF FF special value in your version ?

    Oh, I see! The type is always "LabVIEW Object." I missed that. You described that in a previous post... Returning to variants would solve this but leave the wiring probem.... XNodes, huh? I'm not sure what to do about this one....

  7. QUOTE(Gavin Burnell @ Jul 18 2007, 01:28 PM)

    I've edited my original post with a new version of my class namer tool that extracts more information from the class reference and (I think) now includes enough to properly test the class identity.

    My search algorithm works fine now but there is the minor issue--well, minor for my purposes--that one can wire pretty much anything to it (although Gavin's code will filter this at run-time) since I left the input as variant (and array of variant). Is there a "LabVIEW object" type that I can use here? Hmmm....Gavin, I see you have an object called "LV Class In" on your diagram. Is this a specific class or did you find a generic class? If so, where did you get it? I don't see such a thing....

  8. Gavin and Tomi,

    Your (similar) solutions look like just what I was seeking. Thanks! :thumbup:

    In particular, using the variant input means I can write a general search method rather than a custom method for each class (which I had to do--well, or else copy a large code snippet) with the downcast check method.

    Anyway, I wrote a class-specific search 1D array method. I'm still testing it, but so far so good. I need to look closer at the parsing of the type string and data string you did, Gavin, to make sure I understand it.

  9. QUOTE(Tomi Maila @ Jul 17 2007, 12:18 PM)

    Classes that use OpenG Class Templates for LabVIEW Object-Oriented Programming can take advantage of OpenG Object method "MatchRuntimeType". This particular method allows users to easily check if the object is of some known type and select action based on the matched type. This functionality is called Pattern Matching in object-oriented programming.

    OK, I downloaded the VIPM, the OpenG Class Templates, and Endevo's GDS community edition. (It's all pretty impressive, by the way.) I configured OpenG100 as the class provider. I don't see (nor can the Function pallete search find) the "Match Runtime Type" function/method. Where do I find it?

    QUOTE(Aristos Queue @ Jul 18 2007, 11:15 AM)

    Pop up on the Flatten To String node and select the
    LV
    7.x compatibility mode. This gives causes the node to add a type descriptor output. You can then compare the type descriptors for equality. Note, this allows to test for *equality* ... it won't help if you're looking for "this class or any child of this class."

    OK, I retrieved the type string from the 7.x version, which returns an array. I need to compare some of the elements in the type string array, not all, though. (If I include all the comparison shows a mismatch as before.) How do I know which elements are necessary and sufficient?

  10. Well, there is another topic on this board (http://forums.lavag.org/Finding-out-LabVOO...lass-t5220.html) that in part describes the class coding and the differences between the root LabVIEW Object class and developer-created classes. I'm not sure there's quite enough information there to figure out how to do the comparison reliably (not just by class name, but perhaps application instance and certainly by namespace as well).

    By the way, it is not sufficient just to compare the "data string" output of "Flatten To String" because the data is encoded in the data string. (We have the same problem the built-in Search 1D Array method has.) We have to extract the information we need from the data string (as Gavin has done in his solution). Is the class name the only information we need for the comparison?

    I looked for more information on LAVA but haven't found it yet....

  11. How can I programmatically compare objects (without comparing the object data)?

    In my case I have one class in which I initialize a number of objects and insert these into an array. The array is of type "Parameter" class and the elements are objects corresponding to child classes of "Parameter" representing individual parameters (e.g., AirTemperature, BarometricPressure, etc.). This allows me to autoindex the array in a for loop when I want to run a common method (well, usually with dynamic override methods) for each parameter.

    Sometimes, however, I need to retrieve a specific parameter from the array. I tried using an object constant as the search element input in "Search 1D Array" and this works if I have not initialized or otherwise altered the array objects. If, on the other hand, I have initialized the objects or otherwise changed the data in the objects the comparison method within "Search 1D Array" does not find a match. (The comparison method doesn't compare what I want it to compare.)

    How do I compare objects without comparing their data?

  12. For the record, I was able to find a solution for my UI that uses shared PSP shared variables and maintains inheritance principles. I can write to the PSP shared variables using a DataSocket connection. I can specify the connection with a DataSocket Open inside the UI VI. This way I can use the same parent VI (no dynamic terminals) for my UI, since I identify the shared variables inside the UI VI from the class data and I write to these shared variables using a DataSocket Write. This methodology allows the UI VIs to use inheritance in the project. :thumbup:

    I have attached my latest example (still very much a work in progress and not pretty since I'm still testing some basic ideas). (The next thing to do is to add functionality in the UI to subscribe to shared variable events arising from measurements elsewhere, which simply requires applying the methods here in "reverse"....)

    I'm much happier now....

    Paul

  13. Actually, Tomi, your response was helpful to me. I understood how dynamic terminals affect which VI to call, but I was confused about how they affect which data to use (data scope) if the method has no override. (It's simple enough now that I understand it.) I did what you suggested and it worked, of course, and I applied the same fix to some of the methods in my real project. I'm very happy about that--thanks! :worship:

    The remaining question (where this all started for me, actually) is using a UI with controls that link to shared variables (network publish-subscribe variables with the DSC module). I want to use the same UI for each child class but have the controls link to the appropriate shared variables for the particular UI. I have tried two solutions:

    1) Creating dynamic dispatch VIs of the UI where I bind the controls manually in the override versions. (This works but there is no inheritance.) This solution is attached. (ECS level.vi is the top-level VI and the FanUI.vis are the VIs in question.)

    2) Changing the links from the controls to the shared variables at run-time. I would like to pass the shared variable names to the VI and change the links at run-time, but this (via an invoke node "DataBinding.Bind to Network Path") is only available when the VI is in edit mode, requiring a call from VI server (a workable but messy solution).

    I would like to use a variation of method 1 somehow that retains some level of inheritance but I haven't figured out how to do this.

    Paul

  14. I am attempting to use LVOOP for the first time in an application and I have encountered a no-doubt common problem (I see direct and indirect references to the problem in this forum) but I am unsure of the best solution that allows for inheritance consistent with LVOOP design goals.

    Problem: I want to instantiate several children of a single parent simultaneously. Any override methods that call the parent methods (the default when creating an override VI) cannot execute simultaneously since dynamic VIs cannot be reentrant. Some methods I would very much like the children to inherit (UIs, event response methods, time-critical methods) require parallel execution. How can I execute these methods in parallel while maintaining inheritance in the current LVOOP implementation?

    (Not that it's necessary, but the "CreateGiftListWithLoopAndDelayOOP.vi"—where I have inserted a delay to simulate a function that requires a long time to execute—illustrates an example, admittedly somewhat artificial, of the problem, certainly not how one would in practice code it!)

×
×
  • Create New...

Important Information

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