127 lines
5.9 KiB
OpenEdge ABL
127 lines
5.9 KiB
OpenEdge ABL
\subsubsection{The Tcl Environment Driver}
|
|
Sometimes a quick way for defining an environment
|
|
device driver is needed. A suitable way for doing this
|
|
is to define the device driver in the SICS servers Tcl macro language. Then
|
|
a device driver can even be developed and tested offline from a psish before
|
|
inclusion in the server. Clearly a means of communication between SICs and
|
|
the actual device is needed. Usually this communication happens via
|
|
a RS--232 serial port. Such a communication is catered for by the SICS
|
|
serialport command. This section describes the environment device driver
|
|
which links the SICS C code with Tcl. For each of the device drivers
|
|
functions a C language wrapper function is provided, which in turn calls
|
|
the Tcl interpreter with some parameters. This scheme is initialised by
|
|
providing the Tcl environment device driver with the name of a Tcl array
|
|
which has to hold Tcl implementations for all the necessary driver functions.
|
|
The name of this array will also be passed to each of the Tcl procedures as
|
|
first parameter. The Tcl procedures to define for a Tcl driver are:
|
|
\begin{description}
|
|
\item[Init] to be called at initialisation of the driver. This Tcl procedure must connect
|
|
to the device and prepare it for accepting further commands. The parameters to
|
|
init are all the parameters still left in the command line after the name
|
|
of the Tcl array in the EVFactory command line.
|
|
\item[Close] should close down the connection to the device after bringing the
|
|
device into a clean state.
|
|
\item[SetValue] will be called with a float value as second parameter. It
|
|
should issue a command to set the device to a new value. The return value is an
|
|
integer error code, defined by the driver. Error returns use the normal Tcl mechanism
|
|
with the Tcl error command. On errors a negative error code defined by the driver
|
|
must be returned.
|
|
\item[GetValue] reads the current value from the device. The return value is
|
|
either the floating point value of the current control variable or the
|
|
string pending if the request is still pending. In case of failure an error
|
|
is returned with a negative integer error code.
|
|
\item[Send] should concatenate all parameters and send them down to the
|
|
device. Returns error codes as described above.
|
|
\item[GetError] gets as a parameter the negative error code possibly returned
|
|
from one of the calls above. GetError should return a textual description
|
|
of the error.
|
|
\item[TryFixIt] gets as a parameter a negative error code as returned from one
|
|
of the calls described above. TryFixIt should do everything possible in
|
|
software to get the device working again: perhaps send some commands,
|
|
reopen the connection or whatever apropriate. Depending on the success
|
|
of this TryFixIt returns either DEVREDO if the command shall be resend or
|
|
DEVFAIL if the problem cannot be fixed without human intervention.
|
|
\item[Wrapper] This function will will be called by the environment variable
|
|
interpreter wrapper function before the general part of the wrapper
|
|
function gets executed. Its purpose is the handling of subcommands special
|
|
to the specific environment device. For instance modifying its mode of
|
|
operation or setting special variables not covered in the general
|
|
environment device setup. It has to return 1 on success, 0 on failure. On
|
|
failure it has to print error messages as well.
|
|
\end{description}
|
|
|
|
In order to do all this a new driver must be defined. This driver needs the
|
|
following data structure:
|
|
|
|
@d tclevdat @{
|
|
typedef struct __TclEv {
|
|
char *pArray;
|
|
char *pInit;
|
|
char *pClose;
|
|
char *pSetValue;
|
|
char *pGetValue;
|
|
char *pSend;
|
|
char *pGetError;
|
|
char *pTryFixIt;
|
|
char *pWrapper;
|
|
char *pName;
|
|
Tcl_Interp *pTcl;
|
|
int iLastError;
|
|
} TclEv, *pTclEv;
|
|
@}
|
|
|
|
The fields correspond to the names of the Tcl functions to call for each of the
|
|
functions specified above. Plus the name of a Tcl array used for storing
|
|
driver special data in Tcl. iLastError will be used to keep the last error code.
|
|
pName is the name of the device in SICS. This will be copied into the
|
|
Tcl-array describing the device as MyName. May be used to set general
|
|
evcontroller parameters from within driver code and for error messages.
|
|
|
|
SICS sees this driver through the following interface:
|
|
@d tclevint @{
|
|
pEVDriver CreateTclDriver(int argc, char *argv[],char *pName, SConnection *pCon);
|
|
int UpdateTclVariable(pEVDriver self, char *name, float fVal);
|
|
|
|
int TclEnvironmentWrapper(SConnection *pCon, SicsInterp *pSics,
|
|
void *pData, int argc, char *argv[]);
|
|
@}
|
|
\begin{description}
|
|
\item[CreateTclDriver] creates the Tcl driver and initialises it.
|
|
\item[UpdateTclVariable] will be called from the general environment
|
|
variable parameter update code in order to allow updating of Tcl variables
|
|
as well.
|
|
\item[TclEnvironmentWrapper] is the interpreter wrapper function for a Tcl
|
|
driver.
|
|
\end{description}
|
|
|
|
@o tclev.h @{
|
|
/*---------------------------------------------------------------------------
|
|
T C L E N V I R O N M E N T
|
|
|
|
This is the header file for an environment device driver defined in
|
|
the Tcl macro language. Dor more details see tclev.tex
|
|
|
|
copyright: see copyright.h
|
|
|
|
Mark Koennecke, February 1998
|
|
------------------------------------------------------------------------------*/
|
|
#ifndef SICSTCLEV
|
|
#define SICSTCLEV
|
|
|
|
@<tclevint@>
|
|
|
|
#endif
|
|
|
|
|
|
@}
|
|
@o tclev.i @{
|
|
/*---------------------------------------------------------------------------
|
|
Tcl environment device driver data structure definition file.
|
|
|
|
No general usable header file.
|
|
|
|
Mark Koenencke, February 1998
|
|
----------------------------------------------------------------------------*/
|
|
@<tclevdat@>
|
|
@}
|