LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Creating a TCP connection / refnum in a subvi

Solved!
Go to solution

Hello all,

 

First, I apologize if my title is ambiguous or unclear, I am still trying my best to understand LabView's vernacular and best practices (coming from a background in Python). 

 

I have a GUI that I am trying to implement using a producer / consumer framework, and one of the devices controlled by this GUI is a high voltage power supply (HVPS) that communicates via TCP. My goal is to present an "Enable" toggle switch to the user that when pressed would initialize the TCP connection and store a reference to the connection for future commands. I have all of my controls for the power supply defined in a typedef, and it seems like it would make sense for me to add the TCP connection reference to that typedef....but I cannot figure out how I would take the output of the TCP Open command called in a subvi and use it to update the value of the TCP connection for the typedef instance (is that the correct language?) in the main Vi.

 

Hopefully some photos will help - attached are images of the main Vi, the subvi, and the typedef for the input cluster. Any tips, recommendations, or "You definitely shouldn't do it that way" would be greatly appreciated. 

 

Cheers,

 

Ian

Download All
0 Kudos
Message 1 of 10
(674 Views)

Edit: attached photos to the main post. 

0 Kudos
Message 2 of 10
(671 Views)

I would recommend using JKI State Machine or Queued Message Handler

They both have a shift register cluster that allows you to store runtime data like the TCP connection refnum.

-------------------------------------------------------
Applications Engineer | TME Systems
https://tmesystems.net/
-------------------------------------------------------
https://github.com/ZhiYang-Ong
Message 3 of 10
(634 Views)

Thanks ZYOng - I was not familiar with the JKI State Machine (or the third party LabView tool ecosystem, for that matter)... I'll have to do some more research and see what functionality they offer. 

 

Second, what I have implemented so far is a queued message handler, no? If I understand what you are saying, you would initialize the TCP connection in the main vi and then use the shift register to reference it in future loop iterations. I can see how it would work but I feel like there must be a "cleaner" solution that would allow me to move my initialization into the subvi. I know labview is an opinionated framework in many ways, so maybe I am approaching the problem in the wrong way. 

 

Cheers,

 

Ian

0 Kudos
Message 4 of 10
(616 Views)

LabVIEW is a full blown programming environment which allows you to do pretty much any programming pattern that you would like. As such there are of course umpteen ways to solve a particular problem. I would not call that opiniated however, multifaceted maybe.

 

What you try to do could be solved with a LabVIEW Intelligent Global, a LabVIEW 2 style global on steroids. It works fairly well and was something that I did use a lot 25 years ago as a very powerful tool. However it has many limitations and maintenance gets very costly as you start to add new functionality to you "Intelligent Global".

 

What you show is the beginning of a queued message handler but really just that. It is not prepared to handle multiple actions, but instead multiple devices (HVPS) for now.

 

Instead you want to create one message consumer loop per device and provide an action to the message such as open, enable, disable, set SP, read CP, close. You send the open message somewhere after your application has initialized with the network device address as parameter, then send the according message with the correct parameters, and eventually the close message before quitting your application. Then you can store the network refnum created in the open handler into a local shift register in your message consumer loop.

Once you got that somehow working you put the entire message consumer loop into a subVI and just put that on your main diagram. If you want to go advanced you can also instantiate that subVI dynamically and in that way create multiple clones of your device. Once you head in this direction you will most likely want to look into according well designed queued messages handler frameworks such as DQMH, or if you want to really go nuclear all the way into the Actor Framework.

 

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 5 of 10
(583 Views)

Hello Rolf,

 

Thank you for your reply. You are right that opinionated is probably not the right word, I guess it's more like there are lots of footguns (for me, at least!) as a newcomer and so I am trying to avoid "hacking" something together and trying to find a solution that will be easy to maintain and scale over time. 

 

I have a few questions on your comments about my queued message handler. 

 

