Difference between revisions of "V4 CA Client User Interface"

From EPICSWIKI
(Split DataListener off)
Line 62: Line 62:
* DataAccess = getData(property_list)<BR> Waits for the data.
* DataAccess = getData(property_list)<BR> Waits for the data.
* getDataNotify(property_list)<BR>  Will invoke DataListener once data arrives.
* getDataNotify(property_list)<BR>  Will invoke DataListener once data arrives.
* addDataListener(dn), removeDataListener(dl)<BR>  The data listener is invoked with the channel and the data access interface to the actual data.<br> In addition, does it include event information, so when it's in response to a subscription (see below), we know why the data was sent? Or is that event information embedded in DataAccess?
* addDataListener(dn), removeDataListener(dl)
 
=== Data Listener Interface===
The data listener is invoked in response to an async. 'get' as well as a subscription update and contains the following:
* Channel that send this notification
* DataAccess interface to the data
* Reason for the update
** event 'x'
** channel is disconnected
** access rights changed
** channel moved to different IOC


=== Channel, Subscription Related Methods ===
=== Channel, Subscription Related Methods ===

Revision as of 22:55, 23 June 2005

Channel Access Client User Interface

Under V4, a ProcessVariable would no longer be limited to the current properties 'value', 'units', ... but allow the users to create CA servers and clients that understand new properties.

The low-level V4 CA client API is likely to be rather complex because it now needs to handle arbitrary property catalogs.

  • There still needs to be an easy to use high-level API, not much more complex than the existing one.
  • There needs to be access to CA from languages like Matlab in a way that's as easy as
pv = caopen('fred');
value = caget(pv);

Food for thought

Is there anything we can learn from other communication libraries?

Skeleton API

What follows is in the form of pseudo classes and associated methods that a CA client API should provide.

Directory Server

  • setServer(string URL-type-server-address)
    Optional; otherwise some site-specific default name server is used. That 'URL' might contain a user & password, which decides if this name server connection is read-only (for OPI clients) or if writes are allowed (for IOCs that add PVs to the name server).
  • getChannelInfo(string PV_or_pattern)
    Returns list of
    • CA server - IP & port of server that has the PV
    • quality - is this the IOC, a gateway, backup/primary
  • addChannelInfo(string PV, CASInfo addr_and_port, CASType primary_or_backup_or...)
    Used by CA servers to register their PV in directory
  • deleteChannelInfo(string PV, CASInfo addr_and_port, CASType primary_or_backup_or...)
    Used by CA servers to remove their PV from directory

Data Access

All the data is accessed via DataAccess, which handles the introspection of arbitrary data types. It should provide the following convenience routines in addition to whatever more efficient methods it might have (which use hash IDs instead of strings to access properties, use magic copy routines ins:

  • list<string> getProperties()
    Get a list of all the properties
  • type_info getType(string property)
  • bool hasWriteAccess(string property)
  • string getAsString(string property)

Channel, General Methods

  • Channel(string name)
    Constructor. Channel has to have a name.
  • getName()
    Returns the name of the channel.

Channel, Connection Related Methods

One idea is that - in contrast to the V3 API - the user shouldn't have to connect at all. The first 'get' or 'put' will try to connect. A disconnect is a special type of data notification, not a separate connection callback.

  • setDirectory(string directory_URL)
    Use specific directory server, otherwise the default one is used.
  • setServer(CA server info)
    Attempts to connect & maintain the connection with specific server. Otherwise, the directory is queried.
  • bool isConnected()
    .. for those who want to poll
  • xxx getServerInfo(), xxx getType()
    .. only valid when isConnected().
  • setUser(), ...
    Sets/changes the 'user' that determines the access rights, allowing OPI tools to adjust this per-channel at runtime.

Channel, 'Put' Related Methods

  • put(new value)
    Sends data to the server.
    Returns error if currently disconnected or other local problem, no other feedback wether the value actually reached the server.
  • putNotify(new value), putCompletionNotify(new value)
    Sends the value to the server, invokes putNotification when receiving record has received the value respectively all the processing triggered by the new value has completed.
  • addPutListener(pnl), removePutListener(pnl)
    Need to register listener to actually receive the put*Notify info.

Channel, 'Get' Related Methods

  • DataAccess = getData(property_list)
    Waits for the data.
  • getDataNotify(property_list)
    Will invoke DataListener once data arrives.
  • addDataListener(dn), removeDataListener(dl)

Data Listener Interface

The data listener is invoked in response to an async. 'get' as well as a subscription update and contains the following:

  • Channel that send this notification
  • DataAccess interface to the data
  • Reason for the update
    • event 'x'
    • channel is disconnected
    • access rights changed
    • channel moved to different IOC

Channel, Subscription Related Methods

  • addSubscription(event, filter)
    • event: alarm condition change, some hardware event (like blue beam).
      Is this still simply a bit mask, and one needs detailed info from the IOC to know that 'blue beam' == bit 14?
    • filters: min/max period, range, rate of change, absolute change
  • cancelSubscription(event, filter)

The idea is that the end result of a subscription is just like a getDataNotify, invoking the dataListener, except that a subscription will typically return data more than once. One can add more then one subscription to the same channel.

Container

The Channel does not store any data from a 'put', 'get' or subscription. When attaching a container to a channel, the container will subscribe to the channel and keep a copy of all data, so one can always ask the container for the current values.

  • attach(channel)
  • detach()
  • implements the DataAccess interface to allow access to the data.

caget 101

This is how a simple 'caget' could be written:

Channel channel("fred"); 
DataAccess da = channel.get("value");
cout << "Value of " << channel.getName() << " : " << da.getAsString("value") << "\n";
channel.disconnect();