Experimental Physics and Industrial Control System
Subject: |
common API |
From: |
[email protected] (Kay Rehlich) |
Date: |
Tue, 09 Aug 1994 09:18:57 +0200 |
This is a response to the mail from Nick Karonis from 8/5/94.
On the last TESLA collaboration meeting on controls we decided to dev=
elop
and use a common API for all client programs. This was proposed by
Chip Watson (CEBAF). The idea is to hide the three different
communication protocols used in TESLA from the user program. One of t=
he
protocols is EPICS CA.
The alternative is to use a "protocol translators" rather than an API
for adapting the different systems. But, a translator increases
the network traffic about a factor of two. And, even more important,
the API would be a boost in portability of application programs.
I hope we come to a common solution for an open API and I am sure a=
=20
lot of people would appreciate such a progress.
Kay
---------------------------------------------------------------------=
---------
Some remarks on the goals of the API:
- The API should be "general". But, on the other hand it should be
simple to use for a beginner. A "one page description" for the basi=
c
calls (get and put) is a good idea and necessary. The API should hi=
de
inits, establishing/reconnecting of links and cleanup from the user=
.
But, the API should define advanced functionality also. Otherwise
we'll end up with several API=B3s. And it would be a big step from =
a
program which uses get=B3s and put=B3s only to make use of an=20
"advanced" function.
- The API should *not* be restricted to EPICS. It should cover most o=
f
the functionality of EPICS but must be open. At DESY we would like =
to
interface to our object oriented RPC based system. And I think call=
s
to the libdev and others should also be possible. In other words th=
e
API should be open for more existing communication protocols
and open for future developments.
- The internal layout of the API should allow to easily integrate
one, two or more protocols but hides this from the application. Thi=
s
could be done by a user call e.g. "get(args)"
which is mapped directly into "CAget(args)" or "DEVLIBget(args)" or
"RPCget(args)" by an implementation specific switch. All get=B3s ha=
ve the=20
same arguments. The lowest level implements the network call.
Possible software layers are :
=09get (args)=09=09=09=09=09<- C API
=09 |
=09get (args)=09=09=09=09=09<- C++ API
=09 |
=09switch =3D f(address)=09=09=09=09<- internal switch
=09 | | |
=09CAget(args) DEVLIBget(args) RPCget(args)=09<- net call
Remarks on the features of the API:
- An optional argument in get and put calls should be considered. The=
=20
option could select MONITOR rather than polling for instance.
- I think a general call to set options, e.g. TIMEOUT, is useful.
- A DevLib call 'devSend("S1AQ1","ON")' could be implemented in
the API as 'put("S1AQ1/ON", ...)'. "ON" is appended to the address
as a property and the data argument could be send with the message.
- This leads to the idea of a common addressing nomenclature. We are
using a "<facility>/<device>/<location>/<property>" form. This
allows simple queries by wild card characters to discover all
device names or all location of a device or all properties of a
device.
- The API *needs* a name discovery service to get the online availabl=
e
devices, locations/numbers or properties together with its data typ=
e.
- Not common but very useful is a data arg in a get call which is
send to the device. One needs it to specify different kinds of=20
ranges for instance.
Proposal for an object oriented API (C++):
The API needs three different classes:=20
1. a client API class with the get, put and other calls
2. an address class to specify and operate on the name
3. a data class which holds read and write data, error code etc.
Example for a read call :
EqData ed, result; EqAdr ea; EqClient eq;
ea.set_adr("TTF.VAC/PIRANI/BOX1/P"); // sets the name
eq.get(ea, result); // and read from the device
printf ("Pressure reading is: %s\n", result.string());
// prints out the reading as =
an
// ASCII string or the error =
msg
float f =3D result.get_float(); // return the same as float
int i =3D result.error(); // error code of call
time_t t =3D result.time_string(); // and time stamp
=20
Example for a read of historical data:
ea.set_adr("TTF.VAC/PIRANI/BOX1/P.HIST"); // sets the name
ed.time_range(<from_time>, <to_time>); // set time range of inter=
est
eq.get(ea, result, ed); // to read from the device
for (i=3D0; i < result.length(); i++ )
printf ("Pressure reading is: %g @ %s\n",=20
=09=09result.get_float(i), // value
=09=09result.time_string(i)); // and time stamp
=20
=20
The "get" call may have two, three or four arguments. The 3. arg =
is
optional data to the device e.g. a range specification. The 4.
arg is a transfer option.
The result data contains all info. With methods on the result
object one can read the error code, the length if data was an
array or the time stamp etc. There methods to get the data as
int, float or ASCII string etc. The conversion is done on the
client!
In addition one can consider "lightweight" calls which does not
store the address and data as methods in the client class :
=09int i =3D eq.devGet ("TTF.VAC/PIRANI/BOX1/P");
=09float f =3D eq.devGet ("TTF.VAC/PIRANI/BOX1/P");
and
=09eq.devPut ("TTF.VAC/PIRANI/BOX1/P", (int)123);
=09eq.devPut ("TTF.VAC/PIRANI/BOX1/P", 1.23);
=09eq.devPut ("S1AQ1/ON", TRUE);
This has to be specified for all simple data types. Because of
the C++ compiler abiltity to detect the different data types and
map them into different calls this seems to be a simple user=20
interface.
The following definitions are not complete! They should describe
the ideas only. The API is implemented in TTF already and running.
But it is extended by some new ideas. One new idea is the block
definition which comes from Nick Karonis mail. To implement this
the result data has to be transfered by reference. Before it was
result =3D get (...).
Definition of the API client class:
class EqClient {
public:
=09EqClient ();
=09~EqClient ();
=09get ( EqAdr* name, EqData& result, EqData* to=3D0, EqOption o=3D0)=
;
=09put ( EqAdr* name, EqData& result, EqData* to=3D0, EqOption o=3D0)=
;
+---- optional ------------+
=09=09// Discover names. The address contains wild cards.
=09=09// Results are in an array of "result".
=09names ( EqAdr* name, EqData& result, EqData* to=3D0, EqOption o=
=3D0);
+---- optional -----------=
-+
// Advanced commands:
=09=09// Block operations. The "get" and "put" calls
=09=09// between "begin_block" and "end_block" are executed
=09=09// and stored. A "update_block" call updates all
=09=09// data of the stored block. The option arg could
=09=09// specify a monitor. Default is polling. The result
=09=09// data contains the error code and the time stamp.
=09void=09begin_block ();
=09void=09end_block ();
=09void=09update_block ();
=09=09// Creates online a new device by cloning the=20
=09=09// existing one specified in the address. The name
=09=09// of the new device is in "data".
=09create ( EqAdr* name, EqData& result, EqData* to=3D0, EqOption o=
=3D0);
+---- optional ----------=
--+
=09=09// Set the options for all calls e.g. timeout.
=09void=09option ( char* option, EqData* parameter );
}
Definition of the address class:
class EqAdr {
public:
=09EqAdr( char* name =3D 0 );=09// constructor with optional
=09=09=09=09=09// name arg.
=09~EqAdr();=09=09=09// destructor
=09void=09name (char* name);=09// set the name
=09char* name();=09=09=09// return the name
// Advanced:
=09=09// With a nomenclature like ours some utilities
=09=09// are useful to set part of the name:
=09void=09set_facility ( char* facility_name );
=09void=09set_device ( char* facility_name );
=09void=09set_location ( char* facility_name );
=09void=09set_property ( char* facility_name );
=09=09// and to read back the parts:
=09char* facility();
=09char* device();
=09char* location();
=09char* property();
=09=09// To permit symbolic strings in names, e.g. $BASE,
=09=09// we define calls to define them. Symbols are
=09=09// global and valid in all instances of EqAdr.
=09void=09define (char* symbol_key, char* symbol_value);
=09void=09undefine (char* symbol_key);
=09=09// The address class holds a pointer to the lower
=09=09// communication class "EqObject". From this pointer
=09=09// one can get the CHID in case of EPICS and the
=09=09// type of the used protocol of this address. The
=09=09// EqObject pointer is mainly used for the=20
=09=09// implementation to hold a channel id etc. But,=20
=09=09// not for user programs (except for 'tricks' with the
=09=09// price of being not portable).
=09EqObject*=09service();
=09int=09=09type();=09=09// protocol type
=09=09// Possible implementation to get the CHID:
=09=09// s =3D service();
=09=09// id =3D s->chid(); ??
}
Definition of the data class:
=09=09// The data class depends very much on the data types
=09=09// to be transfered. This needs a loger discussion
=09=09// and I give a few examples only.=09
class EqData {
=09EqData();
=09~EqData();
=09=09// Set functions. Also used on the server side. The
=09=09// index arg is optional and used to address arrays.
=09=09// If data is a single value index is ignored.
=09void=09init ();=09=09// init the data (error=3Dlength=3D0..)
=09void=09error (int code);=09// set the error code
=09void=09time (time_t stamp);
=09void=09length (int l);
=09void=09set (int i, int index=3D0);=09// set integer arg
=09=09=09 +--optional-+
=09void=09set (float f, int index=3D0);=09// set float arg
=09=09=09 +--optional-+
=09
=09... sets for x/y, time stamped data, triplets etc.
=09=09// Get functions to read the data class:
=09int=09error();=09=09// error code
=09int=09length();=09=09// array or string length
=09time_t=09time();=09=09=09// time stamp in UNIX format
=09char*=09time_string();=09=09// time stamp as ASCII string
=09int=09type();=09=09=09// get native data type
=09char*=09type_string();=09=09// get native data type as string
=09int=09get_int ( int index=3D0 );// get as integer=20
=09=09=09 +-optional-+
=09... gets for x/y, time stamped data, triplets etc.
}
-----------------------------------------------------------------
*** **** ** * * Kay Rehlich =20
* * * * * * DESY, -MKV4- [email protected]
* * *** ** * Notkestrasse 85 Tel.: +49 40 8998 3456
* * * * * 22603 Hamburg FAX : +49 40 8998 4448
*** **** ** * Germany
-----------------------------------------------------------------
- Navigate by Date:
- Prev:
N.I. GPIB-1014 hack - was Granville-Phillips VG-307 vs GPIB Bill Brown
- Next:
Re: VxWorks development-license pricing Bob Dalesio
- Index:
<1994>
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
N.I. GPIB-1014 hack - was Granville-Phillips VG-307 vs GPIB Bill Brown
- Next:
common API William Lupton
- Index:
<1994>
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024