First, when you say "It is not prepared to handle multiple actions, but instead multiple devices (HVPS) for now", I'm not sure that I understand what you mean. In the top level Vi, my UI message producer loop responds to all events that are related to GUI operation. In the message producer loop, I make a new event object with fields for the device that should respond to the event (target) and the text label of the control that triggered the event. In my message consumer loop, I dequeue the elements and pass them to the relevant subvi as determined by the target field in the event object. The subvi's have a case selector for the text label and take whatever action is necessary for that particular event. So the top level Vi creates the events and dispatches them to the correct subvi, and the subvi's determine what action to take for a given event. 

 

I'm having a hard time envisioning how the program would look if each device has its own message consumer loop. I can imagine moving the loop into the subvi and using the shift register to hold the TCP connection reference, but I am not as clear on how things would look in the main vi. How does a device know if it should be the consumer loop to handle an event? If I have a single event queue and both my HVPS and some other, unique subsystem (say, a microwave generator) are dequeuing elements from the queue, how would I make sure that the HVPS consumer is only dequeuing HVPS events? I suppose I could have unique queues, but then I need multiple message producer loops as well. 

 

I will try to fiddle with moving the consumer loops into the subvis and see if I can get a better idea of how that would work, thank you for your response. 

 

0 Kudos
Message 6 of 10
(565 Views)

I meant that your "Target" element specifies the device to operate on, the Event specifies the "Command type" and the parameters is then IMPLICITLY implied by passing the actual control terminal to the subVI. This is very suboptimal.

Typically you do ABSOLUTELY NOT want to couple the UI (your control labels) that tightly to your execution logic. In programming the UI should be a separate from the logic as possible (which the JKI state machine for instance gives you some levers to do). With the JKI state machine you should never directly execute anything but basic UI operations such as enabling or disabling other controls etc, in the actual event structure cases but always add an explicit event to the internal event queue to execute the actual logic in. And if you happen to do any device interaction that can potentially take some time and needs to wait on something in the device, that even includes things like saving large amounts of data to disk, this should usually placed in its separate event consumer loop and controlled through messages send through an explicit message queue.

 

You might want to include your Target in the message if you absolutely insist, but in my opinion that is making things just more complicated. It's more clear to use separate message queues for each device with each their own message consumer loop. In your case you only have one device anyhow so far. If you eventually add another you can easily add another message queue for that too and accordingly an message consumer loop. Normally each message queue needs its own message consumer loop to keep things easy to manage. And if you ever start to have more than two or three devices you should likely look into a more dynamic message handler framework such as DQMH.

 

Basically your message could drop the Target, and instead contain a Command that specifies the actual control you operate on. And I would NOT pass the control label text as command but an explicit Enum. Then you can add a Parameter in form of a variant. Because even your Enable event has actually a parameter, namely the boolean state of the Enable button. Or do you not want to be able to disable the device when you click that button again?

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 7 of 10
(524 Views)

Rolf, thank you for your response.

 

I can understand how coupling the control labels to the business logic is suboptimal and will need to investigate variants to figure out how to pass the relevant data directly through the message. 

 

I have a total of ~5-7 unique devices that need to be controlled by this GUI, so it seems like investigating the DQMH framework is probably worthwhile at this point. Alternatively, I was playing around with creating unique queues and message handling loops for each device and ended up with messaging handling loops with their own event cases inside - is this a design pattern that you have used or see an issue with? My reasoning is that each subvi can be a standalone program that handles all of the events relating to the device's operation, and then the message queues can be used to pass information between devices and the main GUI.

 

multiple_queues.png 

Also, slightly off topic, but when I was attempting to bundle the queues by name, I had a hard time creating the input cluster with the references to Device1 and Device2. To create them I had to create a control for the queues, then move the references into the cluster, then delete the controls from the front panel. Is there a simpler way to create the input cluster for the bundle by name function?

 

Cheers,

 

Ian

0 Kudos
Message 8 of 10
(503 Views)
Solution
Accepted by adelphi_labview

Here's one quick suggestion.

Yamaeda_0-1754477925810.png

 

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 9 of 10
(433 Views)

Yamaeda, 

 

Thank you for your suggestion, I think it will work well for my setup! 

 

Ian

0 Kudos
Message 10 of 10
(320 Views)