LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Easiest Generic Data Transmit Method to External Programs

Hello All,

I'm looking to send data from 1 Transmit VI to N Receiver programs (Python, LabVIEW, and C++). I believe a UDP connection based on the multicast example library is what I'm looking for. However, I wanted to both make sure and get an in-forumed opinion 🙂

My requirements/scope:

1) My Main VI collects data, logs the majority of it to disk and keeps the most recent line in memory as a representative state.

2) The Main VI Transmits this state (via flattened string, likely JSON or XML) to a number of listeners that can be written by other users with limited knowledge of / access to my source code.

3) Update Rate on the order of 10's to 100's of ms

4) All programs are running on the same computer.

 

My Thoughts:

1) Integrate UDP multicast example into my Main.vi

2) Make a config file to set UDP address for Main.vi

3) Have Main.vi send to the UDP address every 20 ms

3) Give other developers the UDP address/port, system description, and sample flattened string. 

 

My neophyte networking questions (" " 's are for words I've heard but may be using wrong):

1) Should I be using UDP?

    I understand that I might instead want "data sockets"? or "named pipes"?

 

2) I vaguely understand that "networks," don't like programs broadcasting data?

    Would it be better to have the Main.vi listen for requests for data and respond to them? 

0 Kudos
Message 1 of 7
(1,179 Views)

Do you want to share state (current value) or data (FIFO).

 

That's a big difference.

 

UDP doesn't guarantee that data arrived. There's no way to know if packages, although a counter could inform clients that a package was lost.

 

A TCP\IP listener spawning for each connecting application would (also) work. With TCP\IP it would be easier to make 2 way communication.  This might make the design of connecting applications easier. A Python application can simply connect, and request a value (state?) when needed. Where a UDP construction would require continuous monitoring. Not sure how easy that is in Python (it could be an OoTB feature).

0 Kudos
Message 2 of 7
(1,156 Views)

We want to share a representative state (current value with an acceptable delay)

 

TCP sounds like it might be the way to go over UDP then. Are there examples for how to set up a listener to spawn for each application?

 

The objective would be to have (effectively) a 1:N broadcast. It sounds like TCP is set up for an N:1 call/response.

0 Kudos
Message 3 of 7
(1,142 Views)

If you really are looking for the simplest method.   Just write to file from the producer and open it for read access in the other applications.   Rock-Stupid simple! Easy to implement easy to maintain, easy to debug and test, simple regression. Don't overthink the OS.


"Should be" isn't "Is" -Jay
0 Kudos
Message 4 of 7
(1,131 Views)

@JScherer wrote:

The objective would be to have (effectively) a 1:N broadcast. It sounds like TCP is set up for an N:1 call/response.


You probably actually want to use UDP since it is a broadcast instead of point-to-point transmission protocol.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 5 of 7
(1,124 Views)

@JScherer wrote:

TCP sounds like it might be the way to go over UDP then. Are there examples for how to set up a listener to spawn for each application?


I don't think there are examples shipped with LabVIEW.

 

It's not that hard though, just a mix of the examples that are there, and VI server.

 

Simply make a listener, and if it gets a connection, start a dynamic VI with that connection. The listener continues waiting for a new connection.

 

UPD would definitely be easier from the LabVIEW side. I just wander how that works if you have a simple, single thread, client application. If it's a slow sequence, will it miss messages? Or would the messages be queued up? I don't know...

 

A shared variable would also work, as IIRC you can read them with a HTTP Get.

0 Kudos
Message 6 of 7
(1,092 Views)

If you really want to do broadcasts you definitely want to look into UDP. That is THE broadcast solution on IP based networks.

As to your terminology about listeners if you go the TCP route, it is a bit off in terms of how TCP/IP works.

 

There is usually always only one listener per process that sits and waits for connection requests. It can then handle those requests itself one by one but that limits it to only serve one connection at any moment. Instead it can also spawn a thread or even process and hand the request to it. This secondary thread is not a listener in terms of TCP/IP but simply another TCP/IP connection endpoint. The only difference is that its connection was not gotten by calling connect() but as return value from the listen() call. The actual code to handle this connection is using read() and write() exactly the same as with any other connection. Most of the times there is one difference though: This connection handler usually is waiting for command requests from the other side to act on, by checking for incoming data. The typical client on the other side is rather sending command requests and then waiting for a response, so the sequence of read() and write() is almost always reversed between the connection handler that was created from a listen() connection and the connection handler that initiated the connection with connect().

 

LabVIEW does have an example showing how to handle multiple concurrent incoming connections as a TCP/IP listener. It's not a full featured example as it tries to be simple and just show the principle but it is a good starting point.

 

<LabVIEW xxxx>\examples\Data Communication\Protocols\TCP\TCP Multiple Connections

 

This can be expanded to separate the listen loop and the connection handling into their own separate loops and passing the new connection refnum from the listener to the handler through a queue. But since the active connections are all handled sequentially in the handler loop this won't scale well for many concurrent connections.

 

Or you can even go full fancy and spawn a new VI clone for each incoming connection through "Start Asynchronous Call" to handle the connection. This scales better but poses a higher resource load on the system as you need to spawn new VI clones for every incoming connection and it also requires a more elaborate messaging structure so your main app has some control over the spawned connection handlers and can shut them down if it needs to. 

Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 7
(1,085 Views)