How do I send data from LabView to Python and get a result back?
One other solution is using the smart messaging library ZeroMQ, which comes with a lot of bindings, almost for all major languages.
For the Python/Labview case there is a nice demo project on sourceforge:
Python-LabVIEW Communication
Client-side ~LabVIEW
+
Server-side part (example)
#-----------------------------------------# INFRASTRUCTURE for communication
context = zmq.Context() # I/O-DAEMON CONTEXT
socket = context.socket(zmq.REP) # ARCHETYPE for a Smart Messaging
socket.bind( "tcp://127.0.0.1:5555" ) # PORT ready for LabView to .connect()
#-----------------------------------------# TRANSPORT-CLASS-es {ipc|tcp|+..}
while True: # LOOP & WAIT FOR REQ-calls
# # Wait for request from client
message = socket.recv()
print("Received request: %s" % message )
try:
r = eval( message )
print(r )
socket.send(bytearray(str( r ),
'utf-8' )) # send returned value as bytearry to client
except NameError:
socket.send( b"Unknown command" )
except:
socket.send( b"Unknown error" )
LabView allows you to write extensions in several languages, the primary technique these days is to use a network connection. Native language toolkits that run inside the labview process itself are avoided.
It seems there is a Python Labview toolkit here but it no longer works.
Use a socket server and socket client to talk between Labview and python. (Most cross-platform solution, and now you don't have to have your python and labview running on the same PC, or in the same process).
Unfortunately a sample is beyond me at the moment as I don't have labview installed, but I have done ole automation based integrations from LabView to dozens of apps in two or three languages, but that was many years ago. These days I would use the network socket technique.
LabVIEW 2018 now offers a "native" solution to calling Python code from LabVIEW with "sending data" back and forth:
The Connectivity palette includes the new Python subpalette, which you can use to call Python code from LabVIEW code. The Python palette includes the following functions:
Open Python Session — Opens a Python session with a specific version of Python.
Python Node — Calls a Python function directly.
Close Python Session — Closes a Python session.
Note You must install Python 2.7 or 3.6 to use the LabVIEW Python functions.
Although unsupported versions might work with the LabVIEW Python functions, NI recommends using supported versions of Python only.
Reference: LabVIEW 2018 Features and Changes
The Python Node is provided with the module path, function name, input parameters, and the expected data type of the return value. These inputs and output support a number of basic data types: numerics, (multi-dimensional) arrays, strings, clusters; with automatic conversion to corresponding data types, i.e. LabVIEW arrays are converted to Python lists, and clusters to tuples (and vice versa for the return value).
I was using stdio communication with a Python process for a while and recently noticed Python for .Net ( http://pythonnet.github.io/ ) which works for me.
Just copy the .dll in your LabVIEW project, create .Net constructors, and using the LabVIEW .Net you can quickly figure out how to use this library, which basically provides you with the unmanaged Python shared library, wrapped with .Net goodness.
Server side with Python
import socket
server = socket.socket(2,1)
server.bind(('localhost',2000))
server.listen(1)
while True :
(conn,addr) = server.accept()
command = conn.recv(4)
print (command)
if 'INIT' in str(command):
conn.sendall(b'INIT-DONE')
elif 'PLAY' in str(command):
conn.sendall(b'PLAY-DONE')
elif 'QUIT' in str(command):
conn.sendall(b'QUIT-DONE')
break
server.close()
Labview Client Side
There is a new Python/LabVIEW connector out, built mostly by yours truly, called TestScript. It's a free, source-released Python/LabVIEW connector that is fully bidirectional. You can control LabVIEW from within a Python script, and you can call Python scripts from LabVIEW. It ships with several examples illustrating how you can send data from LabVIEW to Python and get a result back. In particular, the Simple Scripting Example - Add on Python Side.vi shows how TestScript accomplishes what you need.
Enjoy!
Python-LabVIEW-Interface (PyLVi) is an open-source project based on the ZeroMQ library to call Python functions and read the results back to LabVIEW.
It supports call of class methods and properties, and can handle structured datatypes (e.g. Python dictionaries are mapped to LabVIEW clusters) as well as numpy arrays.
You can try this: https://forums.ni.com/t5/LabVIEW-APIs-Documents/Open-Python-Interface/ta-p/3612981
Its an Open Python Interface toolkit for LabVIEW.
Here is a good quick solution but kind of unelegant. Just use a text file that both labview and python can read/write from. Labview writes commands to text file and python waits until a command is read or vice versa. you can have a read text file and a write text file at the same time. However this is a slower solution as it takes time to read and write.
Related
I have a large Pandas DataFrame in Python that I would like to access in a Julia program (as a Julia DataFrames.DataFrame object). As I would like to avoid writing to disk for each file send from Python to Julia, it seems as though storing the DataFrame in an Apache Arrow/Feather file in a buffer and sending that via TCP from python to Julia is ideal.
I have tried extensively but cannot figure out how to
Write Apache Arrow/Feather files to memory (not storage)
Send them over TCP from python
Access them from the TCP port in Julia
Thanks for your help.
Hmmm, good question. I'm not sure using a TCP socket is necessarily the easiest, since you need one end to be the "server" socket and the other to be the client. So typically the TCP flow is: 1) server binds and listens to a port, 2) server calls to "accept" a new connection, 3) client calls "connect" on the port to initialize connection, 4) once server accepts, the connection is established, then server/client can write data to each other over connected socket.
I've had success doing something similar to what you've described by using mmapped files, though maybe you have a hard requirement to not touch disk at all. This works nicely though because both the python and Julia processes just "share" the mmapped file.
Another approach you could check out is what I setup to do "round trip" testing in the Arrow.jl Julia package: https://github.com/apache/arrow-julia/blob/main/test/pyarrow_roundtrip.jl. It's setup to use PyCall.jl from Julia to share the bytes between python and Julia.
Hope that helps!
How do I make a TCP connection between LabVIEW server and Python client where (data) angles from Python are to be transferred to LabVIEW?
To answer your "how do I do this" question. First, start from the basics. Do not start with a more complicated program that has some error as you showed in robotic wrist mimicking - Kinect as a Sensor(Python Coded) to a labview Simulation using TCP.
With almost any LabVIEW problem, first check the LabVIEW examples in the Example Finder. Start with the LabVIEW "Simple Data Client.vi" that can be found in the LabVIEW examples, accessible via Help->LabVIEW Examples-> (search on tcp/ip server). For reference here also the code snippet:
From the Python side, just send a simple number or list of numbers. If this is working then you know you have set up your server and client correctly. Until that is working, you should not worry about more complicated code. After the communication working then you can expand your code.
In case it is not working, ask a very specific question about the part that is not working. Include any error codes and describe what you did, what the responses of the program were, and what responses you expected.
I am running the following code and it terminates with the following message. Please refer to the screenshot.
import zmq
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect('tcp://0.0.0.0:5555')
zmq is the Python binding for ØMQ. There are links for Python.exe stopped working, however the solutions appear to be problem specific. Please suggest the way forward. Thanks in advance.
Using ZeroMQ inside quasi-cluster-enabled clients requires more care:
Be it iPython, Jupyter or even Spyder, these python WYSIWYG- or IDE-frontends use ZeroMQ on their own internally, and quite intensively, to communicate between the GUI in "terminal" or the "notebook" and the backend python-engine(s).
So a double care is needed. Every port-mapping is even more delicate.
As one might read, O/S reports that the problems are on the backend-engine, that went mad, not on the GUI frontend.
Anyway,rather do not use bewildered constructors like tcp://0.0.0.0:<port#> or tcp://*:<port#>
Documentation explicitly advises another approach how to safely .connect() to localhost ( sure, that port was still free from iPython / Jupyter / Spyder own use ):
>>> print zmq.Socket.connect.__doc__
s.connect(addr)
Connect to a remote 0MQ socket.
Parameters
----------
addr : str
The address string. This has the form 'protocol://interface:port',
for example 'tcp://127.0.0.1:5555'. Protocols supported are
tcp, upd, pgm, inproc and ipc. If the address is unicode, it is
encoded to utf-8 first.
>>>
I'm trying to set up a simple client to server interface for calling functions/programs on the server. A client will send a simple command to the server listening for such commands. Once the server receives a command from the client it will execute the following function or program on the server. I have looked into a simple TCP server receiving a text string and parsing that string then executing the a function or external program. I have read into using XML-RPC implemented with a twisted server as well.
What I'm asking is which would be the easiest to set up or are there any other ways to easily do this task?
Thanks.
There is a great tutorial for twisted that will do just fine as a teaching tool (and guide you by hand in writing a basic server/client services). Have a go at it http://twistedmatrix.com/documents/current/core/howto/tutorial/ what you will probably want to do is parse received info and act accordingly.
If it is appliable in your case, maybe you can use full-featured system for async/remote job execution like Celery?
There are more than one way to achieve your requirement ach with some pros and cons:
Python Low Level Sockets
Using Standard python socket libraries and cliet server architecture
Connecting to Server via protocols like Telnet/SSh and then triggering some code.
Using Python libraries like Telnet/ssh or Subprocess.
XML-RPC
Sending a XMP RPC request as described here http://docs.python.org/2/library/xmlrpclib.html
In my opinion easiest method to achieve remote method triggering is via Python Subprocess Module. I generally use following kind of syntax for my general purposes.
import subprocess
ret = subprocess.call(["ssh", "user#host", "program"]);
# or, with stderr:
prog = subprocess.Popen(["ssh", "user#host", "program"], stderr=subprocess.PIPE)
errdata = prog.communicate()[1]
Hope it helps
My setup is as follows:
Python 2.6 (embedded in commercial app) uses subprocess to launch an external script in (external) python 2.7.
The external script then uses the socket module to send python commands back to embedded python.
The socket is initialized with the following code:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
And I send commands using:
self.sock.send("print ('hello, world!')")
This is working quite well at the moment. I am able to send all the commands I want, and control the program nicely.
My question: how can I request to be sent information back through the socket?
I need to ask the program to give me a list of strings, for example. But I have a hard time grasping how the embedded python would send any data back through my open socket?
Thanks!
You can always have a bidirectional socket communication.
When the external python send something, always send in a tuple where one of the arguments can specify that you are asking for something.
Let me give an example,
Setup a bidirectional socket communication (Simple client-server model- synchronous or asynchronous depends on what your project/app requires.)
2.7 sends a tuple like this -
(<command>, 1)
The 1 indicating that you want the output of the command that you sent ( which you said is working, would be sent back to 2.7.
So, when 2.6 receives the tuple, the 0th position of the tuple always represents the command it is trying to send, and the 1st position represents the send back argument.
Using a simple if-else condition, you can check if it is 1, then send back the result to 2.7 - otherwise not.
Fairly simple logic.