02-14-2019 01:48 PM
Hello,
I am trying to make 2 LabView Vi's detect when a change is made in the other. Here is an example. A and B are the names of the two VI's which are both running. If a true/false button is pressed in A, then B will detect it and switch its button as well. As well, if a button is pressed in B, then A will detect it. All of the examples I have seen use a server/client system for the TCP connections which I have applied and works well, but this only seems to be a one way transfer system and the server can never detect what is happening in the client.
I have attached the attempt I have made in order to detect them, which I can explain a little more about. First the TCP connection is opened the same way any server/client pairs open. The server computer sends a cluster of 5 elements which updates continuously. When a button is pressed in the server (hence the event structure), it is supposed to change the same button on the client computer. As well after the event, it is supposed to be reading the value of the button press in the client VI. Is there an easier way to do this, or a way that acts as a two way road instead of having 2 individual 1 way tunnels?
Thanks!
02-14-2019 02:18 PM - edited 02-14-2019 02:24 PM
TCP is connection based, so it needs to be initiated from one side, but once the connection is established, data can freely flow both ways. Your current code is deadlocked because the event structure prevents it from receiving data. You need more code!
Note that writing to a local variable ("run a step") will not fire any event. Events are mostly for user interactions.
Of course what you can do is use two different connections, one established from each side.
What is your definition of "occasionally". If this is hours, unused connections might get shut down by a TCP timeout mechanism.
You might also look into UDP, which is connectionless.
However, a much better idea would be the use of "network shared variables". No real code needed. 😄
We cannot really debug a picture, so if you want help, please attach the actual VI instead. Where are the terminals? Do you really need all these local variables?
02-14-2019 02:29 PM
Your problem is that the Event Structures are blocking your reading. What I typically do is use a separate loop that handles the TCP connection. That loop can just attempt to read a byte and continue reading if something comes in or let the timeout happen and try again. But for your simple example, you can just throw your reading into the Timeout case of the Event Structure. Have a timeout of something like 50ms on the Event Structure to make sure you are attempting to read often enough.
02-14-2019 02:33 PM
@altenbach wrote:
However, a much better idea would be the use of "network shared variables". No real code needed. 😄
NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO...
In case you didn't know, I DESPISE Network Published Shared Variables (NPSV). Been nothing but headaches for me.
02-14-2019 02:48 PM
@crossrulz wrote:
@altenbach wrote:
However, a much better idea would be the use of "network shared variables". No real code needed. 😄
NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO...
In case you didn't know, I DESPISE Network Published Shared Variables (NPSV). Been nothing but headaches for me.
Do you remember Jim Black?
He was with NI and located in OH.
He warned me early on that I should avoid shared variables.
But back to the topic of this thread.
What you need to do is figure out if you can establish a "Master" somewhere in your grand scheme. Treating both A and B as peers will crate the possibility of a race condition if the two fight over what the state of the buttons should be. A race condition can be nasty to chase down but it is even worse if the race condition is across a network.
But first question is "Are A and B different nodes on a network or two VIs running on the same machine or same process context?"
If you are indeed running across the network and they two VIs have to be peers then you will need to establish some ground rules so they are not fighting over which one gets to set/reset the button. A Semaphore that is served on one of the machines could be used where before changing the shared value, A OR B must first acquire the semaphore before making the change and then release the semaphore after the change is made. When a change is made you should include a mechanism to let the OTHER VI know that the value has changed.
Ben
02-14-2019 02:58 PM
Now if you could avoid making them peers and set-up a Client Server relationship, the Master could keep the "Master Copy" of the data.
In an application developed back in LV 7.1 we needed to control the valves in a factory which routed nasty gas to or from where it was needed. No big deal there BUT... The setting had to be made available to four unique PC each controlling two stations each.
In that case we used a Master PC that had access to all of the I/O and exposed VI Served Action Engines to all of the client PC. When the stations were configured for "remote" mode, the Action Engines that were running on the Master PC but invoked from the clients would dictate what the value of the buttons were. When not in Remote mode the Master PC controlled the buttons and the clients would read the sate of the buttons on the Master PC.
That approach made it dirt simple to expose control to the clients since they were only mirroring the Master PC and submitting requests to the Master PC. The image on the client PC differed only in the which Action Engines each station invoked via VI Server. There was no real logic on the Client side. All fo the logic was handle by the Master PC.
So the answer depends on a lot of things so I should stop rambling now.
Ben
02-14-2019 09:39 PM
How quickly do you want to recipient to react to the message? I've used Network Streams to set up Message Streams between a PC Host and a Real-Time Target. Two channels allowed two-way Messaging (which, I'd estimate, had at most a 100 msec lag time, while two more Streams sent 1000kHz Analog data to the Host (50 samples at a time, i.e. a transfer rate of 20 Hz) and episodic "event" data (such as button presses) when they occurred.
Having two one-way channels means each side only needs one "receiver" and one "sender", a natural Producer/Consumer Design which is pretty (time)-efficient and (because of LabVIEW's parallelism) independent of each other.
Bob Schor
02-19-2019 12:08 PM
Thank you everyone with the help. I have made some progress on the labVIEW VI and think I have a clearer example of what I would like to accomplish. The server and client VI's attached are supposed to continuously read and write what the other boolean is reading. If one gets turned to true, the other should become false and if one gets turned false the other turns false. This way the only time any of the booleans will change is on the user command.
To run the VI's, make sure the ports both read 2055 and the address is localhost. Run the Server, then the Client and try to press the boolean button. The other boolean button should change regardless of which VI is pressed.
When these two VIs are run, they aren't consistently changed to true because they are constantly overriding the mouse click. Does anyone have a way to accomplish this.
Thanks!
02-19-2019 12:25 PM
I haven't tested your code, and can't figure out just by looking at it what you are trying to do, but I think I can help with "over-riding the mouse click". Go to the Boolean on the Front Panel, right-click it, and look at "Mechanical Action" (there are six of them). You might try "Switch when released".
Bob Schor
02-19-2019 02:05 PM - edited 02-19-2019 02:05 PM
The problem is you are constantly updating client and server with the value of the controls (with a race condition mixed in on the client side). You should only send an update when the value has changed.