Skip to content
Julian Badillo edited this page Jan 31, 2022 · 5 revisions

This package hopes to become the de facto package to be installed when trying to access our control system. If services aren't available to Python scripts, programmers are encouraged to add support rather than create a new, dependent package. The base package provides support to low-level Accelerator Control System (ACSys) APIs (e.g. request/replies, status values, ACNET-specific node information). Sub-packages provide higher-level APIs to services.

Python error and message logging are done using the logging module. Scripts importing acsys can configure it to control how much logging is generated and where it is sent, likewise for sub-packages.

This package requires Python 3.6, or later.

Documentation is provided in the package so help(acsys) will display helpful information.

A acsys tutorial page shows how to use the low-level API.

Sub-packages

acsys.dpm -- An API for using the Data Pool Manager (DPM).

acsys.scaling -- An API to access the scaling service.

acsys.sync -- An API for using the SYNCD service; a service that delivers clock and state event information.

Modules

acsys

This module is the base for all other modules and sub-packages. It contains the top-level entry point for scripts to use and provides useful, low-level functions that API authors can use when supporting other services.

Classes

Connection()

Constructs a new, but unready, instance. Finishing the set-up of a Connection object requires some async calls to be made. Scripts should not try to create their own Connection object but should, rather, use the value received from acsys.run_client().

.get_addr(name) - async method

Returns the ACNET node address associated with the name. If there is no node associated with the name, acsys.status.ACNET_NO_SUCH is raised.

.get_local_node() - async method

Return the node name associated with this connection. Python scripts and web applications gain access to the control system through a pool of ACNET nodes. This method returns which node of the pool is being used for the connection.

.get_name(addr) - async method

Returns the ACNET node name associated with addr. An address is a 16-bit, unsigned integer where the upper 8 bits are the trunk and the lower 8 bits are the node within the trunk. If there is no node associated with the address, acsys.status.ACNET_NO_SUCH is raised.

.handle - property

Initially None, this property will get set to the handle assigned by the ACSys service once the script connects.

.ping(node) - async method

Detects whether an ACNET node is on the network by sending a PING request to the remote node's ACNET service. The remote node is specified by name, passed as a string in node or by address, passed as an integer (in the range of unsigned, 16-bits). Returns True if the remote node responded in a reasonable amount of time, False otherwise. If ACNET isn't active on the remote node, the machine may still respond to IP pings. This method simply checks to see if ACNET is available.

.request_reply(self, remtsk, message, *, proto=None, timeout=1000) - async method

Sends a request to the remote task, remtsk, and waits for a reply. The task name is a string in the format "TASK@NODE".

message is either a bytearray or bytes type when the proto parameter is None. When proto is specified, it should be the name of a module generated by the Protocol Compiler and message can be any request type of the protocol. This method will handle the encoding/decoding of the message.

The timeout parameter is given in milliseconds and defaults to 1 second. If a reply doesn't arrive within this time, acsys.status.ACNET_UTIME will be raised.

The return value is a 2-tuple where the first element is the trunk/node address of the sender and the second is the reply message. The message will be a binary type if proto is None, or a decoded message otherwise. If the request results in any fatal ACNET status, this method will raise the status as an exception.

.request_stream(self, remtsk, message, *, proto=None, timeout=1000) - async method

Sends a request to the remote task, remtsk to return a stream of replies. The task name is a string in the format "TASK@NODE".

message is either a bytearray or bytes type when the proto parameter is None. When proto is specified, it should be the name of a module generated by the Protocol Compiler and message can be any request type of the protocol. This method will handle the encoding/decoding of the message.

The timeout parameter is given in milliseconds and defaults to 1 second. If any reply doesn't arrive within this time, acsys.status.ACNET_UTIME will be raised.

The return value is an asynchronous generator that can be used in an async-for-loop. This generator produces 2-tuples where the first element is the trunk/node address of the sender and the second is the reply message. The message will be a binary type if proto is None, or a decoded message otherwise. If any reply contains a fatal ACNET status, the generator will end and raise the fatal status.

Functions

run_client(main)

All scripts eventually need to call this function to run their ACSys code. The argument, main, is a reference to an async function that takes a single argument. Once the ACSys environment is set-up, main will be called with a Connection object. If main ever returns or raises an exception, this function will exit.

acsys.status

The acsys.status module defines and implements the ACNET error status type, Status. This module gets imported automatically when acsys is imported.

Classes

Status.create(val)

Constructs a new Status value. val must be a value that matches a signed, 16-bit integer. Scripts shouldn't create their own Status value because all the recognized values should already be defined as module-level constants. To instantiate a Status object from a status code, use:

st = Status.create(status_code)

Status types are organized into groups called facilities. Within each facility, an error code is defined. Positive codes indicate success but could provide extra information associated with the reply data. Negative codes are fatal and will terminate a request (meaning a fatal status will always be in the last reply of a request.)

Some types of Status are derived from Exception so they can be raised (AcnetException). Very few positive statuses are used in ACNET services so the general philosophy of this package is to deliver reply data if the status is non-fatal. Fatal statuses will be raised, and can be captured as:

try:
    # do something that may raise an exception
except AcnetDestinationQueueFull as aeqf:
    # capture explicit error status for ACNET_QUEFULL
except AcnetException as aex:
    # Capture general exception
.err_code - property

Property that returns the error code of the status.

.facility - property

Property that returns the facility code of the status.

.is_fatal - property

Property that returns True if the error code is less than 0, False otherwise.

.is_success - property

Property that returns True if the error code is 0, False otherwise.

.is_warning - property

Property that returns True if the error code is greater than 0, False otherwise. Most, if not all, functions and methods in the acsys package will silently treat warning statuses as success, so this property has limited use but is included for completeness.