The client and server interfaces for MatLab applications follow the Buffered Client and the Buffered Server paradigms. In addition, several utilities for browsing and for retrieving archived data, etc. are also available. These will be covered in the sections which follow.
Specifically these are:
Note that if you have installed the TINE MatLab libraries to a local directory (default will be TINE_ROOT%\MatLab, e.g. c:\tine\MatLab) then you will likely need to add this directory to your MatLab path. For instance:
addpath('C:\tine\MatLab')
savepath
will ensure that the MatLab libraries are found on the path by MatLab and that this change in the path persists for future MatLab sessions.
On the client side, dedicated 'read' and 'write' calls generally allow for easy access to control system variables from MatLab.
In their most basic forms, the calls appear to be 'transactional', which in fact they are for 'write' commands. 'read' calls generally start an asynchronous static listener (i.e. a local monitor) on the desired variable, which is then stored in a local buffer. Thus, repeated 'read' calls merely retrieve the most recent updated value from the local buffer. The update rate can of course be influenced by the calling parameters. A 'read' call can likewise be constructed to in fact issue a synchronous transactional read request.
We shall expore these read calls in some detail below.
tine_read (see also tine_attach_link)
With 'tine_read' you can access the current readback value of any targeted endpoint which contains readback data. Simply typing 'tine_read' at the MatLab prompt will display the following
One sees that there is one primary required argument, namely the 'targeted endpoint', and several optional arguments which influence the underlying behavior.
targeted_endpoint | is the initial parameter and must be a string of the form /<context>/<server>/<device>[<property>] which essentially follows the TINE naming hierarchy. If NO other input parameters are given, the default 'read' data type and data size (as established by the targeted server) will be acquired; AND if the property is not 'static' then an asynchronous listener will be established updating the value every 1000 msec. No 'callbacks' events will be issued. It is assumed that the application will continue to issue the same read requests for its life cycle. If this is not the case, then after an idle period of 5 minutes without any subsequent 'read' requests on the same parameter will cause the listener to be canceled, thereby notifying the corresonding server that this client is no longer interested in the parameter. |
data_type | is the second parameter and is optional. If used it can specify the desired data acquisition format. MatLab generally works with matrices of 'doubles' or 'strings', and the necessary conversion will always take place. However some servers might potentially have overloaded properties which can return data in different forms depending on what is asked for. Additionally, if it is known that a property has been multiply exported with different data types (i.e. overloaded) then this parameter can be used to determine which specific call is intended. This is often true in the case of structures. If a structure is wished for and the structure tag is known, then the property form of this parameter follows the paradigm: 'STRUCT.<tag>' (see example below. If the canonical data type is a structure, this parameter may be omitted, in which case the data structure will be 'discovered'. |
data_size | (optional) is the requested data size. Many servers prefer by default to deliver 'multi-channel' arrays of all elements of the desired property (for instance an array containing ALL vacuum pressures beginning at the index determined by the 'device name' input). If the application only needs a single value (or subset), the 'data size' can be used to specify the precise number of elements required. |
timer_interval | (optional) is the requested timer interval (in milliseconds) which determines the polling access of the underlying 'listener'. By the default this is 1000 msec. If a faster update of the local buffers is desired, then this value may be adjusted accordingly. Note: if the the desired property is being 'scheduled' by the server, then the underlying listener will ALWAYS be updated 'immediately'. |
callback_id | (optional) is the caller's desired callback ID. If this argument is not included, then it is assumed that no callback event is desired. |
callback_fcn | (optional) is the name of the MatLab (.m) function which should be called when new data arrive in the listening buffer. If this parameter is missing, but a callback ID was given, then a callback routine under the name of 'tine_dispatch_<property>.m' will be looked for and called if present. In any case the desired .m function must be found in the current working directory. If it does not exist, no attempt will be made to issue a callback. The callback .m file must accept a single scalar matrix, which will contain the value of the 'ID' passed as the fifth argument. A MatLab function with any other input arguments will likely result in an error and unpredictable behavior. Any return values from the callback function will be ignored. |
Note that instead of 'polling' within a MatLab timer function for the desired data (which would introduce extra latency), the MatLab program can be structured to issue a 'tine_read' inside the callback routine, thus making the data available to the application logic immediately after new data have been delivered.
As noted above, in the case of structures, one can specify the 'known' structure type in the call to tine_read as shown:
If the structure type is unknown, it may be safely omitted, in which case it will be discovered. In the above example all optional parameters are omitted. Thus the call returns the 'registered' data size and type, in this case an array of 10 such structures:
As a final note: the data type given in the 'data_type' parameter is case 'insensitive' with respect to the TINE format type. That it, 'struct' is identical to 'STRUCT', 'float' is identical to 'FLOAT'. However (and this is important) if a structure tag is appended to the format string 'struct' it is case 'sensitive'! That is 'SineInfo' is NOT the same as 'SINEINFO', etc. as far as structure tags are concerned.
tine_readimage
'tine_readimage' is a special call to acquire images. Simply typing 'tine_readimage' at the MatLab prompt produces the following output:
One sees that there is one primary required argument, namely the 'targeted endpoint', and one optional argument which can be used to specify a polling interval.
targeted_endpoint | is the initial parameter and must be a string of the form /<context>/<server>/<device>[<property>] which essentially follows the TINE naming hierarchy. There is no validation on the entered parameters to insure that the target does produce an image. However it should be noted that for modern (i.e. video system 3) servers, the device entered should be 'Output' and the property entered should be either 'Frame' (for acquisition at the specified timer rate) or 'Frame.Sched' for acquistion at the server's scheduling rate. |
polling_interval | [optional] is the requested polling interval. If this parameter is either omitted or passed as '0' then the call reverts to a single synchronous acquisition of an image. Otherwise an underyling data link will be established providing a local buffer from which future calls to the same target will retrieve their image data. |
access_mode | [optional] is the desired access mode flags for the underlying asynchronous link to the data target. Any entered text other than 'NETWORK' (request as multicast) or 'CONNECT' (request as a TCP stream) will be ignored. |
Example:
The above example will launch a Matlab image display which looks like the following:
tine_write
With 'tine_write' you can set the current target value of any targeted endpoint which allows WRITE access. Simply typing 'tine_write' at the MatLab prompt will display the following
One sees that there are in this case two primary required arguments, namely the values to be 'written' and the 'targeted endpoint'. Actually the initial argument (the values to be written) may be omitted to issue a 'command' which does not take input values but does require WRITE access. If this form is used, then ONLY a single input argument is allowed, namely the 'targeted endpoint'. There are also several optional arguments which influence the underlying behavior.
values | is the values to be written and can be a string or an array of values. The precise data format will be determined either by property query to the server or by specifying the data type in the optional third parameter. |
targeted_endpoint | is the target which is to process the WRITE request. Once again, this essentially follows the TINE naming hierarchy. If NO other input parameters are given, the default data type will be acquired from the server. The input data size will be the array dimension of the 'values' argument passed. |
data_type | is optional and if used can specify the desired input data type. And as in the case of tine_read, a structure type may be specified using the same paradigm: 'struct.<tag>' for the data_type string |
timeout | is optional and if used can specify the maximum amount of time to wait (in milliseconds) for a response. |
Note: If a structure is to be sent, then the structure fields (at least as far as the data types and sizes are concerned) MUST be known a priori. Theoretically a call to tine_read can be made to discover the structure data type (as long as it is known that the designated property supports the delivered structure data type also as an 'input' data type!).
In the example below, the data type is explicitly given.
An alternative case might omit the optional parameters. However the input data MUST be of the apropriate structure data type. This default input data type will be in this case queried from the server and the given data type must agree with this.
tine_writeread
With 'tine_writeread' you can atomically set and readback the current target value of any targeted endpoint which allows WRITE access. Primarily this assumes the targeted endpoint represents an 'attribute'. That is, the property and device accept a 'set' value and deliver a 'read' value with the same data size and format. This is in general different for a 'call', whereby the input data set and output data set are generally different objects and in many cases do not require WRITE access. If such 'calls' are desired, please make use of 'tine_call'.
You can nevertheless use 'tine_writeread' with different data types and sizes for input and output. However, WRITE access will always be assumed!
Simply typing 'tine_writeread' at the MatLab prompt will display the following
One sees that there are in this case two primary required arguments, namely the values to be 'written' and the 'targeted endpoint'. Actually the initial argument (the values to be written) may be omitted to issue a 'command' which does not take input values but does require WRITE access. If this form is used, then ONLY a single input argument is allowed, namely the 'targeted endpoint'. There are also several optional arguments which influence the underlying behavior.
values | is the values to be written, can be a string or an array of values. The precise data format will be determined either by property query to the server or by specifying the data type in the optional third parameter. |
targeted_endpoint | is the target which is to process the WRITE request. Once again, this essentially follows the TINE naming hierarchy. If NO other input parameters are given, the default data type will be acquired from the server. The input data size will be the array dimension of the 'values' argument passed. |
data_type | is optional and if used can specify the desired input and output data types. If a single type is given then it will be use for both the input and output data types (attribute style). Otherwise both the input and output types can be specified by separating them with a colon ':' as in 'float:int32'. If the 'data_type' is omitted, then a query will ensue in order to determine the default output data size and type. And as in the case of tine_read, a structure type may be specified using the same paradigm: 'struct.<tag>' for the data_type string. If the the input and output take different types (i.e. tags) then again passing the data_type in the form 'struct.<tag_input>:struct.<tag_output>' will instruct the subsystem as to which structures to use. |
data_size | refers to the requested output data size. Note: the input data size is completely determined by the size of the input data array in parameter 1. |
timeout | is optional and if used can specify the maximum amount of time to wait (in milliseconds) for a response. |
The example below shows how to send and receive a structure from a server. In this case the same structure format (tag) is used for input and output and passed explicitly in the call, although the same results would be obtained by simply passing 'struct.SineInfo'.
tine_call
As noted above, you can also make use of 'tine_call' to access target endpoints using different input and output data objects, and without the restriction that the access be a WRITE command. In fact, the default data access using 'tine_call' is READ access.
In many ways the use of 'tine_call' parallels that of 'tine_writeread'.
Simply typing 'tine_call' at the MatLab prompt will display the following
One sees that there are in this case two primary required arguments, namely the values to be 'sent' and the 'targeted endpoint'. The initial argument (the values to be sent) is in this case NOT optional. However a 'WRITE' command can be fashioned by supplying the data access as 'WRITE' and by providing an empty (zero-length) string as the initial argument. There are also several optional arguments which influence the underlying behavior.
values | is the values to be written, can be a string or an array of values. The precise data format will be determined either by property query to the server or by specifying the data type in the optional third parameter. |
targeted_endpoint | is the target which is to process the CALL request. Once again, this essentially follows the TINE naming hierarchy. If NO other input parameters are given, the default data type will be acquired from the server. The input data size will be the array dimension of the 'values' argument passed. |
data_type | is optional and if used can specify the desired input data type. If a single type is given then it will be use for both the input and output data types (attribute style). Otherwise both the input and output types can be specified by separating them with a colon ':' as in 'float:int32'. If the 'data_type' is omitted, then a query will ensue in order to determine the default output data size and type. And as in the case of tine_read, a structure type may be specified using the same paradigm: 'struct.<tag>' for the data_type string. If the the input and output take different types (i.e. tags) then again passing the data_type in the form 'struct.<tag_input>:struct.<tag_output>' will instruct the subsystem as to which structures to use. |
data_size | refers to the requested output data size. Note: the input data size is completely determined by the size of the input data array in parameter 1. |
timer_interval | is optional and if used can specify the maximum amount of time to wait (in milliseconds) for a response in the case of a WRITE call or synchronous request, or it specifies the timer polling interval when an asynchronous static listener is in play. |
access | mode can be used to specify the desired CALL access. By default this is simply 'READ', which will in fact start an asynchronous static listener for the calling parameters. To specify a synchronous transaction, you should supply the string 'SYNC'. By specifying 'WRITE' the CALL will automatically be made via a synchronous transaction. |
Examples for tine_call essentially follow the same model as per tine_writeread.
tine_attach_link
If it is known a priori that the MatLab application should deal in some circumstances with monitor 'links' the the call 'tine_attach_link' should perhaps be used in lieu of 'tine_read'. This call differs from 'tine_read' primarily in that ALL input parameters are required. In addition, the 'partner' call 'tine_close_link' can be used to terminate the underlying listener immediately without waiting for its 'idle time' to expire.
Simply typing 'tine_attach_link' at the MatLab prompt will display the following
One sees that there are six required arguments. 'tine_attach_link' will always assume that readback data are being monitored and the access mode is READ.
targeted_endpoint | is the initial parameter and must be a string of the form /<context>/<server>/<device>[<property>] which essentially follows the TINE naming hierarchy. If NO other input parameters are given, the default 'read' data type and data size (as established by the targeted server) will be acquired; AND if the property is not 'static' then an asynchronous listener will be established updating the value every 1000 msec. No 'callbacks' events will be issued. It is assumed that the application will continue to issue the same read requests for its life cycle. If this is not the case, then after an idle period of 5 minutes without any subsequent 'read' requests on the same parameter will cause the listener to be canceled, thereby notifying the corresonding server that this client is no longer interested in the parameter. |
data_type | is the second parameter and is optional. If used it can specify the desired data acquisition format. MatLab generally works with matrices of 'doubles' or 'strings', and the necessary conversion will always take place. However some servers might potentially have overloaded properties which can return data in different forms depending on what is asked for. And as in the case of tine_read, a structure type may be specified using the same paradigm: 'struct.<tag>' for the data_type string |
data_size | (optional) is the requested data size. Many servers prefer by default to deliver 'multi-channel' arrays of all elements of the desired property (for instance an array containing ALL vacuum pressures beginning at the index determined by the 'device name' input). If the application only needs a single value (or subset), the 'data size' can be used to specify the precise number of elements required. |
timer_interval | (optional) is the requested timer interval (in milliseconds) which determines the polling access of the underlying 'listener'. By the default this is 1000 msec. If a faster update of the local buffers is desired, then this value may be adjusted accordingly. Note: if the the desired property is being 'scheduled' by the server, then the underlying listener will ALWAYS be updated 'immediately'. |
callback_id | (optional) is the caller's desired callback ID. If this argument is not included, then it is assumed that no callback event is desired. |
callback_fcn | (optional) is the name of the MatLab (.m) function which should be called when new data arrive in the listening buffer. If this parameter is missing, but a callback ID was given, then a callback routine under the name of 'tine_dispatch_<property>.m' will be looked for and called if present. In any case the desired .m function must be found in the current working directory. If it does not exist, no attempt will be made to issue a callback. The callback .m file must accept a single scalar matrix, which will contain the value of the 'ID' passed as the fifth argument. A MatLab function with any other input arguments will likely result in an error and unpredictable behavior. Any return values from the callback function will be ignored. |
A call to tine_attach_link will 'wait' for the initial incoming data set and then return the acquired data.
Note that instead of 'polling' within a MatLab timer function for the desired data (which would introduce extra latency), the MatLab program can be structured to issue a 'tine_read' inside the callback routine, thus making the data available to the application logic immediately after new data have been delivered.
Consider the following example, which establishes a data link to get the horizontal orbit:
Example:
The link specifies a callback 'sa_x_callback' which instructs the subsystem to call the matlab 'm' file named sa_x_callback.m when data arrive. An example callback file might look like the following:
So within this callback file, an additional call to tine_read() with the same data endpoint is made in order to acquire the most recent data set and, in this case, dump the first array element to the screen.
tine_close_link
As noted above, if the MatLab application knows it has started an asynchronous static listener, it can terminate the listener at any time by calling 'tine_close_link'. Otherwise an idle period of 5 minutes will need to expire before the listener is terminated automatically. An 'idle period' is defined as a period of time where NO calls to 'tine_read' are made to access the current buffered contents of the listener data.
Simply typing 'tine_call' at the MatLab prompt will display the following
The parameter passed are used to identify the link parameters in the listener table. These must match exactly in order for the listening link to be identified so that it can be terminated.
targeted_endpoint | is the initial parameter and must be a string of the form /<context>/<server>/<device>[<property>] which essentially follows the TINE naming hierarchy. If NO other input parameters are given, the default 'read' data type and data size (as established by the targeted server) will be acquired and assumed; |
data_type | is optional and if used can specify the known data acquisition format. |
data_size | is optional and if used contains the known requested data size. |
Legacy MatLab routines
The legacy MatLab routines 'tineread' and 'tinewrite' are still available but should be considered as deprecated. These are
tineread
and
tinewrite
Various routines are available for browing the control system within Matlab. These are described below.
tine_contexts
The top tier of the TINE naming hierarchy is the 'context'. To ascertain the available contexts within the control system, simply call 'tine_contexts'. A list of the known contexts will then be provided in the output.
A call to 'tine_contexts' does not take any parameters.
Typing 'tine_contexts' at the MatLab prompt will generate output containing list of available contexts as seen in the example below.
tine_servers
The next tier of the TINE naming hierarchy is the device server (or device group). Note: a device 'group' can appear as a logical server in a list of device servers, when in fact it refers to a 'group' of physically distinct servers of a the same variety.
In any event a call to 'tine_servers' will return a list of the known servers within the context provided. Simply typing 'tine_servers' at the command prompt will generate the 'usage' message shown below:
Supplying a valid 'context' will generate a list of servers as shown in the following example:
tine_devices
The next tier of the TINE naming hierarchy is the device name. Simply typing 'tine_devices' at the command prompt will generate the 'usage' message shown below:
We see that two parameters are required, namely the desired context and the desired server name. For instance, the device list from the PETRA BPM server might be obtained as shown below
In addition, the optional parameter 'property' can be supplied for accessing the device 'keywords' for known property servers. 'Property servers' unlike device servers are property oriented and can maintain different keyword lists for different properties. Attempting the simpler variant of the 'tine_devices' query on a property server will likely produce the status 'error' : 'has query function'. Supplying a particular property in the call will then generate a property specific 'device' (i.e. keyword) list as shown below:
tine_properties
The next tier of the TINE naming hierarchy is the property. Simply typing 'tine_properties' at the command prompt will generate the 'usage' message shown below:
This takes a single argument supplying the targeted endpoint, which may contain the device name (device oriented servers) but does not have to.
For instance a simpler (without a specific device name) form will work fine for 'property servers' or 'flat' servers (where each device supports the same property list and each property is supported by all devices)
\incluce eg_mlab_tine_properties1.txt
For known 'device oriented' servers, supplying the targeted device name is preferred:
\incluce eg_mlab_tine_properties2.txt
Many of the control system parameters will be archived and ready for retrievel and examination when called for.
Archived data can be stored 'centrally', where a range of filtering parameters might be in play (so as to reduce the amount of unnecessary data commited to disk). 'centrally' stored data are always availible and never expired.
Archive data can also be stored 'locally', where simpler filtering based on tolerances might be in play. 'locally' stored data are available only for a (configurable) duration, typically 1 to 3 months.
Archive data might be stored 'centrally' based on an 'event trigger'. This usually refers to 'post-mortem' events, such as an RF trip or unexpected beam loss, etc. Such data are managed differently than the regular trend archives descibed above. Event data generally have an associated event 'comment' (the reason why the event was triggered), which can be edited by 'experts' at any time. Event data are associated with a specific point in time and a specific trigger. Consequently retrieving archived event data is a bit more 'involved' than simple history trends of stored machine variabled.
Many MatLab routines are available to assist in retrieving and analysizing archive data. These will be described below.
tine_history
Simply typing 'tine_history' at the command prompt will generate the 'usage' message shown below:
We see that there are three required input parameters, namely the targeted endpoint, the 'stop time' (i.e. the most recent requested data point) and the depth of the archive trend.
All parameters are strings. The 'stop time' should be given in a string data format ('dd.mm.yyyy hh:mm:ss') or the string 'now' to refer to the current time. The 'depth' is a string begining with a number and followed by a representative unit of time ('days','hours','minutes', etc.)
Optionally one can specify a 'sampling interval'. If this is '0' or less then the targeted server will determined a suitable sampling raster so that the returned data cover the desired time interval. Internally a maximum of 8000 data points will be returned. Thus for a large time interval it could happen that stored data points are 'skipped' in order to supply data throughout the requested range. If this is not the desired behavior, an explicit sampling interval can be provided. To avoid skipping any points a value of '1' should be passed (default = '0'). One can also optionally specify an array 'index' as the 5th parameter. If this value is greater than '0' then the specific array index will be selected from the any archive record that refers to an array. In the case of multi-channel arrays, this parameter is usually not necessary as the the device name will determine the array index (default = '0'). Finally one can optionally indicate in the 6th parameter whether or not to return associated 'system stamps' with the archive data. In most cases one is interested in data versus a timestamp. As most data are also archived along with the accompanying system stamp, it could be useful to retrieve this information as well. The system stamp might refer to a 'cycle number', 'pulse number', or 'shot number' depending on the nature of the accelerator. The timestamp returned is the MatLab time (and not UTC).
The targeted end point can be a specific server, in which case the 'local history' is obtained directly from the server (if it is available!), as in:
Note that as the number involved are large it is frequently useful to make use of the 'format long' specification in MatLab.
As another example obtaining the system stamp information and a sampling raster of '1':
The targeted end point can also be a central archive server (the server 'HISTORY' in the desired context) as in:
or
These above examples demonstrate the acquisition of the history 'trend' of a specific value over time, which is the most common form of an archive call. Some history records are composed of a waveform 'trace' (or spectrum) of data, that is, an array. A record might also be a multi-channel array (another form on an array). It might be desireable to acquire the archived array at a specific time. This can also be acquieved with a call to 'tine_history'. In such a case, instead of specifying the depth parameter as a number of 'days', 'hours', 'minutes', etc. one gives the simple text 'snapshot', which signals the acquisition of the associated archive record at the time given as the 'stop time' parameter. There is more than likely no record stored at precisely the time indicated as the 'stop time', thus the matlab routine will return a structure containing the 'time of the record found' (equal to or more recent than specified) both in UTC and in text and a 'data' array containing the record at that time. This is shown in the example below:
tine_eventdata
The event data for a specific event can be retrieved using the call 'tine_eventdata'.
Simply typing 'tine_eventdata' at the command prompt will generate the 'usage' message shown below:
We notice that this call requires three input parameters representing the 'context' and 'event' desired. This must be in the form '/<context>/<event trigger>'. The second parameter is the fully specified stored parameter and this must in the form '/<context>/<server>/<device>[<property>]'. And note here, that the 'context' specified for the stored parameter need NOT be the same as the context for the event server! The third parameter is the desired event number (as a raw UTC event number passed as a string). An optional fourth parameter 'data_index' can be used to specify an index within a stored array.
As an example, consider:
tine_eventtriggers
An event server for a given TINE context will respond to those 'events' which have been configured by an administrator. Such events are then 'triggered' whenever conditions warrant the collection of event data. To see a list of those configured event triggers, use 'tine_eventtriggers'.
Simply typing 'tine_eventtriggers' at the command prompt will generate the 'usage' message shown below:
We notice that this call requires the single input parameter 'context'.
As an example, consider:
tine_eventproperties
To see which properties are stored for a given server within a specific event use the call 'tine_eventproperties'. Simply typing 'tine_eventproperties' at the command prompt will generate the 'usage' message shown below:
We notice that call takes two input parameters which must be the desired 'context' qualified with the desired 'event trigger' in the form '/<context>/<event trigger>', as well as the desired server.
For example:
tine_eventservers
To see which servers are incorporated within a specific event use the call 'tine_eventservers'. Simply typing 'tine_eventservers' at the command prompt will generate the 'usage' message shown below:
We notice that call takes a single input parameter which must be the desired 'context' qualified with the desired 'event trigger' in the form '/<context>/<event trigger>'.
For example:
tine_eventlist
To see which events were recorded for a specific event trigger over a time range, use the call 'tine_eventlist'. Simply typing 'tine_eventlist' at the command prompt will generate the 'usage' message shown below:
We notice that call takes two required input parameter which must be the desired 'context' qualified with the desired 'event trigger' in the form '/<context>/<event trigger>' and the 'stop time' used to terminate the search for events. Optionally the 'depth' can be provided as the third argument. The 'stop time' and 'depth' are parsed in the same manner as for the 'tine_history' call. Omitting the 3rd argument will assume a depth of the last 24 hours.
For example:
We see that the event is identified by its event 'time', which is maintained as a UTC time constant. The event list dumped by the above call will give both the raw UTC time as well as the human readable time string, essentially giving the time of the event trigger.
tine_eventcomment
Stored event generally have an associated event comment generated at the time of the event, which can later be 'annotated' by experts who have later deciphered cause of the event.
To see the associated comment for a given event, use the call 'tine_eventcomment'. Simply typing 'tine_eventcomment' at the command prompt will generate the 'usage' message shown below:
We notice that call takes two required input parameter which must be the desired 'context' qualified with the desired 'event trigger' in the form '/<context>/<event trigger>' and the event 'id', i.e. the event UTC time (shown in the 'tine_eventlist' dump). This second parameter should be the raw UTC 'long' time stamp, input as a string.
For example:
You are always at liberty to invoke the MatLab engine routines within a standard TINE server to access functions written in MatLab from a standard server. This approach has its merits but also requires you to know your way around in 2 programming languages, namely MatLab AND either C or java.
In many cases this is an unnecessary and unwarranted complication. You can also write a TINE server completely in MatLab by making use of the following MatLab functions described below. Once again, these routines follow in the most part the paradigm of the Buffered Server.
tine_attach_server
If the server's properties and devices are available via a TINE database (produced, for instance, by using the TINE server wizard), then a simple call to 'tine_attach_server' will cause the configuration database to be read and make the configured properties and devices avialable. The server will automatically 'plug' itself into the control system and be visable to prospective clients. At this stage there will likely be NO intersting data to be read from any of the properties, as the underlying buffers will have been initialized to contain '0'.
equipment_module_name | is the so-called 'local name' of the equipment module. This is a 6-character name used for administration purposes within the running process and is thus required only to be unique within the process. In MatLab, you will likely have only a single registered server per MatLab process, so this minimal restriction scarely presents a problem. Although a meaningless character string such as "1" will suffice, it is typical to provide a 3-letter acronym followed by "EQM" (for equipment module), for instance "MLBEQM". |
export_name | is the equipment module's exported name. This is the server name which all control system clients will 'see'. This can be up to 32-characters in length. This name must be unique within the registered context (as given in the fecid.csv file or fec.xml file). |
device_capacity | is the maximum number of device instances that this server will manage. |
Alternatively you can completely forgo any configuration database and register all necessary information via the registration API calls 'tine_register_fec', 'tine_register_server', 'tine_register_device', and 'tine_register_property' (see below).
tine_pushdata
In order to supply the registered properties with data, the MatLab 'server' should call 'tine_pushdata' when it has determined that new data are available for the property in question. Using just 'tine_attach_server' and 'tine_pushdata' in this manner are theoretically the only MatLab calls necessary to provide a 'READ-ONLY' server.
property | is the property for which the supplied data are to be used. |
device | is the specific device instance for which the supplied data are to be used. This must be a string corresponding to a registered device or a string of the form "#1", etc. which then indicates the device instance 'numerically'. |
data | is the data (array) which is to be 'pushed' into the underlying property buffer. |
size | (optional) is the length of the data array to push into the property buffer. If omitted, the entire contents of the data array will be used. |
isScheduled | (optional) is an integer flag which if non-zero instructs the subsystem to immediately notify all listening clients of a change in the property's data. |
If the server is to respond to WRITE commands, it should provide a property dispatch handler by making use of 'tine_attach_handler'.
Note that if the data to be pushed is a structure, this must correspond to a registered structure AND the property in question must be registered to support this structure. See the discussion below concerning registering a structure and registering a property.
tine_attach_handler
If a property is to accept WRITE requests, that is requests which attempt to change a setting, then the Matlab server should provide a dispatch handler for the corresponding property. This is done by make a call to 'tine_attach_handler' and providing the appropriate MatLab function to act as the dispatcher.
property | is the property to which the handler is to be associated. |
handler_name | is the name of a MatLab '.m' function to be called when a WRITE transaction for the property is being requested by some client. This '.m' function must return a status (an integer value, where '0' means 'success'), and it must have the prototype <dispatch>('property','device',data), where 'property' and 'device' will be set to the values in the call and 'data' will contain the contents of the set values. If no data have been sent, then this will be a null value. It is up to the dispatch routine to check the data type of this parameter and to either accept the call (return '0') or to reject the setting on some other grounds (return non-zero : see the section on TINE error codes). |
tine_dispatch
In some unsual circumstances, the provided MatLab dispatch handler might throw an exception or otherwise be unable to complete normally. This will effectively block any WRITE access to the corresponding property indefinitely (until the process is restarted). In order to free the property WRITE dispatch handler again, a call to tine_dispatch can be made.
Sine Server Example
An example of a fully function Sine Generator written entirely in MatLab is shown below. A MatLab .m file makes calls to 'tine_attach_server', which attaches itself to a pre-configured data base, 'tine_attach_handler', which is used to assign WRITE dispatch routines for certain 'settable' properties. It also starts a MatLab timer which updates the waveforms returned in calls to the property 'Sine'. It also exercises the call 'tine_pushdata'.
As this server uses global arrays for the values of the amplitudes, frequencies, and noise for the individual Sine curves (there are 10 of them), these are also declared in this starup routine.
The call to 'tine_attach_server' as noted above attaches itself to a configuration database.
In this case, it consists of a set of .csv files.
The file 'fecid.csv' is located in the FEC_HOME directory:
The file 'exports.csv' is located in a subdirectory of the FEC_HOME directory called 'SINEQM' (the subdirectory name MUST be the same as given the call to 'tine_attach_server').
This file essentially gives the names of the exported properties as well as all relevant information about the exported properties. This information is in fact used to determine the sizes and behaviors of the underlying property buffers. The file 'exports.csv' also provides the exported server name, in this case "MLSineServer". This exported server name is used as a cross-reference within the fecid.csv file to latch onto the appropriate FEC, in case of any ambiguity (note: a fecid.csv can contain multiple entries).
The file 'devices.csv' is also located in the 'SINEQM' subdirectory and provides the device names for the individual devices.
Note that the number of devices in total is given in the 'exports.csv' file as '10' (the NUM_DEVICES column). Thus, at most 10 entries will be read from the 'devices.csv' file.
The update routine used in the Matlab timer looks like the following:
The update routine used in the MatLab timer is called 'putsine'. It looks like the following:
This routine in turn makes use of a .m File to determine the device index from a device name. This looks like the following:
Several dispatch routines are also registered to handle any incoming WRITE commands to change the value settings. For instance, the dispatch routine used to handle WRITE commands to the property "Amplitude" looks like:
tine_register_fec
You can assign a FEC name to your MatLab server via the API call 'tine_register_fec'. This will, of course', hard-wire the FEC name within the MatLab code, but this could be a a reasonable alternative to using configuration files, as a MatLab server is most likely to be a single instance middle-layer server and will only ever run as a single instance.
Simply typing 'tine_register_fec' at the MatLab prompt will produce the following output:
The one required argument is the 'fec_name', which must be system wide unique (see the Overview documentation: 'What's in a Name?'). However if all other arguments are omitted, then the default port offset will be '0' which could be in conflict with other servers which are possibly running on the same host, so be careful here! Likewise it is often useful to provide information as the location, responsibility, 'context' (default = "TEST") and 'subsystem' (default = "TEST"). So making use of all parameters is encouraged.
fec_name | is the system wide unique name of the FEC process (up to 16 characters in length) |
sub_system | is the control subsystem to which the servers should be associated. (e.g. "VAC", "DIAG", "MAG", etc.). This is not a part of the name hierarchy but can be used in browsing. |
context | is the control system context in which the servers should be registered. |
description | is a description (up to 64 characters) of the functionality of the FEC. |
location | is a string (32 characters) containing the phyisical location of the FEC host computer. |
hardware | is a string description of attached hardware. For most MatLab middle layers, this will simply be "none". |
responsible | is the person (or persons) to contact in case of problems. It should also contain the 'user name' if possible of such persons, as administrative actions (such as 'removing' the FEC from the ENS database) will require a 'match' on the user name of the person attempting such actions versus those 'responsible' for the FEC in question. |
portOffset | is the port 'offset' to be applied to all of the server's listening service ports. This should be a simple integer between 0 and 65535, but preferably small. The default is '0'. If multiple FECs run on a single computer, then each must have its own unique port offset. Hence the default value of '0' will work only once per host. Once again, this is not the listening 'port address' but is an 'offset' to be applied to a set of listening ports (UDP, TCP, STREAM, Debug, and even possibly IPX). |
tine_register_server
You can assign the server's exported name and local equipment module name to your MatLab server via the API call 'tine_register_server'.
Simply typing 'tine_register_server' at the MatLab prompt will produce the following output:
export_name | is the equipment module's exported name. This is the server name which all control system clients will 'see'. This can be up to 32-characters in length. This name must be unique within the registered context (as given in the fecid.csv file or fec.xml file). |
equipment_module_name | is the so-called 'local name' of the equipment module. This is a 6-character name used for administration purposes within the running process and is thus required only to be unique within the process. In MatLab, you will likely have only a single registered server per MatLab process, so this minimal restriction scarely presents a problem. Although a meaningless character string such as "1" will suffice, it is typical to provide a 3-letter acronym followed by "EQM" (for equipment module), for instance "MLBEQM". |
device_capacity | is the maximum number of device instances that this server will manage. |
tine_register_device
You can assign the server's device instance names within your MatLab server via the API call 'tine_register_device'.
Simply typing 'tine_register_device' at the MatLab prompt will produce the following output:
device_name | is the name of the device instance to be registered. |
device_number | is the associated device number. This must be greater than or equal to 0 and smaller than the 'device_capacity' entered in 'tine_register_server' in order to succeed. |
device_redirection | (optional) must be a string of the form '/<context>/<server>/<device>[<property>]' if the device instance in question does reside on the local server but should be redirected to a remote server. |
device_description | (optional) can be used to supply a device description. |
tine_register_property
You can assign the server's property names and information within your MatLab server via the API call 'tine_register_property'.
Simply typing 'tine_register_property' at the MatLab prompt will produce the following output:
Here there are in all 10 required parameters:
property_name | is the property name to be registered |
in_size | gives the array size of any input parameters required by the property |
in_type | gives the data type of any input parameters required by the property. This should by a string such as 'float', 'int32' (synonym: 'int'), etc. Strings entries are best dealt with by using a 'fixed-capacity' string type such as 'NAME16' or 'NAME64', etc. |
out_size | gives the array size of any output parameters deliverd by the property |
out_type | gives the data type of any output parameters delivered by the property. This should by a string such as 'float', 'int32' (synonym: 'int'), etc. Strings entries are best dealt with by using a 'fixed-capacity' string type such as 'NAME16' or 'NAME64', etc. |
max | gives the maximum range of the property values |
min | gives the minimum range of the property values |
egu | gives the engineering units of the property (a string not to exceed 16 characters) |
access | gives the supported access ('READ', 'WRITE', 'READ|WRITE', etc.) |
description | gives a description of the data supplied by, or the action initiated by calling the property. |
In addition, there are two optional parameters which can (and should) be used to supply useful information. These are:
array_type | gives the type of array returned by a call to the property. This is typically 'unknown', 'scalar', or in the case of a real array 'channel' (for multi-channel arrays) or 'spectrum'(for waveform or trace arrays). |
row_length | gives the row length in cases where 'multi-dimensional' arrays are returned. The row length will default to the output data size if not explicitly given. |
Sine Server Example II
A second example of a fully function Sine Generator written entirely in MatLab is shown below. This example simply duplicates the functionality of the example shown above, but in this case ALL server information is registered via API.
tine_register_type
A MatLab server can handle structures as input or output like any other TINE server. You will need to register the structure(s) you wish to use during initialization. This is best accomplished by making use of a call to 'tine_register_type'.
Simply typing 'tine_register_type' at the command prompt produced the following output:
name_tag | is the structure tag to assign to the data type (16 characters maximum) |
values | is a reference to the structure object to use to register the data type. Note that if this is an array of structures, then the size of the array will reserve the proper amount of space for the structure storage. |
The easiest way to register a structure then is to form an instance and pass it along with a structure 'tag' name in a call to tine_register_type.
Note that for simplicity, all number fields will automatically use type 'double' and all character fields will automatically use a string capacity on the next largest 64-character boundary. The fields within the structure can also be arrays.
You are now in a position to register a property which uses this structure. Below is an example which will use this both as input and as output.
To push data into this property's buffer simply call 'tine_push_data' as before:
To react to clients sending a structure as input for this property, simply register a dispatch routine as always. The 'data' parameter passed to the dispatch routine will contain the contents of the incoming structure. The dispatch routine should of course examine the contents and make a decision to accept or not.