LabView interface for TACO - V1.5
A.Götz
14 June 2000
This document describes the LabView interface to TACO control systems.
It describes the DSAPI client interface and how to write TACO device servers
in the LabView graphical programming language G.
In order to get started you need access to the following tools :
- LabView on Unix (Linux, HP-UX or Solaris)
- the LabView-TACO shared libraries lv_dsapi.so and lv_dsclass.so (only needed
if you plan to write a device server in TACO) in your shared library path ($LD_LIBRARY_PATH
for Linux/Solaris and $SHLIB_PATH for HP-UX)
- start LabView (normally by typing labview) and open one of the example
VI's or wire your own following the instructions in this document.
2.1 Clients
The following shared library calls have been implemented to interface TACO
clients to LabView :
- lv_dev_putget() - will execute a command on a device, one input and output
argument is l passed, an error code is returned and a status. The call has
the following calling syntax :
lv_dev_putget (char *name, char *cmd, void
*argin, void *argout, long *error)
name : device name e.g. "id11/oregon/1"
(passed as C string type)
cmd : command to execute e.g. "DevMoveRelative" (passed
as C string type)
argin : input argument e.g. array of floats (passed as "Adapt
to Type" type, this means the G program has to wire the correct input type expected
by the command to the input argument e.g. if a double array is expected the
LabView program has to provide a double array as input, failure to do so can
result in a core dump of the LabView program ! NOTE: the input has to be wired
even it is not used to a dummy type of the correct type; this is because LabView
does not differentiate between not used input types when calling library functions
and will not allow the program to run if an input is not wired - the RUN arrow
is broken)
argout: output argument e.g. array of floats (passed as "Adapt to
Type" type, see text above for advice on how to use this type. NOTE: the input
has to be wired even it is an output to a dummy type of the correct type; this
is because LabView does not differentiate between output only types when calling
library functions and will not allow the program to run if an input is not
wired - the RUN arrow is broken)
error : output error if any (passed as pointer
to 32 bit integer. See NOTE above for wiring the output error)
returns : a
32 bit integer indicating the status of the command (0 = OK, -1 = NOT OK)
NOTE
: refer to section on types to know which are supported for argin and argout
- lv_dc_devget() - will retrieve the result of a command on a device from
the data collector (the TACO data cache), one output argument is passed, an
error code is returned and a status. The call has the following calling syntax
:
lv_dc_devget (char *name, char *cmd, void *argout, long *error)
name :
device name e.g. "sr/d-ct/1" (passed as C string type)
cmd : command to execute
e.g. "DevReadSigValues" (passed as C string type)
argout: output argument e.g.
array of floats (passed as "Adapt to Type" type, see text above for advice on
how to use this type. NOTE: the input has to be wired even it is an output
to a dummy type of the correct type; this is because LabView does not differentiate
between output only types when calling library functions and will not allow
the program to run if an input is not wired - the RUN arrow is broken)
error
: output error if any (passed as pointer to 32 bit integer. See NOTE above
for wiring the output error)
returns : a 32 bit integer indicating the status
of the command (0 = OK, -1 = NOT OK)
NOTE : refer to section on types to know
which are supported for argin and argout
- lv_dev_protocol() - change the RPC protocol on a device to TCP or UDP.
NOTE: the default is UDP. Changing to TCP will make client connections more
reliable and allow correct error detection (e.g. server down error). The call
has the following syntax :
lv_dev_protocol(char *name, char*protocol, long
*error);
name : name of device e.g. "id11/oregon/1" (passed as C string type)
protocol
: RPC protocol e.g. "tcp" or "udp" (passed as C string type)
error : error if
any (passed a pointer to 32 bit integer)
- lv_dev_timeout() - change RPC timeout on a device. The call has following
syntax :
lv_dev_timeout(char *name, long timeout, long *error);
name : name
of device e.g. "id11/oregon/1" (passed as C string type)
timeout : new timeout
in milliseconds (pass as 32 bit integer)
error : error code if any (passed
as pointer to 32 bit integer)
- lv_dev_free() - close down all connections to a device. This call is useful
for releasing access to devices not used anymore. It closes all open network
connections to the device thereby also saving open file descriptors. The first
call to the device will reimport the device. The call has following syntax
:
lv_dev_free(char *name, long *error);
name : name of device e.g. "id11/oregon/1"
(passed as C string type)
error : error code if any (passed as pointer to
32 bit integer)
- lv_dev_error_str() - return TACO error string corresponding to error_no.
The call has following syntax :
char *lv_dev_error_str( long error_no);
error_no
: error number
- lv_dev_cmd_query() - return the list of commands supported by a device
and their types. This call is mainly useful as info for the LabView programmer
to know what commands and what data types are supported for a device . The
call has following syntax :
long lv_dev_cmd_query(char *device, void* cmd_list,
long *error);
device : the name of the device
cmd_list : list of commands
and their input/output types returned as an array of strings (passed as Adapt
to Type)
error : pointer to error code in case routine fails
- lv_dc_cmd_query() - return the list of commands polled by the data collector
for a device and their types. This call is mainly useful as info for the LabView
programmer to know what commands and what data types are supported for a device
in the data collector. The call has following syntax :
long lv_dc_cmd_query(char
*device, void* cmd_list, long *error);
device : the name of the device
cmd_list
: list of commands and their input/output types returned as an array of strings
(passed as Adapt to Type)
error : pointer to error code in case routine fails
- lv_db_getdevexp() - return the list of exported devices whose names satisfy
the filter. The call has following syntax :
long lv_db_getdevexp(char *filter,
void* device_list, long *error);
device : name filter of format D/M/F where
either of D, F or M can be the wildcard *
device_list : list of device names
returned as an array of strings (passed as Adapt to Type)
error : pointer
to error code in case routine fails
2.2 Servers
It is possible to write TACO device servers in LabView. They work by implementing
a device server loop in a part of the G program which polls the network periodically
(using the lv_ds_cmd_get() call) to see if there are any client requests. Once
a request is detected the LabView program has to execute it and then return
the answer to the client (using the lv_ds_cmd_put()) call. Clients and servers
communicate using the TACO RPC protocol on the network. The TACO devices have
to be defined beforehand in the TACO database. The following shared library
calls have been implemented to write TACO device servers in G :
- lv_ds_init() - create and initialise a LabView TACO device server, to be
called once in a LabView device server before calling lv_ds_cmd_get(). The
call has the following calling syntax :
lv_ds_init(char *server, char*name);
server
: device server executable name e.g. "StressRigds" (passed as C string type)
name
: device server instance/personal name e.g. "id11" (passed as C string type)
- lv_ds_cmd_get() - poll network to see if a client request has arrived,
if yes command returned is non-zero. Can only be called after lv_ds_init()
has been called. The call has the following syntax :
lv_ds_cmd_get(long *command,
void *argin);
command : command received, can be one of DevLVIOStringDevState
(1) takes array of strings as input and returns array of strings as output,
DevLVIODouble (2) takes array of doubles as input and returns array of doubles
as output, DevReadValue (3) returns an array of doubles as output, DevSetValue
(4) takes array of doubles as input, DevState (5) and DevStatus (6) or 0 if
no client request. DevState and DevStatus are handled automatically by the
LabView device server
argin : passed as "Adapt to Type".
- lv_ds_cmd_put() - return result to client after completing executing of
command. Must only be called after a lv_ds_cmd_get() has returned a non-zero
command value. The call has the following calling syntax :
lv_ds_cmd_put(long
command, void *argout);
command : command returned by lv_ds_cmd_get() (passed
as 32 bit integer)
argout : double array to be passed back to client if command
was DevIOLVString, DevIOLVDouble or DevReadValue (passed as "Adapt to Type")
2.3 Debugging
An additional command exists to set the debugging flag in the library in
order to display debugging information in a graphical window. The command is
:
- lv_ds_debug(long debug) : sets the debug flag. Setting the debug flag to
a non-zero value switches on the debugging, zero switches it off.
All TACO kernel types and motor types are supported. The following types
are supported as input and output :
- D_VOID_TYPE
- D_SHORT_TYPE
- D_LONG_TYPE
- D_FLOAT_TYPE
- D_DOUBLE_TYPE
- D_STRING_TYPE
- D_VAR_STRINGARR
- D_VAR_SHORTARR
- D_VAR_LONGARR
- D_VAR_ULONGARR
- D_VAR_FLOATARR
- D_VAR_DOUBLEARR
The following types are supported as input only :
- D_MOTOR_FLOAT
- D_MULMOVE_TYPE
The following arguments are supported in output only :
- D_LONG_READPOINT
- D_FLOAT_READPOINT
- D_DOUBLE_READPOINT
- D_STATE_FLOAT_READPOINT
- D_VAR_LRPARR
- D_VAR_FRPARR
- D_VAR_SFRPARR
There are examples of calling all the functions as well as examples of
a TACO LabView device server (device_server.vi) and client (device_client.vi)
are available. Study them to find out how to write your own clients and servers
in LabView.
Some of the known problems with the TACO LabView interface are :
- out of memory - sometimes LabView gives this error message when calling
the lv_dev_putget() function. I don't know what this is due to. It seems to
be occur when a string is passed as output. The only solution I have found
is to rewire the corresponding (dummy) input for the output to another string
type or to recreate it as a constant. This problem has been mostly occurring
on HP-UX. If anyone finds a better explaination/solution for this problem let
me know.
- limited number of devices - the present interface is limited to 1000 TACO
devices in a LabView session
- not unregistered LabView device servers - there is no routine yet for unregistering
LabView device servers. This is not a major problem. It simply means the number
of reserved program numbers will go up every time a LabView device server is
started.
- blocked lv_dev_putget() call - this can happen on HPUX when trying to access
a device running on a host which is not reachable from the host on which LabView
is running. The present implementation will block. This problem does not occur
on Linux.
- client cannot run in same Labview session as server - the present version
does not support running clients in the same Labview session as the device
server.
- too many files open - this problem can be encountered in Labview applications
which have too many devices open. The latest (V1.5) version of the TACO interface
sets the limit of the number of open files to the maximum operating system
allowed value at the first call. If you still have problems then your application
is too big ! Previous versions (<V1.5) are limited by the default limit
for no. of open files e.g. 60 on HP-UX.
- Labview hangs - this can happen when accessing a device with UDP protocol
and the server/host are down. The solution is to switch to TCP protocol.
This is the fifth release of the LabView TACO interface. A number of improvements
been made e.g. adding support for the data base, dynamic device management,
increasing limit on open files. In the future we plan to offer a VI library
for TACO which will reduce the programming effort on clients even more. If
any readers have ideas for other improvements they should send their comments
to the author (goetz@esrf.fr) or even better add them to the source code themselves
and then send the code to the author !