Документ взят из кэша поисковой машины. Адрес
оригинального документа
: http://www.apo.nmsu.edu/35m_operations/MC2/TclActorInternals.html
Дата изменения: Wed Jul 9 22:07:55 2008 Дата индексирования: Sat Apr 9 23:26:29 2016 Кодировка: Поисковые слова: п п п п п п п п п п п п п п п п п п п п п п п п п п |
TclActor is a set of classes that allow one to write an actor for the 3.5m control system. An actor can be a script running in the hub (aka "tron") or an Instrument Control Computer (ICC) running elsewhere.
This manual is intended to help people writing actors based on TclActor. In addition there is a manul describing the user interface: TclActor.
TclActor is written in Python and uses the tcl event loop (via Tkinter) for cooperative multitasking. This is as opposed to Actor, the original hub actor that used multithreading. Cooperative multitasking generally results in simpler code than multithreaded code. However, one must be careful not to take too long while handling a particular event.
TclActor is intrinsically asynchronous. Thus, to the extent that the underlying hardware controllers support it, an actor based on TclActor can execute multiple commands at the same time. If a new command is received while an old command is executing then the new command will either be accepted (if compatible) or rejected (if not). Note that it will *not* be queued up; this simplifies programming and removes the need for commands to report and clear the queue.
Commands must be in the following format: [cmdId [msgId]] [verb [arguments]] where:
Replies must be in hub-standard format (reference?) and prefixed with cmdID userID.
Warning: Replies that indicate the end of a command (using message code ":" or "f") must be prefixed with the correct cmdID and userID. If you fail to do this the user has no way of knowing the command is finished! (On the other hand, cmdID and userID are not important for messages that indicate status; you may use 0 for either or both if that is more convenient.)
An actor typically controls one or more devices. For example an Instrument Control Computer (ICC) controls an imager and often a filterwheel or slit turret. A hub actor typically controls an ICC or other hardware controller.
For each device controlled by your actor: write a software representation of this device as a sublcass of TclActor.Device or TclActor.TCPDevice. This is a very important part of the actor; expect to spend 50-80% of your time on this task.
The device code tends to fall into several categories: code to support executing commands, code to handle replies and code to represent the internal state of the device.
One thing to keep in mind while writing your device code is: which actor commands can the device handle directly? You can specify these using the cmdInfo argument.
Write one actor as a sublcass of TclActor.Actor. This contains the list of devices your actor controls and code to execute certain commands called "local commands"...
Local commands are commands implemented as methods of your actor class. Each such method must be named cmd_verb where verb is the command verb. The first line of the doc string for that method is the help for that command (as printed by the command "help"). Each method that implements a local command must return True if the command executes in the background; otherwise the command is reported as finished when the cmd_ method ends.
Note that TclActor.Actor implements several local commands; do not override these unless you are sure you know what you are doing. These include:
Actor class methods include:
As each command string is received by the actor it is parsed and turned into a UserCmd object. This object contains:
The actor then executes the UserCmd object as follows:
This verifies that the new command is compatible with whatever else is going on at the time. If there are conditions that prevent a command from executing then you should override checkLocalCmd and add code to detect this (though you may put such code into the code for the command itself if you prefer).
You may also put code in checkLocalCmd to supersede other commands. But that is more likely to be done in the code that executes a particular command.
For a local command this is in a method called cmd_verb where verb is the command verb. This code should:
To report a UserCmd as finished call cmd.setState("done") or cmd.setState("failed") as appropriate (note that you can provide an explanatory message at the same time; this is highly recommended if the command fails). The Actor keeps track of the state of each UserCmd and will report the command as finished and then delete the command.
In addition whenever you call newCmd on a device it creates a DevCmd which is very similar to a UserCmd but with slightly different information. It is possible to tie a UserCmd to a DevCmd such that the state of the former tracks the state of the latter. This is especially useful when a user command can be directly handled by a device (perhaps after some initial massaging).
Note that you will probably have to provide a device callback to track each DevCmd and delete it when it is finished (or has timed out).