Документ взят из кэша поисковой машины. Адрес
оригинального документа
: http://www.apo.nmsu.edu/Telescopes/twistedActor/writingAnActor.html
Дата изменения: Fri Aug 29 22:08:58 2014 Дата индексирования: Sat Apr 9 23:26:52 2016 Кодировка: Поисковые слова: п п п п п п п п |
This manual describes the details of writing an actor based on twistedActor.
The general issue of writing an actor (such as an instrument control computer) is described in Instrument Control Computer Design. Please make sure you understand this material before proceeding.
twistedActor is written in Python and uses Twisted framework for communications and event-based multitasking. Event-based multitasking generally results in simpler code than multithreaded code. However, one must be careful not to take too long while handling a particular event.
twistedActor is intrinsically asynchronous. Thus, to the extent that the underlying hardware controllers support it, an actor based on twistedActor 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). I do not recommend queueing commands unless you must; avoiding queueing simplifies programming and removes the need for adding commands to report and clear the queue.
Commands must be in the following APO-standard format:
[cmdID [msgID]] [cmdBody]]
where:
In addition, the default parser in Command.UserCmd subdivides cmdBody into a command verb and arguments:
[cmdVerb [cmdArgs]]
where:
cmdVerb cmdArgs is used by most actors at APO (not including the TCC). Please use it if possible. However, if you have need a different format then you may implement it as follows:
Replies must be in hub-standard format 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 twistedActor.Device or twistedActor.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 twistedActor.Actor or twistedActor.BaseActor. Actor is suitable for the typical actor on the mountain; it contains a command dispatcher that assumes commands consist of a verb and arguments. BaseActor requires you to write your own command dispatcher and thus makes fewer assumptions about the command format.
Both classes are described in more detail below
BaseActor is a minimalistic actor class. It accepts connections from users, parses commands and has methods that will issue replies to commands. However, it has no command dispatcher and makes few assumptions about the command format.
Command parsing is performed by the UserCmdClass class attribute. The default is Command.UserCmd, which uses a command format describe above under Commands. A user command must contain the following fields (see also Commands above):
In addition, the default Command.UserCmd contains these fields:
BaseActor calls dispatchCmd to dispatch the command. However, it does not include an implementation of this method; your subclass must override it. Actor (described below) does includes an implementation of dispatchCmd that you can probably use as is.
BaseActor/Actor methods include:
Actor is a subclass of BaseActor. It has many more capabilities and, in most cases, will be the most suitable class to subclass for your own actor.
Actor 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 subclass. 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 Actor implements several local commands; do not override these unless you know what you are doing. These include:
The full list is documented in twistedActor.Actor Standard Commands
Actor 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 a little 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).
Existing actors that are based on twistedActor include: