Grail: A Generic Programming Interface to the GBT
Grail Client | About SOAPpy | Current Open Issues | Code Review Results | Current Status
*WARNING:* Grail is not recommended for general use by astronomers! Instead, please use one of the APIs (Configuration, Observing, or Data Preprocessing). Grail is designed for use by programmers to help them write APIs and applications which are required to directly interface with the control system. Please notify RamonCreager and NicoleRadziwill if you are an astronomer who wishes to use Grail for application development.
Grail (which is neither Holy nor an acronym) is an Ygor service that provides a Simple Object Access Protocol (SOAP) interface to the M&C system. Using this interface, clients will be able to control all aspects of M&C operations. The Generic Interface will provide full access to Managers, their parameters and their samplers.
Why a SOAP based interface? SOAP provides a language neutral, OS neutral and architecture independent messaging and Remote Procedure Call (RPC) facility. To date, SOAP libraries are available for a variety of languages, including (but not limited to) C, C++, C#, Visual Basic, Delphi (Borland Pascal), ADA, Java, JavaScript, Python, Perl, Ruby, Tcl, SmallTalk and PHP. Implementations of these languages and SOAP libraries for them are available for all major operating systems: Win32, Unix (Linux, Solaris etc.), and Mac OS/X. Finally, because the SOAP protocol is implemented in XML using ASCII, it is completely architecture neutral (no byte alignment/endian issues, etc.) and human readable.
Grail in its current state (October 2003) has the following capabilities:
- You can access it using any programming language that supports SOAP. For the purposes of this discussion, Python will be used as the client language. The server itself is written in C++.
- It exposes full Manager interface
- It keeps a cache of all parameters for a given manager. If a new value is sent, it is only passed on to the manager if the new value differs from the old one.
- If you specify a bad M&C device, parameter or value for that parameter, you will get an error message
- Connections from the client to the SOAP adapter are made on a per-request basis: that is, when the client makes a request, the TCP connection is made. When the request is served, the connection is closed. There is no continuous connection between a client and the SOAP adapter.
- Returns device and sub-devices, retaining hierarchy between devices and sub-devices.
- Provides a polling-only interface to samplers.
The following capabilities may be added in the future. Some may not be appropriate for enhancements to this program.
- Full interface to Samplers
- Maintain connection with all devices, even after the latter have been reset or shut-off and have come back on-line.
- Provide callbacks for event notification (parameter changed, etc.)
- Show all parameter details: type, range of values etc.
- Document, through the interface, the SOAP adapter's services.
A client to Grail is easy to write in Python. Grail clients written in Python should run equally well on Windows, Linux, or Solaris. The only requirement is an appropriately configured Python 2.x installation that includes the SOAPpy (Python SOAP library) module. Nothing else is needed. (For the die-hard Perl fanatics out there, it should be just as easy to use Perl with SOAP::Lite to write Grail clients. Most of what follows on installing and running Python also applies to Perl).
The general Python installation currently does not include SOAPpy. Until this deficiency is rectified users wishing to run Grail clients have two choices: install their own copy of SOAPpy and use the global Python installation, or use the M&C Python installation that does include SOAPpy. To do the latter users must source /home/gbt7/igkya/igkya.bash every time prior to running Python.
Windows installations generally do not include Python at all. Thus, the first step is to instal Python 2.2 or above. ActiveState's ActivePython is a good choice. Next, install SOAPpy.
Python can be used interactively, or on the command line to run a script. To start up the Python interpreter, type python in the shell (ActiveState users can also use PythonWin, a nice Python interactive environment). Or, a Python script can be written in your favorite editor and executed later: python yourscript.py will work on both platforms.
Two Grail TaskMaster processes run on Vortex. Both should be up and running at all times. One, accessed through TCP port 18000, gives complete control to the client. The other, accessed at port 18005, is a read-only version.
NOTE: Grail is capable of controling any GBT M&C manager. Misuse of Grail can cause interference with legitimate use of the telescope! Always use either the read-only Grail on vortex, or your own copy of Grail in simulation mode, or your own copy on a telescope simulator (see below) when experimenting with its capabilities.
Those who wish to experiment with Grail but not use it to control telescope devices should checkout the code from CVS, compile it and run a separate copy of it in simulation mode on a solaris machine. Grail is located in the ygor source tree at ygor/user/Grail. It requires ygor libraries to link properly, so make sure your YGOR_ROOT is set appropriately.
Once compiled, you can use a couple of command line parameters to customize Grail's behavior:
- -s: Simulation mode. This runs Grail in a read-only mode. All parameter and sampler values can be read, but any call to modify anything on a manager will result in the call merely being echoed on stdout. When starting Grail with the
-s option, Grail will print a message stating that it is in simulation mode. Be sure to look for this message if you do not wish to control a manager! In the following example, the ToyTelescope manager 'Undulator' was turned on by a client, but Grail only prints out Undulator.on() without actually turning the manager on:
[rcreager@titan sparc-solaris]$Grail -s
NOTE: Grail is in simulation mode
Socket connection successful: master socket = 3
1: accepted connection from IP = 192.33.116.175 socket = 4
Undulator.on()
request served
- -p port: The port number you wish to have Grail listen for connections. Using this option allows you to avoid interference with a port already in use, and allows multiple copies of Grail to run on the same machine. NOTE: To find a free port, use the command
netstat -a and look for a free area, or netstat -a | grep port, if you have port in mind. If the port does not show up in the netstat output, it is probably OK to use it.
Grail will look for the environment variable YGOR_TELESCOPE, so an alternative way to experiment with Grail is to set YGOR_TELESCOPE to something other than the GBT. I use Mark Clark's ToyTelescope to test Grail during development.
- Find out names of all parameters with a manager (note the ./, convention when referring to managers; see section "Services" for an explanation)
>>> a = cl.show_params("LO1.LO1A")
>>> for i in a:
... print i
...
{u'name': 'asap', u'description': 'controls whether the manager starts as soon as possible'}
{u'name': 'requestedStartTime', u'description': 'target start time of next scan if asap flag is clear'}
{u'name': 'requestedStopTime', u'description': 'target stop time of next scan'}
{u'name': 'startTime', u'description': 'expected start time of the next scan'}
{u'name': 'scanLength', u'description': 'expected duration of next scan'}
{u'name': 'nextScanNumber', u'description': 'scan number of next scan'}
{u'name': 'scanNumber', u'description': 'scan number of current or last scan'}
{u'name': 'projectId', u'description': 'project identifier string < 16 char'}
{u'name': 'source', u'description': 'source identifier string < 32 char'}
(etc.)
- Poll a sampler on a manager (Note the empty string provided to reg_sampler() and unreg_sampler(). This is an optional callback URL, should the user wish to subscribe to the sampler.):
>>> cl.reg_sampler("TemperatureMonitor", "StructureTemp", "")
'OK'
>>> cl.get_sampler_value("TemperatureMonitor", "StructureTemp,gbtts1_2001")
'5.29'
>>> cl.get_sampler_value("TemperatureMonitor", "StructureTemp,MJD")
'52914'
>>> cl.get_sampler_value("TemperatureMonitor", "StructureTemp,seconds")
'71808.809368'
>>> cl.unreg_sampler("TemperatureMonitor", "StructureTemp", "")
'OK'
There are some common aspects of the Grail services that bear discussion
The names of most of the Grail SOAP methods are closely allied to the names of the corresponding Manager class methods. The exceptions are Grail methods that do not map to a Manager call. The biggest difference between Manager class method names and Grail method names is that Grail uses underscores to separate words, not capitalization. Also, one name in particular had to be changed (invoke() into invoke_param()) to avoid a name conflict with a SOAPpy proxy member function name.
The descriptions and explanations of most of these functions were taken outright from Manager.h, or are closely based on those explanations.
Ygor managers are named according to a 'major,minor' convention. Ygor managers can be part of a very shallow hierarchy of managers (coordinators and submanagers). Coordinators can have many submanagers. Submanagers cannot have their own submanagers. The 'major' portion of the name refers to the coordinator, and the 'minor' portion to the submanager. In single or top level managers, 'major' and 'minor' are the same. Grail reflects all this by requiring managers to be specified in a 'major,minor' format. For those managers where 'major' is the same as 'minor', Grail allows the shortcut of using only the 'major' portion. For example:
cl.on("LO1")
is the same as
cl.on("LO1,LO1")
A submanager must be named using the 'major,minor' format. 'LO1A' is not a shortcut for 'LO1,LO1A'.
NOTE: Grail allows either a period or a comma to delimit the manager names. For consistency with parameter paths, it is recommended that the comma be used.
Ygor parameters are dynamic objects that consist of many data elements. At this time, Grail cannot send or receive entire Ygor parameters in one function call. For this reason, and because it is often convenient to access single fields in a parameter, Grail supports the use of the Ygor TCL interface that allows individual fields in a parameter to be accessed using a field path. There are three simple rules in using field paths:
- A path must extend from the top and end in a field that does not posess sub-fields.
- Fields are represented by their names and separated from parent fields by commas, with no spaces between names and commas.
- Array elements are represented by numbers (1 based), delimited from the owning field by a comma. Again, no spaces should be used between names or indexes and commas.
Here is an example that shows both of these rules in action:
cl.get_value("Undulator", "dynamicParameter,1,a")
Here, we are accessing field 'a' of element '1' of a dynamic array 'dynamicParameter'.
Values are read simply by calling the get_value() function. This returns the latest value received from the manager by Grail. Grail does not support callbacks at this time, so parameter values must be polled.
Grail does not support callbacks at this time, so samplers must be polled to get values from them. A sampler must first be started before it is read. Once started, it can be read any number of times. When done, it is good practice to stop the sampler.
Calls to start and stop samplers are reference counted. That is, if sampler 'a' is started by one client, and then started again by another client, Grail only starts it once. It will however take 2 calls to unreg_sampler() to close the sampler.
Changing parameter values must be done one field at a time, using set_value(). This changes a copy of the parameter on Grail without actually modifying anything on the manager. Once all changes are made to the parameter(s), Grail must be told to send all modified parameters to the manager. This is done with a call to send_values(). Finally, the manager itself must be told to incorporate these new parameters. This may be done with reg_change() or any of its related functions.
For examples illustrating all of these actions, see the Sample Python Client Examples section.
- xsd:string abort(xsd:string device)
- xsd:string activate(xsd:string device)
- xsd:string check(xsd:string device)
- xsd:string clear_locks(xsd:string device)
- xsd:string conform(xsd:string device)
- xsd:string get_sampler_value(xsd:string device, xsd:string path)
- xsd:string get_value(xsd:string device, xsd:string path)
- xsd:string invoke_param(xsd:string device, int id)
- xsd:string off(xsd:string device)
- xsd:string on(xsd:string device)
- xsd:string prepare(xsd:string device)
- xsd:string recalculate(xsd:string device)
- xsd:string reg_change(xsd:string device)
- xsd:string reg_sampler(xsd:string device, xsd:string sampler, xsd:string cb_url = "")
- xsd:string reset(xsd:string device)
- xsd:string revert(xsd:string device)
- xsd:string send_values(xsd:string device)
- xsd:string set_lock(xsd:string device, int id)
- xsd:string set_value(xsd:string device, xsd:string path, xsd:string value)
- xsd:string set_values_array(ygor_parameter_array params)
- xsd:string set_values_list(ygor_parameter_list params)
- xsd:string vector show_managers()
- param_desc vector show_params(xsd:string device)
- param_desc vector show_samplers(xsd:string device)
- xsd:string standby(xsd:string device)
- xsd:string start_at(xsd:string device, grail:time_stamp starttime)
- xsd:string stop(xsd:string device)
- xsd:string stop_at(xsd:string device, grail:time_stamp stoptime)
- xsd:string sync(xsd:string device)
- xsd:string unlock(xsd:string device, int id)
- xsd:string unreg_sampler(xsd:string device, xsd:string sampler, xsd:string cb_url = "")
This method places the Manager into a Aborting state which initiates any activity needed to stop the operation of a system. This is a transistion state and would be immediate for Managers that require no shutdown actions, i.e., have no need to for cleanup or resetting between scans. This is almost always relevant only for "synchronous" systems. The rule here is to halt the system as quickly as possible. Also in a Coordinator, unlike stop(), abort() is unconditional(), i.e., the command is acted on whenever possible, and passed on to child Managers.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method initiates Activating by loading the current ControlParameter values, which have been touched since the last activate(), into the system which begins all the requisite activity. It will fail if either the system is not in the correct state, or the Manager contains any ControlParameter with an illegal value.
Non-synchronous servers almost in all cases cause the Manager to move quickly from Activating to Ready.
Synchronous servers may cause significant latencies in the Manager in Activating and Committed before entering Running.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method calls all of the check methods for this Manager without setting the associated legal flags.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
Clear the locking of all Parameters.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method makes the Manager's ControlParameters consistent regardless of new value or manual flags, i.e., it execute all dependency methods. It is possible to create computational inconsistencies within a Manager by manually setting a the value of a ControlParameter which would have normally been computed using other ControlParameters. This method forces all dependencies calculations to take place rather than just the ones from ControlParameters with new values.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
Returns the value of a field specified by path of a sampler on manager device. reg_sampler(device) should be called before this function is called, and unreg_sampler(device) should be called after the last call to this function.
Note that all samplers have a TimeStamp associated with them. Though the TimeStamp are not really a part of the sampler, they can be accessed as if they were. For example, 'sampler_name,MJD' will return the MJD portion of the TimeStamp associated with the sampler.
xsd:string device: The name of the manager.
xsd:string path: The path of the sampler field.
An xsd:string representing the value of the sampler field if all went well, error message if not. The ASCII value representation will make sense to the type of value being returned. A double may be returned as '9.8e3', whereas an int would be returned as '9800'
>>> cl.reg_sampler("TemperatureMonitor", "StructureTemp")
'OK'
>>> cl.get_sampler_value("TemperatureMonitor", "StructureTemp,MJD")
'52934'
>>> cl.get_sampler_value("TemperatureMonitor", "StructureTemp,seconds")
'68353.605198'
>>> cl.get_sampler_value("TemperatureMonitor", "StructureTemp,gbtts1_2001")
'5.5'
>>> cl.unreg_sampler("TemperatureMonitor", "StructureTemp")
'OK'
Returns the value of a field specified by path of a parameter on manager device. Grail registers a callback for every parameter on every manager that it is connected to, so the value returned by get_value() is always current.
xsd:string device: The name of the manager
xsd:string path: The path of the sampler field.
An xsd:string representing the value of the sampler field if all went well, error message if not. The ASCII value representation will make sense to the type of value being returned. A double may be returned as '9.8e3', whereas an int would be returned as '9800'
Writes the specified ControlParameter to hardware if an activate method has been defined for it regardless of legality or whether it has been touched. This method is used by AutoParameters, and for engineering and debugging purposes.
(This is the one function whose name has been substantially changed from the corresponding Manager member function name. On a Manager, it is known as invoke(). This conflicts with a member function name in the SOAPProxy class of SOAPpy, so I have renamed it.)
xsd:string device: The name of the manager
int id: The numeric ID of the parameter (O based)
An xsd:string, 'OK' if all went well, error message if not.
Places Manager into 'Off' state from 'Ready' or 'Standby', i.e., the software disconnects from the "real world," e.g., hardware drivers.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
Places Manager into 'Ready' state from 'Off' or 'Standby'. This allows the Manager to be activated.
In preparation for the software to take control of the device this method recomputes all values and set each Parameter as touched, i.e., to be activated.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
Prepares for a scan without starting it. This method is an aggregate command: it sets the Parameters requestedStartTime, requested StopTime?, and asap; and then calls regChange() and activate().
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method works just like regChange except within Panels it is not associated with getTouchedValues() calls nor is the value of asap checked.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method register changes in the Manager, i.e., call the ControlParameters' dependency and check methods. This method causes the Manager to compute the values of all ControlParameters dependent on any other ControlParameter whose value has been reset. It also causes the ControlParameters' check methods to be called. A typical use would to be call set_value() for all the ControlParameters affected by one command followed by a call to send_values() and a call to reg_change() to completely reflect the action.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method activates all of the active ControlParameters regardless whether they have been modified.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method returns the ControlParameters to values at the last successful activate(). Whenever activate() is invoked, the current value of all of the ControlParameters of a Manager are saved. The method revert() returns all Parameters to the saved value and therefore brings the Manager back into a state consistent with the system as last activated.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
This method goes through all the local copies of parameters for the specified manager and sends the ones that have been modified by the client to the manager using the Ygor Manager::newParam() method.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
Locks a parameter, specified by its index. Once locked, a parameter cannot be changed.
xsd:string device: The name of the manager
int id: The 0-based index number of the parameter.
An xsd:string, 'OK' if all went well, error message if not.
Modifies a local copy of a parameter in Grail. This does nothing to update the parameter on the manager itself. Once all parameters have been localy modified to the client's satisfaction, the client can then call send_values() to have Grail go through all local copies of parameters for that manager and call the Ygor PanelRemote::newParam() for each modified parameter. Finally, the client must call one of the functions that registers the new parameters (reg_change(), activate(), prepare(), etc.)
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
Provides a way to configure the M&C managers all in one call. set_values_array() accepts an array, each element of which specifies a manager, parameter path, and value for that path. I then does the following:
- Updates the local copies of the parameters, just as set_value() does.
- Checks the state of each manager in the list. If it is 'Off' or 'Standby', it turns the manager on. Regardless of whether it turned it on or not, it waits for the manager's state to change to 'Ready'
- If the Scan Coordinator was one of the managers in the list, it will prepare() it and it alone. If not, it will prepare() every manager in the list.
set_values_array() will compile and return a list of anything that went wrong during the process. Even if set_values_array() encounters an error, it will proceed with processing the remaining elements in the list.
ygor_parameter_array params: An array of ygor_parameters, which is a structure that consists of 3 fields: device, path, and value.
An xsd:string, 'OK' if all went well, error message if not.
This example client code in Python sends an array of manager/path/value structures to Grail for action. In SOAPpy, sending complex structures to a SOAP server is best done with the types in the SOAPpy Types module. This example creates an array type Types.arrayType(), and adds structure elements of type Types.structType(). To make the example simpler, I've written a helper function mkypv() that given the 3 values creates the Types.structType().
>>> from SOAPpy import *
>>> def mkypv(d, p, v):
... a = Types.structType()
... a._typename = "anyType"
... a._addItem("device", d)
... a._addItem("path", p)
... a._addItem("value", v)
... return a
...
>>> cl = SOAPProxy("http://titan:18000", namespace="urn:grail")
>>> U = "Undulator.Undulator"
>>>
>>> a = Types.arrayType()
>>> a.append(mkypv(U, "levelHW", "15.6"))
>>> a.append(mkypv(U, "dynamicParameter,1,a", "666.666"))
>>>
>>> cl.set_values_array(a)
'OK'
>>>
set_values_list() does exactly the same thing as set_values_array() does. The only difference is that it accepts a linked list of ygor_parameters instead of an array of them.
ygor_parameter_list params: A linked list of ygor_parameters, which is a structure that consists of 3 fields: device, path, and value. There is no Python example at this time.
An xsd:string, 'OK' if all went well, error message if not.
Returns an array of xsd:strings, listing every manager available in the M&C system. Each string lists one manager in the system in 'major.minor' format.
No parameters.
An array of xsd:string, each one of which is a manager name.
>>> for i in cl.show_managers():
... print i
...
QDDataAcquisition.QDDataAcquisition
ScanCoordinator.ScanCoordinator
Archivist.Archivist
SwitchingSignalSelector.SwitchingSignalSelector
DCR.DCR
Holography.Holography
SpectralProcessor.SpectralProcessor
SpectralProcessor.SpStorage
SpectralProcessor.SpectralProcessorA
(etc.)
Returns an array listing every parameter of the specified manager.
xsd:string device: The name of the manager
An array of param_desc, which currently is a structure containing two xsd:strings:
*=name=, which is the parameter name.
*=description=, which is the description of the parameter, as given in the manager's DDL.
>>> for i in cl.show_params("TemperatureMonitor"):
... print i
...
{u'name': 'asap', u'description': 'controls whether the manager starts as soon as possible'}
{u'name': 'requestedStartTime', u'description': 'target start time of next scan if asap flag is clear'}
{u'name': 'requestedStopTime', u'description': 'target stop time of next scan'}
{u'name': 'startTime', u'description': 'expected start time of the next scan'}
{u'name': 'scanLength', u'description': 'expected duration of next scan'}
{u'name': 'nextScanNumber', u'description': 'scan number of next scan'}
{u'name': 'scanNumber', u'description': 'scan number of current or last scan'}
{u'name': 'projectId', u'description': 'project identifier string < 16 char'}
{u'name': 'source', u'description': 'source identifier string < 32 char'}
{u'name': 'scanId', u'description': 'scan identifier string < 32 char'}
{u'name': 'recipientNumber', u'description': 'number of clients of Manager'}
{u'name': 'state', u'description': 'current operational state of Manager'}
{u'name': 'debugLevel', u'description': 'controls the level of debug printing'}
{u'name': 'status', u'description': 'summarizes the severity of the Message levels'}
{u'name': 'reboot_concentrator', u'description': 'reboots concentrator for a given temperature sensor'}
{u'name': 'configure_concentrator', u'description': 'configures concentrator for a given temperature sensor'}
>>>
Returns an array listing every sampler on the specified manager.
xsd:string device: The name of the manager
An array of param_desc, which currently is a structure containing two xsd:strings:
*=name=, which is the sampler name.
*=description=, which is the description of the sampler, as given in the manager's DDL.
>>> for i in cl.show_samplers("TemperatureMonitor"):
... print i
...
{u'name': 'StructureTemp', u'description': 'Temperature Sensor readings'}
Places Manager into 'Standby' state from 'Off' or 'Ready'. This allows a Manager to be connected to hardware for monitoring, but ignored for purposes of scanning since activate() is ignored.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
>>> cl.standby("Undulator")
'OK'
Starts a scan at the given time or as-soon-as-possible if the time is zero. The starting time is given through a time stamp structure (see Parameters).
xsd:string device: The name of the manager
grail:time_stamp: The starting time. This is given through the fields of this structure, which match the Ygor TimeStamp class data members and have the same name:
-
theMJD: an int, holds the Modified Julian Day.
-
theSec: a double, holds the seconds elapsed in the day
-
refFrame: an int, can be one of the following values:
- 0: NOREF
- 1: UTC
- 2: UT0
- 3: UT1
- 4: UT2
- 5: GAST
- 6: GMST
- 7: LAST
- 8: LMST
-
units: an int, determines what unit theSec is in. This can be one of:
- 0: NOTSET
- 1: SECS
- 2: MSEC
- 3: USEC
- 4: NSEC
An xsd:string, 'OK' if all went well, error message if not.
In the following example, a Types.structType() is constructed to hold the time stamp fields. This structure is part of the SOAPpy module that must be imported before SOAP can be used. Note the _typename field. If this is not set to "anyType", Grail expects the typename to match the name of the structure in Grail. This is touchy and not needed. All that is required is that the field names match. It is planned that the fields refFrame and units default to 1 as well, so that the client will not have to set these.
>>> from SOAPpy import *
>>> cl = SOAPProxy("http://titan:18000", namespace="urn:grail")
>>> ts = Types.structType()
>>> ts._typename = "anyType"
>>> ts.theMJD = 52929
>>> ts.theSec = 45000.0
>>> ts.refFrame = 1
>>> ts.units = 1
>>> cl.start_at("Undulator", ts)
'OK'
>>>
Tells Grail to start receiving data from the specified sampler on the specified manager. Grail then receives this data automatically from the specified sampler. Grail does not yet support callbacks, so get_sampler_value() must be used to retrieve the latest values received.
The first time reg_sampler() is called, it will start a Monitor receiving the sampler data. Subsequent calls to reg_sampler() merely increase a reference count to that sampler. When the client is done with the sampler, it must call unreg_sampler(). This will decrease the reference count, and when it reaches 0, stop the Monitor from receiving data from that sampler. This reference counting scheme is used to allow different clients to get data from samplers without running multiple Monitors for the sampler, and to keep the Monitor running until the last client is done with it.
- xsd:string device: The name of the manager
- xsd:string sampler: The name of the sampler
- xsd:string cb_url: An optional callback URL. When callbacks are implemented, this URL will be used by Grail to direct sampler data to a client supplied SOAP server that will handle the sampler data. This parameter defaults to "", and need not be provided. Note that if it is provided as other than "", the same string must be provided to unreg_sampler()!
An xsd:string, 'OK' if all went well, error message if not.
>>> cl.reg_sampler("TemperatureMonitor", "StructureTemp")
'OK'
See get_sampler_value() for a complete example.
This method places the Manager into a Stopping state which initiates any activity needed to stop the operation of a system. This is a transistion state and would be immediate for Managers that require no shutdown actions, i.e., have no need to for cleanup or resetting between scans. This is almost always relevant only for synchronous systems. The rule here is to halt the system as sanely as
possible.
xsd:string device: The name of the manager
An xsd:string, 'OK' if all went well, error message if not.
>>> cl.stop("DCR")
'OK'
Starts as-soon-as-possible, but stops at the given time (if the time is zero then it is equivalent to a startAt() with a time of zero. The stop time is given through a time stamp structure (see Parameters).
xsd:string device: The name of the manager
grail:time_stamp stoptime: The stop time. This is given through the fields of this structure, which match the Ygor TimeStamp class data members and have the same name:
-
theMJD: an int, holds the Modified Julian Day.
-
theSec: a double, holds the seconds elapsed in the day
-
refFrame: an int, can be one of the following values:
- 0: NOREF
- 1: UTC
- 2: UT0
- 3: UT1
- 4: UT2
- 5: GAST
- 6: GMST
- 7: LAST
- 8: LMST
-
units: an int, determines what unit theSec is in. This can be one of:
- 0: NOTSET
- 1: SECS
- 2: MSEC
- 3: USEC
- 4: NSEC
An xsd:string, 'OK' if all went well, error message if not.
In the following example, a Types.structType() is constructed to hold the time stamp fields. This structure is part of the SOAPpy module that must be imported before SOAP can be used. Note the _typename field. If this is not set to "anyType", Grail expects the typename to match the name of the structure in Grail. This is touchy and not needed. All that is required is that the field names match. It is planned that the fields refFrame and units default to 1 as well, so that the client will not have to set these.
>>> from SOAPpy import *
>>> cl = SOAPProxy("http://titan:18000", namespace="urn:grail")
>>> ts = Types.structType()
>>> ts._typename = "anyType"
>>> ts.theMJD = 52929
>>> ts.theSec = 45000.0
>>> ts.refFrame = 1
>>> ts.units = 1
>>> cl.stop_at("Undulator", ts)
'OK'
>>>
Stops the Monitor on Grail from receiving sampler data from the specified device and sampler. See reg_sampler() and get_sampler_value() for more on how to access samplers.
- xsd:string device: The name of the manager
- xsd:string sampler: The name of the sampler
- xsd:string cb_url: An optional callback URL. When callbacks are implemented, this URL will be used by Grail to direct sampler data to a client supplied SOAP server that will handle the sampler data. This parameter defaults to "", and need not be provided. Note that if it is provided as other than "", the same string that was provide to reg_sampler() must be provided here.
An xsd:string, 'OK' if all went well, error message if not.
>>> cl.unreg_sampler("TemperatureMonitor", "StructureTemp")
'OK'
See get_sampler_value() for a complete example.
This function calls RPC procedure 0 for the specified device's PanelServer interface. If the PanelServer responds, it returns 'OK', and if not, it returns 'FAILED'. This is a useful diagnostic in determining if the Manager is actually running and responsive.
xsd:string device: The name of the manager
An xsd:string, 'OK' if the Manager responded, 'FAILED' if not.
>>> cl.sync("Spectrometer")
'OK'
Unlocks a parameter that has been locked by set_lock().
xsd:string device: The name of the manager
int id: The 0-based index number of the parameter.
An xsd:string, 'OK' if all went well, error message if not.
>>> cl.lock("DCR", 34)
'OK'
-- RamonCreager - 22 Oct 2003
|
Revision r1.20 - 23 Feb 2005 - 18:27 GMT - RamonCreager
|
Content copyright © 1999-2007 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
|
| |