LabView allows the incorporation of the C or VisualBasic APIs (including ActiveX controls) in its application development environment.
However, these can in general be quite unwieldly to use. To this end, we provide several simple LabView VIs which are based on the TINE BufferServer API and which provide an easy-to-understand quick entry into the world of client/server development from the LabView perspective.
It is strongly suggested that server information be registered via the local database files fecid.csv, exports.csv, and <EQM>-devices.csv. These files are all described in detail in the section on csv Files. Suffice it to say that registering server names, property names and information, and device names via API calls in LabView is rather cumbersome (although possible).
lvTineSrvInit
In LabView it is only neccessary to 'attach' the server to the registered information from the database files. This should be done once in the principal server vi. The principal server vi might in fact be the only vi you need to deal with if you have a 'read-only' server. In any event this 'principal' vi will service all read requests. lvTineSrvInit should be called once at initialization (for instance in a sequence structure), passing only the desired 'Export Name' of the server, which is used to cross-check the information in the local database files.
ExportName | (String) is the Export Name of the device server. This must match an entry in the exports.csv file. |
Example:
lvTineSrvInit.vi takes only one String input parameter, namely the Export Name of the device server to be managed by the underlying subsystem.
lvTineSrvPushSingle
Following this initialization, the server is ready to provide the data associated with the registered properties to its clients. The data returned will be initialized to zero and remain so until new data is 'pushed' into the underlying data buffers. This should occur following a hardware readout by using one of the 'push' VIs: lvTineSrvPushSingle.vi, lvTineSrvPushDouble.vi, lvTineSrvPushShort.vi, lvTineSrvPushLong.vi, lvTineSrvPushString.vi.
prpName | (String) is the name of the property whose data is to be pushed into the underlying TINE engine. |
devName | (String) is the name of the device whose data is to be pushed into the underlying TINE engine. The device name is matched to the device index as initialized via the <EQM>-devices.csv initialization file. A single element of an array property can thus be pushed by specifying the corresponding device and using an array size of '1'. Likewise a segment of an array property or the entire array can be pushed by giving the starting device and passing the array size of the entire array or desired segment. |
arraySize | (Integer) is the array size of data array or segment to be pushed. |
sngData | (Single) is the reference to the data array or segment to be pushed. |
flgSchedule | (int) is an optional parameter which if non-zero signals the underlying subsystem to schedule the property for immediate delivery to its clients. This parameter can be used where the minimization of latency are important. |
Example:
The Single (i.e. float) data associated with property 'prpName' are pushed every 1000 milliseconds into the underlying subsystem using lvTineSrvPushSingle.vi. lvTineSrvPushSingle.vi takes the String input parameters Property Name and Device Name, as well as the integer Array Size and a reference to the Single Data array. Optionally it can take a property schedule flag, which is not used in the example shown.
In this simple approach, the data will be timestamped at the time of the push and only the primitive data types can be used (or arrays thereof).
lvTineWaitCmd
If the server supports properties which respond to WRITE commands then it should handle such command in a separate vi for each property (which is run by LabView on a separate thread).
This vi should contain a sequence inside a while loop.
The first element of the sequence should call lvTineWaitCmd and pass the output to a LabView occurence.
propertyName | is the Name of the property for which the thread is to wait. |
wasCalled | is the boolean output which is to be passed as input to the LabView occurence. |
Example:
lvTineSrvInputChanged
The LabView sequence is blocked until the occurence fires, at which time the second frame in the sequence will be entered. Here one can check to see if the buffered input associated with the property has changed by calling lvTineSrvInputChanged.vi
prpName | is the Name of the property for which the input is to be checked |
If the input has changed, then the incoming data needs to be pulled into the LabView application by calling one of lvTineSrvPullShort.vi, lvTineSrvPullLong.vi, lvTineSrvPullSingle.vi, or lvTineSrvPullDouble.vi. In this example we use lvTineSrvPullShort.vi:
devName | is the device name (optional) for which the data are to be pulled. |
prpName | is the property name for which the data are to be pulled. |
shtData | is a reference to the LabView Array which is to receive the incoming data. |
arraySize | is the size of the array to be pulled. |
As the server can optionally accept the input data or reject it, and the caller may issue a READ/WRITE request (a 'put/get' in some terminology) the LabView sequence in question might also want to issue a call to lvTineSrvPutShort.vi.
Example:
lvTineSetCompletion
The final sequence step is very important and is simply a call to lvTineSetCompletion.vi which signals the underlying TINE engine that LabView is finished handling the call.
CompletionCode | is the completion code to be assigned to the call and returned to the caller. |
Example:
set FECPOLLRATE=100
will instruct the server to allow polling intervals as small as 100 msec (as opposed to the default value of 200 msec).
set FECWORKAREASIZE=512000
will instruct the server to allow payloads of up to 512 Kbytes (as opposed to the default value of 64 Kbytes).
Where information from other servers is required inside your LabView application, you can make use of the client-side put and get 'vi's. In analogy with the server 'vi's which 'push' data into or 'pull' data from the TINE buffered server, the client 'vi's will 'get' data from or 'put' data to a remote server. The 'get' routines are available as lvTineClnGetShort.vi, lvTineClnGetLong.vi, lvTineClnGetSingle.vi, lvTineClnGetDouble.vi, and lvTineClnGetString.vi.
For instance:
fullName | is the 'fully qualified' device name in the form /<context>/<server>/<device>[<property>] from which the data is desired. |
arraySize | is the size of the data array desired. |
shtData | is a reference to the LabView array object to receive the data returned. |
Example:
Note that 'get' calls which do not refer to stock- or meta- properties are retrieved synchronously once. Otherwise, a 'get' call will initiate an asynchronous static listener which will monitor the desired data. Thus, any subsequent 'get' call for the same data set will return immediately with the most recent data stored in the static listeners buffer. The listener will remain active unless no get call is made within a deadtime of 5 minutes. The listener will monitor by default at a polling interval of 1000 msec unless otherwise input. To request another polling rate, the 'fullName' parameter should be appended with '\<polling rate in msec>'. Also, note that if this 'polling rate in msec' is less than 50 msec, then it will not start a static listener at all and instead try to complete synchronously, unsing the polling rate as a timeout value.
The 'put' routines are available as lvTineClnPutShort.vi, lvTineClnPutLong.vi, lvTineClnPutSingle.vi, lvTineClnPutDouble.vi, and lvTineClnPutString.vi.
For instance:
fullName | is the 'fully qualified' device name in the form /<context>/<server>/<device>[<property>] to which the data are to be sent. |
inputDataSize | is the size of the data array being sent to the server. |
putData | is a reference to the LabView array object containing the data to be sent. |
Example:
Note that 'put' calls always complete synchronously and do not involve a static listener as in the case of the 'get' calls. Also note, that there is (as yet) no 'putget' call which can be used to make an atomic read/write access of a remote data element.